2 * files.c Read config files into memory.
8 static const char rcsid[] = "$Id$";
11 #include "libradius.h"
16 #include <netinet/in.h>
32 void pairlist_free(PAIR_LIST **pl)
36 for (p = *pl; p; p = next) {
37 if (p->name) free(p->name);
38 if (p->check) pairfree(&p->check);
39 if (p->reply) pairfree(&p->reply);
49 * If Password or Crypt-Password is set, but there is no
50 * Auth-Type, add one (kludge!).
52 static void auth_type_fixup(VALUE_PAIR *check)
59 * See if a password is present. Return right away
60 * if we see Auth-Type.
62 for (vp = check; vp; vp = vp->next) {
63 if (vp->attribute == PW_AUTHTYPE)
65 if (vp->attribute == PW_PASSWORD) {
67 n = PW_AUTHTYPE_LOCAL;
69 if (vp->attribute == PW_CRYPT_PASSWORD) {
71 n = PW_AUTHTYPE_CRYPT;
79 * Add an Auth-Type attribute.
80 * FIXME: put Auth-Type _first_ (doesn't matter now,
81 * might matter some day).
84 if ((vp = paircreate(PW_AUTHTYPE, PW_TYPE_INTEGER)) == NULL) {
85 radlog(L_CONS|L_ERR, "no memory");
89 vp->operator = T_OP_ADD;
97 #define FIND_MODE_NAME 0
98 #define FIND_MODE_REPLY 1
101 * Read the users, huntgroups or hints file.
102 * Return a PAIR_LIST.
104 int pairlist_read(const char *file, PAIR_LIST **list, int complain)
107 int mode = FIND_MODE_NAME;
111 VALUE_PAIR *check_tmp;
112 VALUE_PAIR *reply_tmp;
113 PAIR_LIST *pl = NULL, *last = NULL, *t;
120 * Open the file. The error message should be a little
123 if ((fp = fopen(file, "r")) == NULL) {
124 if (!complain) return -1;
125 radlog(L_CONS|L_ERR, "Couldn't open %s for reading: %s",
126 file, strerror(errno));
132 * Read the entire file into memory for speed.
134 while(fgets(buffer, sizeof(buffer), fp) != NULL) {
136 if (strchr(buffer, '\n') == NULL) {
137 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
141 if (buffer[0] == '#' || buffer[0] == '\n') continue;
143 if(mode == FIND_MODE_NAME) {
145 * Find the entry starting with the users name
147 if (isspace(buffer[0])) {
148 if (parsecode != T_EOL) {
150 "%s[%d]: Unexpected trailing comma for entry %s",
151 file, lineno, entry);
159 getword(&ptr, entry, sizeof(entry));
162 * Include another file if we see
165 if (strcasecmp(entry, "$include") == 0) {
169 while (!isspace(*ptr))
174 * If it's an absolute pathname,
175 * then use it verbatim.
177 * If not, then make the $include
178 * files *relative* to the current
182 strNcpy(newfile, file,
184 ptr = strrchr(newfile, '/');
190 if (pairlist_read(s, &t, 0) != 0) {
193 "%s[%d]: Could not open included file %s: %s",
194 file, lineno, s, strerror(errno));
203 while (last && last->next)
209 * Parse the check values
214 parsecode = userparse(ptr, &check_tmp);
218 "%s[%d]: Parse error (check) for entry %s: %s",
219 file, lineno, entry, librad_errstr);
222 } else if (parsecode == T_COMMA) {
224 "%s[%d]: Unexpected trailing comma in check item list for entry %s",
225 file, lineno, entry);
229 mode = FIND_MODE_REPLY;
233 if(*buffer == ' ' || *buffer == '\t') {
234 if (parsecode != T_COMMA) {
236 "%s[%d]: Syntax error: Previous line is missing a trailing comma for entry %s",
237 file, lineno, entry);
243 * Parse the reply values
245 parsecode = userparse(buffer, &reply_tmp);
249 "%s[%d]: Parse error (reply) for entry %s: %s",
250 file, lineno, entry, librad_errstr);
257 * Done with this entry...
259 t = rad_malloc(sizeof(PAIR_LIST));
261 auth_type_fixup(check_tmp);
262 memset(t, 0, sizeof(*t));
263 t->name = strdup(entry);
264 t->check = check_tmp;
265 t->reply = reply_tmp;
266 t->lineno = old_lineno;
275 mode = FIND_MODE_NAME;
282 * Make sure that we also read the last line of the file!
284 if (mode == FIND_MODE_REPLY) {
299 static void debug_pair_list(PAIR_LIST *pl)
304 printf("Pair list: %s\n", pl->name);
305 printf("** Check:\n");
306 for(vp = pl->check; vp; vp = vp->next) {
308 fprint_attr_val(stdout, vp);
311 printf("** Reply:\n");
312 for(vp = pl->reply; vp; vp = vp->next) {
314 fprint_attr_val(stdout, vp);
322 #ifndef BUILDDBM /* HACK HACK */
327 static void realm_free(REALM *cl)
339 * Read the realms file.
341 int read_realms_file(const char *file)
356 if ((fp = fopen(file, "r")) == NULL) {
357 #if 1 /* For now - realms file is not obligatory */
360 radlog(L_CONS|L_ERR, "cannot open %s", file);
364 while(fgets(buffer, 256, fp) != NULL) {
366 if (strchr(buffer, '\n') == NULL) {
367 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
370 if (buffer[0] == '#' || buffer[0] == '\n')
373 if (!getword(&p, realm, sizeof(realm)) ||
374 !getword(&p, hostnm, sizeof(hostnm))) {
375 radlog(L_ERR, "%s[%d]: syntax error", file, lineno);
379 c = rad_malloc(sizeof(REALM));
380 memset(c, 0, sizeof(REALM));
382 if ((s = strchr(hostnm, ':')) != NULL) {
384 c->auth_port = atoi(s);
385 c->acct_port = c->auth_port + 1;
387 c->auth_port = auth_port;
388 c->acct_port = acct_port;
391 if (strcmp(hostnm, "LOCAL") == 0) {
392 c->ipaddr = htonl(INADDR_LOOPBACK);
394 c->ipaddr = ip_getaddr(hostnm);
397 if (c->ipaddr == 0) {
398 radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
399 file, lineno, hostnm);
404 * Find the remote server in the "clients" list.
405 * If we can't find it, there's a big problem...
407 client = client_find(c->ipaddr);
408 if (client == NULL) {
409 radlog(L_CONS|L_ERR, "%s[%d]: Cannot find 'clients' file entry of remote server %s for realm \"%s\"",
410 file, lineno, hostnm, realm);
413 memcpy(c->secret, client->secret, sizeof(c->secret));
416 * Double-check lengths to be sure they're sane
418 if (strlen(hostnm) >= sizeof(c->server)) {
419 radlog(L_ERR, "%s[%d]: server name of length %d is greater than the allowed maximum of %d.",
421 strlen(hostnm), sizeof(c->server) - 1);
424 if (strlen(realm) > sizeof(c->realm)) {
425 radlog(L_ERR, "%s[%d]: realm of length %d is greater than the allowed maximum of %d.",
427 strlen(realm), sizeof(c->realm) - 1);
432 * OK, they're sane, copy them over.
434 strcpy(c->realm, realm);
435 strcpy(c->server, hostnm);
436 c->striprealm = TRUE;
438 while (getword(&p, opts, sizeof(opts))) {
439 if (strcmp(opts, "nostrip") == 0)
440 c->striprealm = FALSE;
441 if (strstr(opts, "noacct") != NULL)
443 if (strstr(opts, "trusted") != NULL)
445 if (strstr(opts, "notrealm") != NULL)
447 if (strstr(opts, "notsuffix") != NULL)
458 #endif /* BUILDDBM */
461 * Find a realm in the REALM list.
463 REALM *realm_find(const char *realm)
468 * If we're passed a NULL realm pointer,
469 * then look for a "NULL" realm string.
475 for(cl = realms; cl; cl = cl->next)
476 if (strcmp(cl->realm, realm) == 0)
479 for(cl = realms; cl; cl = cl->next)
480 if (strcmp(cl->realm, "DEFAULT") == 0)
487 * Find a realm for a proxy reply by proxy's IP
489 REALM *realm_findbyaddr(uint32_t ipaddr)
493 for(cl = realms; cl; cl = cl->next)
494 if (ipaddr == cl->ipaddr)