Annotation of embedaddon/ntp/libntp/authkeys.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * authkeys.c - routines to manage the storage of authentication keys
                      3:  */
                      4: #ifdef HAVE_CONFIG_H
                      5: # include <config.h>
                      6: #endif
                      7: 
                      8: #include <stdio.h>
                      9: 
                     10: #include "ntp_types.h"
                     11: #include "ntp_fp.h"
                     12: #include "ntp.h"
                     13: #include "ntpd.h"
                     14: #include "ntp_string.h"
                     15: #include "ntp_malloc.h"
                     16: #include "ntp_stdlib.h"
                     17: 
                     18: /*
                     19:  * Structure to store keys in in the hash table.
                     20:  */
                     21: struct savekey {
                     22:        struct savekey *next;
                     23:        union {
                     24:                u_char MD5_key[64];     /* for keys up to to 512 bits */
                     25:        } k;
                     26:        keyid_t keyid;          /* key identifier */
                     27:        int     type;           /* key type */
                     28:        u_short flags;          /* flags that wave */
                     29:        u_long lifetime;        /* remaining lifetime */
                     30:        int keylen;             /* key length */
                     31: };
                     32: 
                     33: #define        KEY_TRUSTED     0x001   /* this key is trusted */
                     34: 
                     35: /*
                     36:  * The hash table. This is indexed by the low order bits of the
                     37:  * keyid. We make this fairly big for potentially busy servers.
                     38:  */
                     39: #define        HASHSIZE        64
                     40: #define        HASHMASK        ((HASHSIZE)-1)
                     41: #define        KEYHASH(keyid)  ((keyid) & HASHMASK)
                     42: 
                     43: struct savekey *key_hash[HASHSIZE];
                     44: 
                     45: u_long authkeynotfound;                /* keys not found */
                     46: u_long authkeylookups;         /* calls to lookup keys */
                     47: u_long authnumkeys;            /* number of active keys */
                     48: u_long authkeyexpired;         /* key lifetime expirations */
                     49: u_long authkeyuncached;                /* cache misses */
                     50: u_long authnokey;              /* calls to encrypt with no key */
                     51: u_long authencryptions;                /* calls to encrypt */
                     52: u_long authdecryptions;                /* calls to decrypt */
                     53: 
                     54: /*
                     55:  * Storage for free key structures.  We malloc() such things but
                     56:  * never free them.
                     57:  */
                     58: struct savekey *authfreekeys;
                     59: int authnumfreekeys;
                     60: 
                     61: #define        MEMINC  12              /* number of new free ones to get */
                     62: 
                     63: /*
                     64:  * The key cache. We cache the last key we looked at here.
                     65:  */
                     66: keyid_t        cache_keyid;            /* key identifier */
                     67: u_char *cache_key;             /* key pointer */
                     68: u_int  cache_keylen;           /* key length */
                     69: int    cache_type;             /* key type */
                     70: u_short cache_flags;           /* flags that wave */
                     71: 
                     72: 
                     73: /*
                     74:  * init_auth - initialize internal data
                     75:  */
                     76: void
                     77: init_auth(void)
                     78: {
                     79:        /*
                     80:         * Initialize hash table and free list
                     81:         */
                     82:        memset((char *)key_hash, 0, sizeof key_hash);
                     83: }
                     84: 
                     85: 
                     86: /*
                     87:  * auth_findkey - find a key in the hash table
                     88:  */
                     89: struct savekey *
                     90: auth_findkey(
                     91:        keyid_t keyno
                     92:        )
                     93: {
                     94:        struct savekey *sk;
                     95: 
                     96:        sk = key_hash[KEYHASH(keyno)];
                     97:        while (sk != 0) {
                     98:                if (keyno == sk->keyid)
                     99:                        return (sk);
                    100: 
                    101:                sk = sk->next;
                    102:        }
                    103:        return (0);
                    104: }
                    105: 
                    106: 
                    107: /*
                    108:  * auth_havekey - return one if the key is known
                    109:  */
                    110: int
                    111: auth_havekey(
                    112:        keyid_t keyno
                    113:        )
                    114: {
                    115:        struct savekey *sk;
                    116: 
                    117:        if (keyno == 0 || (keyno == cache_keyid))
                    118:                return (1);
                    119: 
                    120:        sk = key_hash[KEYHASH(keyno)];
                    121:        while (sk != 0) {
                    122:                if (keyno == sk->keyid)
                    123:                        return (1);
                    124: 
                    125:                sk = sk->next;
                    126:        }
                    127:        return (0);
                    128: }
                    129: 
                    130: 
                    131: /*
                    132:  * authhavekey - return one and cache the key, if known and trusted.
                    133:  */
                    134: int
                    135: authhavekey(
                    136:        keyid_t keyno
                    137:        )
                    138: {
                    139:        struct savekey *sk;
                    140: 
                    141:        authkeylookups++;
                    142:        if (keyno == 0 || keyno == cache_keyid)
                    143:                return (1);
                    144: 
                    145:        /*
                    146:         * Seach the bin for the key. If found and the key type
                    147:         * is zero, somebody marked it trusted without specifying
                    148:         * a key or key type. In this case consider the key missing.
                    149:         */
                    150:        authkeyuncached++;
                    151:        sk = key_hash[KEYHASH(keyno)];
                    152:        while (sk != NULL) {
                    153:                if (keyno == sk->keyid) {
                    154:                        if (sk->type == 0) {
                    155:                                authkeynotfound++;
                    156:                                return (0);
                    157:                        }
                    158:                        break;
                    159:                }
                    160:                sk = sk->next;
                    161:        }
                    162: 
                    163:        /*
                    164:         * If the key is not found, or if it is found but not trusted,
                    165:         * the key is not considered found.
                    166:         */
                    167:        if (sk == NULL) {
                    168:                authkeynotfound++;
                    169:                return (0);
                    170: 
                    171:        }
                    172:        if (!(sk->flags & KEY_TRUSTED)) {
                    173:                authnokey++;
                    174:                return (0);
                    175:        }
                    176: 
                    177:        /*
                    178:         * The key is found and trusted. Initialize the key cache.
                    179:         */
                    180:        cache_keyid = sk->keyid;
                    181:        cache_type = sk->type;
                    182:        cache_flags = sk->flags;
                    183:        cache_key = sk->k.MD5_key;
                    184:        cache_keylen = sk->keylen;
                    185:        return (1);
                    186: }
                    187: 
                    188: 
                    189: /*
                    190:  * auth_moremem - get some more free key structures
                    191:  */
                    192: int
                    193: auth_moremem(void)
                    194: {
                    195:        struct savekey *sk;
                    196:        int i;
                    197: 
                    198:        sk = (struct savekey *)calloc(MEMINC, sizeof(struct savekey));
                    199:        if (sk == 0)
                    200:                return (0);
                    201:        
                    202:        for (i = MEMINC; i > 0; i--) {
                    203:                sk->next = authfreekeys;
                    204:                authfreekeys = sk++;
                    205:        }
                    206:        authnumfreekeys += MEMINC;
                    207:        return (authnumfreekeys);
                    208: }
                    209: 
                    210: 
                    211: /*
                    212:  * authtrust - declare a key to be trusted/untrusted
                    213:  */
                    214: void
                    215: authtrust(
                    216:        keyid_t keyno,
                    217:        u_long trust
                    218:        )
                    219: {
                    220:        struct savekey *sk;
                    221: 
                    222:        /*
                    223:         * Search bin for key; if it does not exist and is untrusted,
                    224:         * forget it.
                    225:         */
                    226:        sk = key_hash[KEYHASH(keyno)];
                    227:        while (sk != 0) {
                    228:                if (keyno == sk->keyid)
                    229:                    break;
                    230: 
                    231:                sk = sk->next;
                    232:        }
                    233:        if (sk == 0 && !trust)
                    234:                return;
                    235: 
                    236:        /*
                    237:         * There are two conditions remaining. Either it does not
                    238:         * exist and is to be trusted or it does exist and is or is
                    239:         * not to be trusted.
                    240:         */     
                    241:        if (sk != 0) {
                    242:                if (cache_keyid == keyno) {
                    243:                        cache_flags = 0;
                    244:                        cache_keyid = 0;
                    245:                }
                    246: 
                    247:                /*
                    248:                 * Key exists. If it is to be trusted, say so and
                    249:                 * update its lifetime. If not, return it to the
                    250:                 * free list.
                    251:                 */
                    252:                if (trust > 0) {
                    253:                        sk->flags |= KEY_TRUSTED;
                    254:                        if (trust > 1)
                    255:                                sk->lifetime = current_time + trust;
                    256:                        else
                    257:                                sk->lifetime = 0;
                    258:                        return;
                    259:                }
                    260:                sk->flags &= ~KEY_TRUSTED; {
                    261:                        struct savekey *skp;
                    262: 
                    263:                        skp = key_hash[KEYHASH(keyno)];
                    264:                        if (skp == sk) {
                    265:                                key_hash[KEYHASH(keyno)] = sk->next;
                    266:                        } else {
                    267:                                while (skp->next != sk)
                    268:                                    skp = skp->next;
                    269:                                skp->next = sk->next;
                    270:                        }
                    271:                        authnumkeys--;
                    272: 
                    273:                        sk->next = authfreekeys;
                    274:                        authfreekeys = sk;
                    275:                        authnumfreekeys++;
                    276:                }
                    277:                return;
                    278:        }
                    279: 
                    280:        /*
                    281:         * Here there is not key, but the key is to be trusted. There
                    282:         * seems to be a disconnect here. Here we allocate a new key,
                    283:         * but do not specify a key type, key or key length.
                    284:         */ 
                    285:        if (authnumfreekeys == 0)
                    286:            if (auth_moremem() == 0)
                    287:                return;
                    288: 
                    289:        sk = authfreekeys;
                    290:        authfreekeys = sk->next;
                    291:        authnumfreekeys--;
                    292:        sk->keyid = keyno;
                    293:        sk->type = 0;
                    294:        sk->keylen = 0;
                    295:        sk->flags = KEY_TRUSTED;
                    296:        sk->next = key_hash[KEYHASH(keyno)];
                    297:        key_hash[KEYHASH(keyno)] = sk;
                    298:        authnumkeys++;
                    299:        return;
                    300: }
                    301: 
                    302: 
                    303: /*
                    304:  * authistrusted - determine whether a key is trusted
                    305:  */
                    306: int
                    307: authistrusted(
                    308:        keyid_t keyno
                    309:        )
                    310: {
                    311:        struct savekey *sk;
                    312: 
                    313:        if (keyno == cache_keyid)
                    314:            return ((cache_flags & KEY_TRUSTED) != 0);
                    315: 
                    316:        authkeyuncached++;
                    317:        sk = key_hash[KEYHASH(keyno)];
                    318:        while (sk != 0) {
                    319:                if (keyno == sk->keyid)
                    320:                    break;
                    321:                sk = sk->next;
                    322:        }
                    323:        if (sk == 0) {
                    324:                authkeynotfound++;
                    325:                return (0);
                    326: 
                    327:        } else if (!(sk->flags & KEY_TRUSTED)) {
                    328:                authkeynotfound++;
                    329:                return (0);
                    330:        }
                    331:        return (1);
                    332: }
                    333: 
                    334: 
                    335: void
                    336: MD5auth_setkey(
                    337:        keyid_t keyno,
                    338:        int     keytype,
                    339:        const u_char *key,
                    340:        const int len
                    341:        )
                    342: {
                    343:        struct savekey *sk;
                    344:        
                    345:        /*
                    346:         * See if we already have the key.  If so just stick in the
                    347:         * new value.
                    348:         */
                    349:        sk = key_hash[KEYHASH(keyno)];
                    350:        while (sk != NULL) {
                    351:                if (keyno == sk->keyid) {
                    352:                        sk->type = keytype;
                    353:                        sk->keylen = min(len, sizeof(sk->k.MD5_key));
                    354: #ifndef DISABLE_BUG1243_FIX
                    355:                        memcpy(sk->k.MD5_key, key, sk->keylen);
                    356: #else
                    357:                        strncpy((char *)sk->k.MD5_key, (const char *)key,
                    358:                            sizeof(sk->k.MD5_key));
                    359: #endif
                    360:                        if (cache_keyid == keyno) {
                    361:                                cache_flags = 0;
                    362:                                cache_keyid = 0;
                    363:                        }
                    364:                        return;
                    365:                }
                    366:                sk = sk->next;
                    367:        }
                    368: 
                    369:        /*
                    370:         * Need to allocate new structure.  Do it.
                    371:         */
                    372:        if (0 == authnumfreekeys && !auth_moremem())
                    373:                return;
                    374: 
                    375:        sk = authfreekeys;
                    376:        authfreekeys = sk->next;
                    377:        authnumfreekeys--;
                    378: 
                    379:        sk->keyid = keyno;
                    380:        sk->type = keytype;
                    381:        sk->flags = 0;
                    382:        sk->lifetime = 0;
                    383:        sk->keylen = min(len, sizeof(sk->k.MD5_key));
                    384: #ifndef DISABLE_BUG1243_FIX
                    385:        memcpy(sk->k.MD5_key, key, sk->keylen);
                    386: #else
                    387:        strncpy((char *)sk->k.MD5_key, (const char *)key,
                    388:            sizeof(sk->k.MD5_key));
                    389: #endif
                    390:        sk->next = key_hash[KEYHASH(keyno)];
                    391:        key_hash[KEYHASH(keyno)] = sk;
                    392: #ifdef DEBUG
                    393:        if (debug > 1) {
                    394:                char    hex[] = "0123456789abcdef";
                    395:                int     j;
                    396: 
                    397:                printf("auth_setkey: key %d type %d len %d ", sk->keyid,
                    398:                    sk->type, sk->keylen);
                    399:                for (j = 0; j < sk->keylen; j++)
                    400:                                printf("%c%c", hex[key[j] >> 4],
                    401:                                    hex[key[j] & 0xf]);
                    402:                printf("\n");
                    403:        }       
                    404: #endif
                    405:        authnumkeys++;
                    406: }
                    407: 
                    408: 
                    409: /*
                    410:  * auth_delkeys - delete all known keys, in preparation for rereading
                    411:  *               the keys file (presumably)
                    412:  */
                    413: void
                    414: auth_delkeys(void)
                    415: {
                    416:        struct savekey *sk;
                    417:        struct savekey **skp;
                    418:        int i;
                    419: 
                    420:        for (i = 0; i < HASHSIZE; i++) {
                    421:                skp = &(key_hash[i]);
                    422:                sk = key_hash[i];
                    423:                /*
                    424:                 * Leave autokey keys alone.
                    425:                 */
                    426:                while (sk != 0 && sk->keyid <= NTP_MAXKEY) {
                    427:                        /*
                    428:                         * Don't lose info as to which keys are trusted.
                    429:                         */
                    430:                        if (sk->flags & KEY_TRUSTED) {
                    431:                                skp = &(sk->next);
                    432:                                memset(&sk->k, 0, sizeof(sk->k));
                    433:                                sk->lifetime = 0;
                    434:                                sk->keylen = 0;
                    435:                                sk = sk->next;
                    436:                        } else {
                    437:                                *skp = sk->next;
                    438:                                authnumkeys--;
                    439:                                sk->next = authfreekeys;
                    440:                                authfreekeys = sk;
                    441:                                authnumfreekeys++;
                    442:                                sk = *skp;
                    443:                        }
                    444:                }
                    445:        }
                    446: }
                    447: 
                    448: /*
                    449:  * auth_agekeys - delete keys whose lifetimes have expired
                    450:  */
                    451: void
                    452: auth_agekeys(void)
                    453: {
                    454:        struct savekey *sk;
                    455:        struct savekey *skp;
                    456:        int i;
                    457: 
                    458:        for (i = 0; i < HASHSIZE; i++) {
                    459:                sk = skp = key_hash[i];
                    460:                while (sk != 0) {
                    461:                        skp = sk->next;
                    462:                        if (sk->lifetime > 0 && current_time >
                    463:                            sk->lifetime) {
                    464:                                authtrust(sk->keyid, 0);
                    465:                                authkeyexpired++;
                    466:                        }
                    467:                        sk = skp;
                    468:                }
                    469:        }
                    470: #ifdef DEBUG
                    471:        if (debug)
                    472:                printf("auth_agekeys: at %lu keys %lu expired %lu\n",
                    473:                    current_time, authnumkeys, authkeyexpired);
                    474: #endif
                    475: }
                    476: 
                    477: /*
                    478:  * authencrypt - generate message authenticator
                    479:  *
                    480:  * Returns length of authenticator field, zero if key not found.
                    481:  */
                    482: int
                    483: authencrypt(
                    484:        keyid_t keyno,
                    485:        u_int32 *pkt,
                    486:        int length
                    487:        )
                    488: {
                    489: 
                    490:        /*
                    491:         * A zero key identifier means the sender has not verified
                    492:         * the last message was correctly authenticated. The MAC
                    493:         * consists of a single word with value zero.
                    494:         */
                    495:        authencryptions++;
                    496:        pkt[length / 4] = htonl(keyno);
                    497:        if (keyno == 0) {
                    498:                return (4);
                    499:        }
                    500:        if (!authhavekey(keyno))
                    501:                return (0);
                    502: 
                    503:        return (MD5authencrypt(cache_type, cache_key, pkt, length));
                    504: }
                    505: 
                    506: /*
                    507:  * authdecrypt - verify message authenticator
                    508:  *
                    509:  * Returns one if authenticator valid, zero if invalid or key not found.
                    510:  */
                    511: int
                    512: authdecrypt(
                    513:        keyid_t keyno,
                    514:        u_int32 *pkt,
                    515:        int length,
                    516:        int size
                    517:        )
                    518: {
                    519: 
                    520:        /*
                    521:         * A zero key identifier means the sender has not verified
                    522:         * the last message was correctly authenticated. Nevertheless,
                    523:         * the authenticator itself is considered valid.
                    524:         */
                    525:        authdecryptions++;
                    526:        if (keyno == 0)
                    527:                return (0);
                    528: 
                    529:        if (!authhavekey(keyno) || size < 4)
                    530:                return (0);
                    531: 
                    532:        return (MD5authdecrypt(cache_type, cache_key, pkt, length,
                    533:           size));
                    534: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>