1 /* $NetBSD: authreadkeys.c,v 1.1.1.1 2009/12/13 16:54:59 kardel Exp $ */ 2 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> 9 10 #include "ntp_fp.h" 11 #include "ntp.h" 12 #include "ntp_syslog.h" 13 #include "ntp_stdlib.h" 14 15 #ifdef OPENSSL 16 #include "openssl/objects.h" 17 #endif /* OPENSSL */ 18 19 /* Forwards */ 20 static char *nexttok (char **); 21 22 /* 23 * nexttok - basic internal tokenizing routine 24 */ 25 static char * 26 nexttok( 27 char **str 28 ) 29 { 30 register char *cp; 31 char *starttok; 32 33 cp = *str; 34 35 /* 36 * Space past white space 37 */ 38 while (*cp == ' ' || *cp == '\t') 39 cp++; 40 41 /* 42 * Save this and space to end of token 43 */ 44 starttok = cp; 45 while (*cp != '\0' && *cp != '\n' && *cp != ' ' 46 && *cp != '\t' && *cp != '#') 47 cp++; 48 49 /* 50 * If token length is zero return an error, else set end of 51 * token to zero and return start. 52 */ 53 if (starttok == cp) 54 return (NULL); 55 56 if (*cp == ' ' || *cp == '\t') 57 *cp++ = '\0'; 58 else 59 *cp = '\0'; 60 61 *str = cp; 62 return starttok; 63 } 64 65 66 /* 67 * authreadkeys - (re)read keys from a file. 68 */ 69 int 70 authreadkeys( 71 const char *file 72 ) 73 { 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; 83 84 /* 85 * Open file. Complain and return if it can't be opened. 86 */ 87 fp = fopen(file, "r"); 88 if (fp == NULL) { 89 msyslog(LOG_ERR, "authreadkeys: file %s: %m", 90 file); 91 return (0); 92 } 93 INIT_SSL(); 94 95 /* 96 * Remove all existing keys 97 */ 98 auth_delkeys(); 99 100 /* 101 * Now read lines from the file, looking for key entries 102 */ 103 while ((line = fgets(buf, sizeof buf, fp)) != NULL) { 104 token = nexttok(&line); 105 if (token == NULL) 106 continue; 107 108 /* 109 * First is key number. See if it is okay. 110 */ 111 keyno = atoi(token); 112 if (keyno == 0) { 113 msyslog(LOG_ERR, 114 "authreadkeys: cannot change key %s", token); 115 continue; 116 } 117 118 if (keyno > NTP_MAXKEY) { 119 msyslog(LOG_ERR, 120 "authreadkeys: key %s > %d reserved for Autokey", 121 token, NTP_MAXKEY); 122 continue; 123 } 124 125 /* 126 * Next is keytype. See if that is all right. 127 */ 128 token = nexttok(&line); 129 if (token == NULL) { 130 msyslog(LOG_ERR, 131 "authreadkeys: no key type for key %d", keyno); 132 continue; 133 } 134 #ifdef OPENSSL 135 /* 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. 140 */ 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; 146 } 147 if (EVP_get_digestbynid(keytype) == NULL) { 148 msyslog(LOG_ERR, 149 "authreadkeys: no algorithm for key %d", keyno); 150 continue; 151 } 152 #else /* OPENSSL */ 153 154 /* 155 * The key type is unused, but is required to be 'M' or 156 * 'm' for compatibility. 157 */ 158 if (!(*token == 'M' || *token == 'm')) { 159 msyslog(LOG_ERR, 160 "authreadkeys: invalid type for key %d", keyno); 161 continue; 162 } 163 keytype = KEY_TYPE_MD5; 164 #endif /* OPENSSL */ 165 166 /* 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. 171 */ 172 token = nexttok(&line); 173 if (token == NULL) { 174 msyslog(LOG_ERR, 175 "authreadkeys: no key for key %d", keyno); 176 continue; 177 } 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; 186 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; 194 } 195 temp = (u_char)(ptr - hex); 196 if (j & 1) 197 keystr[j / 2] |= temp; 198 else 199 keystr[j / 2] = temp << 4; 200 } 201 MD5auth_setkey(keyno, keytype, keystr, jlim / 2); 202 } 203 } 204 fclose(fp); 205 return (1); 206 } 207