diff options
-rw-r--r-- | krl.c | 651 | ||||
-rw-r--r-- | krl.h | 38 | ||||
-rw-r--r-- | sshbuf-getput-basic.c | 4 |
3 files changed, 357 insertions, 336 deletions
@@ -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.19 2014/11/21 01:00:38 djm Exp $ */ | 17 | /* $OpenBSD: krl.c,v 1.20 2014/12/04 01:49:59 djm Exp $ */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | 20 | ||
@@ -30,12 +30,12 @@ | |||
30 | #include <time.h> | 30 | #include <time.h> |
31 | #include <unistd.h> | 31 | #include <unistd.h> |
32 | 32 | ||
33 | #include "buffer.h" | 33 | #include "sshbuf.h" |
34 | #include "key.h" | 34 | #include "sshkey.h" |
35 | #include "authfile.h" | 35 | #include "authfile.h" |
36 | #include "misc.h" | 36 | #include "misc.h" |
37 | #include "log.h" | 37 | #include "log.h" |
38 | #include "xmalloc.h" | 38 | #include "ssherr.h" |
39 | 39 | ||
40 | #include "krl.h" | 40 | #include "krl.h" |
41 | 41 | ||
@@ -72,7 +72,7 @@ RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp); | |||
72 | /* Tree of blobs (used for keys and fingerprints) */ | 72 | /* Tree of blobs (used for keys and fingerprints) */ |
73 | struct revoked_blob { | 73 | struct revoked_blob { |
74 | u_char *blob; | 74 | u_char *blob; |
75 | u_int len; | 75 | size_t len; |
76 | RB_ENTRY(revoked_blob) tree_entry; | 76 | RB_ENTRY(revoked_blob) tree_entry; |
77 | }; | 77 | }; |
78 | static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b); | 78 | static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b); |
@@ -81,7 +81,7 @@ RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp); | |||
81 | 81 | ||
82 | /* Tracks revoked certs for a single CA */ | 82 | /* Tracks revoked certs for a single CA */ |
83 | struct revoked_certs { | 83 | struct revoked_certs { |
84 | Key *ca_key; | 84 | struct sshkey *ca_key; |
85 | struct revoked_serial_tree revoked_serials; | 85 | struct revoked_serial_tree revoked_serials; |
86 | struct revoked_key_id_tree revoked_key_ids; | 86 | struct revoked_key_id_tree revoked_key_ids; |
87 | TAILQ_ENTRY(revoked_certs) entry; | 87 | TAILQ_ENTRY(revoked_certs) entry; |
@@ -155,7 +155,7 @@ revoked_certs_free(struct revoked_certs *rc) | |||
155 | free(rki); | 155 | free(rki); |
156 | } | 156 | } |
157 | if (rc->ca_key != NULL) | 157 | if (rc->ca_key != NULL) |
158 | key_free(rc->ca_key); | 158 | sshkey_free(rc->ca_key); |
159 | } | 159 | } |
160 | 160 | ||
161 | void | 161 | void |
@@ -190,12 +190,13 @@ ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version) | |||
190 | krl->krl_version = version; | 190 | krl->krl_version = version; |
191 | } | 191 | } |
192 | 192 | ||
193 | void | 193 | int |
194 | ssh_krl_set_comment(struct ssh_krl *krl, const char *comment) | 194 | ssh_krl_set_comment(struct ssh_krl *krl, const char *comment) |
195 | { | 195 | { |
196 | free(krl->comment); | 196 | free(krl->comment); |
197 | if ((krl->comment = strdup(comment)) == NULL) | 197 | if ((krl->comment = strdup(comment)) == NULL) |
198 | fatal("%s: strdup", __func__); | 198 | return SSH_ERR_ALLOC_FAIL; |
199 | return 0; | ||
199 | } | 200 | } |
200 | 201 | ||
201 | /* | 202 | /* |
@@ -203,14 +204,15 @@ ssh_krl_set_comment(struct ssh_krl *krl, const char *comment) | |||
203 | * create a new one in the tree if one did not exist already. | 204 | * create a new one in the tree if one did not exist already. |
204 | */ | 205 | */ |
205 | static int | 206 | static int |
206 | revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key, | 207 | revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key, |
207 | struct revoked_certs **rcp, int allow_create) | 208 | struct revoked_certs **rcp, int allow_create) |
208 | { | 209 | { |
209 | struct revoked_certs *rc; | 210 | struct revoked_certs *rc; |
211 | int r; | ||
210 | 212 | ||
211 | *rcp = NULL; | 213 | *rcp = NULL; |
212 | TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { | 214 | TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { |
213 | if (key_equal(rc->ca_key, ca_key)) { | 215 | if (sshkey_equal(rc->ca_key, ca_key)) { |
214 | *rcp = rc; | 216 | *rcp = rc; |
215 | return 0; | 217 | return 0; |
216 | } | 218 | } |
@@ -219,15 +221,15 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key, | |||
219 | return 0; | 221 | return 0; |
220 | /* If this CA doesn't exist in the list then add it now */ | 222 | /* If this CA doesn't exist in the list then add it now */ |
221 | if ((rc = calloc(1, sizeof(*rc))) == NULL) | 223 | if ((rc = calloc(1, sizeof(*rc))) == NULL) |
222 | return -1; | 224 | return SSH_ERR_ALLOC_FAIL; |
223 | if ((rc->ca_key = key_from_private(ca_key)) == NULL) { | 225 | if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) { |
224 | free(rc); | 226 | free(rc); |
225 | return -1; | 227 | return r; |
226 | } | 228 | } |
227 | RB_INIT(&rc->revoked_serials); | 229 | RB_INIT(&rc->revoked_serials); |
228 | RB_INIT(&rc->revoked_key_ids); | 230 | RB_INIT(&rc->revoked_key_ids); |
229 | TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry); | 231 | TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry); |
230 | debug3("%s: new CA %s", __func__, key_type(ca_key)); | 232 | debug3("%s: new CA %s", __func__, sshkey_type(ca_key)); |
231 | *rcp = rc; | 233 | *rcp = rc; |
232 | return 0; | 234 | return 0; |
233 | } | 235 | } |
@@ -245,14 +247,14 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) | |||
245 | if (ers == NULL || serial_cmp(ers, &rs) != 0) { | 247 | if (ers == NULL || serial_cmp(ers, &rs) != 0) { |
246 | /* No entry matches. Just insert */ | 248 | /* No entry matches. Just insert */ |
247 | if ((irs = malloc(sizeof(rs))) == NULL) | 249 | if ((irs = malloc(sizeof(rs))) == NULL) |
248 | return -1; | 250 | return SSH_ERR_ALLOC_FAIL; |
249 | memcpy(irs, &rs, sizeof(*irs)); | 251 | memcpy(irs, &rs, sizeof(*irs)); |
250 | ers = RB_INSERT(revoked_serial_tree, rt, irs); | 252 | ers = RB_INSERT(revoked_serial_tree, rt, irs); |
251 | if (ers != NULL) { | 253 | if (ers != NULL) { |
252 | KRL_DBG(("%s: bad: ers != NULL", __func__)); | 254 | KRL_DBG(("%s: bad: ers != NULL", __func__)); |
253 | /* Shouldn't happen */ | 255 | /* Shouldn't happen */ |
254 | free(irs); | 256 | free(irs); |
255 | return -1; | 257 | return SSH_ERR_ALLOC_FAIL; |
256 | } | 258 | } |
257 | ers = irs; | 259 | ers = irs; |
258 | } else { | 260 | } else { |
@@ -305,40 +307,42 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) | |||
305 | } | 307 | } |
306 | 308 | ||
307 | int | 309 | int |
308 | ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key, | 310 | ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const struct sshkey *ca_key, |
309 | u_int64_t serial) | 311 | u_int64_t serial) |
310 | { | 312 | { |
311 | return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial); | 313 | return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial); |
312 | } | 314 | } |
313 | 315 | ||
314 | int | 316 | int |
315 | ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key, | 317 | ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const struct sshkey *ca_key, |
316 | u_int64_t lo, u_int64_t hi) | 318 | u_int64_t lo, u_int64_t hi) |
317 | { | 319 | { |
318 | struct revoked_certs *rc; | 320 | struct revoked_certs *rc; |
321 | int r; | ||
319 | 322 | ||
320 | if (lo > hi || lo == 0) | 323 | if (lo > hi || lo == 0) |
321 | return -1; | 324 | return -1; |
322 | if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0) | 325 | if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0) |
323 | return -1; | 326 | return r; |
324 | return insert_serial_range(&rc->revoked_serials, lo, hi); | 327 | return insert_serial_range(&rc->revoked_serials, lo, hi); |
325 | } | 328 | } |
326 | 329 | ||
327 | int | 330 | int |
328 | ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, | 331 | ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const struct sshkey *ca_key, |
329 | const char *key_id) | 332 | const char *key_id) |
330 | { | 333 | { |
331 | struct revoked_key_id *rki, *erki; | 334 | struct revoked_key_id *rki, *erki; |
332 | struct revoked_certs *rc; | 335 | struct revoked_certs *rc; |
336 | int r; | ||
333 | 337 | ||
334 | if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0) | 338 | if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0) |
335 | return -1; | 339 | return r; |
336 | 340 | ||
337 | debug3("%s: revoke %s", __func__, key_id); | 341 | debug3("%s: revoke %s", __func__, key_id); |
338 | if ((rki = calloc(1, sizeof(*rki))) == NULL || | 342 | if ((rki = calloc(1, sizeof(*rki))) == NULL || |
339 | (rki->key_id = strdup(key_id)) == NULL) { | 343 | (rki->key_id = strdup(key_id)) == NULL) { |
340 | free(rki); | 344 | free(rki); |
341 | fatal("%s: strdup", __func__); | 345 | return SSH_ERR_ALLOC_FAIL; |
342 | } | 346 | } |
343 | erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki); | 347 | erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki); |
344 | if (erki != NULL) { | 348 | if (erki != NULL) { |
@@ -350,21 +354,20 @@ ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, | |||
350 | 354 | ||
351 | /* Convert "key" to a public key blob without any certificate information */ | 355 | /* Convert "key" to a public key blob without any certificate information */ |
352 | static int | 356 | static int |
353 | plain_key_blob(const Key *key, u_char **blob, u_int *blen) | 357 | plain_key_blob(const struct sshkey *key, u_char **blob, size_t *blen) |
354 | { | 358 | { |
355 | Key *kcopy; | 359 | struct sshkey *kcopy; |
356 | int r; | 360 | int r; |
357 | 361 | ||
358 | if ((kcopy = key_from_private(key)) == NULL) | 362 | if ((r = sshkey_from_private(key, &kcopy)) != 0) |
359 | return -1; | 363 | return r; |
360 | if (key_is_cert(kcopy)) { | 364 | if (sshkey_is_cert(kcopy)) { |
361 | if (key_drop_cert(kcopy) != 0) { | 365 | if ((r = sshkey_drop_cert(kcopy)) != 0) { |
362 | error("%s: key_drop_cert", __func__); | 366 | sshkey_free(kcopy); |
363 | key_free(kcopy); | 367 | return r; |
364 | return -1; | ||
365 | } | 368 | } |
366 | } | 369 | } |
367 | r = key_to_blob(kcopy, blob, blen); | 370 | r = sshkey_to_blob(kcopy, blob, blen); |
368 | free(kcopy); | 371 | free(kcopy); |
369 | return r; | 372 | return r; |
370 | } | 373 | } |
@@ -376,7 +379,7 @@ revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len) | |||
376 | struct revoked_blob *rb, *erb; | 379 | struct revoked_blob *rb, *erb; |
377 | 380 | ||
378 | if ((rb = calloc(1, sizeof(*rb))) == NULL) | 381 | if ((rb = calloc(1, sizeof(*rb))) == NULL) |
379 | return -1; | 382 | return SSH_ERR_ALLOC_FAIL; |
380 | rb->blob = blob; | 383 | rb->blob = blob; |
381 | rb->len = len; | 384 | rb->len = len; |
382 | erb = RB_INSERT(revoked_blob_tree, rbt, rb); | 385 | erb = RB_INSERT(revoked_blob_tree, rbt, rb); |
@@ -388,36 +391,38 @@ revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len) | |||
388 | } | 391 | } |
389 | 392 | ||
390 | int | 393 | int |
391 | ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key) | 394 | ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key) |
392 | { | 395 | { |
393 | u_char *blob; | 396 | u_char *blob; |
394 | u_int len; | 397 | size_t len; |
398 | int r; | ||
395 | 399 | ||
396 | debug3("%s: revoke type %s", __func__, key_type(key)); | 400 | debug3("%s: revoke type %s", __func__, sshkey_type(key)); |
397 | if (plain_key_blob(key, &blob, &len) < 0) | 401 | if ((r = plain_key_blob(key, &blob, &len)) != 0) |
398 | return -1; | 402 | return r; |
399 | return revoke_blob(&krl->revoked_keys, blob, len); | 403 | return revoke_blob(&krl->revoked_keys, blob, len); |
400 | } | 404 | } |
401 | 405 | ||
402 | int | 406 | int |
403 | ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key) | 407 | ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key) |
404 | { | 408 | { |
405 | u_char *blob; | 409 | u_char *blob; |
406 | u_int len; | 410 | size_t len; |
411 | int r; | ||
407 | 412 | ||
408 | debug3("%s: revoke type %s by sha1", __func__, key_type(key)); | 413 | debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key)); |
409 | if ((blob = key_fingerprint_raw(key, SSH_FP_SHA1, &len)) == NULL) | 414 | if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, &blob, &len)) != 0) |
410 | return -1; | 415 | return r; |
411 | return revoke_blob(&krl->revoked_sha1s, blob, len); | 416 | return revoke_blob(&krl->revoked_sha1s, blob, len); |
412 | } | 417 | } |
413 | 418 | ||
414 | int | 419 | int |
415 | ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key) | 420 | ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key) |
416 | { | 421 | { |
417 | if (!key_is_cert(key)) | 422 | if (!sshkey_is_cert(key)) |
418 | return ssh_krl_revoke_key_sha1(krl, key); | 423 | return ssh_krl_revoke_key_sha1(krl, key); |
419 | 424 | ||
420 | if (key_cert_is_legacy(key) || key->cert->serial == 0) { | 425 | if (sshkey_cert_is_legacy(key) || key->cert->serial == 0) { |
421 | return ssh_krl_revoke_cert_by_key_id(krl, | 426 | return ssh_krl_revoke_cert_by_key_id(krl, |
422 | key->cert->signature_key, | 427 | key->cert->signature_key, |
423 | key->cert->key_id); | 428 | key->cert->key_id); |
@@ -429,8 +434,8 @@ ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key) | |||
429 | } | 434 | } |
430 | 435 | ||
431 | /* | 436 | /* |
432 | * Select a copact next section type to emit in a KRL based on the | 437 | * Select the most compact section type to emit next in a KRL based on |
433 | * current section type, the run length of contiguous revoked serial | 438 | * the current section type, the run length of contiguous revoked serial |
434 | * numbers and the gaps from the last and to the next revoked serial. | 439 | * numbers and the gaps from the last and to the next revoked serial. |
435 | * Applies a mostly-accurate bit cost model to select the section type | 440 | * Applies a mostly-accurate bit cost model to select the section type |
436 | * that will minimise the size of the resultant KRL. | 441 | * that will minimise the size of the resultant KRL. |
@@ -513,29 +518,26 @@ choose_next_state(int current_state, u_int64_t contig, int final, | |||
513 | 518 | ||
514 | /* Generate a KRL_SECTION_CERTIFICATES KRL section */ | 519 | /* Generate a KRL_SECTION_CERTIFICATES KRL section */ |
515 | static int | 520 | static int |
516 | revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) | 521 | revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) |
517 | { | 522 | { |
518 | int final, force_new_sect, r = -1; | 523 | int final, force_new_sect, r = -1; |
519 | u_int64_t i, contig, gap, last = 0, bitmap_start = 0; | 524 | u_int64_t i, contig, gap, last = 0, bitmap_start = 0; |
520 | struct revoked_serial *rs, *nrs; | 525 | struct revoked_serial *rs, *nrs; |
521 | struct revoked_key_id *rki; | 526 | struct revoked_key_id *rki; |
522 | int next_state, state = 0; | 527 | int next_state, state = 0; |
523 | Buffer sect; | 528 | struct sshbuf *sect; |
524 | u_char *kblob = NULL; | ||
525 | u_int klen; | ||
526 | BIGNUM *bitmap = NULL; | 529 | BIGNUM *bitmap = NULL; |
527 | 530 | ||
528 | /* Prepare CA scope key blob if we have one supplied */ | 531 | if ((sect = sshbuf_new()) == NULL) |
529 | if (key_to_blob(rc->ca_key, &kblob, &klen) == 0) | 532 | return SSH_ERR_ALLOC_FAIL; |
530 | return -1; | ||
531 | |||
532 | buffer_init(§); | ||
533 | 533 | ||
534 | /* Store the header */ | 534 | /* Store the header: CA scope key, reserved */ |
535 | buffer_put_string(buf, kblob, klen); | 535 | if ((r = sshkey_to_blob_buf(rc->ca_key, sect)) != 0 || |
536 | buffer_put_string(buf, NULL, 0); /* Reserved */ | 536 | (r = sshbuf_put_stringb(buf, sect)) != 0 || |
537 | (r = sshbuf_put_string(buf, NULL, 0)) != 0) | ||
538 | goto out; | ||
537 | 539 | ||
538 | free(kblob); | 540 | sshbuf_reset(sect); |
539 | 541 | ||
540 | /* Store the revoked serials. */ | 542 | /* Store the revoked serials. */ |
541 | for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials); | 543 | for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials); |
@@ -567,31 +569,36 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) | |||
567 | case KRL_SECTION_CERT_SERIAL_RANGE: | 569 | case KRL_SECTION_CERT_SERIAL_RANGE: |
568 | break; | 570 | break; |
569 | case KRL_SECTION_CERT_SERIAL_BITMAP: | 571 | case KRL_SECTION_CERT_SERIAL_BITMAP: |
570 | buffer_put_bignum2(§, bitmap); | 572 | if ((r = sshbuf_put_bignum2(sect, bitmap)) != 0) |
573 | goto out; | ||
571 | BN_free(bitmap); | 574 | BN_free(bitmap); |
572 | bitmap = NULL; | 575 | bitmap = NULL; |
573 | break; | 576 | break; |
574 | } | 577 | } |
575 | buffer_put_char(buf, state); | 578 | if ((r = sshbuf_put_u8(buf, state)) != 0 || |
576 | buffer_put_string(buf, | 579 | (r = sshbuf_put_stringb(buf, sect)) != 0) |
577 | buffer_ptr(§), buffer_len(§)); | 580 | goto out; |
578 | buffer_clear(§); | 581 | sshbuf_reset(sect); |
579 | } | 582 | } |
580 | 583 | ||
581 | /* If we are starting a new section then prepare it now */ | 584 | /* If we are starting a new section then prepare it now */ |
582 | if (next_state != state || force_new_sect) { | 585 | if (next_state != state || force_new_sect) { |
583 | debug3("%s: start state 0x%02x", __func__, next_state); | 586 | debug3("%s: start state 0x%02x", __func__, next_state); |
584 | state = next_state; | 587 | state = next_state; |
585 | buffer_clear(§); | 588 | sshbuf_reset(sect); |
586 | switch (state) { | 589 | switch (state) { |
587 | case KRL_SECTION_CERT_SERIAL_LIST: | 590 | case KRL_SECTION_CERT_SERIAL_LIST: |
588 | case KRL_SECTION_CERT_SERIAL_RANGE: | 591 | case KRL_SECTION_CERT_SERIAL_RANGE: |
589 | break; | 592 | break; |
590 | case KRL_SECTION_CERT_SERIAL_BITMAP: | 593 | case KRL_SECTION_CERT_SERIAL_BITMAP: |
591 | if ((bitmap = BN_new()) == NULL) | 594 | if ((bitmap = BN_new()) == NULL) { |
595 | r = SSH_ERR_ALLOC_FAIL; | ||
592 | goto out; | 596 | goto out; |
597 | } | ||
593 | bitmap_start = rs->lo; | 598 | bitmap_start = rs->lo; |
594 | buffer_put_int64(§, bitmap_start); | 599 | if ((r = sshbuf_put_u64(sect, |
600 | bitmap_start)) != 0) | ||
601 | goto out; | ||
595 | break; | 602 | break; |
596 | } | 603 | } |
597 | } | 604 | } |
@@ -599,12 +606,15 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) | |||
599 | /* Perform section-specific processing */ | 606 | /* Perform section-specific processing */ |
600 | switch (state) { | 607 | switch (state) { |
601 | case KRL_SECTION_CERT_SERIAL_LIST: | 608 | case KRL_SECTION_CERT_SERIAL_LIST: |
602 | for (i = 0; i < contig; i++) | 609 | for (i = 0; i < contig; i++) { |
603 | buffer_put_int64(§, rs->lo + i); | 610 | if ((r = sshbuf_put_u64(sect, rs->lo + i)) != 0) |
611 | goto out; | ||
612 | } | ||
604 | break; | 613 | break; |
605 | case KRL_SECTION_CERT_SERIAL_RANGE: | 614 | case KRL_SECTION_CERT_SERIAL_RANGE: |
606 | buffer_put_int64(§, rs->lo); | 615 | if ((r = sshbuf_put_u64(sect, rs->lo)) != 0 || |
607 | buffer_put_int64(§, rs->hi); | 616 | (r = sshbuf_put_u64(sect, rs->hi)) != 0) |
617 | goto out; | ||
608 | break; | 618 | break; |
609 | case KRL_SECTION_CERT_SERIAL_BITMAP: | 619 | case KRL_SECTION_CERT_SERIAL_BITMAP: |
610 | if (rs->lo - bitmap_start > INT_MAX) { | 620 | if (rs->lo - bitmap_start > INT_MAX) { |
@@ -613,8 +623,10 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) | |||
613 | } | 623 | } |
614 | for (i = 0; i < contig; i++) { | 624 | for (i = 0; i < contig; i++) { |
615 | if (BN_set_bit(bitmap, | 625 | if (BN_set_bit(bitmap, |
616 | rs->lo + i - bitmap_start) != 1) | 626 | rs->lo + i - bitmap_start) != 1) { |
627 | r = SSH_ERR_ALLOC_FAIL; | ||
617 | goto out; | 628 | goto out; |
629 | } | ||
618 | } | 630 | } |
619 | break; | 631 | break; |
620 | } | 632 | } |
@@ -629,113 +641,122 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) | |||
629 | case KRL_SECTION_CERT_SERIAL_RANGE: | 641 | case KRL_SECTION_CERT_SERIAL_RANGE: |
630 | break; | 642 | break; |
631 | case KRL_SECTION_CERT_SERIAL_BITMAP: | 643 | case KRL_SECTION_CERT_SERIAL_BITMAP: |
632 | buffer_put_bignum2(§, bitmap); | 644 | if ((r = sshbuf_put_bignum2(sect, bitmap)) != 0) |
645 | goto out; | ||
633 | BN_free(bitmap); | 646 | BN_free(bitmap); |
634 | bitmap = NULL; | 647 | bitmap = NULL; |
635 | break; | 648 | break; |
636 | } | 649 | } |
637 | buffer_put_char(buf, state); | 650 | if ((r = sshbuf_put_u8(buf, state)) != 0 || |
638 | buffer_put_string(buf, | 651 | (r = sshbuf_put_stringb(buf, sect)) != 0) |
639 | buffer_ptr(§), buffer_len(§)); | 652 | goto out; |
640 | } | 653 | } |
641 | debug3("%s: serial done ", __func__); | 654 | debug3("%s: serial done ", __func__); |
642 | 655 | ||
643 | /* Now output a section for any revocations by key ID */ | 656 | /* Now output a section for any revocations by key ID */ |
644 | buffer_clear(§); | 657 | sshbuf_reset(sect); |
645 | RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { | 658 | RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { |
646 | debug3("%s: key ID %s", __func__, rki->key_id); | 659 | debug3("%s: key ID %s", __func__, rki->key_id); |
647 | buffer_put_cstring(§, rki->key_id); | 660 | if ((r = sshbuf_put_cstring(sect, rki->key_id)) != 0) |
661 | goto out; | ||
648 | } | 662 | } |
649 | if (buffer_len(§) != 0) { | 663 | if (sshbuf_len(sect) != 0) { |
650 | buffer_put_char(buf, KRL_SECTION_CERT_KEY_ID); | 664 | if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERT_KEY_ID)) != 0 || |
651 | buffer_put_string(buf, buffer_ptr(§), | 665 | (r = sshbuf_put_stringb(buf, sect)) != 0) |
652 | buffer_len(§)); | 666 | goto out; |
653 | } | 667 | } |
654 | r = 0; | 668 | r = 0; |
655 | out: | 669 | out: |
656 | if (bitmap != NULL) | 670 | if (bitmap != NULL) |
657 | BN_free(bitmap); | 671 | BN_free(bitmap); |
658 | buffer_free(§); | 672 | sshbuf_free(sect); |
659 | return r; | 673 | return r; |
660 | } | 674 | } |
661 | 675 | ||
662 | int | 676 | int |
663 | ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys, | 677 | ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, |
664 | u_int nsign_keys) | 678 | const struct sshkey **sign_keys, u_int nsign_keys) |
665 | { | 679 | { |
666 | int r = -1; | 680 | int r = -1; |
667 | struct revoked_certs *rc; | 681 | struct revoked_certs *rc; |
668 | struct revoked_blob *rb; | 682 | struct revoked_blob *rb; |
669 | Buffer sect; | 683 | struct sshbuf *sect; |
670 | u_char *kblob = NULL, *sblob = NULL; | 684 | u_char *sblob = NULL; |
671 | u_int klen, slen, i; | 685 | size_t slen, i; |
672 | 686 | ||
673 | if (krl->generated_date == 0) | 687 | if (krl->generated_date == 0) |
674 | krl->generated_date = time(NULL); | 688 | krl->generated_date = time(NULL); |
675 | 689 | ||
676 | buffer_init(§); | 690 | if ((sect = sshbuf_new()) == NULL) |
691 | return SSH_ERR_ALLOC_FAIL; | ||
677 | 692 | ||
678 | /* Store the header */ | 693 | /* Store the header */ |
679 | buffer_append(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1); | 694 | if ((r = sshbuf_put(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1)) != 0 || |
680 | buffer_put_int(buf, KRL_FORMAT_VERSION); | 695 | (r = sshbuf_put_u32(buf, KRL_FORMAT_VERSION)) != 0 || |
681 | buffer_put_int64(buf, krl->krl_version); | 696 | (r = sshbuf_put_u64(buf, krl->krl_version)) != 0 || |
682 | buffer_put_int64(buf, krl->generated_date); | 697 | (r = sshbuf_put_u64(buf, krl->generated_date) != 0) || |
683 | buffer_put_int64(buf, krl->flags); | 698 | (r = sshbuf_put_u64(buf, krl->flags)) != 0 || |
684 | buffer_put_string(buf, NULL, 0); | 699 | (r = sshbuf_put_string(buf, NULL, 0)) != 0 || |
685 | buffer_put_cstring(buf, krl->comment ? krl->comment : ""); | 700 | (r = sshbuf_put_cstring(buf, krl->comment)) != 0) |
701 | goto out; | ||
686 | 702 | ||
687 | /* Store sections for revoked certificates */ | 703 | /* Store sections for revoked certificates */ |
688 | TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { | 704 | TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { |
689 | buffer_clear(§); | 705 | sshbuf_reset(sect); |
690 | if (revoked_certs_generate(rc, §) != 0) | 706 | if ((r = revoked_certs_generate(rc, sect)) != 0) |
707 | goto out; | ||
708 | if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERTIFICATES)) != 0 || | ||
709 | (r = sshbuf_put_stringb(buf, sect)) != 0) | ||
691 | goto out; | 710 | goto out; |
692 | buffer_put_char(buf, KRL_SECTION_CERTIFICATES); | ||
693 | buffer_put_string(buf, buffer_ptr(§), | ||
694 | buffer_len(§)); | ||
695 | } | 711 | } |
696 | 712 | ||
697 | /* Finally, output sections for revocations by public key/hash */ | 713 | /* Finally, output sections for revocations by public key/hash */ |
698 | buffer_clear(§); | 714 | sshbuf_reset(sect); |
699 | RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { | 715 | RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { |
700 | debug3("%s: key len %u ", __func__, rb->len); | 716 | debug3("%s: key len %zu ", __func__, rb->len); |
701 | buffer_put_string(§, rb->blob, rb->len); | 717 | if ((sshbuf_put_string(sect, rb->blob, rb->len)) != 0) |
718 | goto out; | ||
702 | } | 719 | } |
703 | if (buffer_len(§) != 0) { | 720 | if (sshbuf_len(sect) != 0) { |
704 | buffer_put_char(buf, KRL_SECTION_EXPLICIT_KEY); | 721 | if ((r = sshbuf_put_u8(buf, KRL_SECTION_EXPLICIT_KEY)) != 0 || |
705 | buffer_put_string(buf, buffer_ptr(§), | 722 | (r = sshbuf_put_stringb(buf, sect)) != 0) |
706 | buffer_len(§)); | 723 | goto out; |
707 | } | 724 | } |
708 | buffer_clear(§); | 725 | sshbuf_reset(sect); |
709 | RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { | 726 | RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { |
710 | debug3("%s: hash len %u ", __func__, rb->len); | 727 | debug3("%s: hash len %zu ", __func__, rb->len); |
711 | buffer_put_string(§, rb->blob, rb->len); | 728 | if ((sshbuf_put_string(sect, rb->blob, rb->len)) != 0) |
729 | goto out; | ||
712 | } | 730 | } |
713 | if (buffer_len(§) != 0) { | 731 | if (sshbuf_len(sect) != 0) { |
714 | buffer_put_char(buf, KRL_SECTION_FINGERPRINT_SHA1); | 732 | if ((r = sshbuf_put_u8(buf, |
715 | buffer_put_string(buf, buffer_ptr(§), | 733 | KRL_SECTION_FINGERPRINT_SHA1)) != 0 || |
716 | buffer_len(§)); | 734 | (r = sshbuf_put_stringb(buf, sect)) != 0) |
735 | goto out; | ||
717 | } | 736 | } |
718 | 737 | ||
719 | for (i = 0; i < nsign_keys; i++) { | 738 | for (i = 0; i < nsign_keys; i++) { |
720 | if (key_to_blob(sign_keys[i], &kblob, &klen) == 0) | 739 | sshbuf_reset(sect); |
740 | if ((r = sshkey_to_blob_buf(sign_keys[i], sect)) != 0) | ||
721 | goto out; | 741 | goto out; |
722 | 742 | ||
723 | debug3("%s: signature key len %u", __func__, klen); | 743 | debug3("%s: signature key len %zu", __func__, sshbuf_len(sect)); |
724 | buffer_put_char(buf, KRL_SECTION_SIGNATURE); | 744 | if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 || |
725 | buffer_put_string(buf, kblob, klen); | 745 | (r = sshbuf_put_stringb(buf, sect)) != 0) |
746 | goto out; | ||
726 | 747 | ||
727 | if (key_sign(sign_keys[i], &sblob, &slen, | 748 | if ((r = sshkey_sign(sign_keys[i], &sblob, &slen, |
728 | buffer_ptr(buf), buffer_len(buf)) == -1) | 749 | sshbuf_ptr(buf), sshbuf_len(buf), 0)) == -1) |
750 | goto out; | ||
751 | debug3("%s: signature sig len %zu", __func__, slen); | ||
752 | if ((r = sshbuf_put_string(buf, sblob, slen)) != 0) | ||
729 | goto out; | 753 | goto out; |
730 | debug3("%s: signature sig len %u", __func__, slen); | ||
731 | buffer_put_string(buf, sblob, slen); | ||
732 | } | 754 | } |
733 | 755 | ||
734 | r = 0; | 756 | r = 0; |
735 | out: | 757 | out: |
736 | free(kblob); | ||
737 | free(sblob); | 758 | free(sblob); |
738 | buffer_free(§); | 759 | sshbuf_free(sect); |
739 | return r; | 760 | return r; |
740 | } | 761 | } |
741 | 762 | ||
@@ -756,189 +777,167 @@ format_timestamp(u_int64_t timestamp, char *ts, size_t nts) | |||
756 | } | 777 | } |
757 | 778 | ||
758 | static int | 779 | static int |
759 | parse_revoked_certs(Buffer *buf, struct ssh_krl *krl) | 780 | parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl) |
760 | { | 781 | { |
761 | int ret = -1, nbits; | 782 | int r = -1, nbits; |
762 | u_char type; | 783 | u_char type; |
763 | const u_char *blob; | 784 | const u_char *blob; |
764 | u_int blen; | 785 | size_t blen; |
765 | Buffer subsect; | 786 | struct sshbuf *subsect = NULL; |
766 | u_int64_t serial, serial_lo, serial_hi; | 787 | u_int64_t serial, serial_lo, serial_hi; |
767 | BIGNUM *bitmap = NULL; | 788 | BIGNUM *bitmap = NULL; |
768 | char *key_id = NULL; | 789 | char *key_id = NULL; |
769 | Key *ca_key = NULL; | 790 | struct sshkey *ca_key = NULL; |
770 | 791 | ||
771 | buffer_init(&subsect); | 792 | if ((subsect = sshbuf_new()) == NULL) |
793 | return SSH_ERR_ALLOC_FAIL; | ||
772 | 794 | ||
773 | if ((blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL || | 795 | /* Header: key, reserved */ |
774 | buffer_get_string_ptr_ret(buf, NULL) == NULL) { /* reserved */ | 796 | if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 || |
775 | error("%s: buffer error", __func__); | 797 | (r = sshbuf_skip_string(buf)) != 0) |
776 | goto out; | 798 | goto out; |
777 | } | 799 | if ((r = sshkey_from_blob(blob, blen, &ca_key)) != 0) |
778 | if ((ca_key = key_from_blob(blob, blen)) == NULL) | ||
779 | goto out; | 800 | goto out; |
780 | 801 | ||
781 | while (buffer_len(buf) > 0) { | 802 | while (sshbuf_len(buf) > 0) { |
782 | if (buffer_get_char_ret(&type, buf) != 0 || | 803 | if (subsect != NULL) { |
783 | (blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL) { | 804 | sshbuf_free(subsect); |
784 | error("%s: buffer error", __func__); | 805 | subsect = NULL; |
785 | goto out; | ||
786 | } | 806 | } |
787 | buffer_clear(&subsect); | 807 | if ((r = sshbuf_get_u8(buf, &type)) != 0 || |
788 | buffer_append(&subsect, blob, blen); | 808 | (r = sshbuf_froms(buf, &subsect)) != 0) |
809 | goto out; | ||
789 | debug3("%s: subsection type 0x%02x", __func__, type); | 810 | debug3("%s: subsection type 0x%02x", __func__, type); |
790 | /* buffer_dump(&subsect); */ | ||
791 | 811 | ||
792 | switch (type) { | 812 | switch (type) { |
793 | case KRL_SECTION_CERT_SERIAL_LIST: | 813 | case KRL_SECTION_CERT_SERIAL_LIST: |
794 | while (buffer_len(&subsect) > 0) { | 814 | while (sshbuf_len(subsect) > 0) { |
795 | if (buffer_get_int64_ret(&serial, | 815 | if ((r = sshbuf_get_u64(subsect, &serial)) != 0) |
796 | &subsect) != 0) { | ||
797 | error("%s: buffer error", __func__); | ||
798 | goto out; | 816 | goto out; |
799 | } | 817 | if ((r = ssh_krl_revoke_cert_by_serial(krl, |
800 | if (ssh_krl_revoke_cert_by_serial(krl, ca_key, | 818 | ca_key, serial)) != 0) |
801 | serial) != 0) { | ||
802 | error("%s: update failed", __func__); | ||
803 | goto out; | 819 | goto out; |
804 | } | ||
805 | } | 820 | } |
806 | break; | 821 | break; |
807 | case KRL_SECTION_CERT_SERIAL_RANGE: | 822 | case KRL_SECTION_CERT_SERIAL_RANGE: |
808 | if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 || | 823 | if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 || |
809 | buffer_get_int64_ret(&serial_hi, &subsect) != 0) { | 824 | (r = sshbuf_get_u64(subsect, &serial_hi)) != 0) |
810 | error("%s: buffer error", __func__); | ||
811 | goto out; | 825 | goto out; |
812 | } | 826 | if ((r = ssh_krl_revoke_cert_by_serial_range(krl, |
813 | if (ssh_krl_revoke_cert_by_serial_range(krl, ca_key, | 827 | ca_key, serial_lo, serial_hi)) != 0) |
814 | serial_lo, serial_hi) != 0) { | ||
815 | error("%s: update failed", __func__); | ||
816 | goto out; | 828 | goto out; |
817 | } | ||
818 | break; | 829 | break; |
819 | case KRL_SECTION_CERT_SERIAL_BITMAP: | 830 | case KRL_SECTION_CERT_SERIAL_BITMAP: |
820 | if ((bitmap = BN_new()) == NULL) { | 831 | if ((bitmap = BN_new()) == NULL) { |
821 | error("%s: BN_new", __func__); | 832 | r = SSH_ERR_ALLOC_FAIL; |
822 | goto out; | 833 | goto out; |
823 | } | 834 | } |
824 | if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 || | 835 | if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 || |
825 | buffer_get_bignum2_ret(&subsect, bitmap) != 0) { | 836 | (r = sshbuf_get_bignum2(subsect, bitmap)) != 0) |
826 | error("%s: buffer error", __func__); | ||
827 | goto out; | 837 | goto out; |
828 | } | ||
829 | if ((nbits = BN_num_bits(bitmap)) < 0) { | 838 | if ((nbits = BN_num_bits(bitmap)) < 0) { |
830 | error("%s: bitmap bits < 0", __func__); | 839 | error("%s: bitmap bits < 0", __func__); |
840 | r = SSH_ERR_INVALID_FORMAT; | ||
831 | goto out; | 841 | goto out; |
832 | } | 842 | } |
833 | for (serial = 0; serial < (u_int)nbits; serial++) { | 843 | for (serial = 0; serial < (u_int)nbits; serial++) { |
834 | if (serial > 0 && serial_lo + serial == 0) { | 844 | if (serial > 0 && serial_lo + serial == 0) { |
835 | error("%s: bitmap wraps u64", __func__); | 845 | error("%s: bitmap wraps u64", __func__); |
846 | r = SSH_ERR_INVALID_FORMAT; | ||
836 | goto out; | 847 | goto out; |
837 | } | 848 | } |
838 | if (!BN_is_bit_set(bitmap, serial)) | 849 | if (!BN_is_bit_set(bitmap, serial)) |
839 | continue; | 850 | continue; |
840 | if (ssh_krl_revoke_cert_by_serial(krl, ca_key, | 851 | if ((r = ssh_krl_revoke_cert_by_serial(krl, |
841 | serial_lo + serial) != 0) { | 852 | ca_key, serial_lo + serial)) != 0) |
842 | error("%s: update failed", __func__); | ||
843 | goto out; | 853 | goto out; |
844 | } | ||
845 | } | 854 | } |
846 | BN_free(bitmap); | 855 | BN_free(bitmap); |
847 | bitmap = NULL; | 856 | bitmap = NULL; |
848 | break; | 857 | break; |
849 | case KRL_SECTION_CERT_KEY_ID: | 858 | case KRL_SECTION_CERT_KEY_ID: |
850 | while (buffer_len(&subsect) > 0) { | 859 | while (sshbuf_len(subsect) > 0) { |
851 | if ((key_id = buffer_get_cstring_ret(&subsect, | 860 | if ((r = sshbuf_get_cstring(subsect, |
852 | NULL)) == NULL) { | 861 | &key_id, NULL)) != 0) |
853 | error("%s: buffer error", __func__); | ||
854 | goto out; | 862 | goto out; |
855 | } | 863 | if ((r = ssh_krl_revoke_cert_by_key_id(krl, |
856 | if (ssh_krl_revoke_cert_by_key_id(krl, ca_key, | 864 | ca_key, key_id)) != 0) |
857 | key_id) != 0) { | ||
858 | error("%s: update failed", __func__); | ||
859 | goto out; | 865 | goto out; |
860 | } | ||
861 | free(key_id); | 866 | free(key_id); |
862 | key_id = NULL; | 867 | key_id = NULL; |
863 | } | 868 | } |
864 | break; | 869 | break; |
865 | default: | 870 | default: |
866 | error("Unsupported KRL certificate section %u", type); | 871 | error("Unsupported KRL certificate section %u", type); |
872 | r = SSH_ERR_INVALID_FORMAT; | ||
867 | goto out; | 873 | goto out; |
868 | } | 874 | } |
869 | if (buffer_len(&subsect) > 0) { | 875 | if (sshbuf_len(subsect) > 0) { |
870 | error("KRL certificate section contains unparsed data"); | 876 | error("KRL certificate section contains unparsed data"); |
877 | r = SSH_ERR_INVALID_FORMAT; | ||
871 | goto out; | 878 | goto out; |
872 | } | 879 | } |
873 | } | 880 | } |
874 | 881 | ||
875 | ret = 0; | 882 | r = 0; |
876 | out: | 883 | out: |
877 | if (ca_key != NULL) | ||
878 | key_free(ca_key); | ||
879 | if (bitmap != NULL) | 884 | if (bitmap != NULL) |
880 | BN_free(bitmap); | 885 | BN_free(bitmap); |
881 | free(key_id); | 886 | free(key_id); |
882 | buffer_free(&subsect); | 887 | sshkey_free(ca_key); |
883 | return ret; | 888 | sshbuf_free(subsect); |
889 | return r; | ||
884 | } | 890 | } |
885 | 891 | ||
886 | 892 | ||
887 | /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */ | 893 | /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */ |
888 | int | 894 | int |
889 | ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, | 895 | ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, |
890 | const Key **sign_ca_keys, u_int nsign_ca_keys) | 896 | const struct sshkey **sign_ca_keys, u_int nsign_ca_keys) |
891 | { | 897 | { |
892 | Buffer copy, sect; | 898 | struct sshbuf *copy = NULL, *sect = NULL; |
893 | struct ssh_krl *krl; | 899 | struct ssh_krl *krl = NULL; |
894 | char timestamp[64]; | 900 | char timestamp[64]; |
895 | int ret = -1, r, sig_seen; | 901 | int r = -1, sig_seen; |
896 | Key *key = NULL, **ca_used = NULL; | 902 | struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used; |
897 | u_char type, *rdata = NULL; | 903 | u_char type, *rdata = NULL; |
898 | const u_char *blob; | 904 | const u_char *blob; |
899 | u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used; | 905 | size_t i, j, sig_off, sects_off, rlen, blen, nca_used; |
906 | u_int format_version; | ||
900 | 907 | ||
901 | nca_used = 0; | 908 | nca_used = 0; |
902 | *krlp = NULL; | 909 | *krlp = NULL; |
903 | if (buffer_len(buf) < sizeof(KRL_MAGIC) - 1 || | 910 | if (sshbuf_len(buf) < sizeof(KRL_MAGIC) - 1 || |
904 | memcmp(buffer_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) { | 911 | memcmp(sshbuf_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) { |
905 | debug3("%s: not a KRL", __func__); | 912 | debug3("%s: not a KRL", __func__); |
906 | /* | 913 | return SSH_ERR_KRL_BAD_MAGIC; |
907 | * Return success but a NULL *krlp here to signal that the | ||
908 | * file might be a simple list of keys. | ||
909 | */ | ||
910 | return 0; | ||
911 | } | 914 | } |
912 | 915 | ||
913 | /* Take a copy of the KRL buffer so we can verify its signature later */ | 916 | /* Take a copy of the KRL buffer so we can verify its signature later */ |
914 | buffer_init(©); | 917 | if ((copy = sshbuf_fromb(buf)) == NULL) { |
915 | buffer_append(©, buffer_ptr(buf), buffer_len(buf)); | 918 | r = SSH_ERR_ALLOC_FAIL; |
916 | 919 | goto out; | |
917 | buffer_init(§); | 920 | } |
918 | buffer_consume(©, sizeof(KRL_MAGIC) - 1); | 921 | if ((r = sshbuf_consume(copy, sizeof(KRL_MAGIC) - 1)) != 0) |
922 | goto out; | ||
919 | 923 | ||
920 | if ((krl = ssh_krl_init()) == NULL) { | 924 | if ((krl = ssh_krl_init()) == NULL) { |
921 | error("%s: alloc failed", __func__); | 925 | error("%s: alloc failed", __func__); |
922 | goto out; | 926 | goto out; |
923 | } | 927 | } |
924 | 928 | ||
925 | if (buffer_get_int_ret(&format_version, ©) != 0) { | 929 | if ((r = sshbuf_get_u32(copy, &format_version)) != 0) |
926 | error("%s: KRL truncated", __func__); | ||
927 | goto out; | 930 | goto out; |
928 | } | ||
929 | if (format_version != KRL_FORMAT_VERSION) { | 931 | if (format_version != KRL_FORMAT_VERSION) { |
930 | error("%s: KRL unsupported format version %u", | 932 | r = SSH_ERR_INVALID_FORMAT; |
931 | __func__, format_version); | ||
932 | goto out; | 933 | goto out; |
933 | } | 934 | } |
934 | if (buffer_get_int64_ret(&krl->krl_version, ©) != 0 || | 935 | if ((r = sshbuf_get_u64(copy, &krl->krl_version)) != 0 || |
935 | buffer_get_int64_ret(&krl->generated_date, ©) != 0 || | 936 | (r = sshbuf_get_u64(copy, &krl->generated_date)) != 0 || |
936 | buffer_get_int64_ret(&krl->flags, ©) != 0 || | 937 | (r = sshbuf_get_u64(copy, &krl->flags)) != 0 || |
937 | buffer_get_string_ptr_ret(©, NULL) == NULL || /* reserved */ | 938 | (r = sshbuf_skip_string(copy)) != 0 || |
938 | (krl->comment = buffer_get_cstring_ret(©, NULL)) == NULL) { | 939 | (r = sshbuf_get_cstring(copy, &krl->comment, NULL)) != 0) |
939 | error("%s: buffer error", __func__); | ||
940 | goto out; | 940 | goto out; |
941 | } | ||
942 | 941 | ||
943 | format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); | 942 | format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); |
944 | debug("KRL version %llu generated at %s%s%s", | 943 | debug("KRL version %llu generated at %s%s%s", |
@@ -950,16 +949,20 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, | |||
950 | * detailed parsing of data whose provenance is unverified. | 949 | * detailed parsing of data whose provenance is unverified. |
951 | */ | 950 | */ |
952 | sig_seen = 0; | 951 | sig_seen = 0; |
953 | sects_off = buffer_len(buf) - buffer_len(©); | 952 | if (sshbuf_len(buf) < sshbuf_len(copy)) { |
954 | while (buffer_len(©) > 0) { | 953 | /* Shouldn't happen */ |
955 | if (buffer_get_char_ret(&type, ©) != 0 || | 954 | r = SSH_ERR_INTERNAL_ERROR; |
956 | (blob = buffer_get_string_ptr_ret(©, &blen)) == NULL) { | 955 | goto out; |
957 | error("%s: buffer error", __func__); | 956 | } |
957 | sects_off = sshbuf_len(buf) - sshbuf_len(copy); | ||
958 | while (sshbuf_len(copy) > 0) { | ||
959 | if ((r = sshbuf_get_u8(copy, &type)) != 0 || | ||
960 | (r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0) | ||
958 | goto out; | 961 | goto out; |
959 | } | ||
960 | debug3("%s: first pass, section 0x%02x", __func__, type); | 962 | debug3("%s: first pass, section 0x%02x", __func__, type); |
961 | if (type != KRL_SECTION_SIGNATURE) { | 963 | if (type != KRL_SECTION_SIGNATURE) { |
962 | if (sig_seen) { | 964 | if (sig_seen) { |
965 | r = SSH_ERR_INVALID_FORMAT; | ||
963 | error("KRL contains non-signature section " | 966 | error("KRL contains non-signature section " |
964 | "after signature"); | 967 | "after signature"); |
965 | goto out; | 968 | goto out; |
@@ -969,94 +972,118 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, | |||
969 | } | 972 | } |
970 | sig_seen = 1; | 973 | sig_seen = 1; |
971 | /* First string component is the signing key */ | 974 | /* First string component is the signing key */ |
972 | if ((key = key_from_blob(blob, blen)) == NULL) { | 975 | if ((r = sshkey_from_blob(blob, blen, &key)) != 0) { |
976 | r = SSH_ERR_INVALID_FORMAT; | ||
973 | error("%s: invalid signature key", __func__); | 977 | error("%s: invalid signature key", __func__); |
974 | goto out; | 978 | goto out; |
975 | } | 979 | } |
976 | sig_off = buffer_len(buf) - buffer_len(©); | 980 | if (sshbuf_len(buf) < sshbuf_len(copy)) { |
981 | /* Shouldn't happen */ | ||
982 | r = SSH_ERR_INTERNAL_ERROR; | ||
983 | goto out; | ||
984 | } | ||
985 | sig_off = sshbuf_len(buf) - sshbuf_len(copy); | ||
977 | /* Second string component is the signature itself */ | 986 | /* Second string component is the signature itself */ |
978 | if ((blob = buffer_get_string_ptr_ret(©, &blen)) == NULL) { | 987 | if ((r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0) { |
979 | error("%s: buffer error", __func__); | 988 | r = SSH_ERR_INVALID_FORMAT; |
980 | goto out; | 989 | goto out; |
981 | } | 990 | } |
982 | /* Check signature over entire KRL up to this point */ | 991 | /* Check signature over entire KRL up to this point */ |
983 | if (key_verify(key, blob, blen, | 992 | if ((r = sshkey_verify(key, blob, blen, |
984 | buffer_ptr(buf), buffer_len(buf) - sig_off) != 1) { | 993 | sshbuf_ptr(buf), sshbuf_len(buf) - sig_off, 0)) != 0) { |
985 | error("bad signaure on KRL"); | 994 | error("bad signaure on KRL"); |
986 | goto out; | 995 | goto out; |
987 | } | 996 | } |
988 | /* Check if this key has already signed this KRL */ | 997 | /* Check if this key has already signed this KRL */ |
989 | for (i = 0; i < nca_used; i++) { | 998 | for (i = 0; i < nca_used; i++) { |
990 | if (key_equal(ca_used[i], key)) { | 999 | if (sshkey_equal(ca_used[i], key)) { |
991 | error("KRL signed more than once with " | 1000 | error("KRL signed more than once with " |
992 | "the same key"); | 1001 | "the same key"); |
1002 | r = SSH_ERR_SIGNATURE_INVALID; | ||
993 | goto out; | 1003 | goto out; |
994 | } | 1004 | } |
995 | } | 1005 | } |
996 | /* Record keys used to sign the KRL */ | 1006 | /* Record keys used to sign the KRL */ |
997 | ca_used = xrealloc(ca_used, nca_used + 1, sizeof(*ca_used)); | 1007 | tmp_ca_used = reallocarray(ca_used, nca_used + 1, |
1008 | sizeof(*ca_used)); | ||
1009 | if (tmp_ca_used == NULL) { | ||
1010 | r = SSH_ERR_ALLOC_FAIL; | ||
1011 | goto out; | ||
1012 | } | ||
1013 | ca_used = tmp_ca_used; | ||
998 | ca_used[nca_used++] = key; | 1014 | ca_used[nca_used++] = key; |
999 | key = NULL; | 1015 | key = NULL; |
1000 | break; | 1016 | break; |
1001 | } | 1017 | } |
1002 | 1018 | ||
1019 | if (sshbuf_len(copy) != 0) { | ||
1020 | /* Shouldn't happen */ | ||
1021 | r = SSH_ERR_INTERNAL_ERROR; | ||
1022 | goto out; | ||
1023 | } | ||
1024 | |||
1003 | /* | 1025 | /* |
1004 | * 2nd pass: parse and load the KRL, skipping the header to the point | 1026 | * 2nd pass: parse and load the KRL, skipping the header to the point |
1005 | * where the section start. | 1027 | * where the section start. |
1006 | */ | 1028 | */ |
1007 | buffer_append(©, (u_char*)buffer_ptr(buf) + sects_off, | 1029 | sshbuf_free(copy); |
1008 | buffer_len(buf) - sects_off); | 1030 | if ((copy = sshbuf_fromb(buf)) == NULL) { |
1009 | while (buffer_len(©) > 0) { | 1031 | r = SSH_ERR_ALLOC_FAIL; |
1010 | if (buffer_get_char_ret(&type, ©) != 0 || | 1032 | goto out; |
1011 | (blob = buffer_get_string_ptr_ret(©, &blen)) == NULL) { | 1033 | } |
1012 | error("%s: buffer error", __func__); | 1034 | if ((r = sshbuf_consume(copy, sects_off)) != 0) |
1035 | goto out; | ||
1036 | while (sshbuf_len(copy) > 0) { | ||
1037 | if (sect != NULL) { | ||
1038 | sshbuf_free(sect); | ||
1039 | sect = NULL; | ||
1040 | } | ||
1041 | if ((r = sshbuf_get_u8(copy, &type)) != 0 || | ||
1042 | (r = sshbuf_froms(copy, §)) != 0) { | ||
1013 | goto out; | 1043 | goto out; |
1014 | } | 1044 | } |
1015 | debug3("%s: second pass, section 0x%02x", __func__, type); | 1045 | debug3("%s: second pass, section 0x%02x", __func__, type); |
1016 | buffer_clear(§); | ||
1017 | buffer_append(§, blob, blen); | ||
1018 | 1046 | ||
1019 | switch (type) { | 1047 | switch (type) { |
1020 | case KRL_SECTION_CERTIFICATES: | 1048 | case KRL_SECTION_CERTIFICATES: |
1021 | if ((r = parse_revoked_certs(§, krl)) != 0) | 1049 | if ((r = parse_revoked_certs(sect, krl)) != 0) |
1022 | goto out; | 1050 | goto out; |
1023 | break; | 1051 | break; |
1024 | case KRL_SECTION_EXPLICIT_KEY: | 1052 | case KRL_SECTION_EXPLICIT_KEY: |
1025 | case KRL_SECTION_FINGERPRINT_SHA1: | 1053 | case KRL_SECTION_FINGERPRINT_SHA1: |
1026 | while (buffer_len(§) > 0) { | 1054 | while (sshbuf_len(sect) > 0) { |
1027 | if ((rdata = buffer_get_string_ret(§, | 1055 | if ((r = sshbuf_get_string(sect, |
1028 | &rlen)) == NULL) { | 1056 | &rdata, &rlen)) != 0) |
1029 | error("%s: buffer error", __func__); | ||
1030 | goto out; | 1057 | goto out; |
1031 | } | ||
1032 | if (type == KRL_SECTION_FINGERPRINT_SHA1 && | 1058 | if (type == KRL_SECTION_FINGERPRINT_SHA1 && |
1033 | rlen != 20) { | 1059 | rlen != 20) { |
1034 | error("%s: bad SHA1 length", __func__); | 1060 | error("%s: bad SHA1 length", __func__); |
1061 | r = SSH_ERR_INVALID_FORMAT; | ||
1035 | goto out; | 1062 | goto out; |
1036 | } | 1063 | } |
1037 | if (revoke_blob( | 1064 | if ((r = revoke_blob( |
1038 | type == KRL_SECTION_EXPLICIT_KEY ? | 1065 | type == KRL_SECTION_EXPLICIT_KEY ? |
1039 | &krl->revoked_keys : &krl->revoked_sha1s, | 1066 | &krl->revoked_keys : &krl->revoked_sha1s, |
1040 | rdata, rlen) != 0) | 1067 | rdata, rlen)) != 0) |
1041 | goto out; | 1068 | goto out; |
1042 | rdata = NULL; /* revoke_blob frees blob */ | 1069 | rdata = NULL; /* revoke_blob frees blob */ |
1043 | } | 1070 | } |
1044 | break; | 1071 | break; |
1045 | case KRL_SECTION_SIGNATURE: | 1072 | case KRL_SECTION_SIGNATURE: |
1046 | /* Handled above, but still need to stay in synch */ | 1073 | /* Handled above, but still need to stay in synch */ |
1047 | buffer_clear(§); | 1074 | sshbuf_reset(sect); |
1048 | if ((blob = buffer_get_string_ptr_ret(©, | 1075 | sect = NULL; |
1049 | &blen)) == NULL) { | 1076 | if ((r = sshbuf_skip_string(copy)) != 0) |
1050 | error("%s: buffer error", __func__); | ||
1051 | goto out; | 1077 | goto out; |
1052 | } | ||
1053 | break; | 1078 | break; |
1054 | default: | 1079 | default: |
1055 | error("Unsupported KRL section %u", type); | 1080 | error("Unsupported KRL section %u", type); |
1081 | r = SSH_ERR_INVALID_FORMAT; | ||
1056 | goto out; | 1082 | goto out; |
1057 | } | 1083 | } |
1058 | if (buffer_len(§) > 0) { | 1084 | if (sshbuf_len(sect) > 0) { |
1059 | error("KRL section contains unparsed data"); | 1085 | error("KRL section contains unparsed data"); |
1086 | r = SSH_ERR_INVALID_FORMAT; | ||
1060 | goto out; | 1087 | goto out; |
1061 | } | 1088 | } |
1062 | } | 1089 | } |
@@ -1067,11 +1094,12 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, | |||
1067 | if (ssh_krl_check_key(krl, ca_used[i]) == 0) | 1094 | if (ssh_krl_check_key(krl, ca_used[i]) == 0) |
1068 | sig_seen = 1; | 1095 | sig_seen = 1; |
1069 | else { | 1096 | else { |
1070 | key_free(ca_used[i]); | 1097 | sshkey_free(ca_used[i]); |
1071 | ca_used[i] = NULL; | 1098 | ca_used[i] = NULL; |
1072 | } | 1099 | } |
1073 | } | 1100 | } |
1074 | if (nca_used && !sig_seen) { | 1101 | if (nca_used && !sig_seen) { |
1102 | r = SSH_ERR_SIGNATURE_INVALID; | ||
1075 | error("All keys used to sign KRL were revoked"); | 1103 | error("All keys used to sign KRL were revoked"); |
1076 | goto out; | 1104 | goto out; |
1077 | } | 1105 | } |
@@ -1083,74 +1111,74 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, | |||
1083 | for (j = 0; j < nca_used; j++) { | 1111 | for (j = 0; j < nca_used; j++) { |
1084 | if (ca_used[j] == NULL) | 1112 | if (ca_used[j] == NULL) |
1085 | continue; | 1113 | continue; |
1086 | if (key_equal(ca_used[j], sign_ca_keys[i])) { | 1114 | if (sshkey_equal(ca_used[j], sign_ca_keys[i])) { |
1087 | sig_seen = 1; | 1115 | sig_seen = 1; |
1088 | break; | 1116 | break; |
1089 | } | 1117 | } |
1090 | } | 1118 | } |
1091 | } | 1119 | } |
1092 | if (!sig_seen) { | 1120 | if (!sig_seen) { |
1121 | r = SSH_ERR_SIGNATURE_INVALID; | ||
1093 | error("KRL not signed with any trusted key"); | 1122 | error("KRL not signed with any trusted key"); |
1094 | goto out; | 1123 | goto out; |
1095 | } | 1124 | } |
1096 | } | 1125 | } |
1097 | 1126 | ||
1098 | *krlp = krl; | 1127 | *krlp = krl; |
1099 | ret = 0; | 1128 | r = 0; |
1100 | out: | 1129 | out: |
1101 | if (ret != 0) | 1130 | if (r != 0) |
1102 | ssh_krl_free(krl); | 1131 | ssh_krl_free(krl); |
1103 | for (i = 0; i < nca_used; i++) { | 1132 | for (i = 0; i < nca_used; i++) |
1104 | if (ca_used[i] != NULL) | 1133 | sshkey_free(ca_used[i]); |
1105 | key_free(ca_used[i]); | ||
1106 | } | ||
1107 | free(ca_used); | 1134 | free(ca_used); |
1108 | free(rdata); | 1135 | free(rdata); |
1109 | if (key != NULL) | 1136 | sshkey_free(key); |
1110 | key_free(key); | 1137 | sshbuf_free(copy); |
1111 | buffer_free(©); | 1138 | sshbuf_free(sect); |
1112 | buffer_free(§); | 1139 | return r; |
1113 | return ret; | ||
1114 | } | 1140 | } |
1115 | 1141 | ||
1116 | /* Checks whether a given key/cert is revoked. Does not check its CA */ | 1142 | /* Checks whether a given key/cert is revoked. Does not check its CA */ |
1117 | static int | 1143 | static int |
1118 | is_key_revoked(struct ssh_krl *krl, const Key *key) | 1144 | is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) |
1119 | { | 1145 | { |
1120 | struct revoked_blob rb, *erb; | 1146 | struct revoked_blob rb, *erb; |
1121 | struct revoked_serial rs, *ers; | 1147 | struct revoked_serial rs, *ers; |
1122 | struct revoked_key_id rki, *erki; | 1148 | struct revoked_key_id rki, *erki; |
1123 | struct revoked_certs *rc; | 1149 | struct revoked_certs *rc; |
1150 | int r; | ||
1124 | 1151 | ||
1125 | /* Check explicitly revoked hashes first */ | 1152 | /* Check explicitly revoked hashes first */ |
1126 | memset(&rb, 0, sizeof(rb)); | 1153 | memset(&rb, 0, sizeof(rb)); |
1127 | if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL) | 1154 | if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, |
1128 | return -1; | 1155 | &rb.blob, &rb.len)) != 0) |
1156 | return r; | ||
1129 | erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); | 1157 | erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); |
1130 | free(rb.blob); | 1158 | free(rb.blob); |
1131 | if (erb != NULL) { | 1159 | if (erb != NULL) { |
1132 | debug("%s: revoked by key SHA1", __func__); | 1160 | debug("%s: revoked by key SHA1", __func__); |
1133 | return -1; | 1161 | return SSH_ERR_KEY_REVOKED; |
1134 | } | 1162 | } |
1135 | 1163 | ||
1136 | /* Next, explicit keys */ | 1164 | /* Next, explicit keys */ |
1137 | memset(&rb, 0, sizeof(rb)); | 1165 | memset(&rb, 0, sizeof(rb)); |
1138 | if (plain_key_blob(key, &rb.blob, &rb.len) < 0) | 1166 | if ((r = plain_key_blob(key, &rb.blob, &rb.len)) != 0) |
1139 | return -1; | 1167 | return r; |
1140 | erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); | 1168 | erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); |
1141 | free(rb.blob); | 1169 | free(rb.blob); |
1142 | if (erb != NULL) { | 1170 | if (erb != NULL) { |
1143 | debug("%s: revoked by explicit key", __func__); | 1171 | debug("%s: revoked by explicit key", __func__); |
1144 | return -1; | 1172 | return SSH_ERR_KEY_REVOKED; |
1145 | } | 1173 | } |
1146 | 1174 | ||
1147 | if (!key_is_cert(key)) | 1175 | if (!sshkey_is_cert(key)) |
1148 | return 0; | 1176 | return 0; |
1149 | 1177 | ||
1150 | /* Check cert revocation */ | 1178 | /* Check cert revocation */ |
1151 | if (revoked_certs_for_ca_key(krl, key->cert->signature_key, | 1179 | if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key, |
1152 | &rc, 0) != 0) | 1180 | &rc, 0)) != 0) |
1153 | return -1; | 1181 | return r; |
1154 | if (rc == NULL) | 1182 | if (rc == NULL) |
1155 | return 0; /* No entry for this CA */ | 1183 | return 0; /* No entry for this CA */ |
1156 | 1184 | ||
@@ -1160,14 +1188,14 @@ is_key_revoked(struct ssh_krl *krl, const Key *key) | |||
1160 | erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki); | 1188 | erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki); |
1161 | if (erki != NULL) { | 1189 | if (erki != NULL) { |
1162 | debug("%s: revoked by key ID", __func__); | 1190 | debug("%s: revoked by key ID", __func__); |
1163 | return -1; | 1191 | return SSH_ERR_KEY_REVOKED; |
1164 | } | 1192 | } |
1165 | 1193 | ||
1166 | /* | 1194 | /* |
1167 | * Legacy cert formats lack serial numbers. Zero serials numbers | 1195 | * Legacy cert formats lack serial numbers. Zero serials numbers |
1168 | * are ignored (it's the default when the CA doesn't specify one). | 1196 | * are ignored (it's the default when the CA doesn't specify one). |
1169 | */ | 1197 | */ |
1170 | if (key_cert_is_legacy(key) || key->cert->serial == 0) | 1198 | if (sshkey_cert_is_legacy(key) || key->cert->serial == 0) |
1171 | return 0; | 1199 | return 0; |
1172 | 1200 | ||
1173 | memset(&rs, 0, sizeof(rs)); | 1201 | memset(&rs, 0, sizeof(rs)); |
@@ -1177,7 +1205,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key) | |||
1177 | KRL_DBG(("%s: %llu matched %llu:%llu", __func__, | 1205 | KRL_DBG(("%s: %llu matched %llu:%llu", __func__, |
1178 | key->cert->serial, ers->lo, ers->hi)); | 1206 | key->cert->serial, ers->lo, ers->hi)); |
1179 | debug("%s: revoked by serial", __func__); | 1207 | debug("%s: revoked by serial", __func__); |
1180 | return -1; | 1208 | return SSH_ERR_KEY_REVOKED; |
1181 | } | 1209 | } |
1182 | KRL_DBG(("%s: %llu no match", __func__, key->cert->serial)); | 1210 | KRL_DBG(("%s: %llu no match", __func__, key->cert->serial)); |
1183 | 1211 | ||
@@ -1185,14 +1213,14 @@ is_key_revoked(struct ssh_krl *krl, const Key *key) | |||
1185 | } | 1213 | } |
1186 | 1214 | ||
1187 | int | 1215 | int |
1188 | ssh_krl_check_key(struct ssh_krl *krl, const Key *key) | 1216 | ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key) |
1189 | { | 1217 | { |
1190 | int r; | 1218 | int r; |
1191 | 1219 | ||
1192 | debug2("%s: checking key", __func__); | 1220 | debug2("%s: checking key", __func__); |
1193 | if ((r = is_key_revoked(krl, key)) != 0) | 1221 | if ((r = is_key_revoked(krl, key)) != 0) |
1194 | return r; | 1222 | return r; |
1195 | if (key_is_cert(key)) { | 1223 | if (sshkey_is_cert(key)) { |
1196 | debug2("%s: checking CA key", __func__); | 1224 | debug2("%s: checking CA key", __func__); |
1197 | if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0) | 1225 | if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0) |
1198 | return r; | 1226 | return r; |
@@ -1201,45 +1229,36 @@ ssh_krl_check_key(struct ssh_krl *krl, const Key *key) | |||
1201 | return 0; | 1229 | return 0; |
1202 | } | 1230 | } |
1203 | 1231 | ||
1204 | /* Returns 0 on success, -1 on error or key revoked, -2 if path is not a KRL */ | ||
1205 | int | 1232 | int |
1206 | ssh_krl_file_contains_key(const char *path, const Key *key) | 1233 | ssh_krl_file_contains_key(const char *path, const struct sshkey *key) |
1207 | { | 1234 | { |
1208 | Buffer krlbuf; | 1235 | struct sshbuf *krlbuf = NULL; |
1209 | struct ssh_krl *krl; | 1236 | struct ssh_krl *krl = NULL; |
1210 | int revoked, fd; | 1237 | int oerrno = 0, r, fd; |
1211 | 1238 | ||
1212 | if (path == NULL) | 1239 | if (path == NULL) |
1213 | return 0; | 1240 | return 0; |
1214 | 1241 | ||
1242 | if ((krlbuf = sshbuf_new()) == NULL) | ||
1243 | return SSH_ERR_ALLOC_FAIL; | ||
1215 | if ((fd = open(path, O_RDONLY)) == -1) { | 1244 | if ((fd = open(path, O_RDONLY)) == -1) { |
1216 | error("open %s: %s", path, strerror(errno)); | 1245 | r = SSH_ERR_SYSTEM_ERROR; |
1217 | error("Revoked keys file not accessible - refusing public key " | 1246 | oerrno = errno; |
1218 | "authentication"); | 1247 | goto out; |
1219 | return -1; | ||
1220 | } | ||
1221 | buffer_init(&krlbuf); | ||
1222 | if (!key_load_file(fd, path, &krlbuf)) { | ||
1223 | close(fd); | ||
1224 | buffer_free(&krlbuf); | ||
1225 | error("Revoked keys file not readable - refusing public key " | ||
1226 | "authentication"); | ||
1227 | return -1; | ||
1228 | } | ||
1229 | close(fd); | ||
1230 | if (ssh_krl_from_blob(&krlbuf, &krl, NULL, 0) != 0) { | ||
1231 | buffer_free(&krlbuf); | ||
1232 | error("Invalid KRL, refusing public key " | ||
1233 | "authentication"); | ||
1234 | return -1; | ||
1235 | } | 1248 | } |
1236 | buffer_free(&krlbuf); | 1249 | if ((r = sshkey_load_file(fd, path, krlbuf)) != 0) { |
1237 | if (krl == NULL) { | 1250 | oerrno = errno; |
1238 | debug3("%s: %s is not a KRL file", __func__, path); | 1251 | goto out; |
1239 | return -2; | ||
1240 | } | 1252 | } |
1253 | if ((r = ssh_krl_from_blob(krlbuf, &krl, NULL, 0)) != 0) | ||
1254 | goto out; | ||
1241 | debug2("%s: checking KRL %s", __func__, path); | 1255 | debug2("%s: checking KRL %s", __func__, path); |
1242 | revoked = ssh_krl_check_key(krl, key) != 0; | 1256 | r = ssh_krl_check_key(krl, key); |
1257 | out: | ||
1258 | close(fd); | ||
1259 | sshbuf_free(krlbuf); | ||
1243 | ssh_krl_free(krl); | 1260 | ssh_krl_free(krl); |
1244 | return revoked ? -1 : 0; | 1261 | if (r != 0) |
1262 | errno = oerrno; | ||
1263 | return r; | ||
1245 | } | 1264 | } |
@@ -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.h,v 1.2 2013/01/18 00:24:58 djm Exp $ */ | 17 | /* $OpenBSD: krl.h,v 1.3 2014/12/04 01:49:59 djm Exp $ */ |
18 | 18 | ||
19 | #ifndef _KRL_H | 19 | #ifndef _KRL_H |
20 | #define _KRL_H | 20 | #define _KRL_H |
@@ -36,28 +36,30 @@ | |||
36 | #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 | 36 | #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 |
37 | #define KRL_SECTION_CERT_KEY_ID 0x23 | 37 | #define KRL_SECTION_CERT_KEY_ID 0x23 |
38 | 38 | ||
39 | struct sshkey; | ||
40 | struct sshbuf; | ||
39 | struct ssh_krl; | 41 | struct ssh_krl; |
40 | 42 | ||
41 | struct ssh_krl *ssh_krl_init(void); | 43 | struct ssh_krl *ssh_krl_init(void); |
42 | void ssh_krl_free(struct ssh_krl *krl); | 44 | void ssh_krl_free(struct ssh_krl *krl); |
43 | void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version); | 45 | void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version); |
44 | void ssh_krl_set_sign_key(struct ssh_krl *krl, const Key *sign_key); | 46 | void ssh_krl_set_sign_key(struct ssh_krl *krl, const struct sshkey *sign_key); |
45 | void ssh_krl_set_comment(struct ssh_krl *krl, const char *comment); | 47 | int ssh_krl_set_comment(struct ssh_krl *krl, const char *comment); |
46 | int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key, | 48 | int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, |
47 | u_int64_t serial); | 49 | const struct sshkey *ca_key, u_int64_t serial); |
48 | int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key, | 50 | int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, |
49 | u_int64_t lo, u_int64_t hi); | 51 | const struct sshkey *ca_key, u_int64_t lo, u_int64_t hi); |
50 | int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, | 52 | int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, |
51 | const char *key_id); | 53 | const struct sshkey *ca_key, const char *key_id); |
52 | int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key); | 54 | int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key); |
53 | int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key); | 55 | int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key); |
54 | int ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key); | 56 | int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key); |
55 | int ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys, | 57 | int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, |
56 | u_int nsign_keys); | 58 | const struct sshkey **sign_keys, u_int nsign_keys); |
57 | int ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, | 59 | int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, |
58 | const Key **sign_ca_keys, u_int nsign_ca_keys); | 60 | const struct sshkey **sign_ca_keys, u_int nsign_ca_keys); |
59 | int ssh_krl_check_key(struct ssh_krl *krl, const Key *key); | 61 | int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key); |
60 | int ssh_krl_file_contains_key(const char *path, const Key *key); | 62 | int ssh_krl_file_contains_key(const char *path, const struct sshkey *key); |
61 | 63 | ||
62 | #endif /* _KRL_H */ | 64 | #endif /* _KRL_H */ |
63 | 65 | ||
diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c index b7d0758c2..682b68d58 100644 --- a/sshbuf-getput-basic.c +++ b/sshbuf-getput-basic.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshbuf-getput-basic.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */ | 1 | /* $OpenBSD: sshbuf-getput-basic.c,v 1.2 2014/12/04 01:49:59 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 Damien Miller | 3 | * Copyright (c) 2011 Damien Miller |
4 | * | 4 | * |
@@ -359,7 +359,7 @@ sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) | |||
359 | int | 359 | int |
360 | sshbuf_put_cstring(struct sshbuf *buf, const char *v) | 360 | sshbuf_put_cstring(struct sshbuf *buf, const char *v) |
361 | { | 361 | { |
362 | return sshbuf_put_string(buf, (u_char *)v, strlen(v)); | 362 | return sshbuf_put_string(buf, (u_char *)v, v == NULL ? 0 : strlen(v)); |
363 | } | 363 | } |
364 | 364 | ||
365 | int | 365 | int |