Annotation of embedaddon/ntp/libntp/authkeys.c, revision 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>