Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / ntp / dist / libntp / authreadkeys.c
blobd8301b5503f4651b8bcd01a38ae18e49082a9436
1 /* $NetBSD$ */
3 /*
4 * authreadkeys.c - routines to support the reading of the key file
5 */
6 #include <config.h>
7 #include <stdio.h>
8 #include <ctype.h>
10 #include "ntp_fp.h"
11 #include "ntp.h"
12 #include "ntp_syslog.h"
13 #include "ntp_stdlib.h"
15 #ifdef OPENSSL
16 #include "openssl/objects.h"
17 #endif /* OPENSSL */
19 /* Forwards */
20 static char *nexttok (char **);
23 * nexttok - basic internal tokenizing routine
25 static char *
26 nexttok(
27 char **str
30 register char *cp;
31 char *starttok;
33 cp = *str;
36 * Space past white space
38 while (*cp == ' ' || *cp == '\t')
39 cp++;
42 * Save this and space to end of token
44 starttok = cp;
45 while (*cp != '\0' && *cp != '\n' && *cp != ' '
46 && *cp != '\t' && *cp != '#')
47 cp++;
50 * If token length is zero return an error, else set end of
51 * token to zero and return start.
53 if (starttok == cp)
54 return (NULL);
56 if (*cp == ' ' || *cp == '\t')
57 *cp++ = '\0';
58 else
59 *cp = '\0';
61 *str = cp;
62 return starttok;
67 * authreadkeys - (re)read keys from a file.
69 int
70 authreadkeys(
71 const char *file
74 FILE *fp;
75 char *line;
76 char *token;
77 keyid_t keyno;
78 int keytype;
79 char buf[512]; /* lots of room for line */
80 u_char keystr[20];
81 int len;
82 int j;
85 * Open file. Complain and return if it can't be opened.
87 fp = fopen(file, "r");
88 if (fp == NULL) {
89 msyslog(LOG_ERR, "authreadkeys: file %s: %m",
90 file);
91 return (0);
93 INIT_SSL();
96 * Remove all existing keys
98 auth_delkeys();
101 * Now read lines from the file, looking for key entries
103 while ((line = fgets(buf, sizeof buf, fp)) != NULL) {
104 token = nexttok(&line);
105 if (token == NULL)
106 continue;
109 * First is key number. See if it is okay.
111 keyno = atoi(token);
112 if (keyno == 0) {
113 msyslog(LOG_ERR,
114 "authreadkeys: cannot change key %s", token);
115 continue;
118 if (keyno > NTP_MAXKEY) {
119 msyslog(LOG_ERR,
120 "authreadkeys: key %s > %d reserved for Autokey",
121 token, NTP_MAXKEY);
122 continue;
126 * Next is keytype. See if that is all right.
128 token = nexttok(&line);
129 if (token == NULL) {
130 msyslog(LOG_ERR,
131 "authreadkeys: no key type for key %d", keyno);
132 continue;
134 #ifdef OPENSSL
136 * The key type is the NID used by the message digest
137 * algorithm. There are a number of inconsistencies in
138 * the OpenSSL database. We attempt to discover them
139 * here and prevent use of inconsistent data later.
141 keytype = keytype_from_text(token, NULL);
142 if (keytype == 0) {
143 msyslog(LOG_ERR,
144 "authreadkeys: invalid type for key %d", keyno);
145 continue;
147 if (EVP_get_digestbynid(keytype) == NULL) {
148 msyslog(LOG_ERR,
149 "authreadkeys: no algorithm for key %d", keyno);
150 continue;
152 #else /* OPENSSL */
155 * The key type is unused, but is required to be 'M' or
156 * 'm' for compatibility.
158 if (!(*token == 'M' || *token == 'm')) {
159 msyslog(LOG_ERR,
160 "authreadkeys: invalid type for key %d", keyno);
161 continue;
163 keytype = KEY_TYPE_MD5;
164 #endif /* OPENSSL */
167 * Finally, get key and insert it. If it is longer than 20
168 * characters, it is a binary string encoded in hex;
169 * otherwise, it is a text string of printable ASCII
170 * characters.
172 token = nexttok(&line);
173 if (token == NULL) {
174 msyslog(LOG_ERR,
175 "authreadkeys: no key for key %d", keyno);
176 continue;
178 len = strlen(token);
179 if (len <= 20) {
180 MD5auth_setkey(keyno, keytype, (u_char *)token, len);
181 } else {
182 char hex[] = "0123456789abcdef";
183 u_char temp;
184 char *ptr;
185 int jlim;
187 jlim = min(len, 2 * sizeof(keystr));
188 for (j = 0; j < jlim; j++) {
189 ptr = strchr(hex, tolower(token[j]));
190 if (ptr == NULL) {
191 msyslog(LOG_ERR,
192 "authreadkeys: invalid hex digit for key %d", keyno);
193 continue;
195 temp = (u_char)(ptr - hex);
196 if (j & 1)
197 keystr[j / 2] |= temp;
198 else
199 keystr[j / 2] = temp << 4;
201 MD5auth_setkey(keyno, keytype, keystr, jlim / 2);
204 fclose(fp);
205 return (1);