summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PROTOCOL.krl9
-rw-r--r--krl.c102
-rw-r--r--ssh-keygen.c26
3 files changed, 86 insertions, 51 deletions
diff --git a/PROTOCOL.krl b/PROTOCOL.krl
index e8caa4527..b9695107b 100644
--- a/PROTOCOL.krl
+++ b/PROTOCOL.krl
@@ -37,7 +37,7 @@ The available section types are:
37#define KRL_SECTION_FINGERPRINT_SHA1 3 37#define KRL_SECTION_FINGERPRINT_SHA1 3
38#define KRL_SECTION_SIGNATURE 4 38#define KRL_SECTION_SIGNATURE 4
39 39
403. Certificate serial section 402. Certificate section
41 41
42These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by 42These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by
43serial number or key ID. The consist of the CA key that issued the 43serial number or key ID. The consist of the CA key that issued the
@@ -47,6 +47,11 @@ ignored.
47 string ca_key 47 string ca_key
48 string reserved 48 string reserved
49 49
50Where "ca_key" is the standard SSH wire serialisation of the CA's
51public key. Alternately, "ca_key" may be an empty string to indicate
52the certificate section applies to all CAs (this is most useful when
53revoking key IDs).
54
50Followed by one or more sections: 55Followed by one or more sections:
51 56
52 byte cert_section_type 57 byte cert_section_type
@@ -161,4 +166,4 @@ Implementations that retrieve KRLs over untrusted channels must verify
161signatures. Signature sections are optional for KRLs distributed by 166signatures. Signature sections are optional for KRLs distributed by
162trusted means. 167trusted means.
163 168
164$OpenBSD: PROTOCOL.krl,v 1.2 2013/01/18 00:24:58 djm Exp $ 169$OpenBSD: PROTOCOL.krl,v 1.3 2015/01/30 01:10:33 djm Exp $
diff --git a/krl.c b/krl.c
index 3fe29c8b1..4bbaa2080 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.c,v 1.30 2015/01/26 02:59:11 djm Exp $ */ 17/* $OpenBSD: krl.c,v 1.31 2015/01/30 01:10:33 djm Exp $ */
18 18
19#include "includes.h" 19#include "includes.h"
20 20
@@ -156,8 +156,7 @@ revoked_certs_free(struct revoked_certs *rc)
156 free(rki->key_id); 156 free(rki->key_id);
157 free(rki); 157 free(rki);
158 } 158 }
159 if (rc->ca_key != NULL) 159 sshkey_free(rc->ca_key);
160 sshkey_free(rc->ca_key);
161} 160}
162 161
163void 162void
@@ -214,7 +213,8 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key,
214 213
215 *rcp = NULL; 214 *rcp = NULL;
216 TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { 215 TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
217 if (sshkey_equal(rc->ca_key, ca_key)) { 216 if ((ca_key == NULL && rc->ca_key == NULL) ||
217 sshkey_equal(rc->ca_key, ca_key)) {
218 *rcp = rc; 218 *rcp = rc;
219 return 0; 219 return 0;
220 } 220 }
@@ -224,14 +224,17 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key,
224 /* If this CA doesn't exist in the list then add it now */ 224 /* If this CA doesn't exist in the list then add it now */
225 if ((rc = calloc(1, sizeof(*rc))) == NULL) 225 if ((rc = calloc(1, sizeof(*rc))) == NULL)
226 return SSH_ERR_ALLOC_FAIL; 226 return SSH_ERR_ALLOC_FAIL;
227 if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) { 227 if (ca_key == NULL)
228 rc->ca_key = NULL;
229 else if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) {
228 free(rc); 230 free(rc);
229 return r; 231 return r;
230 } 232 }
231 RB_INIT(&rc->revoked_serials); 233 RB_INIT(&rc->revoked_serials);
232 RB_INIT(&rc->revoked_key_ids); 234 RB_INIT(&rc->revoked_key_ids);
233 TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry); 235 TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
234 KRL_DBG(("%s: new CA %s", __func__, sshkey_type(ca_key))); 236 KRL_DBG(("%s: new CA %s", __func__,
237 ca_key == NULL ? "*" : sshkey_type(ca_key)));
235 *rcp = rc; 238 *rcp = rc;
236 return 0; 239 return 0;
237} 240}
@@ -554,9 +557,15 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
554 if ((sect = sshbuf_new()) == NULL) 557 if ((sect = sshbuf_new()) == NULL)
555 return SSH_ERR_ALLOC_FAIL; 558 return SSH_ERR_ALLOC_FAIL;
556 559
557 /* Store the header: CA scope key, reserved */ 560 /* Store the header: optional CA scope key, reserved */
558 if ((r = sshkey_puts(rc->ca_key, buf)) != 0 || 561 if (rc->ca_key == NULL) {
559 (r = sshbuf_put_string(buf, NULL, 0)) != 0) 562 if ((r = sshbuf_put_string(buf, NULL, 0)) != 0)
563 goto out;
564 } else {
565 if ((r = sshkey_puts(rc->ca_key, buf)) != 0)
566 goto out;
567 }
568 if ((r = sshbuf_put_string(buf, NULL, 0)) != 0)
560 goto out; 569 goto out;
561 570
562 /* Store the revoked serials. */ 571 /* Store the revoked serials. */
@@ -813,7 +822,7 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
813 if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 || 822 if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 ||
814 (r = sshbuf_skip_string(buf)) != 0) 823 (r = sshbuf_skip_string(buf)) != 0)
815 goto out; 824 goto out;
816 if ((r = sshkey_from_blob(blob, blen, &ca_key)) != 0) 825 if (blen != 0 && (r = sshkey_from_blob(blob, blen, &ca_key)) != 0)
817 goto out; 826 goto out;
818 827
819 while (sshbuf_len(buf) > 0) { 828 while (sshbuf_len(buf) > 0) {
@@ -1154,13 +1163,45 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
1154 return r; 1163 return r;
1155} 1164}
1156 1165
1166/* Checks certificate serial number and key ID revocation */
1167static int
1168is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc)
1169{
1170 struct revoked_serial rs, *ers;
1171 struct revoked_key_id rki, *erki;
1172
1173 /* Check revocation by cert key ID */
1174 memset(&rki, 0, sizeof(rki));
1175 rki.key_id = key->cert->key_id;
1176 erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
1177 if (erki != NULL) {
1178 KRL_DBG(("%s: revoked by key ID", __func__));
1179 return SSH_ERR_KEY_REVOKED;
1180 }
1181
1182 /*
1183 * Legacy cert formats lack serial numbers. Zero serials numbers
1184 * are ignored (it's the default when the CA doesn't specify one).
1185 */
1186 if (sshkey_cert_is_legacy(key) || key->cert->serial == 0)
1187 return 0;
1188
1189 memset(&rs, 0, sizeof(rs));
1190 rs.lo = rs.hi = key->cert->serial;
1191 ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
1192 if (ers != NULL) {
1193 KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__,
1194 key->cert->serial, ers->lo, ers->hi));
1195 return SSH_ERR_KEY_REVOKED;
1196 }
1197 return 0;
1198}
1199
1157/* Checks whether a given key/cert is revoked. Does not check its CA */ 1200/* Checks whether a given key/cert is revoked. Does not check its CA */
1158static int 1201static int
1159is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) 1202is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
1160{ 1203{
1161 struct revoked_blob rb, *erb; 1204 struct revoked_blob rb, *erb;
1162 struct revoked_serial rs, *ers;
1163 struct revoked_key_id rki, *erki;
1164 struct revoked_certs *rc; 1205 struct revoked_certs *rc;
1165 int r; 1206 int r;
1166 1207
@@ -1190,37 +1231,22 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
1190 if (!sshkey_is_cert(key)) 1231 if (!sshkey_is_cert(key))
1191 return 0; 1232 return 0;
1192 1233
1193 /* Check cert revocation */ 1234 /* Check cert revocation for the specified CA */
1194 if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key, 1235 if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key,
1195 &rc, 0)) != 0) 1236 &rc, 0)) != 0)
1196 return r; 1237 return r;
1197 if (rc == NULL) 1238 if (rc != NULL) {
1198 return 0; /* No entry for this CA */ 1239 if ((r = is_cert_revoked(key, rc)) != 0)
1199 1240 return r;
1200 /* Check revocation by cert key ID */
1201 memset(&rki, 0, sizeof(rki));
1202 rki.key_id = key->cert->key_id;
1203 erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
1204 if (erki != NULL) {
1205 KRL_DBG(("%s: revoked by key ID", __func__));
1206 return SSH_ERR_KEY_REVOKED;
1207 } 1241 }
1208 1242 /* Check cert revocation for the wildcard CA */
1209 /* 1243 if ((r = revoked_certs_for_ca_key(krl, NULL, &rc, 0)) != 0)
1210 * Legacy cert formats lack serial numbers. Zero serials numbers 1244 return r;
1211 * are ignored (it's the default when the CA doesn't specify one). 1245 if (rc != NULL) {
1212 */ 1246 if ((r = is_cert_revoked(key, rc)) != 0)
1213 if (sshkey_cert_is_legacy(key) || key->cert->serial == 0) 1247 return r;
1214 return 0;
1215
1216 memset(&rs, 0, sizeof(rs));
1217 rs.lo = rs.hi = key->cert->serial;
1218 ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
1219 if (ers != NULL) {
1220 KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__,
1221 key->cert->serial, ers->lo, ers->hi));
1222 return SSH_ERR_KEY_REVOKED;
1223 } 1248 }
1249
1224 KRL_DBG(("%s: %llu no match", __func__, key->cert->serial)); 1250 KRL_DBG(("%s: %llu no match", __func__, key->cert->serial));
1225 return 0; 1251 return 0;
1226} 1252}
diff --git a/ssh-keygen.c b/ssh-keygen.c
index b435498cb..2c6a56839 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.260 2015/01/30 00:59:19 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.261 2015/01/30 01:10:33 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1973,7 +1973,7 @@ load_krl(const char *path, struct ssh_krl **krlp)
1973} 1973}
1974 1974
1975static void 1975static void
1976update_krl_from_file(struct passwd *pw, const char *file, 1976update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
1977 const struct sshkey *ca, struct ssh_krl *krl) 1977 const struct sshkey *ca, struct ssh_krl *krl)
1978{ 1978{
1979 struct sshkey *key = NULL; 1979 struct sshkey *key = NULL;
@@ -2015,7 +2015,7 @@ update_krl_from_file(struct passwd *pw, const char *file,
2015 if (*cp == '\0') 2015 if (*cp == '\0')
2016 continue; 2016 continue;
2017 if (strncasecmp(cp, "serial:", 7) == 0) { 2017 if (strncasecmp(cp, "serial:", 7) == 0) {
2018 if (ca == NULL) { 2018 if (ca == NULL && !wild_ca) {
2019 fatal("revoking certificates by serial number " 2019 fatal("revoking certificates by serial number "
2020 "requires specification of a CA key"); 2020 "requires specification of a CA key");
2021 } 2021 }
@@ -2052,7 +2052,7 @@ update_krl_from_file(struct passwd *pw, const char *file,
2052 __func__); 2052 __func__);
2053 } 2053 }
2054 } else if (strncasecmp(cp, "id:", 3) == 0) { 2054 } else if (strncasecmp(cp, "id:", 3) == 0) {
2055 if (ca == NULL) { 2055 if (ca == NULL && !wild_ca) {
2056 fatal("revoking certificates by key ID " 2056 fatal("revoking certificates by key ID "
2057 "requires specification of a CA key"); 2057 "requires specification of a CA key");
2058 } 2058 }
@@ -2103,7 +2103,7 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
2103 struct ssh_krl *krl; 2103 struct ssh_krl *krl;
2104 struct stat sb; 2104 struct stat sb;
2105 struct sshkey *ca = NULL; 2105 struct sshkey *ca = NULL;
2106 int fd, i, r; 2106 int fd, i, r, wild_ca = 0;
2107 char *tmp; 2107 char *tmp;
2108 struct sshbuf *kbuf; 2108 struct sshbuf *kbuf;
2109 2109
@@ -2117,11 +2117,15 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
2117 fatal("KRL \"%s\" does not exist", identity_file); 2117 fatal("KRL \"%s\" does not exist", identity_file);
2118 } 2118 }
2119 if (ca_key_path != NULL) { 2119 if (ca_key_path != NULL) {
2120 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); 2120 if (strcasecmp(ca_key_path, "none") == 0)
2121 if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0) 2121 wild_ca = 1;
2122 fatal("Cannot load CA public key %s: %s", 2122 else {
2123 tmp, ssh_err(r)); 2123 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
2124 free(tmp); 2124 if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
2125 fatal("Cannot load CA public key %s: %s",
2126 tmp, ssh_err(r));
2127 free(tmp);
2128 }
2125 } 2129 }
2126 2130
2127 if (updating) 2131 if (updating)
@@ -2135,7 +2139,7 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
2135 ssh_krl_set_comment(krl, identity_comment); 2139 ssh_krl_set_comment(krl, identity_comment);
2136 2140
2137 for (i = 0; i < argc; i++) 2141 for (i = 0; i < argc; i++)
2138 update_krl_from_file(pw, argv[i], ca, krl); 2142 update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
2139 2143
2140 if ((kbuf = sshbuf_new()) == NULL) 2144 if ((kbuf = sshbuf_new()) == NULL)
2141 fatal("sshbuf_new failed"); 2145 fatal("sshbuf_new failed");