[BACK]Return to krl.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/krl.c, Revision 1.10

1.1       djm         1: /*
                      2:  * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
                      3:  *
                      4:  * Permission to use, copy, modify, and distribute this software for any
                      5:  * purpose with or without fee is hereby granted, provided that the above
                      6:  * copyright notice and this permission notice appear in all copies.
                      7:  *
                      8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                      9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     15:  */
                     16:
1.10    ! dtucker    17: /* $OpenBSD: krl.c,v 1.9 2013/01/27 10:06:12 djm Exp $ */
1.2       djm        18:
1.1       djm        19: #include <sys/types.h>
                     20: #include <sys/param.h>
                     21: #include <sys/tree.h>
                     22: #include <sys/queue.h>
                     23:
                     24: #include <errno.h>
                     25: #include <fcntl.h>
                     26: #include <limits.h>
                     27: #include <string.h>
                     28: #include <time.h>
                     29: #include <unistd.h>
                     30:
                     31: #include "buffer.h"
                     32: #include "key.h"
                     33: #include "authfile.h"
                     34: #include "misc.h"
                     35: #include "log.h"
                     36: #include "xmalloc.h"
                     37:
                     38: #include "krl.h"
                     39:
                     40: /* #define DEBUG_KRL */
                     41: #ifdef DEBUG_KRL
                     42: # define KRL_DBG(x) debug3 x
                     43: #else
                     44: # define KRL_DBG(x)
                     45: #endif
                     46:
                     47: /*
                     48:  * Trees of revoked serial numbers, key IDs and keys. This allows
                     49:  * quick searching, querying and producing lists in canonical order.
                     50:  */
                     51:
                     52: /* Tree of serial numbers. XXX make smarter: really need a real sparse bitmap */
                     53: struct revoked_serial {
                     54:        u_int64_t lo, hi;
                     55:        RB_ENTRY(revoked_serial) tree_entry;
                     56: };
                     57: static int serial_cmp(struct revoked_serial *a, struct revoked_serial *b);
                     58: RB_HEAD(revoked_serial_tree, revoked_serial);
                     59: RB_GENERATE_STATIC(revoked_serial_tree, revoked_serial, tree_entry, serial_cmp);
                     60:
                     61: /* Tree of key IDs */
                     62: struct revoked_key_id {
                     63:        char *key_id;
                     64:        RB_ENTRY(revoked_key_id) tree_entry;
                     65: };
                     66: static int key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b);
                     67: RB_HEAD(revoked_key_id_tree, revoked_key_id);
                     68: RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp);
                     69:
                     70: /* Tree of blobs (used for keys and fingerprints) */
                     71: struct revoked_blob {
                     72:        u_char *blob;
                     73:        u_int len;
                     74:        RB_ENTRY(revoked_blob) tree_entry;
                     75: };
                     76: static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b);
                     77: RB_HEAD(revoked_blob_tree, revoked_blob);
                     78: RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp);
                     79:
                     80: /* Tracks revoked certs for a single CA */
                     81: struct revoked_certs {
                     82:        Key *ca_key;
                     83:        struct revoked_serial_tree revoked_serials;
                     84:        struct revoked_key_id_tree revoked_key_ids;
                     85:        TAILQ_ENTRY(revoked_certs) entry;
                     86: };
                     87: TAILQ_HEAD(revoked_certs_list, revoked_certs);
                     88:
                     89: struct ssh_krl {
                     90:        u_int64_t krl_version;
                     91:        u_int64_t generated_date;
                     92:        u_int64_t flags;
                     93:        char *comment;
                     94:        struct revoked_blob_tree revoked_keys;
                     95:        struct revoked_blob_tree revoked_sha1s;
                     96:        struct revoked_certs_list revoked_certs;
                     97: };
                     98:
                     99: /* Return equal if a and b overlap */
                    100: static int
                    101: serial_cmp(struct revoked_serial *a, struct revoked_serial *b)
                    102: {
                    103:        if (a->hi >= b->lo && a->lo <= b->hi)
                    104:                return 0;
                    105:        return a->lo < b->lo ? -1 : 1;
                    106: }
                    107:
                    108: static int
                    109: key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b)
                    110: {
                    111:        return strcmp(a->key_id, b->key_id);
                    112: }
                    113:
                    114: static int
                    115: blob_cmp(struct revoked_blob *a, struct revoked_blob *b)
                    116: {
                    117:        int r;
                    118:
                    119:        if (a->len != b->len) {
                    120:                if ((r = memcmp(a->blob, b->blob, MIN(a->len, b->len))) != 0)
                    121:                        return r;
                    122:                return a->len > b->len ? 1 : -1;
                    123:        } else
                    124:                return memcmp(a->blob, b->blob, a->len);
                    125: }
                    126:
                    127: struct ssh_krl *
                    128: ssh_krl_init(void)
                    129: {
                    130:        struct ssh_krl *krl;
                    131:
                    132:        if ((krl = calloc(1, sizeof(*krl))) == NULL)
                    133:                return NULL;
                    134:        RB_INIT(&krl->revoked_keys);
                    135:        RB_INIT(&krl->revoked_sha1s);
                    136:        TAILQ_INIT(&krl->revoked_certs);
                    137:        return krl;
                    138: }
                    139:
                    140: static void
                    141: revoked_certs_free(struct revoked_certs *rc)
                    142: {
                    143:        struct revoked_serial *rs, *trs;
                    144:        struct revoked_key_id *rki, *trki;
                    145:
                    146:        RB_FOREACH_SAFE(rs, revoked_serial_tree, &rc->revoked_serials, trs) {
                    147:                RB_REMOVE(revoked_serial_tree, &rc->revoked_serials, rs);
                    148:                free(rs);
                    149:        }
                    150:        RB_FOREACH_SAFE(rki, revoked_key_id_tree, &rc->revoked_key_ids, trki) {
                    151:                RB_REMOVE(revoked_key_id_tree, &rc->revoked_key_ids, rki);
                    152:                free(rki->key_id);
                    153:                free(rki);
                    154:        }
                    155:        if (rc->ca_key != NULL)
                    156:                key_free(rc->ca_key);
                    157: }
                    158:
                    159: void
                    160: ssh_krl_free(struct ssh_krl *krl)
                    161: {
                    162:        struct revoked_blob *rb, *trb;
                    163:        struct revoked_certs *rc, *trc;
                    164:
                    165:        if (krl == NULL)
                    166:                return;
                    167:
                    168:        free(krl->comment);
                    169:        RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_keys, trb) {
                    170:                RB_REMOVE(revoked_blob_tree, &krl->revoked_keys, rb);
                    171:                free(rb->blob);
                    172:                free(rb);
                    173:        }
                    174:        RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha1s, trb) {
                    175:                RB_REMOVE(revoked_blob_tree, &krl->revoked_sha1s, rb);
                    176:                free(rb->blob);
                    177:                free(rb);
                    178:        }
                    179:        TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) {
                    180:                TAILQ_REMOVE(&krl->revoked_certs, rc, entry);
                    181:                revoked_certs_free(rc);
                    182:        }
                    183: }
                    184:
                    185: void
                    186: ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version)
                    187: {
                    188:        krl->krl_version = version;
                    189: }
                    190:
                    191: void
                    192: ssh_krl_set_comment(struct ssh_krl *krl, const char *comment)
                    193: {
                    194:        free(krl->comment);
                    195:        if ((krl->comment = strdup(comment)) == NULL)
                    196:                fatal("%s: strdup", __func__);
                    197: }
                    198:
                    199: /*
                    200:  * Find the revoked_certs struct for a CA key. If allow_create is set then
                    201:  * create a new one in the tree if one did not exist already.
                    202:  */
                    203: static int
                    204: revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key,
                    205:     struct revoked_certs **rcp, int allow_create)
                    206: {
                    207:        struct revoked_certs *rc;
                    208:
                    209:        *rcp = NULL;
                    210:        TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
                    211:                if (key_equal(rc->ca_key, ca_key)) {
                    212:                        *rcp = rc;
                    213:                        return 0;
                    214:                }
                    215:        }
                    216:        if (!allow_create)
                    217:                return 0;
                    218:        /* If this CA doesn't exist in the list then add it now */
                    219:        if ((rc = calloc(1, sizeof(*rc))) == NULL)
                    220:                return -1;
                    221:        if ((rc->ca_key = key_from_private(ca_key)) == NULL) {
                    222:                free(rc);
                    223:                return -1;
                    224:        }
                    225:        RB_INIT(&rc->revoked_serials);
                    226:        RB_INIT(&rc->revoked_key_ids);
                    227:        TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
                    228:        debug3("%s: new CA %s", __func__, key_type(ca_key));
                    229:        *rcp = rc;
                    230:        return 0;
                    231: }
                    232:
                    233: static int
                    234: insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
                    235: {
                    236:        struct revoked_serial rs, *ers, *crs, *irs;
                    237:
                    238:        KRL_DBG(("%s: insert %llu:%llu", __func__, lo, hi));
                    239:        bzero(&rs, sizeof(rs));
                    240:        rs.lo = lo;
                    241:        rs.hi = hi;
                    242:        ers = RB_NFIND(revoked_serial_tree, rt, &rs);
                    243:        if (ers == NULL || serial_cmp(ers, &rs) != 0) {
                    244:                /* No entry matches. Just insert */
                    245:                if ((irs = malloc(sizeof(rs))) == NULL)
                    246:                        return -1;
                    247:                memcpy(irs, &rs, sizeof(*irs));
                    248:                ers = RB_INSERT(revoked_serial_tree, rt, irs);
                    249:                if (ers != NULL) {
                    250:                        KRL_DBG(("%s: bad: ers != NULL", __func__));
                    251:                        /* Shouldn't happen */
1.4       markus    252:                        free(irs);
1.1       djm       253:                        return -1;
                    254:                }
                    255:                ers = irs;
                    256:        } else {
                    257:                KRL_DBG(("%s: overlap found %llu:%llu", __func__,
                    258:                    ers->lo, ers->hi));
                    259:                /*
                    260:                 * The inserted entry overlaps an existing one. Grow the
                    261:                 * existing entry.
                    262:                 */
                    263:                if (ers->lo > lo)
                    264:                        ers->lo = lo;
                    265:                if (ers->hi < hi)
                    266:                        ers->hi = hi;
                    267:        }
                    268:        /*
                    269:         * The inserted or revised range might overlap or abut adjacent ones;
                    270:         * coalesce as necessary.
                    271:         */
                    272:
                    273:        /* Check predecessors */
                    274:        while ((crs = RB_PREV(revoked_serial_tree, rt, ers)) != NULL) {
                    275:                KRL_DBG(("%s: pred %llu:%llu", __func__, crs->lo, crs->hi));
                    276:                if (ers->lo != 0 && crs->hi < ers->lo - 1)
                    277:                        break;
                    278:                /* This entry overlaps. */
                    279:                if (crs->lo < ers->lo) {
                    280:                        ers->lo = crs->lo;
                    281:                        KRL_DBG(("%s: pred extend %llu:%llu", __func__,
                    282:                            ers->lo, ers->hi));
                    283:                }
                    284:                RB_REMOVE(revoked_serial_tree, rt, crs);
                    285:                free(crs);
                    286:        }
                    287:        /* Check successors */
                    288:        while ((crs = RB_NEXT(revoked_serial_tree, rt, ers)) != NULL) {
                    289:                KRL_DBG(("%s: succ %llu:%llu", __func__, crs->lo, crs->hi));
                    290:                if (ers->hi != (u_int64_t)-1 && crs->lo > ers->hi + 1)
                    291:                        break;
                    292:                /* This entry overlaps. */
                    293:                if (crs->hi > ers->hi) {
                    294:                        ers->hi = crs->hi;
                    295:                        KRL_DBG(("%s: succ extend %llu:%llu", __func__,
                    296:                            ers->lo, ers->hi));
                    297:                }
                    298:                RB_REMOVE(revoked_serial_tree, rt, crs);
                    299:                free(crs);
                    300:        }
                    301:        KRL_DBG(("%s: done, final %llu:%llu", __func__, ers->lo, ers->hi));
                    302:        return 0;
                    303: }
                    304:
                    305: int
                    306: ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key,
                    307:     u_int64_t serial)
                    308: {
                    309:        return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial);
                    310: }
                    311:
                    312: int
                    313: ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key,
                    314:     u_int64_t lo, u_int64_t hi)
                    315: {
                    316:        struct revoked_certs *rc;
                    317:
                    318:        if (lo > hi || lo == 0)
                    319:                return -1;
                    320:        if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0)
                    321:                return -1;
                    322:        return insert_serial_range(&rc->revoked_serials, lo, hi);
                    323: }
                    324:
                    325: int
                    326: ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key,
                    327:     const char *key_id)
                    328: {
                    329:        struct revoked_key_id *rki, *erki;
                    330:        struct revoked_certs *rc;
                    331:
                    332:        if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0)
                    333:                return -1;
                    334:
                    335:        debug3("%s: revoke %s", __func__, key_id);
                    336:        if ((rki = calloc(1, sizeof(*rki))) == NULL ||
                    337:            (rki->key_id = strdup(key_id)) == NULL) {
                    338:                free(rki);
                    339:                fatal("%s: strdup", __func__);
                    340:        }
                    341:        erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki);
                    342:        if (erki != NULL) {
                    343:                free(rki->key_id);
                    344:                free(rki);
                    345:        }
                    346:        return 0;
                    347: }
                    348:
                    349: /* Convert "key" to a public key blob without any certificate information */
                    350: static int
                    351: plain_key_blob(const Key *key, u_char **blob, u_int *blen)
                    352: {
                    353:        Key *kcopy;
                    354:        int r;
                    355:
                    356:        if ((kcopy = key_from_private(key)) == NULL)
                    357:                return -1;
                    358:        if (key_is_cert(kcopy)) {
                    359:                if (key_drop_cert(kcopy) != 0) {
                    360:                        error("%s: key_drop_cert", __func__);
                    361:                        key_free(kcopy);
                    362:                        return -1;
                    363:                }
                    364:        }
                    365:        r = key_to_blob(kcopy, blob, blen);
                    366:        free(kcopy);
                    367:        return r == 0 ? -1 : 0;
                    368: }
                    369:
                    370: /* Revoke a key blob. Ownership of blob is transferred to the tree */
                    371: static int
                    372: revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len)
                    373: {
                    374:        struct revoked_blob *rb, *erb;
                    375:
                    376:        if ((rb = calloc(1, sizeof(*rb))) == NULL)
                    377:                return -1;
                    378:        rb->blob = blob;
                    379:        rb->len = len;
                    380:        erb = RB_INSERT(revoked_blob_tree, rbt, rb);
                    381:        if (erb != NULL) {
                    382:                free(rb->blob);
                    383:                free(rb);
                    384:        }
                    385:        return 0;
                    386: }
                    387:
                    388: int
                    389: ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key)
                    390: {
                    391:        u_char *blob;
                    392:        u_int len;
                    393:
                    394:        debug3("%s: revoke type %s", __func__, key_type(key));
                    395:        if (plain_key_blob(key, &blob, &len) != 0)
                    396:                return -1;
                    397:        return revoke_blob(&krl->revoked_keys, blob, len);
                    398: }
                    399:
                    400: int
                    401: ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key)
                    402: {
                    403:        u_char *blob;
                    404:        u_int len;
                    405:
                    406:        debug3("%s: revoke type %s by sha1", __func__, key_type(key));
                    407:        if ((blob = key_fingerprint_raw(key, SSH_FP_SHA1, &len)) == NULL)
                    408:                return -1;
                    409:        return revoke_blob(&krl->revoked_sha1s, blob, len);
                    410: }
                    411:
                    412: int
                    413: ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key)
                    414: {
                    415:        if (!key_is_cert(key))
                    416:                return ssh_krl_revoke_key_sha1(krl, key);
                    417:
                    418:        if (key_cert_is_legacy(key) || key->cert->serial == 0) {
                    419:                return ssh_krl_revoke_cert_by_key_id(krl,
                    420:                    key->cert->signature_key,
                    421:                    key->cert->key_id);
                    422:        } else {
                    423:                return ssh_krl_revoke_cert_by_serial(krl,
                    424:                    key->cert->signature_key,
                    425:                    key->cert->serial);
                    426:        }
                    427: }
                    428:
                    429: /*
                    430:  * Select a copact next section type to emit in a KRL based on the
                    431:  * current section type, the run length of contiguous revoked serial
                    432:  * numbers and the gaps from the last and to the next revoked serial.
                    433:  * Applies a mostly-accurate bit cost model to select the section type
                    434:  * that will minimise the size of the resultant KRL.
                    435:  */
                    436: static int
                    437: choose_next_state(int current_state, u_int64_t contig, int final,
                    438:     u_int64_t last_gap, u_int64_t next_gap, int *force_new_section)
                    439: {
                    440:        int new_state;
                    441:        u_int64_t cost, cost_list, cost_range, cost_bitmap, cost_bitmap_restart;
                    442:
                    443:        /*
                    444:         * Avoid unsigned overflows.
                    445:         * The limits are high enough to avoid confusing the calculations.
                    446:         */
                    447:        contig = MIN(contig, 1ULL<<31);
                    448:        last_gap = MIN(last_gap, 1ULL<<31);
                    449:        next_gap = MIN(next_gap, 1ULL<<31);
                    450:
                    451:        /*
                    452:         * Calculate the cost to switch from the current state to candidates.
                    453:         * NB. range sections only ever contain a single range, so their
                    454:         * switching cost is independent of the current_state.
                    455:         */
                    456:        cost_list = cost_bitmap = cost_bitmap_restart = 0;
                    457:        cost_range = 8;
                    458:        switch (current_state) {
                    459:        case KRL_SECTION_CERT_SERIAL_LIST:
                    460:                cost_bitmap_restart = cost_bitmap = 8 + 64;
                    461:                break;
                    462:        case KRL_SECTION_CERT_SERIAL_BITMAP:
                    463:                cost_list = 8;
                    464:                cost_bitmap_restart = 8 + 64;
                    465:                break;
                    466:        case KRL_SECTION_CERT_SERIAL_RANGE:
                    467:        case 0:
                    468:                cost_bitmap_restart = cost_bitmap = 8 + 64;
                    469:                cost_list = 8;
                    470:        }
                    471:
                    472:        /* Estimate base cost in bits of each section type */
                    473:        cost_list += 64 * contig + (final ? 0 : 8+64);
                    474:        cost_range += (2 * 64) + (final ? 0 : 8+64);
                    475:        cost_bitmap += last_gap + contig + (final ? 0 : MIN(next_gap, 8+64));
                    476:        cost_bitmap_restart += contig + (final ? 0 : MIN(next_gap, 8+64));
                    477:
                    478:        /* Convert to byte costs for actual comparison */
                    479:        cost_list = (cost_list + 7) / 8;
                    480:        cost_bitmap = (cost_bitmap + 7) / 8;
                    481:        cost_bitmap_restart = (cost_bitmap_restart + 7) / 8;
                    482:        cost_range = (cost_range + 7) / 8;
                    483:
                    484:        /* Now pick the best choice */
                    485:        *force_new_section = 0;
                    486:        new_state = KRL_SECTION_CERT_SERIAL_BITMAP;
                    487:        cost = cost_bitmap;
                    488:        if (cost_range < cost) {
                    489:                new_state = KRL_SECTION_CERT_SERIAL_RANGE;
                    490:                cost = cost_range;
                    491:        }
                    492:        if (cost_list < cost) {
                    493:                new_state = KRL_SECTION_CERT_SERIAL_LIST;
                    494:                cost = cost_list;
                    495:        }
                    496:        if (cost_bitmap_restart < cost) {
                    497:                new_state = KRL_SECTION_CERT_SERIAL_BITMAP;
                    498:                *force_new_section = 1;
                    499:                cost = cost_bitmap_restart;
                    500:        }
                    501:        debug3("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:"
                    502:            "list %llu range %llu bitmap %llu new bitmap %llu, "
                    503:            "selected 0x%02x%s", __func__, contig, last_gap, next_gap, final,
                    504:            cost_list, cost_range, cost_bitmap, cost_bitmap_restart, new_state,
                    505:            *force_new_section ? " restart" : "");
                    506:        return new_state;
                    507: }
                    508:
                    509: /* Generate a KRL_SECTION_CERTIFICATES KRL section */
                    510: static int
                    511: revoked_certs_generate(struct revoked_certs *rc, Buffer *buf)
                    512: {
                    513:        int final, force_new_sect, r = -1;
                    514:        u_int64_t i, contig, gap, last = 0, bitmap_start = 0;
                    515:        struct revoked_serial *rs, *nrs;
                    516:        struct revoked_key_id *rki;
                    517:        int next_state, state = 0;
                    518:        Buffer sect;
                    519:        u_char *kblob = NULL;
                    520:        u_int klen;
                    521:        BIGNUM *bitmap = NULL;
                    522:
                    523:        /* Prepare CA scope key blob if we have one supplied */
                    524:        if (key_to_blob(rc->ca_key, &kblob, &klen) == 0)
                    525:                return -1;
                    526:
                    527:        buffer_init(&sect);
                    528:
                    529:        /* Store the header */
                    530:        buffer_put_string(buf, kblob, klen);
                    531:        buffer_put_string(buf, NULL, 0); /* Reserved */
                    532:
                    533:        free(kblob);
                    534:
                    535:        /* Store the revoked serials.  */
                    536:        for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials);
                    537:             rs != NULL;
                    538:             rs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs)) {
                    539:                debug3("%s: serial %llu:%llu state 0x%02x", __func__,
                    540:                    rs->lo, rs->hi, state);
                    541:
                    542:                /* Check contiguous length and gap to next section (if any) */
                    543:                nrs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs);
                    544:                final = nrs == NULL;
                    545:                gap = nrs == NULL ? 0 : nrs->lo - rs->hi;
                    546:                contig = 1 + (rs->hi - rs->lo);
                    547:
                    548:                /* Choose next state based on these */
                    549:                next_state = choose_next_state(state, contig, final,
                    550:                    state == 0 ? 0 : rs->lo - last, gap, &force_new_sect);
                    551:
                    552:                /*
                    553:                 * If the current section is a range section or has a different
                    554:                 * type to the next section, then finish it off now.
                    555:                 */
                    556:                if (state != 0 && (force_new_sect || next_state != state ||
                    557:                    state == KRL_SECTION_CERT_SERIAL_RANGE)) {
                    558:                        debug3("%s: finish state 0x%02x", __func__, state);
                    559:                        switch (state) {
                    560:                        case KRL_SECTION_CERT_SERIAL_LIST:
                    561:                        case KRL_SECTION_CERT_SERIAL_RANGE:
                    562:                                break;
                    563:                        case KRL_SECTION_CERT_SERIAL_BITMAP:
                    564:                                buffer_put_bignum2(&sect, bitmap);
                    565:                                BN_free(bitmap);
                    566:                                bitmap = NULL;
                    567:                                break;
                    568:                        }
                    569:                        buffer_put_char(buf, state);
                    570:                        buffer_put_string(buf,
                    571:                            buffer_ptr(&sect), buffer_len(&sect));
                    572:                }
                    573:
                    574:                /* If we are starting a new section then prepare it now */
                    575:                if (next_state != state || force_new_sect) {
                    576:                        debug3("%s: start state 0x%02x", __func__, next_state);
                    577:                        state = next_state;
                    578:                        buffer_clear(&sect);
                    579:                        switch (state) {
                    580:                        case KRL_SECTION_CERT_SERIAL_LIST:
                    581:                        case KRL_SECTION_CERT_SERIAL_RANGE:
                    582:                                break;
                    583:                        case KRL_SECTION_CERT_SERIAL_BITMAP:
                    584:                                if ((bitmap = BN_new()) == NULL)
                    585:                                        goto out;
                    586:                                bitmap_start = rs->lo;
                    587:                                buffer_put_int64(&sect, bitmap_start);
                    588:                                break;
                    589:                        }
                    590:                }
                    591:
                    592:                /* Perform section-specific processing */
                    593:                switch (state) {
                    594:                case KRL_SECTION_CERT_SERIAL_LIST:
1.3       djm       595:                        for (i = 0; i < contig; i++)
1.1       djm       596:                                buffer_put_int64(&sect, rs->lo + i);
                    597:                        break;
                    598:                case KRL_SECTION_CERT_SERIAL_RANGE:
                    599:                        buffer_put_int64(&sect, rs->lo);
                    600:                        buffer_put_int64(&sect, rs->hi);
                    601:                        break;
                    602:                case KRL_SECTION_CERT_SERIAL_BITMAP:
                    603:                        if (rs->lo - bitmap_start > INT_MAX) {
                    604:                                error("%s: insane bitmap gap", __func__);
                    605:                                goto out;
                    606:                        }
                    607:                        for (i = 0; i < contig; i++) {
                    608:                                if (BN_set_bit(bitmap,
                    609:                                    rs->lo + i - bitmap_start) != 1)
                    610:                                        goto out;
                    611:                        }
                    612:                        break;
                    613:                }
                    614:                last = rs->hi;
                    615:        }
                    616:        /* Flush the remaining section, if any */
                    617:        if (state != 0) {
                    618:                debug3("%s: serial final flush for state 0x%02x",
                    619:                    __func__, state);
                    620:                switch (state) {
                    621:                case KRL_SECTION_CERT_SERIAL_LIST:
                    622:                case KRL_SECTION_CERT_SERIAL_RANGE:
                    623:                        break;
                    624:                case KRL_SECTION_CERT_SERIAL_BITMAP:
                    625:                        buffer_put_bignum2(&sect, bitmap);
                    626:                        BN_free(bitmap);
                    627:                        bitmap = NULL;
                    628:                        break;
                    629:                }
                    630:                buffer_put_char(buf, state);
                    631:                buffer_put_string(buf,
                    632:                    buffer_ptr(&sect), buffer_len(&sect));
                    633:        }
                    634:        debug3("%s: serial done ", __func__);
                    635:
                    636:        /* Now output a section for any revocations by key ID */
                    637:        buffer_clear(&sect);
                    638:        RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) {
                    639:                debug3("%s: key ID %s", __func__, rki->key_id);
                    640:                buffer_put_cstring(&sect, rki->key_id);
                    641:        }
                    642:        if (buffer_len(&sect) != 0) {
                    643:                buffer_put_char(buf, KRL_SECTION_CERT_KEY_ID);
                    644:                buffer_put_string(buf, buffer_ptr(&sect),
                    645:                    buffer_len(&sect));
                    646:        }
                    647:        r = 0;
                    648:  out:
                    649:        if (bitmap != NULL)
                    650:                BN_free(bitmap);
                    651:        buffer_free(&sect);
                    652:        return r;
                    653: }
                    654:
                    655: int
                    656: ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys,
                    657:     u_int nsign_keys)
                    658: {
                    659:        int r = -1;
                    660:        struct revoked_certs *rc;
                    661:        struct revoked_blob *rb;
                    662:        Buffer sect;
                    663:        u_char *kblob = NULL, *sblob = NULL;
                    664:        u_int klen, slen, i;
                    665:
                    666:        if (krl->generated_date == 0)
                    667:                krl->generated_date = time(NULL);
                    668:
                    669:        buffer_init(&sect);
                    670:
                    671:        /* Store the header */
                    672:        buffer_append(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1);
                    673:        buffer_put_int(buf, KRL_FORMAT_VERSION);
                    674:        buffer_put_int64(buf, krl->krl_version);
                    675:        buffer_put_int64(buf, krl->generated_date);
                    676:        buffer_put_int64(buf, krl->flags);
                    677:        buffer_put_string(buf, NULL, 0);
                    678:        buffer_put_cstring(buf, krl->comment ? krl->comment : "");
                    679:
                    680:        /* Store sections for revoked certificates */
                    681:        TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
                    682:                if (revoked_certs_generate(rc, &sect) != 0)
                    683:                        goto out;
                    684:                buffer_put_char(buf, KRL_SECTION_CERTIFICATES);
                    685:                buffer_put_string(buf, buffer_ptr(&sect),
                    686:                    buffer_len(&sect));
                    687:        }
                    688:
                    689:        /* Finally, output sections for revocations by public key/hash */
                    690:        buffer_clear(&sect);
                    691:        RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
                    692:                debug3("%s: key len %u ", __func__, rb->len);
                    693:                buffer_put_string(&sect, rb->blob, rb->len);
                    694:        }
                    695:        if (buffer_len(&sect) != 0) {
                    696:                buffer_put_char(buf, KRL_SECTION_EXPLICIT_KEY);
                    697:                buffer_put_string(buf, buffer_ptr(&sect),
                    698:                    buffer_len(&sect));
                    699:        }
                    700:        buffer_clear(&sect);
                    701:        RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) {
                    702:                debug3("%s: hash len %u ", __func__, rb->len);
                    703:                buffer_put_string(&sect, rb->blob, rb->len);
                    704:        }
                    705:        if (buffer_len(&sect) != 0) {
                    706:                buffer_put_char(buf, KRL_SECTION_FINGERPRINT_SHA1);
                    707:                buffer_put_string(buf, buffer_ptr(&sect),
                    708:                    buffer_len(&sect));
                    709:        }
                    710:
                    711:        for (i = 0; i < nsign_keys; i++) {
                    712:                if (key_to_blob(sign_keys[i], &kblob, &klen) == 0)
                    713:                        goto out;
                    714:
                    715:                debug3("%s: signature key len %u", __func__, klen);
                    716:                buffer_put_char(buf, KRL_SECTION_SIGNATURE);
                    717:                buffer_put_string(buf, kblob, klen);
                    718:
                    719:                if (key_sign(sign_keys[i], &sblob, &slen,
                    720:                    buffer_ptr(buf), buffer_len(buf)) == -1)
                    721:                        goto out;
                    722:                debug3("%s: signature sig len %u", __func__, slen);
                    723:                buffer_put_string(buf, sblob, slen);
                    724:        }
                    725:
                    726:        r = 0;
                    727:  out:
                    728:        free(kblob);
                    729:        free(sblob);
                    730:        buffer_free(&sect);
                    731:        return r;
                    732: }
                    733:
                    734: static void
                    735: format_timestamp(u_int64_t timestamp, char *ts, size_t nts)
                    736: {
                    737:        time_t t;
                    738:        struct tm *tm;
                    739:
                    740:        t = timestamp;
                    741:        tm = localtime(&t);
                    742:        *ts = '\0';
                    743:        strftime(ts, nts, "%Y%m%dT%H%M%S", tm);
                    744: }
                    745:
                    746: static int
                    747: parse_revoked_certs(Buffer *buf, struct ssh_krl *krl)
                    748: {
                    749:        int ret = -1, nbits;
                    750:        u_char type, *blob;
                    751:        u_int blen;
                    752:        Buffer subsect;
                    753:        u_int64_t serial, serial_lo, serial_hi;
                    754:        BIGNUM *bitmap = NULL;
                    755:        char *key_id = NULL;
                    756:        Key *ca_key = NULL;
                    757:
                    758:        buffer_init(&subsect);
                    759:
                    760:        if ((blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL ||
                    761:            buffer_get_string_ptr_ret(buf, NULL) == NULL) { /* reserved */
                    762:                error("%s: buffer error", __func__);
                    763:                goto out;
                    764:        }
                    765:        if ((ca_key = key_from_blob(blob, blen)) == NULL)
                    766:                goto out;
                    767:
                    768:        while (buffer_len(buf) > 0) {
                    769:                if (buffer_get_char_ret(&type, buf) != 0 ||
                    770:                    (blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL) {
                    771:                        error("%s: buffer error", __func__);
                    772:                        goto out;
                    773:                }
                    774:                buffer_clear(&subsect);
                    775:                buffer_append(&subsect, blob, blen);
                    776:                debug3("%s: subsection type 0x%02x", __func__, type);
                    777:                /* buffer_dump(&subsect); */
                    778:
                    779:                switch (type) {
                    780:                case KRL_SECTION_CERT_SERIAL_LIST:
                    781:                        while (buffer_len(&subsect) > 0) {
                    782:                                if (buffer_get_int64_ret(&serial,
                    783:                                    &subsect) != 0) {
                    784:                                        error("%s: buffer error", __func__);
                    785:                                        goto out;
                    786:                                }
                    787:                                if (ssh_krl_revoke_cert_by_serial(krl, ca_key,
                    788:                                    serial) != 0) {
                    789:                                        error("%s: update failed", __func__);
                    790:                                        goto out;
                    791:                                }
                    792:                        }
                    793:                        break;
                    794:                case KRL_SECTION_CERT_SERIAL_RANGE:
                    795:                        if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 ||
                    796:                            buffer_get_int64_ret(&serial_hi, &subsect) != 0) {
                    797:                                error("%s: buffer error", __func__);
                    798:                                goto out;
                    799:                        }
                    800:                        if (ssh_krl_revoke_cert_by_serial_range(krl, ca_key,
                    801:                            serial_lo, serial_hi) != 0) {
                    802:                                error("%s: update failed", __func__);
                    803:                                goto out;
                    804:                        }
                    805:                        break;
                    806:                case KRL_SECTION_CERT_SERIAL_BITMAP:
                    807:                        if ((bitmap = BN_new()) == NULL) {
                    808:                                error("%s: BN_new", __func__);
                    809:                                goto out;
                    810:                        }
                    811:                        if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 ||
                    812:                            buffer_get_bignum2_ret(&subsect, bitmap) != 0) {
                    813:                                error("%s: buffer error", __func__);
                    814:                                goto out;
                    815:                        }
                    816:                        if ((nbits = BN_num_bits(bitmap)) < 0) {
                    817:                                error("%s: bitmap bits < 0", __func__);
                    818:                                goto out;
                    819:                        }
                    820:                        for (serial = 0; serial < (u_int)nbits; serial++) {
                    821:                                if (serial > 0 && serial_lo + serial == 0) {
                    822:                                        error("%s: bitmap wraps u64", __func__);
                    823:                                        goto out;
                    824:                                }
                    825:                                if (!BN_is_bit_set(bitmap, serial))
                    826:                                        continue;
                    827:                                if (ssh_krl_revoke_cert_by_serial(krl, ca_key,
                    828:                                    serial_lo + serial) != 0) {
                    829:                                        error("%s: update failed", __func__);
                    830:                                        goto out;
                    831:                                }
                    832:                        }
                    833:                        BN_free(bitmap);
                    834:                        bitmap = NULL;
                    835:                        break;
                    836:                case KRL_SECTION_CERT_KEY_ID:
                    837:                        while (buffer_len(&subsect) > 0) {
                    838:                                if ((key_id = buffer_get_cstring_ret(&subsect,
                    839:                                    NULL)) == NULL) {
                    840:                                        error("%s: buffer error", __func__);
                    841:                                        goto out;
                    842:                                }
                    843:                                if (ssh_krl_revoke_cert_by_key_id(krl, ca_key,
                    844:                                    key_id) != 0) {
                    845:                                        error("%s: update failed", __func__);
                    846:                                        goto out;
                    847:                                }
                    848:                                free(key_id);
                    849:                                key_id = NULL;
                    850:                        }
                    851:                        break;
                    852:                default:
                    853:                        error("Unsupported KRL certificate section %u", type);
                    854:                        goto out;
                    855:                }
                    856:                if (buffer_len(&subsect) > 0) {
                    857:                        error("KRL certificate section contains unparsed data");
                    858:                        goto out;
                    859:                }
                    860:        }
                    861:
                    862:        ret = 0;
                    863:  out:
                    864:        if (ca_key != NULL)
                    865:                key_free(ca_key);
                    866:        if (bitmap != NULL)
                    867:                BN_free(bitmap);
                    868:        free(key_id);
                    869:        buffer_free(&subsect);
                    870:        return ret;
                    871: }
                    872:
                    873:
                    874: /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
                    875: int
                    876: ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
                    877:     const Key **sign_ca_keys, u_int nsign_ca_keys)
                    878: {
                    879:        Buffer copy, sect;
                    880:        struct ssh_krl *krl;
                    881:        char timestamp[64];
                    882:        int ret = -1, r, sig_seen;
                    883:        Key *key = NULL, **ca_used = NULL;
                    884:        u_char type, *blob;
                    885:        u_int i, j, sig_off, sects_off, blen, format_version, nca_used = 0;
                    886:
                    887:        *krlp = NULL;
                    888:        if (buffer_len(buf) < sizeof(KRL_MAGIC) - 1 ||
                    889:            memcmp(buffer_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) {
                    890:                debug3("%s: not a KRL", __func__);
                    891:                /*
                    892:                 * Return success but a NULL *krlp here to signal that the
                    893:                 * file might be a simple list of keys.
                    894:                 */
                    895:                return 0;
                    896:        }
                    897:
                    898:        /* Take a copy of the KRL buffer so we can verify its signature later */
                    899:        buffer_init(&copy);
                    900:        buffer_append(&copy, buffer_ptr(buf), buffer_len(buf));
                    901:
                    902:        buffer_init(&sect);
                    903:        buffer_consume(&copy, sizeof(KRL_MAGIC) - 1);
                    904:
                    905:        if ((krl = ssh_krl_init()) == NULL) {
                    906:                error("%s: alloc failed", __func__);
                    907:                goto out;
                    908:        }
                    909:
                    910:        if (buffer_get_int_ret(&format_version, &copy) != 0) {
                    911:                error("%s: KRL truncated", __func__);
                    912:                goto out;
                    913:        }
                    914:        if (format_version != KRL_FORMAT_VERSION) {
                    915:                error("%s: KRL unsupported format version %u",
                    916:                    __func__, format_version);
                    917:                goto out;
                    918:        }
                    919:        if (buffer_get_int64_ret(&krl->krl_version, &copy) != 0 ||
                    920:            buffer_get_int64_ret(&krl->generated_date, &copy) != 0 ||
                    921:            buffer_get_int64_ret(&krl->flags, &copy) != 0 ||
                    922:            buffer_get_string_ptr_ret(&copy, NULL) == NULL || /* reserved */
                    923:            (krl->comment = buffer_get_cstring_ret(&copy, NULL)) == NULL) {
                    924:                error("%s: buffer error", __func__);
                    925:                goto out;
                    926:        }
                    927:
                    928:        format_timestamp(krl->generated_date, timestamp, sizeof(timestamp));
                    929:        debug("KRL version %llu generated at %s%s%s", krl->krl_version,
                    930:            timestamp, *krl->comment ? ": " : "", krl->comment);
                    931:
                    932:        /*
                    933:         * 1st pass: verify signatures, if any. This is done to avoid
                    934:         * detailed parsing of data whose provenance is unverified.
                    935:         */
                    936:        sig_seen = 0;
                    937:        sects_off = buffer_len(buf) - buffer_len(&copy);
                    938:        while (buffer_len(&copy) > 0) {
                    939:                if (buffer_get_char_ret(&type, &copy) != 0 ||
                    940:                    (blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) {
                    941:                        error("%s: buffer error", __func__);
                    942:                        goto out;
                    943:                }
                    944:                debug3("%s: first pass, section 0x%02x", __func__, type);
                    945:                if (type != KRL_SECTION_SIGNATURE) {
                    946:                        if (sig_seen) {
                    947:                                error("KRL contains non-signature section "
                    948:                                    "after signature");
                    949:                                goto out;
                    950:                        }
                    951:                        /* Not interested for now. */
                    952:                        continue;
                    953:                }
                    954:                sig_seen = 1;
                    955:                /* First string component is the signing key */
                    956:                if ((key = key_from_blob(blob, blen)) == NULL) {
                    957:                        error("%s: invalid signature key", __func__);
                    958:                        goto out;
                    959:                }
                    960:                sig_off = buffer_len(buf) - buffer_len(&copy);
                    961:                /* Second string component is the signature itself */
                    962:                if ((blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) {
                    963:                        error("%s: buffer error", __func__);
                    964:                        goto out;
                    965:                }
                    966:                /* Check signature over entire KRL up to this point */
                    967:                if (key_verify(key, blob, blen,
                    968:                    buffer_ptr(buf), buffer_len(buf) - sig_off) == -1) {
                    969:                        error("bad signaure on KRL");
                    970:                        goto out;
                    971:                }
                    972:                /* Check if this key has already signed this KRL */
                    973:                for (i = 0; i < nca_used; i++) {
                    974:                        if (key_equal(ca_used[i], key)) {
                    975:                                error("KRL signed more than once with "
                    976:                                    "the same key");
                    977:                                goto out;
                    978:                        }
                    979:                }
                    980:                /* Record keys used to sign the KRL */
1.9       djm       981:                ca_used = xrealloc(ca_used, nca_used + 1, sizeof(*ca_used));
1.1       djm       982:                ca_used[nca_used++] = key;
                    983:                key = NULL;
                    984:                break;
                    985:        }
                    986:
                    987:        /*
                    988:         * 2nd pass: parse and load the KRL, skipping the header to the point
                    989:         * where the section start.
                    990:         */
                    991:        buffer_append(&copy, (u_char*)buffer_ptr(buf) + sects_off,
                    992:            buffer_len(buf) - sects_off);
                    993:        while (buffer_len(&copy) > 0) {
                    994:                if (buffer_get_char_ret(&type, &copy) != 0 ||
                    995:                    (blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) {
                    996:                        error("%s: buffer error", __func__);
                    997:                        goto out;
                    998:                }
                    999:                debug3("%s: second pass, section 0x%02x", __func__, type);
                   1000:                buffer_clear(&sect);
                   1001:                buffer_append(&sect, blob, blen);
                   1002:
                   1003:                switch (type) {
                   1004:                case KRL_SECTION_CERTIFICATES:
                   1005:                        if ((r = parse_revoked_certs(&sect, krl)) != 0)
                   1006:                                goto out;
                   1007:                        break;
                   1008:                case KRL_SECTION_EXPLICIT_KEY:
                   1009:                case KRL_SECTION_FINGERPRINT_SHA1:
                   1010:                        while (buffer_len(&sect) > 0) {
                   1011:                                if ((blob = buffer_get_string_ret(&sect,
                   1012:                                    &blen)) == NULL) {
                   1013:                                        error("%s: buffer error", __func__);
                   1014:                                        goto out;
                   1015:                                }
                   1016:                                if (type == KRL_SECTION_FINGERPRINT_SHA1 &&
                   1017:                                    blen != 20) {
                   1018:                                        error("%s: bad SHA1 length", __func__);
                   1019:                                        goto out;
                   1020:                                }
                   1021:                                if (revoke_blob(
                   1022:                                    type == KRL_SECTION_EXPLICIT_KEY ?
                   1023:                                    &krl->revoked_keys : &krl->revoked_sha1s,
                   1024:                                    blob, blen) != 0)
                   1025:                                        goto out; /* revoke_blob frees blob */
                   1026:                        }
                   1027:                        break;
                   1028:                case KRL_SECTION_SIGNATURE:
                   1029:                        /* Handled above, but still need to stay in synch */
                   1030:                        buffer_clear(&sect);
1.5       djm      1031:                        if ((blob = buffer_get_string_ptr_ret(&copy,
1.1       djm      1032:                            &blen)) == NULL) {
                   1033:                                error("%s: buffer error", __func__);
                   1034:                                goto out;
                   1035:                        }
                   1036:                        break;
                   1037:                default:
                   1038:                        error("Unsupported KRL section %u", type);
                   1039:                        goto out;
                   1040:                }
                   1041:                if (buffer_len(&sect) > 0) {
                   1042:                        error("KRL section contains unparsed data");
                   1043:                        goto out;
                   1044:                }
                   1045:        }
                   1046:
                   1047:        /* Check that the key(s) used to sign the KRL weren't revoked */
                   1048:        sig_seen = 0;
                   1049:        for (i = 0; i < nca_used; i++) {
                   1050:                if (ssh_krl_check_key(krl, ca_used[i]) == 0)
                   1051:                        sig_seen = 1;
                   1052:                else {
                   1053:                        key_free(ca_used[i]);
                   1054:                        ca_used[i] = NULL;
                   1055:                }
                   1056:        }
                   1057:        if (nca_used && !sig_seen) {
                   1058:                error("All keys used to sign KRL were revoked");
                   1059:                goto out;
                   1060:        }
                   1061:
                   1062:        /* If we have CA keys, then verify that one was used to sign the KRL */
                   1063:        if (sig_seen && nsign_ca_keys != 0) {
                   1064:                sig_seen = 0;
                   1065:                for (i = 0; !sig_seen && i < nsign_ca_keys; i++) {
                   1066:                        for (j = 0; j < nca_used; j++) {
                   1067:                                if (ca_used[j] == NULL)
                   1068:                                        continue;
                   1069:                                if (key_equal(ca_used[j], sign_ca_keys[i])) {
                   1070:                                        sig_seen = 1;
                   1071:                                        break;
                   1072:                                }
                   1073:                        }
                   1074:                }
                   1075:                if (!sig_seen) {
                   1076:                        error("KRL not signed with any trusted key");
                   1077:                        goto out;
                   1078:                }
                   1079:        }
                   1080:
                   1081:        *krlp = krl;
                   1082:        ret = 0;
                   1083:  out:
                   1084:        if (ret != 0)
                   1085:                ssh_krl_free(krl);
                   1086:        for (i = 0; i < nca_used; i++) {
                   1087:                if (ca_used[i] != NULL)
                   1088:                        key_free(ca_used[i]);
                   1089:        }
                   1090:        free(ca_used);
                   1091:        if (key != NULL)
                   1092:                key_free(key);
                   1093:        buffer_free(&copy);
                   1094:        buffer_free(&sect);
                   1095:        return ret;
                   1096: }
                   1097:
                   1098: /* Checks whether a given key/cert is revoked. Does not check its CA */
                   1099: static int
                   1100: is_key_revoked(struct ssh_krl *krl, const Key *key)
                   1101: {
                   1102:        struct revoked_blob rb, *erb;
                   1103:        struct revoked_serial rs, *ers;
                   1104:        struct revoked_key_id rki, *erki;
                   1105:        struct revoked_certs *rc;
                   1106:
                   1107:        /* Check explicitly revoked hashes first */
                   1108:        bzero(&rb, sizeof(rb));
                   1109:        if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL)
                   1110:                return -1;
                   1111:        erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
                   1112:        free(rb.blob);
                   1113:        if (erb != NULL) {
                   1114:                debug("%s: revoked by key SHA1", __func__);
                   1115:                return -1;
                   1116:        }
                   1117:
                   1118:        /* Next, explicit keys */
                   1119:        bzero(&rb, sizeof(rb));
                   1120:        if (plain_key_blob(key, &rb.blob, &rb.len) != 0)
                   1121:                return -1;
                   1122:        erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
                   1123:        free(rb.blob);
                   1124:        if (erb != NULL) {
                   1125:                debug("%s: revoked by explicit key", __func__);
                   1126:                return -1;
                   1127:        }
                   1128:
                   1129:        if (!key_is_cert(key))
                   1130:                return 0;
                   1131:
                   1132:        /* Check cert revocation */
                   1133:        if (revoked_certs_for_ca_key(krl, key->cert->signature_key,
                   1134:            &rc, 0) != 0)
                   1135:                return -1;
                   1136:        if (rc == NULL)
                   1137:                return 0; /* No entry for this CA */
                   1138:
                   1139:        /* Check revocation by cert key ID */
                   1140:        bzero(&rki, sizeof(rki));
                   1141:        rki.key_id = key->cert->key_id;
                   1142:        erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
                   1143:        if (erki != NULL) {
                   1144:                debug("%s: revoked by key ID", __func__);
                   1145:                return -1;
                   1146:        }
                   1147:
1.8       djm      1148:        /*
                   1149:         * Legacy cert formats lack serial numbers. Zero serials numbers
                   1150:         * are ignored (it's the default when the CA doesn't specify one).
                   1151:         */
                   1152:        if (key_cert_is_legacy(key) || key->cert->serial == 0)
1.1       djm      1153:                return 0;
                   1154:
                   1155:        bzero(&rs, sizeof(rs));
                   1156:        rs.lo = rs.hi = key->cert->serial;
                   1157:        ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
                   1158:        if (ers != NULL) {
                   1159:                KRL_DBG(("%s: %llu matched %llu:%llu", __func__,
                   1160:                    key->cert->serial, ers->lo, ers->hi));
                   1161:                debug("%s: revoked by serial", __func__);
                   1162:                return -1;
                   1163:        }
                   1164:        KRL_DBG(("%s: %llu no match", __func__, key->cert->serial));
                   1165:
                   1166:        return 0;
                   1167: }
                   1168:
                   1169: int
                   1170: ssh_krl_check_key(struct ssh_krl *krl, const Key *key)
                   1171: {
                   1172:        int r;
                   1173:
                   1174:        debug2("%s: checking key", __func__);
                   1175:        if ((r = is_key_revoked(krl, key)) != 0)
                   1176:                return r;
                   1177:        if (key_is_cert(key)) {
                   1178:                debug2("%s: checking CA key", __func__);
                   1179:                if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0)
                   1180:                        return r;
                   1181:        }
                   1182:        debug3("%s: key okay", __func__);
                   1183:        return 0;
                   1184: }
                   1185:
                   1186: /* Returns 0 on success, -1 on error or key revoked, -2 if path is not a KRL */
                   1187: int
                   1188: ssh_krl_file_contains_key(const char *path, const Key *key)
                   1189: {
                   1190:        Buffer krlbuf;
                   1191:        struct ssh_krl *krl;
                   1192:        int revoked, fd;
                   1193:
                   1194:        if (path == NULL)
                   1195:                return 0;
                   1196:
                   1197:        if ((fd = open(path, O_RDONLY)) == -1) {
                   1198:                error("open %s: %s", path, strerror(errno));
                   1199:                error("Revoked keys file not accessible - refusing public key "
                   1200:                    "authentication");
                   1201:                return -1;
                   1202:        }
                   1203:        buffer_init(&krlbuf);
                   1204:        if (!key_load_file(fd, path, &krlbuf)) {
                   1205:                close(fd);
                   1206:                buffer_free(&krlbuf);
                   1207:                error("Revoked keys file not readable - refusing public key "
                   1208:                    "authentication");
                   1209:                return -1;
                   1210:        }
                   1211:        close(fd);
                   1212:        if (ssh_krl_from_blob(&krlbuf, &krl, NULL, 0) != 0) {
                   1213:                buffer_free(&krlbuf);
                   1214:                error("Invalid KRL, refusing public key "
                   1215:                    "authentication");
                   1216:                return -1;
                   1217:        }
                   1218:        buffer_free(&krlbuf);
                   1219:        if (krl == NULL) {
                   1220:                debug3("%s: %s is not a KRL file", __func__, path);
                   1221:                return -2;
                   1222:        }
                   1223:        debug2("%s: checking KRL %s", __func__, path);
                   1224:        revoked = ssh_krl_check_key(krl, key) != 0;
                   1225:        ssh_krl_free(krl);
                   1226:        return revoked ? -1 : 0;
                   1227: }