renamed the CLIENT structure to RADCLIENT, as CLIENT conflicts
[freeradius.git] / src / main / conffile.c
1 /*
2  * conffile.c   Read the radius.conf file.
3  *
4  *              Yep I should learn to use lex & yacc, or at least
5  *              write a decent parser. I know how to do that, really :)
6  *              miquels@cistron.nl
7  *
8  * Version:     $Id$
9  *
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #include "radiusd.h"
19 #include "conffile.h"
20 #include "token.h"
21 #include "modules.h"
22
23 #ifdef WITH_NEW_CONFIG
24
25 #define xalloc malloc
26 #define xstrdup strdup
27
28 CONF_SECTION    *config;
29 extern RADCLIENT  *clients;
30 extern REALM    *realms;
31 extern void realm_free(REALM *cl);
32
33 static int generate_realms();
34 static int generate_clients();
35
36 #ifndef RADIUS_CONFIG
37 #define RADIUS_CONFIG "radius.conf"
38 #endif
39
40 /*
41  *      Create a new CONF_PAIR
42  */
43 CONF_PAIR *cf_pair_alloc(const char *attr, const char *value, int operator)
44 {
45         CONF_PAIR       *cp;
46
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;
52
53         return cp;
54 }
55
56 /*
57  *      Add a pair to a configuration section.
58  */
59 void cf_pair_add(CONF_SECTION *cs, CONF_PAIR *cp_new)
60 {
61         CONF_PAIR *cp;
62         
63         for (cp = cs->cps; cp && cp->next; cp = cp->next)
64                 ;
65
66         if (cp == NULL)
67                 cs->cps = cp_new;
68         else
69                 cp->next = cp_new;
70 }
71
72 /*
73  *      Free a CONF_PAIR
74  */
75 void cf_pair_free(CONF_PAIR *cp)
76 {
77         if (cp == NULL) return;
78
79         if (cp->attr)  free(cp->attr);
80         if (cp->value) free(cp->value);
81         free(cp);
82 }
83
84 /*
85  *      Allocate a CONF_SECTION
86  */
87 CONF_SECTION *cf_section_alloc(const char *name1, const char *name2)
88 {
89         CONF_SECTION    *cs;
90
91         if (name1 == NULL) name1 = "main";
92         if (name2 == NULL) name2 = "main";
93
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);
98
99         return cs;
100 }
101
102 /*
103  *      Free a CONF_SECTION
104  */
105 void cf_section_free(CONF_SECTION *cs)
106 {
107         CONF_PAIR       *cp, *next;
108         CONF_SECTION *sub, *next_sub;
109
110         if (cs == NULL) return;
111
112         for (cp = cs->cps; cp; cp = next) {
113                 next = cp->next;
114                 cf_pair_free(cp);
115         }
116
117         /*
118          * Clear out any possible subsections aswell
119          */
120         for (sub = cs->sub; sub; sub = next_sub) {
121                 next_sub = sub->next;
122                 cf_section_free(sub);
123         }
124
125         if (cs->name1) free(cs->name1);
126         if (cs->name2) free(cs->name2);
127
128         /*
129          * And free the section
130          */
131         free(cs);
132 }
133
134 /*
135  * Free _all_ in a CONF_SECTION and below
136  */
137
138 void cf_section_free_all(CONF_SECTION *cs)
139 {
140
141 }
142 /*
143  *      Read a part of the config file.
144  */
145 static CONF_SECTION *conf_readsection(const char *cf, int *lineno, FILE *fp,
146                                 const char *name1, const char *name2)
147 {
148         CONF_SECTION    *cs, *csn, *csp, *css;
149         CONF_PAIR       *cpn;
150         char            *ptr;
151         char            buf[1024];
152         char            buf1[256];
153         char            buf2[256];
154         char            buf3[256];
155         int             t1, t2, t3;
156
157         /*
158          *      Ensure that the user can't add CONF_SECTIONs
159          *      with 'internal' names;
160          */
161         if ((name1 != NULL) && (name1[0] == '_')) {
162                 log(L_ERR, "%s[%d]: Illegal configuration section name",
163                     cf, *lineno);
164                 return NULL;
165         }
166
167         /*
168          *      Allocate new section.
169          */
170         cs = cf_section_alloc(name1, name2);
171
172         /*
173          *      Read.
174          */
175         while (fgets(buf, sizeof(buf), fp) != NULL) {
176                 (*lineno)++;
177                 ptr = buf;
178
179                 t1 = gettoken(&ptr, buf1, sizeof(buf1));
180                 t2 = gettoken(&ptr, buf2, sizeof(buf2));
181                 t3 = gettoken(&ptr, buf3, sizeof(buf3));
182
183                 if (buf1[0] == 0 || buf1[0] == '#')
184                         continue;
185
186                 /*
187                  *      See if it's the end of a section.
188                  */
189                 if (t1 == T_RCBRACE) {
190                         if (name1 == NULL || buf2[0]) {
191                                 log(L_ERR, "%s[%d]: syntax error #1",
192                                         cf, *lineno);
193                                 return NULL;
194                         }
195                         return cs;
196                 }
197
198                 /*
199                  * Perhaps a subsection.
200                  */
201
202                 if (t2 == T_LCBRACE) {
203                         css = conf_readsection(cf, lineno, fp, name2, buf1);
204                         if (css == NULL)
205                                 return NULL;
206                         for (csp = cs->sub; csp && csp->next; csp = csp->next)
207                                 ;
208                         if (csp == NULL)
209                                 cs->sub = css;
210                         else
211                                 csp->next = css;
212
213                         continue;               
214                 }
215
216                 /*
217                  *      Or, the beginning of a new section.
218                  */
219                 if (t3 == T_LCBRACE) {
220                         csn = conf_readsection(cf, lineno, fp, buf1, buf2);
221                         if (csn == NULL)
222                                 return NULL;
223                         /*
224                          *      Add this section after all others.
225                          */
226                         for (csp = cs; csp && csp->next; csp = csp->next)
227                                 ;
228                         if (csp == NULL)
229                                 cs = csn;
230                         else
231                                 csp->next = csn;
232                         continue;
233                 }
234
235                 /*
236                  *      Must be a normal attr = value line.
237                  */
238                 if (buf1[0] != 0 && buf2[0] == 0 && buf3[0] == 0) {
239                         t2 = T_OP_EQ;
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",
243                                 cf, *lineno);
244                         return NULL;
245                 }
246
247                 /*
248                  *      Ensure that the user can't add CONF_PAIRs
249                  *      with 'internal' names;
250                  */
251                 if (buf1[0] == '_') {
252                         log(L_ERR, "%s[%d]: Illegal configuration pair name",
253                                 cf, *lineno);
254                         return NULL;
255                 }
256
257                 /*
258                  *      Add this CONF_PAIR to our CONF_SECTION
259                  */
260                 cpn = cf_pair_alloc(buf1, buf3, t2);
261                 cf_pair_add(cs, cpn);
262         }
263
264         /*
265          *      See if EOF was unexpected ..
266          */
267         if (name1 != NULL) {
268                 log(L_ERR,      
269                         "%s[%d]: unexpected end of file", cf, *lineno);
270                 return NULL;
271         }
272
273         return cs;
274 }
275
276 /*
277  *      Read the config file.
278  */
279 CONF_SECTION *conf_read(const char *conffile)
280 {
281         FILE            *fp;
282         int             lineno = 0;
283
284         cf_section_free(config);
285         config = NULL;  
286
287         if ((fp = fopen(conffile, "r")) == NULL) {
288                 log(L_ERR, "cannot open %s: %s",
289                         conffile, strerror(errno));
290                 return NULL;
291         }
292
293         config = conf_readsection(conffile, &lineno, fp, NULL, NULL);
294         fclose(fp);
295
296         return config;
297 }
298
299 /* JLN
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/
303  */
304
305 int read_new_config_files(void)
306 {
307         char buffer[256];
308
309         /* Lets go for the new configuration files */
310
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");
314                 return -1;
315         }
316
317         /* JLN
318          * After this we should run
319          * generate_realms() and generate_clients()
320          *
321          * Fail if we can't generate list of clients
322          */
323
324         if (generate_clients() < 0) {
325                 log(L_ERR|L_CONS, "Error generation clients list");
326                 return -1;
327         }
328
329         /*
330          * If there isn't any realms it isn't fatal..
331          */
332         if (generate_realms() < 0) {
333                 log(L_ERR|L_CONS, "Error generation realms list");
334         }
335
336
337         return 0;       
338 }
339
340 /* JLN
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
343  */
344
345 static int generate_realms() 
346 {
347         CONF_SECTION    *cs;
348         REALM                   *c;
349         char                    *s, *authhost, *accthost;
350
351         realm_free(realms);
352         realms = NULL;
353
354         for (cs = config; cs; cs = cs->next) {
355                 if (strcmp(cs->name1, "realm") == 0) {
356                         /*
357                          * We've found a realm, allocate space for it
358                          */
359                         if ((c = malloc(sizeof(REALM))) == NULL) {
360                                 log(L_CONS|L_ERR, "Out of memory while generating realms list");
361                                 return -1;
362                         }
363                         memset(c, 0, sizeof(REALM));
364                         /*
365                          * An authhost must exist in the configuration
366                          */
367                         if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
368                                 log(L_CONS|L_ERR, 
369                                         "No authhost entry for realm: %s", 
370                                         cs->name2);
371                                 return -1;
372                         }
373                         if ((s = strchr(authhost, ':')) != NULL) {
374                                 *s++ = 0;
375                                 c->auth_port = atoi(s);
376                         } else {
377                                 c->auth_port = auth_port;
378                         }
379                         accthost = cf_section_value_find(cs, "accthost");
380                         if ((s =strchr(accthost, ':')) != NULL) {
381                                 *s++ = 0;
382                                 c->acct_port = atoi(s); 
383                         } else {
384                                 c->acct_port = acct_port;
385                         }
386                         if (strcmp(authhost, "LOCAL") != 0)
387                                 c->ipaddr = ip_getaddr(authhost);
388
389                         /* 
390                          * Double check length, just to be sure!
391                          */
392
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);
397                                 return -1;
398                         }
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);
403                                 return -1;
404                         }
405                         
406                         strcpy(c->realm, cs->name2);
407                         strcpy(c->server, authhost);    
408                         c->striprealm = 1;
409                         
410                         if ((cf_section_value_find(cs, "nostrip")) != NULL)
411                                 c->striprealm = 0;
412                         if ((cf_section_value_find(cs, "noacct")) != NULL)
413                                 c->acct_port = 0;
414                         if ((cf_section_value_find(cs, "trusted")) != NULL)
415                                 c->acct_port = 0;
416
417                         c->next = realms;
418                         realms = c;
419
420                 }
421         }
422
423         return 0;
424 }
425
426 /*
427  *      Free a RADCLIENT list.
428  */
429
430 static void clients_free(RADCLIENT *cl)
431 {
432         RADCLIENT *next;
433
434         while(cl) {
435                 next = cl->next;
436                 free(cl);
437                 cl = next;
438         }
439 }
440
441 /* JLN
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
444  */
445
446 static int generate_clients() 
447 {
448         CONF_SECTION    *cs;
449         RADCLIENT       *c;
450         char            *hostnm, *secret, *shortnm;
451
452         clients_free(clients);
453         clients = NULL;
454
455         for (cs = config; cs; cs = cs->next) {
456                 if (strcmp(cs->name1, "client") == 0) {
457                         /*
458                          * Check the lengths, we don't want any core dumps
459                          */
460                         hostnm = cs->name2;
461                         secret = cf_section_value_find(cs, "secret");
462                         shortnm = cf_section_value_find(cs, "shortname");
463
464                         if (strlen(secret) >= sizeof(c->secret)) {
465                                 log(L_ERR, "[%s]: secret of length %d is greater than the allowed maximum of %d.",
466                                     hostnm,
467                                     strlen(secret), sizeof(c->secret) - 1);
468                                 return -1;
469                         }
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.",
472                                     hostnm,
473                                     strlen(shortnm), sizeof(c->shortname) - 1);
474                                 return -1;
475                         }
476                         /*
477                          * The size is fine.. Let's create the buffer
478                          */
479                         if ((c = malloc(sizeof(RADCLIENT))) == NULL) {
480                                 log(L_CONS|L_ERR, "[%s]: out of memory while doint client",
481                                         hostnm);
482                                 return -1;
483                         }
484
485                         c->ipaddr = ip_getaddr(hostnm);
486                         strcpy(c->secret, secret);
487                         strcpy(c->shortname, shortnm);
488                         strcpy(c->longname, ip_hostname(c->ipaddr));
489
490                         c->next = clients;
491                         clients = c;
492                 }
493         }
494
495         return 0;
496 }
497
498 /* 
499  * Return a CONF_PAIR within a CONF_SECTION.
500  */
501
502 CONF_PAIR *cf_pair_find(CONF_SECTION *section, const char *name)
503 {
504         CONF_PAIR       *cp;
505
506         for (cp = section->cps; cp; cp = cp->next)
507                 if (strcmp(cp->attr, name) == 0)
508                         break;
509
510         return cp;
511 }
512
513 /*
514  * Return the value of a CONF_PAIR
515  */
516
517 char *cf_pair_value(CONF_PAIR *pair)
518 {
519         return (pair ? pair->value : NULL);
520 }
521
522
523 /* 
524  * Find a value in a CONF_SECTION
525  */
526 char *cf_section_value_find(CONF_SECTION *section, const char *attr)
527 {
528         CONF_PAIR       *cp;
529
530         cp = cf_pair_find(section, attr);
531
532         return (cp ? cp->value : NULL);
533 }
534
535 /*
536  * Return the next pair after a CONF_PAIR
537  * with a certain name (char *attr)
538  */
539
540 CONF_PAIR *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char *attr)
541 {
542         CONF_PAIR       *cp;
543
544         /*
545          * If pair is NULL this must be a first time run
546          * Find the pair with correct name
547          */
548
549         if (pair == NULL){
550                 cp = cf_pair_find(section, attr);
551         } else {
552                 cp = pair->next;
553         }
554
555         for (; cp; cp = cp->next)
556                 if (strcmp(cp->attr, attr) == 0)
557                         break;
558
559         return cp;
560 }
561
562 /*
563  * Find a CONF_SECTION
564  */
565
566 CONF_SECTION *cf_section_find(const char *name)
567 {
568         CONF_SECTION *cs;
569         
570         for (cs = config; cs; cs = cs->next)
571                 if (strcmp(cs->name1, name) == 0)
572                         break;
573
574         return cs;
575 }
576
577 /*
578  * Find a sub-section in a section
579  */
580
581 CONF_SECTION *cf_section_sub_find(CONF_SECTION *section, const char *name) {
582
583         CONF_SECTION *cs;
584         for (cs = section->sub; cs; cs = cs->next)
585                 if (strcmp(cs->name2, name) == 0)
586                         break;
587         
588         return cs;
589
590 }
591
592 /*
593  * Find the configuration section for a module
594  */
595
596 CONF_SECTION *cf_module_config_find(const char *modulename)
597 {
598         CONF_SECTION *cs;
599
600         for (cs = config; cs; cs = cs->next)
601                 if ((strcmp(cs->name1, "module") == 0)
602                         && (strcmp(cs->name2, modulename) == 0))
603                         break;
604
605         return cs;
606 }
607 #endif