version 1.41, 2017/12/18 02:25:15 |
version 1.42, 2018/09/12 01:21:34 |
|
|
char *comment; |
char *comment; |
struct revoked_blob_tree revoked_keys; |
struct revoked_blob_tree revoked_keys; |
struct revoked_blob_tree revoked_sha1s; |
struct revoked_blob_tree revoked_sha1s; |
|
struct revoked_blob_tree revoked_sha256s; |
struct revoked_certs_list revoked_certs; |
struct revoked_certs_list revoked_certs; |
}; |
}; |
|
|
|
|
return NULL; |
return NULL; |
RB_INIT(&krl->revoked_keys); |
RB_INIT(&krl->revoked_keys); |
RB_INIT(&krl->revoked_sha1s); |
RB_INIT(&krl->revoked_sha1s); |
|
RB_INIT(&krl->revoked_sha256s); |
TAILQ_INIT(&krl->revoked_certs); |
TAILQ_INIT(&krl->revoked_certs); |
return krl; |
return krl; |
} |
} |
|
|
free(rb->blob); |
free(rb->blob); |
free(rb); |
free(rb); |
} |
} |
|
RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha256s, trb) { |
|
RB_REMOVE(revoked_blob_tree, &krl->revoked_sha256s, rb); |
|
free(rb->blob); |
|
free(rb); |
|
} |
TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) { |
TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) { |
TAILQ_REMOVE(&krl->revoked_certs, rc, entry); |
TAILQ_REMOVE(&krl->revoked_certs, rc, entry); |
revoked_certs_free(rc); |
revoked_certs_free(rc); |
|
|
return revoke_blob(&krl->revoked_keys, blob, len); |
return revoke_blob(&krl->revoked_keys, blob, len); |
} |
} |
|
|
int |
static int |
ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key) |
revoke_by_hash(struct revoked_blob_tree *target, const u_char *p, size_t len) |
{ |
{ |
u_char *blob; |
u_char *blob; |
size_t len; |
|
int r; |
int r; |
|
|
debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key)); |
/* need to copy hash, as revoke_blob steals ownership */ |
if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, |
if ((blob = malloc(len)) == NULL) |
&blob, &len)) != 0) |
return SSH_ERR_SYSTEM_ERROR; |
|
memcpy(blob, p, len); |
|
if ((r = revoke_blob(target, blob, len)) != 0) { |
|
free(blob); |
return r; |
return r; |
return revoke_blob(&krl->revoked_sha1s, blob, len); |
} |
|
return 0; |
} |
} |
|
|
int |
int |
|
ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len) |
|
{ |
|
debug3("%s: revoke by sha1", __func__); |
|
if (len != 20) |
|
return SSH_ERR_INVALID_FORMAT; |
|
return revoke_by_hash(&krl->revoked_sha1s, p, len); |
|
} |
|
|
|
int |
|
ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len) |
|
{ |
|
debug3("%s: revoke by sha256", __func__); |
|
if (len != 32) |
|
return SSH_ERR_INVALID_FORMAT; |
|
return revoke_by_hash(&krl->revoked_sha256s, p, len); |
|
} |
|
|
|
int |
ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key) |
ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key) |
{ |
{ |
|
/* XXX replace with SHA256? */ |
if (!sshkey_is_cert(key)) |
if (!sshkey_is_cert(key)) |
return ssh_krl_revoke_key_sha1(krl, key); |
return ssh_krl_revoke_key_explicit(krl, key); |
|
|
if (key->cert->serial == 0) { |
if (key->cert->serial == 0) { |
return ssh_krl_revoke_cert_by_key_id(krl, |
return ssh_krl_revoke_cert_by_key_id(krl, |
|
|
(r = sshbuf_put_stringb(buf, sect)) != 0) |
(r = sshbuf_put_stringb(buf, sect)) != 0) |
goto out; |
goto out; |
} |
} |
|
sshbuf_reset(sect); |
|
RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) { |
|
KRL_DBG(("%s: hash len %zu ", __func__, rb->len)); |
|
if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0) |
|
goto out; |
|
} |
|
if (sshbuf_len(sect) != 0) { |
|
if ((r = sshbuf_put_u8(buf, |
|
KRL_SECTION_FINGERPRINT_SHA256)) != 0 || |
|
(r = sshbuf_put_stringb(buf, sect)) != 0) |
|
goto out; |
|
} |
|
|
for (i = 0; i < nsign_keys; i++) { |
for (i = 0; i < nsign_keys; i++) { |
KRL_DBG(("%s: signature key %s", __func__, |
KRL_DBG(("%s: signature key %s", __func__, |
|
|
return r; |
return r; |
} |
} |
|
|
|
static int |
|
blob_section(struct sshbuf *sect, struct revoked_blob_tree *target_tree, |
|
size_t expected_len) |
|
{ |
|
u_char *rdata = NULL; |
|
size_t rlen = 0; |
|
int r; |
|
|
|
while (sshbuf_len(sect) > 0) { |
|
if ((r = sshbuf_get_string(sect, &rdata, &rlen)) != 0) |
|
return r; |
|
if (expected_len != 0 && rlen != expected_len) { |
|
error("%s: bad length", __func__); |
|
free(rdata); |
|
return SSH_ERR_INVALID_FORMAT; |
|
} |
|
if ((r = revoke_blob(target_tree, rdata, rlen)) != 0) { |
|
free(rdata); |
|
return r; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */ |
/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */ |
int |
int |
ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, |
ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, |
|
|
char timestamp[64]; |
char timestamp[64]; |
int r = SSH_ERR_INTERNAL_ERROR, sig_seen; |
int r = SSH_ERR_INTERNAL_ERROR, sig_seen; |
struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used; |
struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used; |
u_char type, *rdata = NULL; |
u_char type; |
const u_char *blob; |
const u_char *blob; |
size_t i, j, sig_off, sects_off, rlen, blen, nca_used; |
size_t i, j, sig_off, sects_off, blen, nca_used; |
u_int format_version; |
u_int format_version; |
|
|
nca_used = 0; |
nca_used = 0; |
|
|
goto out; |
goto out; |
break; |
break; |
case KRL_SECTION_EXPLICIT_KEY: |
case KRL_SECTION_EXPLICIT_KEY: |
|
if ((r = blob_section(sect, |
|
&krl->revoked_keys, 0)) != 0) |
|
goto out; |
|
break; |
case KRL_SECTION_FINGERPRINT_SHA1: |
case KRL_SECTION_FINGERPRINT_SHA1: |
while (sshbuf_len(sect) > 0) { |
if ((r = blob_section(sect, |
if ((r = sshbuf_get_string(sect, |
&krl->revoked_sha1s, 20)) != 0) |
&rdata, &rlen)) != 0) |
goto out; |
goto out; |
|
if (type == KRL_SECTION_FINGERPRINT_SHA1 && |
|
rlen != 20) { |
|
error("%s: bad SHA1 length", __func__); |
|
r = SSH_ERR_INVALID_FORMAT; |
|
goto out; |
|
} |
|
if ((r = revoke_blob( |
|
type == KRL_SECTION_EXPLICIT_KEY ? |
|
&krl->revoked_keys : &krl->revoked_sha1s, |
|
rdata, rlen)) != 0) |
|
goto out; |
|
rdata = NULL; /* revoke_blob frees rdata */ |
|
} |
|
break; |
break; |
|
case KRL_SECTION_FINGERPRINT_SHA256: |
|
if ((r = blob_section(sect, |
|
&krl->revoked_sha256s, 32)) != 0) |
|
goto out; |
|
break; |
case KRL_SECTION_SIGNATURE: |
case KRL_SECTION_SIGNATURE: |
/* Handled above, but still need to stay in synch */ |
/* Handled above, but still need to stay in synch */ |
sshbuf_free(sect); |
sshbuf_free(sect); |
|
|
for (i = 0; i < nca_used; i++) |
for (i = 0; i < nca_used; i++) |
sshkey_free(ca_used[i]); |
sshkey_free(ca_used[i]); |
free(ca_used); |
free(ca_used); |
free(rdata); |
|
sshkey_free(key); |
sshkey_free(key); |
sshbuf_free(copy); |
sshbuf_free(copy); |
sshbuf_free(sect); |
sshbuf_free(sect); |
|
|
free(rb.blob); |
free(rb.blob); |
if (erb != NULL) { |
if (erb != NULL) { |
KRL_DBG(("%s: revoked by key SHA1", __func__)); |
KRL_DBG(("%s: revoked by key SHA1", __func__)); |
|
return SSH_ERR_KEY_REVOKED; |
|
} |
|
memset(&rb, 0, sizeof(rb)); |
|
if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA256, |
|
&rb.blob, &rb.len)) != 0) |
|
return r; |
|
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb); |
|
free(rb.blob); |
|
if (erb != NULL) { |
|
KRL_DBG(("%s: revoked by key SHA256", __func__)); |
return SSH_ERR_KEY_REVOKED; |
return SSH_ERR_KEY_REVOKED; |
} |
} |
|
|