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