File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / libntp / authreadkeys.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:  * authreadkeys.c - routines to support the reading of the key file
    3:  */
    4: #include <config.h>
    5: #include <stdio.h>
    6: #include <ctype.h>
    7: 
    8: #include "ntp_fp.h"
    9: #include "ntp.h"
   10: #include "ntp_syslog.h"
   11: #include "ntp_stdlib.h"
   12: 
   13: #ifdef OPENSSL
   14: #include "openssl/objects.h"
   15: #endif /* OPENSSL */
   16: 
   17: /* Forwards */
   18: static char *nexttok (char **);
   19: 
   20: /*
   21:  * nexttok - basic internal tokenizing routine
   22:  */
   23: static char *
   24: nexttok(
   25: 	char	**str
   26: 	)
   27: {
   28: 	register char *cp;
   29: 	char *starttok;
   30: 
   31: 	cp = *str;
   32: 
   33: 	/*
   34: 	 * Space past white space
   35: 	 */
   36: 	while (*cp == ' ' || *cp == '\t')
   37: 	    cp++;
   38: 	
   39: 	/*
   40: 	 * Save this and space to end of token
   41: 	 */
   42: 	starttok = cp;
   43: 	while (*cp != '\0' && *cp != '\n' && *cp != ' '
   44: 	       && *cp != '\t' && *cp != '#')
   45: 	    cp++;
   46: 	
   47: 	/*
   48: 	 * If token length is zero return an error, else set end of
   49: 	 * token to zero and return start.
   50: 	 */
   51: 	if (starttok == cp)
   52: 	    return (NULL);
   53: 	
   54: 	if (*cp == ' ' || *cp == '\t')
   55: 	    *cp++ = '\0';
   56: 	else
   57: 	    *cp = '\0';
   58: 	
   59: 	*str = cp;
   60: 	return starttok;
   61: }
   62: 
   63: 
   64: /*
   65:  * authreadkeys - (re)read keys from a file.
   66:  */
   67: int
   68: authreadkeys(
   69: 	const char *file
   70: 	)
   71: {
   72: 	FILE	*fp;
   73: 	char	*line;
   74: 	char	*token;
   75: 	keyid_t	keyno;
   76: 	int	keytype;
   77: 	char	buf[512];		/* lots of room for line */
   78: 	u_char	keystr[20];
   79: 	int	len;
   80: 	int	j;
   81: 
   82: 	/*
   83: 	 * Open file.  Complain and return if it can't be opened.
   84: 	 */
   85: 	fp = fopen(file, "r");
   86: 	if (fp == NULL) {
   87: 		msyslog(LOG_ERR, "authreadkeys: file %s: %m",
   88: 		    file);
   89: 		return (0);
   90: 	}
   91: 	INIT_SSL();
   92: 
   93: 	/*
   94: 	 * Remove all existing keys
   95: 	 */
   96: 	auth_delkeys();
   97: 
   98: 	/*
   99: 	 * Now read lines from the file, looking for key entries
  100: 	 */
  101: 	while ((line = fgets(buf, sizeof buf, fp)) != NULL) {
  102: 		token = nexttok(&line);
  103: 		if (token == NULL)
  104: 			continue;
  105: 		
  106: 		/*
  107: 		 * First is key number.  See if it is okay.
  108: 		 */
  109: 		keyno = atoi(token);
  110: 		if (keyno == 0) {
  111: 			msyslog(LOG_ERR,
  112: 			    "authreadkeys: cannot change key %s", token);
  113: 			continue;
  114: 		}
  115: 
  116: 		if (keyno > NTP_MAXKEY) {
  117: 			msyslog(LOG_ERR,
  118: 			    "authreadkeys: key %s > %d reserved for Autokey",
  119: 			    token, NTP_MAXKEY);
  120: 			continue;
  121: 		}
  122: 
  123: 		/*
  124: 		 * Next is keytype. See if that is all right.
  125: 		 */
  126: 		token = nexttok(&line);
  127: 		if (token == NULL) {
  128: 			msyslog(LOG_ERR,
  129: 			    "authreadkeys: no key type for key %d", keyno);
  130: 			continue;
  131: 		}
  132: #ifdef OPENSSL
  133: 		/*
  134: 		 * The key type is the NID used by the message digest 
  135: 		 * algorithm. There are a number of inconsistencies in
  136: 		 * the OpenSSL database. We attempt to discover them
  137: 		 * here and prevent use of inconsistent data later.
  138: 		 */
  139: 		keytype = keytype_from_text(token, NULL);
  140: 		if (keytype == 0) {
  141: 			msyslog(LOG_ERR,
  142: 			    "authreadkeys: invalid type for key %d", keyno);
  143: 			continue;
  144: 		}
  145: 		if (EVP_get_digestbynid(keytype) == NULL) {
  146: 			msyslog(LOG_ERR,
  147: 			    "authreadkeys: no algorithm for key %d", keyno);
  148: 			continue;
  149: 		}
  150: #else /* OPENSSL */
  151: 
  152: 		/*
  153: 		 * The key type is unused, but is required to be 'M' or
  154: 		 * 'm' for compatibility.
  155: 		 */
  156: 		if (!(*token == 'M' || *token == 'm')) {
  157: 			msyslog(LOG_ERR,
  158: 			    "authreadkeys: invalid type for key %d", keyno);
  159: 			continue;
  160: 		}
  161: 		keytype = KEY_TYPE_MD5;
  162: #endif /* OPENSSL */
  163: 
  164: 		/*
  165: 		 * Finally, get key and insert it. If it is longer than 20
  166: 		 * characters, it is a binary string encoded in hex;
  167: 		 * otherwise, it is a text string of printable ASCII
  168: 		 * characters.
  169: 		 */
  170: 		token = nexttok(&line);
  171: 		if (token == NULL) {
  172: 			msyslog(LOG_ERR,
  173: 			    "authreadkeys: no key for key %d", keyno);
  174: 			continue;
  175: 		}
  176: 		len = strlen(token);
  177: 		if (len <= 20) {
  178: 			MD5auth_setkey(keyno, keytype, (u_char *)token, len);
  179: 		} else {
  180: 			char	hex[] = "0123456789abcdef";
  181: 			u_char	temp;
  182: 			char	*ptr;
  183: 			int	jlim;
  184: 
  185: 			jlim = min(len, 2 * sizeof(keystr));
  186: 			for (j = 0; j < jlim; j++) {
  187: 				ptr = strchr(hex, tolower(token[j]));
  188: 				if (ptr == NULL) {
  189: 					msyslog(LOG_ERR,
  190: 					    "authreadkeys: invalid hex digit for key %d", keyno);
  191: 					continue;
  192: 				}
  193: 				temp = (u_char)(ptr - hex);
  194: 				if (j & 1)
  195: 					keystr[j / 2] |= temp;
  196: 				else
  197: 					keystr[j / 2] = temp << 4;
  198: 			}
  199: 			MD5auth_setkey(keyno, keytype, keystr, jlim / 2);
  200: 		}
  201: 	}
  202: 	fclose(fp);
  203: 	return (1);
  204: }

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