2 * files.c Read config files into memory.
8 static const char rcsid[] = "$Id$";
15 #include <netinet/in.h>
37 void pairlist_free(PAIR_LIST **pl)
41 for (p = *pl; p; p = next) {
42 if (p->name) free(p->name);
43 if (p->check) pairfree(p->check);
44 if (p->reply) pairfree(p->reply);
54 * If Password or Crypt-Password is set, but there is no
55 * Auth-Type, add one (kludge!).
57 static void auth_type_fixup(VALUE_PAIR *check)
64 * See if a password is present. Return right away
65 * if we see Auth-Type.
67 for (vp = check; vp; vp = vp->next) {
68 if (vp->attribute == PW_AUTHTYPE)
70 if (vp->attribute == PW_PASSWORD) {
72 n = PW_AUTHTYPE_LOCAL;
74 if (vp->attribute == PW_CRYPT_PASSWORD) {
76 n = PW_AUTHTYPE_CRYPT;
84 * Add an Auth-Type attribute.
85 * FIXME: put Auth-Type _first_ (doesn't matter now,
86 * might matter some day).
89 if ((vp = paircreate(PW_AUTHTYPE, PW_TYPE_INTEGER)) == NULL) {
90 radlog(L_CONS|L_ERR, "no memory");
94 vp->operator = T_OP_ADD;
102 #define FIND_MODE_NAME 0
103 #define FIND_MODE_REPLY 1
106 * Read the users, huntgroups or hints file.
107 * Return a PAIR_LIST.
109 int pairlist_read(const char *file, PAIR_LIST **list, int complain)
112 int mode = FIND_MODE_NAME;
116 VALUE_PAIR *check_tmp;
117 VALUE_PAIR *reply_tmp;
118 PAIR_LIST *pl = NULL, *last = NULL, *t;
125 * Open the file. The error message should be a little
128 if ((fp = fopen(file, "r")) == NULL) {
129 if (!complain) return -1;
130 radlog(L_CONS|L_ERR, "Couldn't open %s for reading: %s",
131 file, strerror(errno));
137 * Read the entire file into memory for speed.
139 while(fgets(buffer, sizeof(buffer), fp) != NULL) {
141 if (strchr(buffer, '\n') == NULL) {
142 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
146 if (buffer[0] == '#' || buffer[0] == '\n') continue;
148 if(mode == FIND_MODE_NAME) {
150 * Find the entry starting with the users name
152 if (isspace(buffer[0])) {
153 if (parsecode != T_EOL) {
155 "%s[%d]: Unexpected trailing comma for entry %s",
156 file, lineno, entry);
164 getword(&ptr, entry, sizeof(entry));
167 * Include another file if we see
170 if (strcasecmp(entry, "$include") == 0) {
174 while (!isspace(*ptr))
179 * If it's an absolute pathname,
180 * then use it verbatim.
182 * If not, then make the $include
183 * files *relative* to the current
187 strNcpy(newfile, file,
189 ptr = strrchr(newfile, '/');
195 if (pairlist_read(s, &t, 0) != 0) {
198 "%s[%d]: Could not open included file %s: %s",
199 file, lineno, s, strerror(errno));
208 while (last && last->next)
214 * Parse the check values
219 parsecode = userparse(ptr, &check_tmp);
223 "%s[%d]: Parse error (check) for entry %s: %s",
224 file, lineno, entry, librad_errstr);
227 } else if (parsecode == T_COMMA) {
229 "%s[%d]: Unexpected trailing comma in check item list for entry %s",
230 file, lineno, entry);
234 mode = FIND_MODE_REPLY;
238 if(*buffer == ' ' || *buffer == '\t') {
239 if (parsecode != T_COMMA) {
241 "%s[%d]: Syntax error: Previous line is missing a trailing comma for entry %s",
242 file, lineno, entry);
248 * Parse the reply values
250 parsecode = userparse(buffer, &reply_tmp);
254 "%s[%d]: Parse error (reply) for entry %s: %s",
255 file, lineno, entry, librad_errstr);
262 * Done with this entry...
264 if ((t = malloc(sizeof(PAIR_LIST))) == NULL) {
268 auth_type_fixup(check_tmp);
269 memset(t, 0, sizeof(*t));
270 t->name = strdup(entry);
271 t->check = check_tmp;
272 t->reply = reply_tmp;
273 t->lineno = old_lineno;
282 mode = FIND_MODE_NAME;
289 * Make sure that we also read the last line of the file!
291 if (mode == FIND_MODE_REPLY) {
306 static void debug_pair_list(PAIR_LIST *pl)
311 printf("Pair list: %s\n", pl->name);
312 printf("** Check:\n");
313 for(vp = pl->check; vp; vp = vp->next) {
315 fprint_attr_val(stdout, vp);
318 printf("** Reply:\n");
319 for(vp = pl->reply; vp; vp = vp->next) {
321 fprint_attr_val(stdout, vp);
329 #ifndef BUILDDBM /* HACK HACK */
334 static void realm_free(REALM *cl)
346 * Read the realms file.
348 static int read_realms_file(const char *file)
363 if ((fp = fopen(file, "r")) == NULL) {
364 #if 1 /* For now - realms file is not obligatory */
367 radlog(L_CONS|L_ERR, "cannot open %s", file);
371 while(fgets(buffer, 256, fp) != NULL) {
373 if (strchr(buffer, '\n') == NULL) {
374 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
377 if (buffer[0] == '#' || buffer[0] == '\n')
380 if (!getword(&p, realm, sizeof(realm)) ||
381 !getword(&p, hostnm, sizeof(hostnm))) {
382 radlog(L_ERR, "%s[%d]: syntax error", file, lineno);
386 if ((c = malloc(sizeof(REALM))) == NULL) {
387 radlog(L_CONS|L_ERR, "%s[%d]: out of memory",
391 memset(c, 0, sizeof(REALM));
393 if ((s = strchr(hostnm, ':')) != NULL) {
395 c->auth_port = atoi(s);
396 c->acct_port = c->auth_port + 1;
398 c->auth_port = auth_port;
399 c->acct_port = acct_port;
402 if (strcmp(hostnm, "LOCAL") == 0) {
403 c->ipaddr = htonl(INADDR_LOOPBACK);
405 c->ipaddr = ip_getaddr(hostnm);
408 if (c->ipaddr == 0) {
409 radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
410 file, lineno, hostnm);
415 * Find the remote server in the "clients" list.
416 * If we can't find it, there's a big problem...
418 client = client_find(c->ipaddr);
419 if (client == NULL) {
420 radlog(L_CONS|L_ERR, "%s[%d]: Cannot find 'clients' file entry of remote server %s for realm \"%s\"",
421 file, lineno, hostnm, realm);
424 memcpy(c->secret, client->secret, sizeof(c->secret));
427 * Double-check lengths to be sure they're sane
429 if (strlen(hostnm) >= sizeof(c->server)) {
430 radlog(L_ERR, "%s[%d]: server name of length %d is greater than the allowed maximum of %d.",
432 strlen(hostnm), sizeof(c->server) - 1);
435 if (strlen(realm) > sizeof(c->realm)) {
436 radlog(L_ERR, "%s[%d]: realm of length %d is greater than the allowed maximum of %d.",
438 strlen(realm), sizeof(c->realm) - 1);
443 * OK, they're sane, copy them over.
445 strcpy(c->realm, realm);
446 strcpy(c->server, hostnm);
447 c->striprealm = TRUE;
449 while (getword(&p, opts, sizeof(opts))) {
450 if (strcmp(opts, "nostrip") == 0)
451 c->striprealm = FALSE;
452 if (strstr(opts, "noacct") != NULL)
454 if (strstr(opts, "trusted") != NULL)
456 if (strstr(opts, "notrealm") != NULL)
458 if (strstr(opts, "notsuffix") != NULL)
469 #endif /* BUILDDBM */
472 * Find a realm in the REALM list.
474 REALM *realm_find(const char *realm)
479 * If we're passed a NULL realm pointer,
480 * then look for a "NULL" realm string.
486 for(cl = realms; cl; cl = cl->next)
487 if (strcmp(cl->realm, realm) == 0)
490 for(cl = realms; cl; cl = cl->next)
491 if (strcmp(cl->realm, "DEFAULT") == 0)
498 * Find a realm for a proxy reply by proxy's IP
500 REALM *realm_findbyaddr(uint32_t ipaddr)
504 for(cl = realms; cl; cl = cl->next)
505 if (ipaddr == cl->ipaddr)
512 #ifndef BUILDDBM /* HACK HACK */
515 * (Re-) read the configuration files.
517 int read_config_files()
521 /* Initialize the dictionary */
522 DEBUG2("read_config_files: reading dictionary");
523 if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
524 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
529 sprintf(buffer, "%.200s/%.50s", radius_dir, RADIUS_CLIENTS);
530 DEBUG2("read_config_files: reading clients");
531 if (read_clients_file(buffer) < 0) {
532 radlog(L_ERR|L_CONS, "Errors reading clients");
536 sprintf(buffer, "%.200s/%.50s", radius_dir, RADIUS_REALMS);
537 DEBUG2("read_config_files: reading realms");
538 if (read_realms_file(buffer) < 0) {
539 radlog(L_ERR|L_CONS, "Errors reading realms");
543 sprintf(buffer, "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
544 DEBUG2("read_config_files: reading naslist");
545 if (read_naslist_file(buffer) < 0) {
546 radlog(L_ERR|L_CONS, "Errors reading naslist");
550 DEBUG2("read_config_files: entering modules setup");
551 if (setup_modules() < 0) {
552 radlog(L_ERR|L_CONS, "Errors setting up modules");