2 * conffile.c Read the radius.conf file.
4 * Yep I should learn to use lex & yacc, or at least
5 * write a decent parser. I know how to do that, really :)
23 #ifdef WITH_NEW_CONFIG
26 #define xstrdup strdup
29 extern RADCLIENT *clients;
31 extern void realm_free(REALM *cl);
33 static int generate_realms();
34 static int generate_clients();
37 #define RADIUS_CONFIG "radius.conf"
41 * Create a new CONF_PAIR
43 CONF_PAIR *cf_pair_alloc(const char *attr, const char *value, int operator)
47 cp = (CONF_PAIR *)xalloc(sizeof(CONF_PAIR));
48 memset(cp, 0, sizeof(CONF_PAIR));
49 cp->attr = xstrdup(attr);
50 cp->value = xstrdup(value);
51 cp->operator = operator;
57 * Add a pair to a configuration section.
59 void cf_pair_add(CONF_SECTION *cs, CONF_PAIR *cp_new)
63 for (cp = cs->cps; cp && cp->next; cp = cp->next)
75 void cf_pair_free(CONF_PAIR *cp)
77 if (cp == NULL) return;
79 if (cp->attr) free(cp->attr);
80 if (cp->value) free(cp->value);
85 * Allocate a CONF_SECTION
87 CONF_SECTION *cf_section_alloc(const char *name1, const char *name2)
91 if (name1 == NULL) name1 = "main";
92 if (name2 == NULL) name2 = "main";
94 cs = (CONF_SECTION *)xalloc(sizeof(CONF_SECTION));
95 memset(cs, 0, sizeof(CONF_SECTION));
96 cs->name1 = xstrdup(name1);
97 cs->name2 = xstrdup(name2);
103 * Free a CONF_SECTION
105 void cf_section_free(CONF_SECTION *cs)
107 CONF_PAIR *cp, *next;
108 CONF_SECTION *sub, *next_sub;
110 if (cs == NULL) return;
112 for (cp = cs->cps; cp; cp = next) {
118 * Clear out any possible subsections aswell
120 for (sub = cs->sub; sub; sub = next_sub) {
121 next_sub = sub->next;
122 cf_section_free(sub);
125 if (cs->name1) free(cs->name1);
126 if (cs->name2) free(cs->name2);
129 * And free the section
135 * Free _all_ in a CONF_SECTION and below
138 void cf_section_free_all(CONF_SECTION *cs)
143 * Read a part of the config file.
145 static CONF_SECTION *conf_readsection(const char *cf, int *lineno, FILE *fp,
146 const char *name1, const char *name2)
148 CONF_SECTION *cs, *csn, *csp, *css;
158 * Ensure that the user can't add CONF_SECTIONs
159 * with 'internal' names;
161 if ((name1 != NULL) && (name1[0] == '_')) {
162 log(L_ERR, "%s[%d]: Illegal configuration section name",
168 * Allocate new section.
170 cs = cf_section_alloc(name1, name2);
175 while (fgets(buf, sizeof(buf), fp) != NULL) {
179 t1 = gettoken(&ptr, buf1, sizeof(buf1));
180 t2 = gettoken(&ptr, buf2, sizeof(buf2));
181 t3 = gettoken(&ptr, buf3, sizeof(buf3));
183 if (buf1[0] == 0 || buf1[0] == '#')
187 * See if it's the end of a section.
189 if (t1 == T_RCBRACE) {
190 if (name1 == NULL || buf2[0]) {
191 log(L_ERR, "%s[%d]: syntax error #1",
199 * Perhaps a subsection.
202 if (t2 == T_LCBRACE) {
203 css = conf_readsection(cf, lineno, fp, name2, buf1);
206 for (csp = cs->sub; csp && csp->next; csp = csp->next)
217 * Or, the beginning of a new section.
219 if (t3 == T_LCBRACE) {
220 csn = conf_readsection(cf, lineno, fp, buf1, buf2);
224 * Add this section after all others.
226 for (csp = cs; csp && csp->next; csp = csp->next)
236 * Must be a normal attr = value line.
238 if (buf1[0] != 0 && buf2[0] == 0 && buf3[0] == 0) {
240 } else if (buf1[0] == 0 || buf2[0] == 0 || buf3[0] == 0 ||
241 (t2 < T_EQSTART || t2 > T_EQEND)) {
242 log(L_ERR, "%s[%d]: syntax error #2",
248 * Ensure that the user can't add CONF_PAIRs
249 * with 'internal' names;
251 if (buf1[0] == '_') {
252 log(L_ERR, "%s[%d]: Illegal configuration pair name",
258 * Add this CONF_PAIR to our CONF_SECTION
260 cpn = cf_pair_alloc(buf1, buf3, t2);
261 cf_pair_add(cs, cpn);
265 * See if EOF was unexpected ..
269 "%s[%d]: unexpected end of file", cf, *lineno);
277 * Read the config file.
279 CONF_SECTION *conf_read(const char *conffile)
284 cf_section_free(config);
287 if ((fp = fopen(conffile, "r")) == NULL) {
288 log(L_ERR, "cannot open %s: %s",
289 conffile, strerror(errno));
293 config = conf_readsection(conffile, &lineno, fp, NULL, NULL);
300 * Read the configuration and library
301 * This uses the new kind of configuration file as defined by
302 * Miquel at http://www.miquels.cistron.nl/radius/
305 int read_new_config_files(void)
309 /* Lets go for the new configuration files */
311 sprintf(buffer, "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
312 if (conf_read(buffer) == NULL) {
313 log(L_ERR|L_CONS, "Error reading new-style configuration file");
318 * After this we should run
319 * generate_realms() and generate_clients()
321 * Fail if we can't generate list of clients
324 if (generate_clients() < 0) {
325 log(L_ERR|L_CONS, "Error generation clients list");
330 * If there isn't any realms it isn't fatal..
332 if (generate_realms() < 0) {
333 log(L_ERR|L_CONS, "Error generation realms list");
341 * Create the linked list of realms from the new configuration type
342 * This way we don't have to change to much in the other source-files
345 static int generate_realms()
349 char *s, *authhost, *accthost;
354 for (cs = config; cs; cs = cs->next) {
355 if (strcmp(cs->name1, "realm") == 0) {
357 * We've found a realm, allocate space for it
359 if ((c = malloc(sizeof(REALM))) == NULL) {
360 log(L_CONS|L_ERR, "Out of memory while generating realms list");
363 memset(c, 0, sizeof(REALM));
365 * An authhost must exist in the configuration
367 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
369 "No authhost entry for realm: %s",
373 if ((s = strchr(authhost, ':')) != NULL) {
375 c->auth_port = atoi(s);
377 c->auth_port = auth_port;
379 accthost = cf_section_value_find(cs, "accthost");
380 if ((s =strchr(accthost, ':')) != NULL) {
382 c->acct_port = atoi(s);
384 c->acct_port = acct_port;
386 if (strcmp(authhost, "LOCAL") != 0)
387 c->ipaddr = ip_getaddr(authhost);
390 * Double check length, just to be sure!
393 if (strlen(authhost) >= sizeof(c->server)) {
394 log(L_ERR, "[%s] servername of length %d is greater that allowed: %d",
395 authhost, strlen(authhost),
396 sizeof(c->server) - 1);
399 if (strlen(cs->name2) >= sizeof(c->realm)) {
400 log(L_ERR, "[%s] realm of length %d is greater that allowed: %d",
401 cs->name2, strlen(cs->name2),
402 sizeof(c->server) - 1);
406 strcpy(c->realm, cs->name2);
407 strcpy(c->server, authhost);
410 if ((cf_section_value_find(cs, "nostrip")) != NULL)
412 if ((cf_section_value_find(cs, "noacct")) != NULL)
414 if ((cf_section_value_find(cs, "trusted")) != NULL)
427 * Free a RADCLIENT list.
430 static void clients_free(RADCLIENT *cl)
442 * Create the linked list of realms from the new configuration type
443 * This way we don't have to change to much in the other source-files
446 static int generate_clients()
450 char *hostnm, *secret, *shortnm;
452 clients_free(clients);
455 for (cs = config; cs; cs = cs->next) {
456 if (strcmp(cs->name1, "client") == 0) {
458 * Check the lengths, we don't want any core dumps
461 secret = cf_section_value_find(cs, "secret");
462 shortnm = cf_section_value_find(cs, "shortname");
464 if (strlen(secret) >= sizeof(c->secret)) {
465 log(L_ERR, "[%s]: secret of length %d is greater than the allowed maximum of %d.",
467 strlen(secret), sizeof(c->secret) - 1);
470 if (strlen(shortnm) > sizeof(c->shortname)) {
471 log(L_ERR, "[%s]: short name of length %d is greater than the allowed maximum of %d.",
473 strlen(shortnm), sizeof(c->shortname) - 1);
477 * The size is fine.. Let's create the buffer
479 if ((c = malloc(sizeof(RADCLIENT))) == NULL) {
480 log(L_CONS|L_ERR, "[%s]: out of memory while doint client",
485 c->ipaddr = ip_getaddr(hostnm);
486 strcpy(c->secret, secret);
487 strcpy(c->shortname, shortnm);
488 strcpy(c->longname, ip_hostname(c->ipaddr));
499 * Return a CONF_PAIR within a CONF_SECTION.
502 CONF_PAIR *cf_pair_find(CONF_SECTION *section, const char *name)
506 for (cp = section->cps; cp; cp = cp->next)
507 if (strcmp(cp->attr, name) == 0)
514 * Return the value of a CONF_PAIR
517 char *cf_pair_value(CONF_PAIR *pair)
519 return (pair ? pair->value : NULL);
524 * Find a value in a CONF_SECTION
526 char *cf_section_value_find(CONF_SECTION *section, const char *attr)
530 cp = cf_pair_find(section, attr);
532 return (cp ? cp->value : NULL);
536 * Return the next pair after a CONF_PAIR
537 * with a certain name (char *attr)
540 CONF_PAIR *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char *attr)
545 * If pair is NULL this must be a first time run
546 * Find the pair with correct name
550 cp = cf_pair_find(section, attr);
555 for (; cp; cp = cp->next)
556 if (strcmp(cp->attr, attr) == 0)
563 * Find a CONF_SECTION
566 CONF_SECTION *cf_section_find(const char *name)
570 for (cs = config; cs; cs = cs->next)
571 if (strcmp(cs->name1, name) == 0)
578 * Find a sub-section in a section
581 CONF_SECTION *cf_section_sub_find(CONF_SECTION *section, const char *name) {
584 for (cs = section->sub; cs; cs = cs->next)
585 if (strcmp(cs->name2, name) == 0)
593 * Find the configuration section for a module
596 CONF_SECTION *cf_module_config_find(const char *modulename)
600 for (cs = config; cs; cs = cs->next)
601 if ((strcmp(cs->name1, "module") == 0)
602 && (strcmp(cs->name2, modulename) == 0))