xref: /freebsd/contrib/ntp/libntp/authreadkeys.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
1 /*
2  * authreadkeys.c - routines to support the reading of the key file
3  */
4 #include <stdio.h>
5 #include <ctype.h>
6 
7 #include "ntp_fp.h"
8 #include "ntp.h"
9 #include "ntp_stdlib.h"
10 #include "ntp_syslog.h"
11 
12 #ifdef	DES
13 /*
14  * Types of ascii representations for keys.  "Standard" means a 64 bit
15  * hex number in NBS format, i.e. with the low order bit of each byte
16  * a parity bit.  "NTP" means a 64 bit key in NTP format, with the
17  * high order bit of each byte a parity bit.  "Ascii" means a 1-to-8
18  * character string whose ascii representation is used as the key.
19  */
20 #define	KEY_TYPE_STD	1
21 #define	KEY_TYPE_NTP	2
22 #define	KEY_TYPE_ASCII	3
23 #endif
24 
25 #ifdef	MD5
26 /*
27  *  Arbitrary long string of ASCII characters.
28  */
29 #define	KEY_TYPE_MD5	4
30 #endif
31 
32 /* Forwards */
33 static char *nexttok P((char **));
34 
35 /*
36  * nexttok - basic internal tokenizing routine
37  */
38 static char *
39 nexttok(
40 	char **str
41 	)
42 {
43 	register char *cp;
44 	char *starttok;
45 
46 	cp = *str;
47 
48 	/*
49 	 * Space past white space
50 	 */
51 	while (*cp == ' ' || *cp == '\t')
52 	    cp++;
53 
54 	/*
55 	 * Save this and space to end of token
56 	 */
57 	starttok = cp;
58 	while (*cp != '\0' && *cp != '\n' && *cp != ' '
59 	       && *cp != '\t' && *cp != '#')
60 	    cp++;
61 
62 	/*
63 	 * If token length is zero return an error, else set end of
64 	 * token to zero and return start.
65 	 */
66 	if (starttok == cp)
67 	    return 0;
68 
69 	if (*cp == ' ' || *cp == '\t')
70 	    *cp++ = '\0';
71 	else
72 	    *cp = '\0';
73 
74 	*str = cp;
75 	return starttok;
76 }
77 
78 
79 /*
80  * authreadkeys - (re)read keys from a file.
81  */
82 int
83 authreadkeys(
84 	const char *file
85 	)
86 {
87 	FILE *fp;
88 	char *line;
89 	char *token;
90 	u_long keyno;
91 	int keytype;
92 	char buf[512];		/* lots of room for line */
93 
94 	/*
95 	 * Open file.  Complain and return if it can't be opened.
96 	 */
97 	fp = fopen(file, "r");
98 	if (fp == NULL) {
99 		msyslog(LOG_ERR, "can't open key file %s: %m", file);
100 		return 0;
101 	}
102 
103 	/*
104 	 * Remove all existing keys
105 	 */
106 	auth_delkeys();
107 
108 	/*
109 	 * Now read lines from the file, looking for key entries
110 	 */
111 	while ((line = fgets(buf, sizeof buf, fp)) != NULL) {
112 		token = nexttok(&line);
113 		if (token == 0)
114 		    continue;
115 
116 		/*
117 		 * First is key number.  See if it is okay.
118 		 */
119 		keyno = atoi(token);
120 		if (keyno == 0) {
121 			msyslog(LOG_ERR,
122 				"cannot change keyid 0, key entry `%s' ignored",
123 				token);
124 			continue;
125 		}
126 
127 		if (keyno > NTP_MAXKEY) {
128 			msyslog(LOG_ERR,
129 				"keyid's > %d reserved for autokey, key entry `%s' ignored",
130 				NTP_MAXKEY, token);
131 			continue;
132 		}
133 
134 		/*
135 		 * Next is keytype.  See if that is all right.
136 		 */
137 		token = nexttok(&line);
138 		if (token == 0) {
139 			msyslog(LOG_ERR,
140 				"no key type for key number %ld, entry ignored",
141 				keyno);
142 			continue;
143 		}
144 		switch (*token) {
145 #ifdef	DES
146 		    case 'S':
147 		    case 's':
148 			keytype = KEY_TYPE_STD; break;
149 
150 		    case 'N':
151 		    case 'n':
152 			keytype = KEY_TYPE_NTP; break;
153 
154 		    case 'A':
155 		    case 'a':
156 			keytype = KEY_TYPE_ASCII; break;
157 #endif
158 #ifdef	MD5
159 		    case 'M':
160 		    case 'm':
161 			keytype = KEY_TYPE_MD5; break;
162 #endif
163 		    default:
164 			msyslog(LOG_ERR,
165 				"invalid key type for key number %ld, entry ignored",
166 				keyno);
167 			continue;
168 		}
169 
170 		/*
171 		 * Finally, get key and insert it
172 		 */
173 		token = nexttok(&line);
174 		if (token == 0) {
175 			msyslog(LOG_ERR,
176 				"no key for number %ld entry, entry ignored",
177 				keyno);
178 		} else {
179 			switch(keytype) {
180 #ifdef	DES
181 			    case KEY_TYPE_STD:
182 			    case KEY_TYPE_NTP:
183 			    case KEY_TYPE_ASCII:
184 				if (!authusekey(keyno, keytype,
185 						(u_char *)token))
186 				    msyslog(LOG_ERR,
187 					    "format/parity error for DES key %ld, not used",
188 					    keyno);
189 				break;
190 #endif
191 #ifdef	MD5
192 			    case KEY_TYPE_MD5:
193 				if (!authusekey(keyno, keytype,
194 						(u_char *)token))
195 				    msyslog(LOG_ERR,
196 					    "format/parity error for MD5 key %ld, not used",
197 					    keyno);
198 				break;
199 #endif
200 			}
201 		}
202 	}
203 	(void) fclose(fp);
204 	return 1;
205 }
206