File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / libntp / authkeys.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 5 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>