Massively cleaned up #include's, so they're in a consistent
[freeradius.git] / src / main / conffile.c
index 8384540..deac55e 100644 (file)
 #include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
-#include <freeradius-devel/autoconf.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_NETINET_IN_H
-#      include <netinet/in.h>
-#endif
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
 
 #ifdef HAVE_DIRENT_H
 #include <dirent.h>
@@ -48,10 +42,6 @@ RCSID("$Id$")
 
 #include <ctype.h>
 
-#include <freeradius-devel/radiusd.h>
-#include <freeradius-devel/rad_assert.h>
-#include <freeradius-devel/modules.h>
-
 typedef enum conf_type {
        CONF_ITEM_INVALID = 0,
        CONF_ITEM_PAIR,
@@ -81,6 +71,8 @@ struct conf_part {
        rbtree_t        *section_tree; /* no jokes here */
        rbtree_t        *name2_tree; /* for sections of the same name2 */
        rbtree_t        *data_tree;
+       void *base;
+       const CONF_PARSER *variables;
 };
 
 
@@ -262,6 +254,59 @@ static int data_cmp(const void *a, const void *b)
        return strcmp(one->name, two->name);
 }
 
+
+/*
+ *     Free strings we've parsed into data structures.
+ */
+static void cf_section_parse_free(void *base, const CONF_PARSER *variables)
+{
+       int i;
+
+       /*
+        *      Don't automatically free the strings if we're being
+        *      called from a module.  This is also for clients.c,
+        *      where client_free() expects to be able to free the
+        *      client structure.  If we moved everything to key off
+        *      of the config files, we might solve some problems...
+        */
+       if (!variables) return;
+
+       /*
+        *      Free up dynamically allocated string pointers.
+        */
+       for (i = 0; variables[i].name != NULL; i++) {
+               char **p;
+
+               if ((variables[i].type != PW_TYPE_STRING_PTR) &&
+                   (variables[i].type != PW_TYPE_FILENAME)) {
+                       continue;
+               }
+
+               /*
+                *      No base struct offset, data must be the pointer.
+                *      If data doesn't exist, ignore the entry, there
+                *      must be something wrong.
+                */
+               if (!base) {
+                       if (!variables[i].data) {
+                               continue;
+                       }
+
+                       p = (char **) variables[i].data;;
+
+               } else if (variables[i].data) {
+                       p = (char **) variables[i].data;;
+
+               } else {
+                       p = (char **) (((char *)base) + variables[i].offset);
+               }
+
+               free(*p);
+               *p = NULL;
+       }
+}
+
+
 /*
  *     Free a CONF_SECTION
  */
@@ -271,6 +316,10 @@ void cf_section_free(CONF_SECTION **cs)
 
        if (!cs || !*cs) return;
 
+       if ((*cs)->variables) {
+               cf_section_parse_free((*cs)->base, (*cs)->variables);
+       }
+
        for (ci = (*cs)->children; ci; ci = next) {
                next = ci->next;
 
@@ -705,14 +754,24 @@ int cf_item_parse(CONF_SECTION *cs, const char *name,
                        radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, name);
                        return -1;
                }
-               DEBUG2(" %s: %s = %s", cs->name1, name, value);
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %s", cs->name1, cs->name2, name, value);
+               } else {
+                       DEBUG2(" %s: %s = %s", cs->name1, name, value);
+               }
                break;
                
        case PW_TYPE_INTEGER:
                *(int *)data = strtol(value, 0, 0);
-               DEBUG2(" %s: %s = %d",
-                      cs->name1, name,
-                      *(int *)data);
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %d",
+                              cs->name1, cs->name2, name,
+                              *(int *)data);
+               } else {
+                       DEBUG2(" %s: %s = %d",
+                              cs->name1, name,
+                              *(int *)data);
+               }
                break;
                
        case PW_TYPE_STRING_PTR:
@@ -740,9 +799,15 @@ int cf_item_parse(CONF_SECTION *cs, const char *name,
                        if (!value) return -1;
                }
                
-               DEBUG2(" %s: %s = \"%s\"",
-                      cs->name1, name,
-                      value ? value : "(null)");
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = \"%s\"",
+                              cs->name1, cs->name2, name,
+                              value ? value : "(null)");
+               } else {
+                       DEBUG2(" %s: %s = \"%s\"",
+                              cs->name1, name,
+                              value ? value : "(null)");
+               }
                *q = value ? strdup(value) : NULL;
                break;
                
@@ -776,9 +841,15 @@ int cf_item_parse(CONF_SECTION *cs, const char *name,
                        if (!value) return -1;
                }
                
-               DEBUG2(" %s: %s = \"%s\"",
-                      cs->name1, name,
-                      value ? value : "(null)");
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = \"%s\"",
+                              cs->name1, cs->name2, name,
+                              value ? value : "(null)");
+               } else {
+                       DEBUG2(" %s: %s = \"%s\"",
+                              cs->name1, name,
+                              value ? value : "(null)");
+               }
                *q = value ? strdup(value) : NULL;
 
                /*
@@ -812,9 +883,15 @@ int cf_item_parse(CONF_SECTION *cs, const char *name,
                        radlog(L_ERR, "Can't find IP address for host %s", value);
                        return -1;
                }
-               DEBUG2(" %s: %s = %s IP address [%s]",
-                      cs->name1, name, value,
-                      ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %s IP address [%s]",
+                              cs->name1, cs->name2, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               } else {
+                       DEBUG2(" %s: %s = %s IP address [%s]",
+                              cs->name1, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               }
                *(uint32_t *) data = ipaddr.ipaddr.ip4addr.s_addr;
                break;
                
@@ -823,9 +900,15 @@ int cf_item_parse(CONF_SECTION *cs, const char *name,
                        radlog(L_ERR, "Can't find IPv6 address for host %s", value);
                        return -1;
                }
-               DEBUG2(" %s: %s = %s IPv6 address [%s]",
-                      cs->name1, name, value,
-                      ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %s IPv6 address [%s]",
+                              cs->name1, cs->name2, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               } else {
+                       DEBUG2(" %s: %s = %s IPv6 address [%s]",
+                              cs->name1, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               }
                memcpy(data, &ipaddr.ipaddr.ip6addr,
                       sizeof(ipaddr.ipaddr.ip6addr));
                break;
@@ -842,7 +925,7 @@ int cf_item_parse(CONF_SECTION *cs, const char *name,
 /*
  *     Parse a configuration section into user-supplied variables.
  */
-int cf_section_parse(const CONF_SECTION *cs, void *base,
+int cf_section_parse(CONF_SECTION *cs, void *base,
                     const CONF_PARSER *variables)
 {
        int i;
@@ -870,11 +953,13 @@ int cf_section_parse(const CONF_SECTION *cs, void *base,
 
                        if (!variables[i].dflt) {
                                DEBUG2("Internal sanity check 1 failed in cf_section_parse");
+                               cf_section_parse_free(base, variables);
                                return -1;
                        }
                        
                        if (cf_section_parse(subcs, base,
                                             (const CONF_PARSER *) variables[i].dflt) < 0) {
+                               cf_section_parse_free(base, variables);
                                return -1;
                        }
                        continue;
@@ -886,6 +971,7 @@ int cf_section_parse(const CONF_SECTION *cs, void *base,
                        data = ((char *)base) + variables[i].offset;
                } else {
                        DEBUG2("Internal sanity check 2 failed in cf_section_parse");
+                       cf_section_parse_free(base, variables);
                        return -1;
                }
 
@@ -894,46 +980,15 @@ int cf_section_parse(const CONF_SECTION *cs, void *base,
                 */
                if (cf_item_parse(cs, variables[i].name, variables[i].type,
                                  data, variables[i].dflt) < 0) {
+                       cf_section_parse_free(base, variables);
                        return -1;
                }
        } /* for all variables in the configuration section */
 
-       return 0;
-}
-
-
-/*
- *     Free strings we've parsed into data structures.
- */
-void cf_section_parse_free_strings(void *base, const CONF_PARSER *variables)
-{
-       int i;
-
-       if (!variables) return;
-       
-       /*
-        *      Free up dynamically allocated string pointers.
-        */
-       for (i = 0; variables[i].name != NULL; i++) {
-               char **p;
+       cs->base = base;
+       cs->variables = variables;
 
-               if ((variables[i].type != PW_TYPE_STRING_PTR) &&
-                   (variables[i].type != PW_TYPE_FILENAME)) {
-                       continue;
-               }
-               
-               /*
-                *      Prefer the data, if it's there.
-                *      Else use the base + offset.
-                */
-               if (variables[i].data) {
-                       p = (char **) &(variables[i].data);
-               } else {
-                       p = (char **) (((char *)base) + variables[i].offset);
-               }
-               free(*p);
-               *p = NULL;
-       }
+       return 0;
 }
 
 
@@ -1201,10 +1256,25 @@ int cf_file_include(const char *file, CONF_SECTION *cs)
 {
        FILE            *fp;
        int             lineno = 0;
-       struct stat     buf;
+       struct stat     statbuf;
+       time_t          *mtime;
 
        DEBUG2( "Config:   including file: %s", file);
 
+       if (stat(file, &statbuf) == 0) {
+               if ((statbuf.st_mode & S_IWOTH) != 0) {
+                       radlog(L_ERR|L_CONS, "Configuration file %s is globally writable.  Refusing to start due to insecure configuration.",
+                              file);
+                       return -1;
+               }
+
+               if (0 && (statbuf.st_mode & S_IROTH) != 0) {
+                       radlog(L_ERR|L_CONS, "Configuration file %s is globally readable.  Refusing to start due to insecure configuration.",
+                              file);
+                       return -1;
+               }
+       }
+
        fp = fopen(file, "r");
        if (!fp) {
                radlog(L_ERR|L_CONS, "Unable to open file \"%s\": %s",
@@ -1224,15 +1294,11 @@ int cf_file_include(const char *file, CONF_SECTION *cs)
        /*
         *      Add the filename to the section
         */
-       if (stat(file, &buf) == 0) {
-               time_t *mtime;
-               
-               mtime = rad_malloc(sizeof(*mtime));
-               *mtime = buf.st_mtime;
-               /* FIXME: error? */
-               cf_data_add_internal(cs, file, mtime, free,
-                                    PW_TYPE_FILENAME);
-       }
+       mtime = rad_malloc(sizeof(*mtime));
+       *mtime = statbuf.st_mtime;
+       /* FIXME: error? */
+       cf_data_add_internal(cs, file, mtime, free,
+                            PW_TYPE_FILENAME);
 
        fclose(fp);
        return 0;