154359Sroberto/*
254359Sroberto * authreadkeys.c - routines to support the reading of the key file
354359Sroberto */
454359Sroberto#include <stdio.h>
554359Sroberto#include <ctype.h>
654359Sroberto
754359Sroberto#include "ntp_fp.h"
854359Sroberto#include "ntp.h"
982498Sroberto#include "ntp_syslog.h"
1054359Sroberto#include "ntp_stdlib.h"
1154359Sroberto
1254359Sroberto/*
1354359Sroberto *  Arbitrary long string of ASCII characters.
1454359Sroberto */
1554359Sroberto#define	KEY_TYPE_MD5	4
1654359Sroberto
1754359Sroberto/* Forwards */
1854359Srobertostatic char *nexttok P((char **));
1954359Sroberto
2054359Sroberto/*
2154359Sroberto * nexttok - basic internal tokenizing routine
2254359Sroberto */
2354359Srobertostatic char *
2454359Srobertonexttok(
2554359Sroberto	char **str
2654359Sroberto	)
2754359Sroberto{
2854359Sroberto	register char *cp;
2954359Sroberto	char *starttok;
3054359Sroberto
3154359Sroberto	cp = *str;
3254359Sroberto
3354359Sroberto	/*
3454359Sroberto	 * Space past white space
3554359Sroberto	 */
3654359Sroberto	while (*cp == ' ' || *cp == '\t')
3754359Sroberto	    cp++;
3854359Sroberto
3954359Sroberto	/*
4054359Sroberto	 * Save this and space to end of token
4154359Sroberto	 */
4254359Sroberto	starttok = cp;
4354359Sroberto	while (*cp != '\0' && *cp != '\n' && *cp != ' '
4454359Sroberto	       && *cp != '\t' && *cp != '#')
4554359Sroberto	    cp++;
4654359Sroberto
4754359Sroberto	/*
4854359Sroberto	 * If token length is zero return an error, else set end of
4954359Sroberto	 * token to zero and return start.
5054359Sroberto	 */
5154359Sroberto	if (starttok == cp)
5254359Sroberto	    return 0;
5354359Sroberto
5454359Sroberto	if (*cp == ' ' || *cp == '\t')
5554359Sroberto	    *cp++ = '\0';
5654359Sroberto	else
5754359Sroberto	    *cp = '\0';
5854359Sroberto
5954359Sroberto	*str = cp;
6054359Sroberto	return starttok;
6154359Sroberto}
6254359Sroberto
6354359Sroberto
6454359Sroberto/*
6554359Sroberto * authreadkeys - (re)read keys from a file.
6654359Sroberto */
6754359Srobertoint
6854359Srobertoauthreadkeys(
6954359Sroberto	const char *file
7054359Sroberto	)
7154359Sroberto{
7254359Sroberto	FILE *fp;
7354359Sroberto	char *line;
7454359Sroberto	char *token;
7554359Sroberto	u_long keyno;
7654359Sroberto	int keytype;
7754359Sroberto	char buf[512];		/* lots of room for line */
7854359Sroberto
7954359Sroberto	/*
8054359Sroberto	 * Open file.  Complain and return if it can't be opened.
8154359Sroberto	 */
8254359Sroberto	fp = fopen(file, "r");
8354359Sroberto	if (fp == NULL) {
8454359Sroberto		msyslog(LOG_ERR, "can't open key file %s: %m", file);
8554359Sroberto		return 0;
8654359Sroberto	}
8754359Sroberto
8854359Sroberto	/*
8954359Sroberto	 * Remove all existing keys
9054359Sroberto	 */
9154359Sroberto	auth_delkeys();
9254359Sroberto
9354359Sroberto	/*
9454359Sroberto	 * Now read lines from the file, looking for key entries
9554359Sroberto	 */
9654359Sroberto	while ((line = fgets(buf, sizeof buf, fp)) != NULL) {
9754359Sroberto		token = nexttok(&line);
9854359Sroberto		if (token == 0)
9954359Sroberto		    continue;
10054359Sroberto
10154359Sroberto		/*
10254359Sroberto		 * First is key number.  See if it is okay.
10354359Sroberto		 */
10454359Sroberto		keyno = atoi(token);
10554359Sroberto		if (keyno == 0) {
10654359Sroberto			msyslog(LOG_ERR,
10754359Sroberto				"cannot change keyid 0, key entry `%s' ignored",
10854359Sroberto				token);
10954359Sroberto			continue;
11054359Sroberto		}
11154359Sroberto
11254359Sroberto		if (keyno > NTP_MAXKEY) {
11354359Sroberto			msyslog(LOG_ERR,
11454359Sroberto				"keyid's > %d reserved for autokey, key entry `%s' ignored",
11554359Sroberto				NTP_MAXKEY, token);
11654359Sroberto			continue;
11754359Sroberto		}
11854359Sroberto
11954359Sroberto		/*
12054359Sroberto		 * Next is keytype.  See if that is all right.
12154359Sroberto		 */
12254359Sroberto		token = nexttok(&line);
12354359Sroberto		if (token == 0) {
12454359Sroberto			msyslog(LOG_ERR,
12554359Sroberto				"no key type for key number %ld, entry ignored",
12654359Sroberto				keyno);
12754359Sroberto			continue;
12854359Sroberto		}
12954359Sroberto		switch (*token) {
13054359Sroberto		    case 'M':
13154359Sroberto		    case 'm':
13254359Sroberto			keytype = KEY_TYPE_MD5; break;
13354359Sroberto		    default:
13454359Sroberto			msyslog(LOG_ERR,
13554359Sroberto				"invalid key type for key number %ld, entry ignored",
13654359Sroberto				keyno);
13754359Sroberto			continue;
13854359Sroberto		}
13954359Sroberto
14054359Sroberto		/*
14154359Sroberto		 * Finally, get key and insert it
14254359Sroberto		 */
14354359Sroberto		token = nexttok(&line);
14454359Sroberto		if (token == 0) {
14554359Sroberto			msyslog(LOG_ERR,
14654359Sroberto				"no key for number %ld entry, entry ignored",
14754359Sroberto				keyno);
14854359Sroberto		} else {
14954359Sroberto			switch(keytype) {
15054359Sroberto			    case KEY_TYPE_MD5:
15154359Sroberto				if (!authusekey(keyno, keytype,
15254359Sroberto						(u_char *)token))
15354359Sroberto				    msyslog(LOG_ERR,
15454359Sroberto					    "format/parity error for MD5 key %ld, not used",
15554359Sroberto					    keyno);
15654359Sroberto				break;
15754359Sroberto			}
15854359Sroberto		}
15954359Sroberto	}
16054359Sroberto	(void) fclose(fp);
16154359Sroberto	return 1;
16254359Sroberto}
163