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>