#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>
#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,
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;
};
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
*/
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;
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:
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;
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;
/*
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;
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;
/*
* 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;
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;
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;
}
*/
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;
}
{
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",
/*
* 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;