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