2 * files.c Read config files into memory.
8 static const char rcsid[] = "$Id$";
11 #include "libradius.h"
16 #include <netinet/in.h>
36 void pairlist_free(PAIR_LIST **pl)
40 for (p = *pl; p; p = next) {
41 if (p->name) free(p->name);
42 if (p->check) pairfree(p->check);
43 if (p->reply) pairfree(p->reply);
53 * If Password or Crypt-Password is set, but there is no
54 * Auth-Type, add one (kludge!).
56 static void auth_type_fixup(VALUE_PAIR *check)
63 * See if a password is present. Return right away
64 * if we see Auth-Type.
66 for (vp = check; vp; vp = vp->next) {
67 if (vp->attribute == PW_AUTHTYPE)
69 if (vp->attribute == PW_PASSWORD) {
71 n = PW_AUTHTYPE_LOCAL;
73 if (vp->attribute == PW_CRYPT_PASSWORD) {
75 n = PW_AUTHTYPE_CRYPT;
83 * Add an Auth-Type attribute.
84 * FIXME: put Auth-Type _first_ (doesn't matter now,
85 * might matter some day).
88 if ((vp = paircreate(PW_AUTHTYPE, PW_TYPE_INTEGER)) == NULL) {
89 radlog(L_CONS|L_ERR, "no memory");
93 vp->operator = T_OP_ADD;
101 #define FIND_MODE_NAME 0
102 #define FIND_MODE_REPLY 1
105 * Read the users, huntgroups or hints file.
106 * Return a PAIR_LIST.
108 int pairlist_read(const char *file, PAIR_LIST **list, int complain)
111 int mode = FIND_MODE_NAME;
115 VALUE_PAIR *check_tmp;
116 VALUE_PAIR *reply_tmp;
117 PAIR_LIST *pl = NULL, *last = NULL, *t;
124 * Open the file. The error message should be a little
127 if ((fp = fopen(file, "r")) == NULL) {
128 if (!complain) return -1;
129 radlog(L_CONS|L_ERR, "Couldn't open %s for reading: %s",
130 file, strerror(errno));
136 * Read the entire file into memory for speed.
138 while(fgets(buffer, sizeof(buffer), fp) != NULL) {
140 if (strchr(buffer, '\n') == NULL) {
141 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
145 if (buffer[0] == '#' || buffer[0] == '\n') continue;
147 if(mode == FIND_MODE_NAME) {
149 * Find the entry starting with the users name
151 if (isspace(buffer[0])) {
152 if (parsecode != T_EOL) {
154 "%s[%d]: Unexpected trailing comma for entry %s",
155 file, lineno, entry);
163 getword(&ptr, entry, sizeof(entry));
166 * Include another file if we see
169 if (strcasecmp(entry, "$include") == 0) {
173 while (!isspace(*ptr))
178 * If it's an absolute pathname,
179 * then use it verbatim.
181 * If not, then make the $include
182 * files *relative* to the current
186 strNcpy(newfile, file,
188 ptr = strrchr(newfile, '/');
194 if (pairlist_read(s, &t, 0) != 0) {
197 "%s[%d]: Could not open included file %s: %s",
198 file, lineno, s, strerror(errno));
207 while (last && last->next)
213 * Parse the check values
218 parsecode = userparse(ptr, &check_tmp);
222 "%s[%d]: Parse error (check) for entry %s: %s",
223 file, lineno, entry, librad_errstr);
226 } else if (parsecode == T_COMMA) {
228 "%s[%d]: Unexpected trailing comma in check item list for entry %s",
229 file, lineno, entry);
233 mode = FIND_MODE_REPLY;
237 if(*buffer == ' ' || *buffer == '\t') {
238 if (parsecode != T_COMMA) {
240 "%s[%d]: Syntax error: Previous line is missing a trailing comma for entry %s",
241 file, lineno, entry);
247 * Parse the reply values
249 parsecode = userparse(buffer, &reply_tmp);
253 "%s[%d]: Parse error (reply) for entry %s: %s",
254 file, lineno, entry, librad_errstr);
261 * Done with this entry...
263 if ((t = malloc(sizeof(PAIR_LIST))) == NULL) {
267 auth_type_fixup(check_tmp);
268 memset(t, 0, sizeof(*t));
269 t->name = strdup(entry);
270 t->check = check_tmp;
271 t->reply = reply_tmp;
272 t->lineno = old_lineno;
281 mode = FIND_MODE_NAME;
288 * Make sure that we also read the last line of the file!
290 if (mode == FIND_MODE_REPLY) {
305 static void debug_pair_list(PAIR_LIST *pl)
310 printf("Pair list: %s\n", pl->name);
311 printf("** Check:\n");
312 for(vp = pl->check; vp; vp = vp->next) {
314 fprint_attr_val(stdout, vp);
317 printf("** Reply:\n");
318 for(vp = pl->reply; vp; vp = vp->next) {
320 fprint_attr_val(stdout, vp);
328 #ifndef BUILDDBM /* HACK HACK */
333 static void realm_free(REALM *cl)
345 * Read the realms file.
347 int read_realms_file(const char *file)
362 if ((fp = fopen(file, "r")) == NULL) {
363 #if 1 /* For now - realms file is not obligatory */
366 radlog(L_CONS|L_ERR, "cannot open %s", file);
370 while(fgets(buffer, 256, fp) != NULL) {
372 if (strchr(buffer, '\n') == NULL) {
373 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
376 if (buffer[0] == '#' || buffer[0] == '\n')
379 if (!getword(&p, realm, sizeof(realm)) ||
380 !getword(&p, hostnm, sizeof(hostnm))) {
381 radlog(L_ERR, "%s[%d]: syntax error", file, lineno);
385 if ((c = malloc(sizeof(REALM))) == NULL) {
386 radlog(L_CONS|L_ERR, "%s[%d]: out of memory",
390 memset(c, 0, sizeof(REALM));
392 if ((s = strchr(hostnm, ':')) != NULL) {
394 c->auth_port = atoi(s);
395 c->acct_port = c->auth_port + 1;
397 c->auth_port = auth_port;
398 c->acct_port = acct_port;
401 if (strcmp(hostnm, "LOCAL") == 0) {
402 c->ipaddr = htonl(INADDR_LOOPBACK);
404 c->ipaddr = ip_getaddr(hostnm);
407 if (c->ipaddr == 0) {
408 radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
409 file, lineno, hostnm);
414 * Find the remote server in the "clients" list.
415 * If we can't find it, there's a big problem...
417 client = client_find(c->ipaddr);
418 if (client == NULL) {
419 radlog(L_CONS|L_ERR, "%s[%d]: Cannot find 'clients' file entry of remote server %s for realm \"%s\"",
420 file, lineno, hostnm, realm);
423 memcpy(c->secret, client->secret, sizeof(c->secret));
426 * Double-check lengths to be sure they're sane
428 if (strlen(hostnm) >= sizeof(c->server)) {
429 radlog(L_ERR, "%s[%d]: server name of length %d is greater than the allowed maximum of %d.",
431 strlen(hostnm), sizeof(c->server) - 1);
434 if (strlen(realm) > sizeof(c->realm)) {
435 radlog(L_ERR, "%s[%d]: realm of length %d is greater than the allowed maximum of %d.",
437 strlen(realm), sizeof(c->realm) - 1);
442 * OK, they're sane, copy them over.
444 strcpy(c->realm, realm);
445 strcpy(c->server, hostnm);
446 c->striprealm = TRUE;
448 while (getword(&p, opts, sizeof(opts))) {
449 if (strcmp(opts, "nostrip") == 0)
450 c->striprealm = FALSE;
451 if (strstr(opts, "noacct") != NULL)
453 if (strstr(opts, "trusted") != NULL)
455 if (strstr(opts, "notrealm") != NULL)
457 if (strstr(opts, "notsuffix") != NULL)
468 #endif /* BUILDDBM */
471 * Find a realm in the REALM list.
473 REALM *realm_find(const char *realm)
478 * If we're passed a NULL realm pointer,
479 * then look for a "NULL" realm string.
485 for(cl = realms; cl; cl = cl->next)
486 if (strcmp(cl->realm, realm) == 0)
489 for(cl = realms; cl; cl = cl->next)
490 if (strcmp(cl->realm, "DEFAULT") == 0)
497 * Find a realm for a proxy reply by proxy's IP
499 REALM *realm_findbyaddr(uint32_t ipaddr)
503 for(cl = realms; cl; cl = cl->next)
504 if (ipaddr == cl->ipaddr)