mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-29 16:54:51 +02:00
upstream commit
permit KRLs that revoke certificates by serial number or key ID without scoping to a particular CA; ok markus@
This commit is contained in:
parent
7a2c368477
commit
669aee9943
@ -37,7 +37,7 @@ The available section types are:
|
|||||||
#define KRL_SECTION_FINGERPRINT_SHA1 3
|
#define KRL_SECTION_FINGERPRINT_SHA1 3
|
||||||
#define KRL_SECTION_SIGNATURE 4
|
#define KRL_SECTION_SIGNATURE 4
|
||||||
|
|
||||||
3. Certificate serial section
|
2. Certificate section
|
||||||
|
|
||||||
These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by
|
These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by
|
||||||
serial number or key ID. The consist of the CA key that issued the
|
serial number or key ID. The consist of the CA key that issued the
|
||||||
@ -47,6 +47,11 @@ ignored.
|
|||||||
string ca_key
|
string ca_key
|
||||||
string reserved
|
string reserved
|
||||||
|
|
||||||
|
Where "ca_key" is the standard SSH wire serialisation of the CA's
|
||||||
|
public key. Alternately, "ca_key" may be an empty string to indicate
|
||||||
|
the certificate section applies to all CAs (this is most useful when
|
||||||
|
revoking key IDs).
|
||||||
|
|
||||||
Followed by one or more sections:
|
Followed by one or more sections:
|
||||||
|
|
||||||
byte cert_section_type
|
byte cert_section_type
|
||||||
@ -161,4 +166,4 @@ Implementations that retrieve KRLs over untrusted channels must verify
|
|||||||
signatures. Signature sections are optional for KRLs distributed by
|
signatures. Signature sections are optional for KRLs distributed by
|
||||||
trusted means.
|
trusted means.
|
||||||
|
|
||||||
$OpenBSD: PROTOCOL.krl,v 1.2 2013/01/18 00:24:58 djm Exp $
|
$OpenBSD: PROTOCOL.krl,v 1.3 2015/01/30 01:10:33 djm Exp $
|
||||||
|
102
krl.c
102
krl.c
@ -14,7 +14,7 @@
|
|||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $OpenBSD: krl.c,v 1.30 2015/01/26 02:59:11 djm Exp $ */
|
/* $OpenBSD: krl.c,v 1.31 2015/01/30 01:10:33 djm Exp $ */
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
@ -156,8 +156,7 @@ revoked_certs_free(struct revoked_certs *rc)
|
|||||||
free(rki->key_id);
|
free(rki->key_id);
|
||||||
free(rki);
|
free(rki);
|
||||||
}
|
}
|
||||||
if (rc->ca_key != NULL)
|
sshkey_free(rc->ca_key);
|
||||||
sshkey_free(rc->ca_key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -214,7 +213,8 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key,
|
|||||||
|
|
||||||
*rcp = NULL;
|
*rcp = NULL;
|
||||||
TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
|
TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
|
||||||
if (sshkey_equal(rc->ca_key, ca_key)) {
|
if ((ca_key == NULL && rc->ca_key == NULL) ||
|
||||||
|
sshkey_equal(rc->ca_key, ca_key)) {
|
||||||
*rcp = rc;
|
*rcp = rc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -224,14 +224,17 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key,
|
|||||||
/* If this CA doesn't exist in the list then add it now */
|
/* If this CA doesn't exist in the list then add it now */
|
||||||
if ((rc = calloc(1, sizeof(*rc))) == NULL)
|
if ((rc = calloc(1, sizeof(*rc))) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) {
|
if (ca_key == NULL)
|
||||||
|
rc->ca_key = NULL;
|
||||||
|
else if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) {
|
||||||
free(rc);
|
free(rc);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
RB_INIT(&rc->revoked_serials);
|
RB_INIT(&rc->revoked_serials);
|
||||||
RB_INIT(&rc->revoked_key_ids);
|
RB_INIT(&rc->revoked_key_ids);
|
||||||
TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
|
TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
|
||||||
KRL_DBG(("%s: new CA %s", __func__, sshkey_type(ca_key)));
|
KRL_DBG(("%s: new CA %s", __func__,
|
||||||
|
ca_key == NULL ? "*" : sshkey_type(ca_key)));
|
||||||
*rcp = rc;
|
*rcp = rc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -554,9 +557,15 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
|
|||||||
if ((sect = sshbuf_new()) == NULL)
|
if ((sect = sshbuf_new()) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
|
||||||
/* Store the header: CA scope key, reserved */
|
/* Store the header: optional CA scope key, reserved */
|
||||||
if ((r = sshkey_puts(rc->ca_key, buf)) != 0 ||
|
if (rc->ca_key == NULL) {
|
||||||
(r = sshbuf_put_string(buf, NULL, 0)) != 0)
|
if ((r = sshbuf_put_string(buf, NULL, 0)) != 0)
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
if ((r = sshkey_puts(rc->ca_key, buf)) != 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_put_string(buf, NULL, 0)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Store the revoked serials. */
|
/* Store the revoked serials. */
|
||||||
@ -813,7 +822,7 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
|
|||||||
if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 ||
|
if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 ||
|
||||||
(r = sshbuf_skip_string(buf)) != 0)
|
(r = sshbuf_skip_string(buf)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
if ((r = sshkey_from_blob(blob, blen, &ca_key)) != 0)
|
if (blen != 0 && (r = sshkey_from_blob(blob, blen, &ca_key)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
while (sshbuf_len(buf) > 0) {
|
while (sshbuf_len(buf) > 0) {
|
||||||
@ -1154,13 +1163,45 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Checks certificate serial number and key ID revocation */
|
||||||
|
static int
|
||||||
|
is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc)
|
||||||
|
{
|
||||||
|
struct revoked_serial rs, *ers;
|
||||||
|
struct revoked_key_id rki, *erki;
|
||||||
|
|
||||||
|
/* Check revocation by cert key ID */
|
||||||
|
memset(&rki, 0, sizeof(rki));
|
||||||
|
rki.key_id = key->cert->key_id;
|
||||||
|
erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
|
||||||
|
if (erki != NULL) {
|
||||||
|
KRL_DBG(("%s: revoked by key ID", __func__));
|
||||||
|
return SSH_ERR_KEY_REVOKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Legacy cert formats lack serial numbers. Zero serials numbers
|
||||||
|
* are ignored (it's the default when the CA doesn't specify one).
|
||||||
|
*/
|
||||||
|
if (sshkey_cert_is_legacy(key) || key->cert->serial == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memset(&rs, 0, sizeof(rs));
|
||||||
|
rs.lo = rs.hi = key->cert->serial;
|
||||||
|
ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
|
||||||
|
if (ers != NULL) {
|
||||||
|
KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__,
|
||||||
|
key->cert->serial, ers->lo, ers->hi));
|
||||||
|
return SSH_ERR_KEY_REVOKED;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Checks whether a given key/cert is revoked. Does not check its CA */
|
/* Checks whether a given key/cert is revoked. Does not check its CA */
|
||||||
static int
|
static int
|
||||||
is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
|
is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
|
||||||
{
|
{
|
||||||
struct revoked_blob rb, *erb;
|
struct revoked_blob rb, *erb;
|
||||||
struct revoked_serial rs, *ers;
|
|
||||||
struct revoked_key_id rki, *erki;
|
|
||||||
struct revoked_certs *rc;
|
struct revoked_certs *rc;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1190,37 +1231,22 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
|
|||||||
if (!sshkey_is_cert(key))
|
if (!sshkey_is_cert(key))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check cert revocation */
|
/* Check cert revocation for the specified CA */
|
||||||
if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key,
|
if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key,
|
||||||
&rc, 0)) != 0)
|
&rc, 0)) != 0)
|
||||||
return r;
|
return r;
|
||||||
if (rc == NULL)
|
if (rc != NULL) {
|
||||||
return 0; /* No entry for this CA */
|
if ((r = is_cert_revoked(key, rc)) != 0)
|
||||||
|
return r;
|
||||||
/* Check revocation by cert key ID */
|
}
|
||||||
memset(&rki, 0, sizeof(rki));
|
/* Check cert revocation for the wildcard CA */
|
||||||
rki.key_id = key->cert->key_id;
|
if ((r = revoked_certs_for_ca_key(krl, NULL, &rc, 0)) != 0)
|
||||||
erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
|
return r;
|
||||||
if (erki != NULL) {
|
if (rc != NULL) {
|
||||||
KRL_DBG(("%s: revoked by key ID", __func__));
|
if ((r = is_cert_revoked(key, rc)) != 0)
|
||||||
return SSH_ERR_KEY_REVOKED;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Legacy cert formats lack serial numbers. Zero serials numbers
|
|
||||||
* are ignored (it's the default when the CA doesn't specify one).
|
|
||||||
*/
|
|
||||||
if (sshkey_cert_is_legacy(key) || key->cert->serial == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memset(&rs, 0, sizeof(rs));
|
|
||||||
rs.lo = rs.hi = key->cert->serial;
|
|
||||||
ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
|
|
||||||
if (ers != NULL) {
|
|
||||||
KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__,
|
|
||||||
key->cert->serial, ers->lo, ers->hi));
|
|
||||||
return SSH_ERR_KEY_REVOKED;
|
|
||||||
}
|
|
||||||
KRL_DBG(("%s: %llu no match", __func__, key->cert->serial));
|
KRL_DBG(("%s: %llu no match", __func__, key->cert->serial));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
26
ssh-keygen.c
26
ssh-keygen.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-keygen.c,v 1.260 2015/01/30 00:59:19 djm Exp $ */
|
/* $OpenBSD: ssh-keygen.c,v 1.261 2015/01/30 01:10:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -1973,7 +1973,7 @@ load_krl(const char *path, struct ssh_krl **krlp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_krl_from_file(struct passwd *pw, const char *file,
|
update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
|
||||||
const struct sshkey *ca, struct ssh_krl *krl)
|
const struct sshkey *ca, struct ssh_krl *krl)
|
||||||
{
|
{
|
||||||
struct sshkey *key = NULL;
|
struct sshkey *key = NULL;
|
||||||
@ -2015,7 +2015,7 @@ update_krl_from_file(struct passwd *pw, const char *file,
|
|||||||
if (*cp == '\0')
|
if (*cp == '\0')
|
||||||
continue;
|
continue;
|
||||||
if (strncasecmp(cp, "serial:", 7) == 0) {
|
if (strncasecmp(cp, "serial:", 7) == 0) {
|
||||||
if (ca == NULL) {
|
if (ca == NULL && !wild_ca) {
|
||||||
fatal("revoking certificates by serial number "
|
fatal("revoking certificates by serial number "
|
||||||
"requires specification of a CA key");
|
"requires specification of a CA key");
|
||||||
}
|
}
|
||||||
@ -2052,7 +2052,7 @@ update_krl_from_file(struct passwd *pw, const char *file,
|
|||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
} else if (strncasecmp(cp, "id:", 3) == 0) {
|
} else if (strncasecmp(cp, "id:", 3) == 0) {
|
||||||
if (ca == NULL) {
|
if (ca == NULL && !wild_ca) {
|
||||||
fatal("revoking certificates by key ID "
|
fatal("revoking certificates by key ID "
|
||||||
"requires specification of a CA key");
|
"requires specification of a CA key");
|
||||||
}
|
}
|
||||||
@ -2103,7 +2103,7 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
|
|||||||
struct ssh_krl *krl;
|
struct ssh_krl *krl;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
struct sshkey *ca = NULL;
|
struct sshkey *ca = NULL;
|
||||||
int fd, i, r;
|
int fd, i, r, wild_ca = 0;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
struct sshbuf *kbuf;
|
struct sshbuf *kbuf;
|
||||||
|
|
||||||
@ -2117,11 +2117,15 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
|
|||||||
fatal("KRL \"%s\" does not exist", identity_file);
|
fatal("KRL \"%s\" does not exist", identity_file);
|
||||||
}
|
}
|
||||||
if (ca_key_path != NULL) {
|
if (ca_key_path != NULL) {
|
||||||
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
|
if (strcasecmp(ca_key_path, "none") == 0)
|
||||||
if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
|
wild_ca = 1;
|
||||||
fatal("Cannot load CA public key %s: %s",
|
else {
|
||||||
tmp, ssh_err(r));
|
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
|
||||||
free(tmp);
|
if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
|
||||||
|
fatal("Cannot load CA public key %s: %s",
|
||||||
|
tmp, ssh_err(r));
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updating)
|
if (updating)
|
||||||
@ -2135,7 +2139,7 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
|
|||||||
ssh_krl_set_comment(krl, identity_comment);
|
ssh_krl_set_comment(krl, identity_comment);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
update_krl_from_file(pw, argv[i], ca, krl);
|
update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
|
||||||
|
|
||||||
if ((kbuf = sshbuf_new()) == NULL)
|
if ((kbuf = sshbuf_new()) == NULL)
|
||||||
fatal("sshbuf_new failed");
|
fatal("sshbuf_new failed");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user