2 * mainconf.c Handle the server's configuration.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2002 The FreeRADIUS server project
21 * Copyright 2002 Alan DeKok <aland@ox.org>
25 #include "libradius.h"
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
39 #include "rad_assert.h"
43 #include <sys/resource.h>
45 #include <sys/types.h>
46 #include <sys/socket.h>
54 #include "udpfromto.h"
58 struct main_config_t mainconfig;
61 * Local variables for stuff.
63 static uid_t server_uid;
64 static gid_t server_gid;
67 * These are not used anywhere else..
69 static const char *localstatedir = NULL;
70 static const char *prefix = NULL;
71 static int auth_port = 0;
74 * Map the proxy server configuration parameters to variables.
76 static CONF_PARSER proxy_config[] = {
77 { "retry_delay", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
78 { "retry_count", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
79 { "synchronous", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_synchronous, "no" },
80 { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
81 { "dead_time", PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
82 { "post_proxy_authorize", PW_TYPE_BOOLEAN, 0, &mainconfig.post_proxy_authorize, "yes" },
83 { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
84 { NULL, -1, 0, NULL, NULL }
88 * Security configuration for the server.
90 static CONF_PARSER security_config[] = {
91 { "max_attributes", PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
92 { "reject_delay", PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
93 { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
94 { NULL, -1, 0, NULL, NULL }
98 * A mapping of configuration file names to internal variables
100 static CONF_PARSER server_config[] = {
102 * FIXME: 'prefix' is the ONLY one which should be
103 * configured at compile time. Hard-coding it here is
104 * bad. It will be cleaned up once we clean up the
105 * hard-coded defines for the locations of the various
108 { "prefix", PW_TYPE_STRING_PTR, 0, &prefix, "/usr/local"},
109 { "localstatedir", PW_TYPE_STRING_PTR, 0, &localstatedir, "${prefix}/var"},
110 { "logdir", PW_TYPE_STRING_PTR, 0, &radlog_dir, "${localstatedir}/log"},
111 { "libdir", PW_TYPE_STRING_PTR, 0, &radlib_dir, "${prefix}/lib"},
112 { "radacctdir", PW_TYPE_STRING_PTR, 0, &radacct_dir, "${logdir}/radacct" },
113 { "hostname_lookups", PW_TYPE_BOOLEAN, 0, &librad_dodns, "no" },
115 { "snmp", PW_TYPE_BOOLEAN, 0, &mainconfig.do_snmp, "no" },
117 { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
118 { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
119 { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
120 { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
121 { "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },
122 { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
123 { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
124 { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
125 { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
126 { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
127 { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
128 { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
129 { "bind_address", PW_TYPE_IPADDR, 0, &mainconfig.myip, "*" },
130 { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
131 { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
132 { "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide, "no" },
133 { "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },
134 { "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },
135 { "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },
136 { "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },
137 { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
138 { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
139 { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
140 { "security", PW_TYPE_SUBSECTION, 0, security_config, NULL },
141 { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
142 { NULL, -1, 0, NULL, NULL }
146 * Xlat for %{config:section.subsection.attribute}
148 static int xlat_config(void *instance, REQUEST *request,
149 char *fmt, char *out,
151 RADIUS_ESCAPE_STRING func)
157 const char *start = fmt;
159 request = request; /* -Wunused */
160 instance = instance; /* -Wunused */
167 * Find the next section.
169 for (p = buffer; (*fmt != 0) && (*fmt != '.'); p++, fmt++) {
175 * The character is a '.', find a section (as the user
176 * has given us a subsection to find)
181 fmt++; /* skip the period */
184 next = cf_section_find(buffer);
186 next = cf_subsection_find_next(cs, NULL, buffer);
189 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
194 } else { /* no period, must be a conf-part */
195 cp = cf_pair_find(cs, buffer);
198 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
202 } /* until cp is non-NULL */
205 * Ensure that we only copy what's necessary.
207 * If 'outlen' is too small, then the output is chopped to fit.
209 value = cf_pair_value(cp);
211 if (outlen > strlen(value)) {
212 outlen = strlen(value) + 1;
216 return func(out, outlen, value);
221 * Recursively make directories.
223 static int r_mkdir(const char *part)
225 char *ptr, parentdir[500];
228 if (stat(part, &st) == 0)
231 ptr = strrchr(part, '/');
236 snprintf(parentdir, (ptr - part)+1, "%s", part);
238 if (r_mkdir(parentdir) != 0)
241 if (mkdir(part, 0770) != 0) {
242 fprintf(stderr, "mkdir(%s) error: %s\n", part, strerror(errno));
250 * Checks if the log directory is writeable by a particular user.
252 static int radlogdir_iswritable(const char *effectiveuser)
254 struct passwd *pwent;
256 if (radlog_dir[0] != '/')
259 if (r_mkdir(radlog_dir) != 0)
262 /* FIXME: do we have this function? */
263 if (strstr(radlog_dir, "radius") == NULL)
266 /* we have a logdir that mentions 'radius', so it's probably
267 * safe to chown the immediate directory to be owned by the normal
268 * process owner. we gotta do it before we give up root. -chad
271 if (!effectiveuser) {
275 pwent = getpwnam(effectiveuser);
277 if (pwent == NULL) /* uh oh! */
280 if (chown(radlog_dir, pwent->pw_uid, -1) != 0)
288 * Switch UID and GID to what is specified in the config file
290 static int switch_users(void)
293 if (mainconfig.gid_name != NULL) {
296 gr = getgrnam(mainconfig.gid_name);
298 if (errno == ENOMEM) {
299 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);
301 radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);
305 server_gid = gr->gr_gid;
306 if (setgid(server_gid) < 0) {
307 radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",
308 mainconfig.gid_name, strerror(errno));
312 server_gid = getgid();
316 if (mainconfig.uid_name != NULL) {
319 pw = getpwnam(mainconfig.uid_name);
321 if (errno == ENOMEM) {
322 radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);
324 radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);
328 server_uid = pw->pw_uid;
329 #ifdef HAVE_INITGROUPS
330 if (initgroups(mainconfig.uid_name, server_gid) < 0) {
331 if (errno != EPERM) {
332 radlog(L_ERR|L_CONS, "Failed setting supplementary groups for User %s: %s", mainconfig.uid_name, strerror(errno));
337 if (setuid(server_uid) < 0) {
338 radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));
347 * Create the linked list of realms from the new configuration type
348 * This way we don't have to change to much in the other source-files
350 static int generate_realms(const char *filename)
353 REALM *my_realms = NULL;
355 char *s, *t, *authhost, *accthost;
359 for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
361 cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {
362 name2 = cf_section_name2(cs);
364 radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",
365 filename, cf_section_lineno(cs));
369 * We've found a realm, allocate space for it
371 c = rad_malloc(sizeof(REALM));
372 memset(c, 0, sizeof(REALM));
377 * No authhost means LOCAL.
379 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
380 c->ipaddr = htonl(INADDR_NONE);
381 c->auth_port = auth_port;
383 if ((s = strchr(authhost, ':')) != NULL) {
385 c->auth_port = atoi(s);
387 c->auth_port = auth_port;
389 if (strcmp(authhost, "LOCAL") == 0) {
391 * Local realms don't have an IP address,
394 c->ipaddr = htonl(INADDR_NONE);
395 c->auth_port = auth_port;
397 c->ipaddr = ip_getaddr(authhost);
398 if (c->ipaddr == htonl(INADDR_NONE)) {
399 radlog(L_ERR, "%s[%d]: Host %s not found",
400 filename, cf_section_lineno(cs),
407 * Double check length, just to be sure!
409 if (strlen(authhost) >= sizeof(c->server)) {
410 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
411 filename, cf_section_lineno(cs),
412 (int) strlen(authhost),
413 (int) sizeof(c->server) - 1);
419 * No accthost means LOCAL
421 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
422 c->acct_ipaddr = htonl(INADDR_NONE);
425 if ((s = strchr(accthost, ':')) != NULL) {
427 c->acct_port = atoi(s);
429 c->acct_port = auth_port + 1;
431 if (strcmp(accthost, "LOCAL") == 0) {
433 * Local realms don't have an IP address,
436 c->acct_ipaddr = htonl(INADDR_NONE);
439 c->acct_ipaddr = ip_getaddr(accthost);
440 if (c->acct_ipaddr == htonl(INADDR_NONE)) {
441 radlog(L_ERR, "%s[%d]: Host %s not found",
442 filename, cf_section_lineno(cs),
448 if (strlen(accthost) >= sizeof(c->acct_server)) {
449 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
450 filename, cf_section_lineno(cs),
451 (int) strlen(accthost),
452 (int) sizeof(c->acct_server) - 1);
457 if (strlen(name2) >= sizeof(c->realm)) {
458 radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",
459 filename, cf_section_lineno(cs),
461 (int) sizeof(c->server) - 1);
465 strcpy(c->realm, name2);
466 if (authhost) strcpy(c->server, authhost);
467 if (accthost) strcpy(c->acct_server, accthost);
470 * If one or the other of authentication/accounting
471 * servers is set to LOCALHOST, then don't require
474 if ((c->ipaddr != htonl(INADDR_NONE)) ||
475 (c->acct_ipaddr != htonl(INADDR_NONE))) {
476 if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
477 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
478 filename, cf_section_lineno(cs), name2);
482 if (strlen(s) >= sizeof(c->secret)) {
483 radlog(L_ERR, "%s[%d]: Secret of length %d is greater than the allowed maximum of %d.",
484 filename, cf_section_lineno(cs),
485 strlen(s), sizeof(c->secret) - 1);
488 strNcpy((char *)c->secret, s, sizeof(c->secret));
493 if ((cf_section_value_find(cs, "nostrip")) != NULL)
495 if ((cf_section_value_find(cs, "noacct")) != NULL)
497 if ((cf_section_value_find(cs, "trusted")) != NULL)
499 if ((cf_section_value_find(cs, "notrealm")) != NULL)
501 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
503 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
504 static const LRAD_NAME_NUMBER ldflags[] = {
506 { "round_robin", 1 },
510 c->ldflag = lrad_str2int(ldflags, t, -1);
511 if (c->ldflag == -1) {
512 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
513 filename, cf_section_lineno(cs),
519 c->ldflag = 0; /* non, make it fail-over */
522 c->acct_active = TRUE;
530 * And make these realms preferred over the ones
531 * in the 'realms' file.
533 *tail = mainconfig.realms;
534 mainconfig.realms = my_realms;
537 * Ensure that all of the flags agree for the realms.
539 * Yeah, it's O(N^2), but it's only once, and the
540 * maximum number of realms is small.
542 for(c = mainconfig.realms; c != NULL; c = c->next) {
546 * Check that we cannot load balance to LOCAL
547 * realms, as that doesn't make any sense.
549 if ((c->ldflag == 1) &&
550 ((c->ipaddr == htonl(INADDR_NONE)) ||
551 (c->acct_ipaddr == htonl(INADDR_NONE)))) {
552 radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
558 * Compare this realm to all others, to ensure
559 * that the configuration is consistent.
561 for (this = c->next; this != NULL; this = this->next) {
562 if (strcasecmp(c->realm, this->realm) != 0) {
567 * Same realm: Different load balancing
570 if (c->ldflag != this->ldflag) {
571 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
583 * Create the linked list of realms from the new configuration
584 * type. This way we don't have to change too much in the other
587 static RADCLIENT *generate_clients(const char *filename, CONF_SECTION *section)
591 char *hostnm, *secret, *shortnm, *netmask;
592 char *nastype, *login, *password;
596 for (cs = cf_subsection_find_next(section, NULL, "client");
598 cs = cf_subsection_find_next(section, cs, "client")) {
600 name2 = cf_section_name2(cs);
602 radlog(L_CONS|L_ERR, "%s[%d]: Missing client name",
603 filename, cf_section_lineno(cs));
608 * Check the lengths, we don't want any core dumps
612 if((secret = cf_section_value_find(cs, "secret")) == NULL) {
613 radlog(L_ERR, "%s[%d]: Missing secret for client: %s",
614 filename, cf_section_lineno(cs), name2);
619 if((shortnm = cf_section_value_find(cs, "shortname")) == NULL) {
620 radlog(L_ERR, "%s[%d]: Missing shortname for client: %s",
621 filename, cf_section_lineno(cs), name2);
626 netmask = strchr(hostnm, '/');
628 if (strlen(secret) >= sizeof(c->secret)) {
629 radlog(L_ERR, "%s[%d]: Secret of length %d is greater than the allowed maximum of %d.",
630 filename, cf_section_lineno(cs),
631 strlen(secret), sizeof(c->secret) - 1);
636 if (strlen(shortnm) > sizeof(c->shortname)) {
637 radlog(L_ERR, "%s[%d]: Client short name of length %d is greater than the allowed maximum of %d.",
638 filename, cf_section_lineno(cs),
639 strlen(shortnm), sizeof(c->shortname) - 1);
644 if((nastype = cf_section_value_find(cs, "nastype")) != NULL) {
645 if(strlen(nastype) >= sizeof(c->nastype)) {
646 radlog(L_ERR, "%s[%d]: nastype of length %d longer than the allowed maximum of %d",
647 filename, cf_section_lineno(cs),
648 strlen(nastype), sizeof(c->nastype) - 1);
654 if((login = cf_section_value_find(cs, "login")) != NULL) {
655 if(strlen(login) >= sizeof(c->login)) {
656 radlog(L_ERR, "%s[%d]: login of length %d longer than the allowed maximum of %d",
657 filename, cf_section_lineno(cs),
658 strlen(login), sizeof(c->login) - 1);
664 if((password = cf_section_value_find(cs, "password")) != NULL) {
665 if(strlen(password) >= sizeof(c->password)) {
666 radlog(L_ERR, "%s[%d]: password of length %d longer than the allowed maximum of %d",
667 filename, cf_section_lineno(cs),
668 strlen(password), sizeof(c->password) - 1);
675 * The size is fine.. Let's create the buffer
677 c = rad_malloc(sizeof(RADCLIENT));
678 memset(c, 0, sizeof(RADCLIENT));
687 mask_length = atoi(netmask + 1);
688 if ((mask_length < 0) || (mask_length > 32)) {
689 radlog(L_ERR, "%s[%d]: Invalid value '%s' for IP network mask.",
690 filename, cf_section_lineno(cs), netmask + 1);
695 if (mask_length == 0) {
698 c->netmask = ~0 << (32 - mask_length);
702 c->netmask = htonl(c->netmask);
705 c->ipaddr = ip_getaddr(hostnm);
706 if (c->ipaddr == INADDR_NONE) {
707 radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
708 filename, cf_section_lineno(cs), hostnm);
714 * Update the client name again...
718 c->ipaddr &= c->netmask;
719 strcpy(c->longname, hostnm);
721 ip_hostname(c->longname, sizeof(c->longname),
725 strcpy((char *)c->secret, secret);
726 strcpy(c->shortname, shortnm);
728 strcpy(c->nastype, nastype);
730 strcpy(c->login, login);
732 strcpy(c->password, password);
743 * Code for handling listening on multiple ports.
745 static rad_listen_t listen_inst;
746 static const char *listen_type = NULL;
748 static const CONF_PARSER listen_config[] = {
749 { "ipaddr", PW_TYPE_IPADDR,
750 offsetof(rad_listen_t,ipaddr), NULL, "0.0.0.0" },
752 { "port", PW_TYPE_INTEGER,
753 offsetof(rad_listen_t,port), NULL, "0" },
755 { "type", PW_TYPE_STRING_PTR,
756 0, &listen_type, "" },
758 { NULL, -1, 0, NULL, NULL } /* end the list */
761 static const LRAD_NAME_NUMBER listen_compare[] = {
762 { "auth", RAD_LISTEN_AUTH },
763 { "acct", RAD_LISTEN_ACCT },
769 * Free a linked list of listeners;
771 static void listen_free(rad_listen_t *list)
774 rad_listen_t *next = list->next;
777 * The code below may have eaten the FD.
779 if (list->fd >= 0) close(list->fd);
787 * Binds a listener to a socket.
789 static int listen_bind(rad_listen_t *this)
791 struct sockaddr salocal;
792 struct sockaddr_in *sa;
797 * If the port is zero, then it means the appropriate
798 * thing from /etc/services.
800 if (this->port == 0) {
803 switch (this->type) {
804 case RAD_LISTEN_AUTH:
805 svp = getservbyname ("radius", "udp");
807 this->port = ntohs(svp->s_port);
809 this->port = PW_AUTH_UDP_PORT;
813 case RAD_LISTEN_ACCT:
814 svp = getservbyname ("radacct", "udp");
816 this->port = ntohs(svp->s_port);
818 this->port = PW_ACCT_UDP_PORT;
823 radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
829 * Find it in the old list, AFTER updating the port. If
830 * it's there, use that, rather than creating a new
831 * socket. This allows HUP's to re-use the old sockets,
832 * which means that packets waiting in the socket queue
834 for (last = &mainconfig.listen;
836 last = &((*last)->next)) {
837 if ((this->ipaddr == (*last)->ipaddr) &&
838 (this->type == (*last)->type) &&
839 (this->port == (*last)->port)) {
840 this->fd = (*last)->fd;
849 this->fd = socket(AF_INET, SOCK_DGRAM, 0);
855 #ifdef WITH_UDPFROMTO
857 * Initialize udpfromto for all sockets.
859 if (udpfromto_init(this->fd) != 0) {
860 radlog(L_ERR|L_CONS, "ERROR: udpfromto init failed.");
864 sa = (struct sockaddr_in *) &salocal;
865 memset ((char *) sa, '\0', sizeof(salocal));
866 sa->sin_family = AF_INET;
867 sa->sin_addr.s_addr = this->ipaddr;
868 sa->sin_port = htons(this->port);
870 if (bind(this->fd, &salocal, sizeof(*sa)) < 0) {
880 static int last_proxy_port = 0;
883 * Externally visible function for creating a new proxy LISTENER.
885 * For now, don't take ipaddr or port.
887 int proxy_new_listener(void)
892 this = rad_malloc(sizeof(*this));
894 memset(this, 0, sizeof(*this));
896 this->ipaddr = mainconfig.myip;
897 this->type = RAD_LISTEN_PROXY;
900 * Proxying was not previously defined: die.
902 if (last_proxy_port == 0) return -1;
905 * Keep going until we find an unused port.
907 for (port = last_proxy_port + 1; port < 64000; port++) {
909 if (listen_bind(this) == 0) {
912 last_proxy_port = port;
915 * Add the new listener to the list of
918 for (last = &mainconfig.listen;
920 last = &((*last)->next)) {
934 * Generate a list of listeners. Takes an input list of
935 * listeners, too, so we don't close sockets with waiting packets.
937 static int listen_init(const char *filename, rad_listen_t **head)
945 * Add to the end of the list.
947 for (last = head; *last != NULL; last = &((*last)->next)) {
952 * Find the first one (if any).
954 for (cs = cf_subsection_find_next(mainconfig.config,
957 cs = cf_subsection_find_next(mainconfig.config,
959 memset(&listen_inst, 0, sizeof(listen_inst));
962 * Fix errors for later.
964 if (cf_section_parse(cs, &listen_inst, listen_config) < 0) {
965 radlog(L_CONS|L_ERR, "%s[%d]: Error parsing listen section.",
966 filename, cf_section_lineno(cs));
971 listen_inst.type = lrad_str2int(listen_compare,
974 if (listen_inst.type == RAD_LISTEN_NONE) {
975 radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
976 filename, cf_section_lineno(cs));
980 this = rad_malloc(sizeof(*this));
981 memcpy(this, &listen_inst, sizeof(*this));
984 * And bind it to the port.
986 if (listen_bind(this) < 0) {
987 radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s:%d",
988 filename, cf_section_lineno(cs),
989 ip_ntoa(buffer, this->ipaddr), this->port);
995 last = &(this->next);
999 * If we're proxying requests, open the proxy FD.
1000 * Otherwise, don't do anything.
1002 if (mainconfig.proxy_requests == TRUE) {
1007 * Find the first authentication port,
1010 for (auth = *head; auth != NULL; auth = auth->next) {
1011 if (auth->type == RAD_LISTEN_AUTH) {
1012 port = auth->port + 2;
1018 * Not found, pick an accounting port.
1020 if (port < 0) for (auth = *head; auth != NULL; auth = auth->next) {
1021 if (auth->type == RAD_LISTEN_ACCT) {
1022 port = auth->port + 1;
1028 * Still no port. Don't do anything.
1034 this = rad_malloc(sizeof(*this));
1035 memset(this, 0, sizeof(*this));
1038 * Create the proxy socket.
1040 this->ipaddr = mainconfig.myip;
1041 this->type = RAD_LISTEN_PROXY;
1044 * Try to find a proxy port (value doesn't matter)
1046 for (this->port = port;
1049 if (listen_bind(this) == 0) {
1050 last_proxy_port = this->port;
1056 radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
1066 * Hack the OLD way of listening on a socket.
1068 static int old_listen_init(rad_listen_t **head)
1071 rad_listen_t *this, **last;
1074 * No "bind_address": all listen directives
1075 * are in the "listen" clauses.
1077 cp = cf_pair_find(mainconfig.config, "bind_address");
1082 this = rad_malloc(sizeof(*this));
1083 memset(this, 0, sizeof(*this));
1086 * Create the authentication socket.
1088 this->ipaddr = mainconfig.myip;
1089 this->type = RAD_LISTEN_AUTH;
1090 this->port = auth_port;
1092 if (listen_bind(this) < 0) {
1093 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", this->port);
1097 auth_port = this->port; /* may have been updated in listen_bind */
1099 last = &(this->next);
1102 * Open Accounting Socket.
1104 * If we haven't already gotten acct_port from /etc/services,
1105 * then make it auth_port + 1.
1107 this = rad_malloc(sizeof(*this));
1108 memset(this, 0, sizeof(*this));
1111 * Create the accounting socket.
1113 * The accounting port is always the authentication port + 1
1115 this->ipaddr = mainconfig.myip;
1116 this->type = RAD_LISTEN_ACCT;
1117 this->port = auth_port + 1;
1119 if (listen_bind(this) < 0) {
1120 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", this->port);
1130 #ifndef RADIUS_CONFIG
1131 #define RADIUS_CONFIG "radiusd.conf"
1134 CONF_SECTION *read_radius_conf_file(void)
1139 /* Lets go look for the new configuration files */
1140 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1141 if ((cs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
1146 * This allows us to figure out where, relative to
1147 * radiusd.conf, the other configuration files exist.
1149 cf_section_parse(cs, NULL, server_config);
1151 /* Initialize the dictionary */
1152 DEBUG2("read_config_files: reading dictionary");
1153 if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
1154 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
1156 cf_section_free(&cs);
1165 * Read config files.
1167 * This function can ONLY be called from the main server process.
1169 int read_mainconfig(int reload)
1171 struct rlimit core_limits;
1172 static int old_debug_level = -1;
1174 CONF_SECTION *cs, *oldcs;
1175 rad_listen_t *listener;
1176 RADCLIENT *c, *tail;
1179 radlog(L_INFO, "Starting - reading configuration files ...");
1181 radlog(L_INFO, "Reloading configuration files.");
1184 /* First read radiusd.conf */
1185 DEBUG2("reread_config: reading radiusd.conf");
1186 if ((cs = read_radius_conf_file()) == NULL) {
1188 (radlog_dir == NULL)) {
1189 radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
1191 radlog(L_ERR|L_CONS, "Errors reading %s/radiusd.conf: For more information, please read the tail end of %s", radlog_dir, mainconfig.log_file);
1197 * Free the old configuration items, and replace them
1198 * with the new ones.
1200 * Note that where possible, we do atomic switch-overs,
1201 * to ensure that the pointers are always valid.
1203 oldcs = mainconfig.config;
1204 mainconfig.config = cs;
1205 cf_section_free(&oldcs);
1207 /* old-style naslist file */
1208 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
1209 DEBUG2("read_config_files: reading naslist");
1210 if (read_naslist_file(buffer) < 0) {
1211 radlog(L_ERR|L_CONS, "Errors reading naslist");
1214 /* old-style clients file */
1215 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CLIENTS);
1216 DEBUG2("read_config_files: reading clients");
1217 if (read_clients_file(buffer) < 0) {
1218 radlog(L_ERR|L_CONS, "Errors reading clients");
1223 * Add to that, the *new* list of clients.
1225 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1226 c = generate_clients(buffer, mainconfig.config);
1232 * The new list of clients takes precedence over the old one.
1234 for (tail = c; tail->next != NULL; tail = tail->next) {
1237 tail->next = mainconfig.clients;
1238 mainconfig.clients = c;
1240 /* old-style realms file */
1241 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
1242 DEBUG2("read_config_files: reading realms");
1243 if (read_realms_file(buffer) < 0) {
1244 radlog(L_ERR|L_CONS, "Errors reading realms");
1249 * If there isn't any realms it isn't fatal..
1251 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1252 if (generate_realms(buffer) < 0) {
1257 * Register the %{config:section.subsection} xlat function.
1259 xlat_register("config", xlat_config, NULL);
1262 * Set the libraries debugging flag to whatever the main
1263 * flag is. Note that on a SIGHUP, to turn the debugging
1264 * off, we do other magic.
1266 * Increase the debug level, if the configuration file
1267 * says to, OR, if we're decreasing the debug from what it
1268 * was before, allow that, too.
1270 if ((mainconfig.debug_level > debug_flag) ||
1271 (mainconfig.debug_level <= old_debug_level)) {
1272 debug_flag = mainconfig.debug_level;
1274 librad_debug = debug_flag;
1275 old_debug_level = mainconfig.debug_level;
1278 * Go update our behaviour, based on the configuration
1282 /* Get the current maximum for core files. */
1283 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
1284 radlog(L_ERR|L_CONS, "Failed to get current core limit: %s", strerror(errno));
1288 if (mainconfig.allow_core_dumps) {
1289 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
1290 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
1295 * If we're running as a daemon, and core
1296 * dumps are enabled, log that information.
1298 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
1299 radlog(L_INFO|L_CONS, "Core dumps are enabled.");
1301 } else if (!debug_flag) {
1303 * Not debugging. Set the core size to zero, to
1304 * prevent security breaches. i.e. People
1305 * reading passwords from the 'core' file.
1307 struct rlimit limits;
1309 limits.rlim_cur = 0;
1310 limits.rlim_max = core_limits.rlim_max;
1312 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
1313 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
1320 * The first time around, ensure that we can write to the
1325 * We need root to do mkdir() and chown(), so we
1326 * do this before giving up root.
1328 radlogdir_iswritable(mainconfig.uid_name);
1333 * Sanity check the configuration for internal
1336 if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
1337 mainconfig.reject_delay = mainconfig.cleanup_delay;
1341 * Initialize the old "bind_address" and "port", first.
1344 if (old_listen_init(&listener) < 0) {
1349 * Read the list of listeners.
1351 snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
1352 if (listen_init(buffer, &listener) < 0) {
1357 radlog(L_ERR|L_CONS, "Server is not configured to listen on any ports. Exiting.");
1361 listen_free(mainconfig.listen);
1362 mainconfig.listen = listener;
1368 * Free the configuration.
1370 int free_mainconfig(void)
1373 * Clean up the configuration data
1376 cf_section_free(&mainconfig.config);
1377 realm_free(mainconfig.realms);
1378 clients_free(mainconfig.clients);