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 */ 18static char *nexttok (char **); 19 20/* 21 * nexttok - basic internal tokenizing routine 22 */ 23static char * 24nexttok( 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 */ 67int 68authreadkeys( 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} 205