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>
52 #ifdef HAVE_SYS_PRCTL_H
53 #include <sys/prctl.h>
57 #include "udpfromto.h"
61 struct main_config_t mainconfig;
64 * Local variables for stuff.
66 static uid_t server_uid;
67 static gid_t server_gid;
70 * These are not used anywhere else..
72 static const char *localstatedir = NULL;
73 static const char *prefix = NULL;
74 static int auth_port = 0;
77 * Map the proxy server configuration parameters to variables.
79 static CONF_PARSER proxy_config[] = {
80 { "retry_delay", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
81 { "retry_count", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
82 { "synchronous", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_synchronous, "no" },
83 { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
84 { "dead_time", PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
85 { "post_proxy_authorize", PW_TYPE_BOOLEAN, 0, &mainconfig.post_proxy_authorize, "yes" },
86 { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
87 { NULL, -1, 0, NULL, NULL }
91 * Security configuration for the server.
93 static CONF_PARSER security_config[] = {
94 { "max_attributes", PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
95 { "reject_delay", PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
96 { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
97 { NULL, -1, 0, NULL, NULL }
101 * A mapping of configuration file names to internal variables
103 static CONF_PARSER server_config[] = {
105 * FIXME: 'prefix' is the ONLY one which should be
106 * configured at compile time. Hard-coding it here is
107 * bad. It will be cleaned up once we clean up the
108 * hard-coded defines for the locations of the various
111 { "prefix", PW_TYPE_STRING_PTR, 0, &prefix, "/usr/local"},
112 { "localstatedir", PW_TYPE_STRING_PTR, 0, &localstatedir, "${prefix}/var"},
113 { "logdir", PW_TYPE_STRING_PTR, 0, &radlog_dir, "${localstatedir}/log"},
114 { "libdir", PW_TYPE_STRING_PTR, 0, &radlib_dir, "${prefix}/lib"},
115 { "radacctdir", PW_TYPE_STRING_PTR, 0, &radacct_dir, "${logdir}/radacct" },
116 { "hostname_lookups", PW_TYPE_BOOLEAN, 0, &librad_dodns, "no" },
118 { "snmp", PW_TYPE_BOOLEAN, 0, &mainconfig.do_snmp, "no" },
120 { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
121 { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
122 { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
123 { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
124 { "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },
125 { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
126 { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
127 { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
128 { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
129 { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
130 { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
131 { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
132 { "bind_address", PW_TYPE_IPADDR, 0, &mainconfig.myip, "*" },
133 { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
134 { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
135 { "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide, "no" },
136 { "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },
137 { "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },
138 { "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },
139 { "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },
140 { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
141 { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
142 { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
143 { "security", PW_TYPE_SUBSECTION, 0, security_config, NULL },
144 { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
145 { NULL, -1, 0, NULL, NULL }
149 * Xlat for %{config:section.subsection.attribute}
151 static int xlat_config(void *instance, REQUEST *request,
152 char *fmt, char *out,
154 RADIUS_ESCAPE_STRING func)
160 const char *start = fmt;
162 request = request; /* -Wunused */
163 instance = instance; /* -Wunused */
170 * Find the next section.
172 for (p = buffer; (*fmt != 0) && (*fmt != '.'); p++, fmt++) {
178 * The character is a '.', find a section (as the user
179 * has given us a subsection to find)
184 fmt++; /* skip the period */
187 next = cf_section_find(buffer);
189 next = cf_subsection_find_next(cs, NULL, buffer);
192 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
197 } else { /* no period, must be a conf-part */
198 cp = cf_pair_find(cs, buffer);
201 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
205 } /* until cp is non-NULL */
208 * Ensure that we only copy what's necessary.
210 * If 'outlen' is too small, then the output is chopped to fit.
212 value = cf_pair_value(cp);
214 if (outlen > strlen(value)) {
215 outlen = strlen(value) + 1;
219 return func(out, outlen, value);
224 * Recursively make directories.
226 static int r_mkdir(const char *part)
228 char *ptr, parentdir[500];
231 if (stat(part, &st) == 0)
234 ptr = strrchr(part, '/');
239 snprintf(parentdir, (ptr - part)+1, "%s", part);
241 if (r_mkdir(parentdir) != 0)
244 if (mkdir(part, 0770) != 0) {
245 fprintf(stderr, "mkdir(%s) error: %s\n", part, strerror(errno));
253 * Checks if the log directory is writeable by a particular user.
255 static int radlogdir_iswritable(const char *effectiveuser)
257 struct passwd *pwent;
259 if (radlog_dir[0] != '/')
262 if (r_mkdir(radlog_dir) != 0)
265 /* FIXME: do we have this function? */
266 if (strstr(radlog_dir, "radius") == NULL)
269 /* we have a logdir that mentions 'radius', so it's probably
270 * safe to chown the immediate directory to be owned by the normal
271 * process owner. we gotta do it before we give up root. -chad
274 if (!effectiveuser) {
278 pwent = getpwnam(effectiveuser);
280 if (pwent == NULL) /* uh oh! */
283 if (chown(radlog_dir, pwent->pw_uid, -1) != 0)
291 * Switch UID and GID to what is specified in the config file
293 static int switch_users(void)
296 if (mainconfig.gid_name != NULL) {
299 gr = getgrnam(mainconfig.gid_name);
301 if (errno == ENOMEM) {
302 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);
304 radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);
308 server_gid = gr->gr_gid;
309 if (setgid(server_gid) < 0) {
310 radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",
311 mainconfig.gid_name, strerror(errno));
315 server_gid = getgid();
319 if (mainconfig.uid_name != NULL) {
322 pw = getpwnam(mainconfig.uid_name);
324 if (errno == ENOMEM) {
325 radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);
327 radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);
331 server_uid = pw->pw_uid;
332 #ifdef HAVE_INITGROUPS
333 if (initgroups(mainconfig.uid_name, server_gid) < 0) {
334 if (errno != EPERM) {
335 radlog(L_ERR|L_CONS, "Failed setting supplementary groups for User %s: %s", mainconfig.uid_name, strerror(errno));
340 if (setuid(server_uid) < 0) {
341 radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));
350 * Create the linked list of realms from the new configuration type
351 * This way we don't have to change to much in the other source-files
353 static int generate_realms(const char *filename)
356 REALM *my_realms = NULL;
358 char *s, *t, *authhost, *accthost;
362 for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
364 cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {
365 name2 = cf_section_name2(cs);
367 radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",
368 filename, cf_section_lineno(cs));
372 * We've found a realm, allocate space for it
374 c = rad_malloc(sizeof(REALM));
375 memset(c, 0, sizeof(REALM));
380 * No authhost means LOCAL.
382 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
383 c->ipaddr = htonl(INADDR_NONE);
386 if ((s = strchr(authhost, ':')) != NULL) {
388 c->auth_port = atoi(s);
390 c->auth_port = PW_AUTH_UDP_PORT;
392 if (strcmp(authhost, "LOCAL") == 0) {
394 * Local realms don't have an IP address,
397 c->ipaddr = htonl(INADDR_NONE);
400 c->ipaddr = ip_getaddr(authhost);
401 if (c->ipaddr == htonl(INADDR_NONE)) {
403 radlog(L_ERR, "%s[%d]: Host %s not found",
404 filename, cf_section_lineno(cs),
411 * Double check length, just to be sure!
413 if (strlen(authhost) >= sizeof(c->server)) {
415 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
416 filename, cf_section_lineno(cs),
417 (int) strlen(authhost),
418 (int) sizeof(c->server) - 1);
424 * No accthost means LOCAL
426 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
427 c->acct_ipaddr = htonl(INADDR_NONE);
430 if ((s = strchr(accthost, ':')) != NULL) {
432 c->acct_port = atoi(s);
434 c->acct_port = PW_ACCT_UDP_PORT;
436 if (strcmp(accthost, "LOCAL") == 0) {
438 * Local realms don't have an IP address,
441 c->acct_ipaddr = htonl(INADDR_NONE);
444 c->acct_ipaddr = ip_getaddr(accthost);
445 if (c->acct_ipaddr == htonl(INADDR_NONE)) {
447 radlog(L_ERR, "%s[%d]: Host %s not found",
448 filename, cf_section_lineno(cs),
454 if (strlen(accthost) >= sizeof(c->acct_server)) {
456 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
457 filename, cf_section_lineno(cs),
458 (int) strlen(accthost),
459 (int) sizeof(c->acct_server) - 1);
464 if (strlen(name2) >= sizeof(c->realm)) {
466 radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",
467 filename, cf_section_lineno(cs),
469 (int) sizeof(c->server) - 1);
473 strcpy(c->realm, name2);
474 if (authhost) strcpy(c->server, authhost);
475 if (accthost) strcpy(c->acct_server, accthost);
478 * If one or the other of authentication/accounting
479 * servers is set to LOCALHOST, then don't require
482 if ((c->ipaddr != htonl(INADDR_NONE)) ||
483 (c->acct_ipaddr != htonl(INADDR_NONE))) {
484 if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
486 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
487 filename, cf_section_lineno(cs), name2);
491 if (strlen(s) >= sizeof(c->secret)) {
493 radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
494 filename, cf_section_lineno(cs),
495 strlen(s), sizeof(c->secret) - 1);
498 strNcpy((char *)c->secret, s, sizeof(c->secret));
503 if ((cf_section_value_find(cs, "nostrip")) != NULL)
505 if ((cf_section_value_find(cs, "noacct")) != NULL)
507 if ((cf_section_value_find(cs, "trusted")) != NULL)
509 if ((cf_section_value_find(cs, "notrealm")) != NULL)
511 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
513 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
514 static const LRAD_NAME_NUMBER ldflags[] = {
516 { "round_robin", 1 },
520 c->ldflag = lrad_str2int(ldflags, t, -1);
521 if (c->ldflag == -1) {
523 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
524 filename, cf_section_lineno(cs),
530 c->ldflag = 0; /* non, make it fail-over */
533 c->acct_active = TRUE;
541 * And make these realms preferred over the ones
542 * in the 'realms' file.
544 *tail = mainconfig.realms;
545 mainconfig.realms = my_realms;
548 * Ensure that all of the flags agree for the realms.
550 * Yeah, it's O(N^2), but it's only once, and the
551 * maximum number of realms is small.
553 for(c = mainconfig.realms; c != NULL; c = c->next) {
557 * Check that we cannot load balance to LOCAL
558 * realms, as that doesn't make any sense.
560 if ((c->ldflag == 1) &&
561 ((c->ipaddr == htonl(INADDR_NONE)) ||
562 (c->acct_ipaddr == htonl(INADDR_NONE)))) {
563 radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
569 * Compare this realm to all others, to ensure
570 * that the configuration is consistent.
572 for (this = c->next; this != NULL; this = this->next) {
573 if (strcasecmp(c->realm, this->realm) != 0) {
578 * Same realm: Different load balancing
581 if (c->ldflag != this->ldflag) {
582 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
594 * Create the linked list of realms from the new configuration
595 * type. This way we don't have to change too much in the other
598 static RADCLIENT *generate_clients(const char *filename, CONF_SECTION *section)
602 char *hostnm, *secret, *shortnm, *netmask;
603 char *nastype, *login, *password;
607 for (cs = cf_subsection_find_next(section, NULL, "client");
609 cs = cf_subsection_find_next(section, cs, "client")) {
611 name2 = cf_section_name2(cs);
613 radlog(L_CONS|L_ERR, "%s[%d]: Missing client name",
614 filename, cf_section_lineno(cs));
619 * Check the lengths, we don't want any core dumps
623 if((secret = cf_section_value_find(cs, "secret")) == NULL) {
624 radlog(L_ERR, "%s[%d]: Missing secret for client: %s",
625 filename, cf_section_lineno(cs), name2);
630 if((shortnm = cf_section_value_find(cs, "shortname")) == NULL) {
631 radlog(L_ERR, "%s[%d]: Missing shortname for client: %s",
632 filename, cf_section_lineno(cs), name2);
637 netmask = strchr(hostnm, '/');
639 if (strlen(secret) >= sizeof(c->secret)) {
640 radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
641 filename, cf_section_lineno(cs),
642 strlen(secret), sizeof(c->secret) - 1);
647 if (strlen(shortnm) > sizeof(c->shortname)) {
648 radlog(L_ERR, "%s[%d]: Client short name of length %u is greater than the allowed maximum of %u.",
649 filename, cf_section_lineno(cs),
650 strlen(shortnm), sizeof(c->shortname) - 1);
655 if((nastype = cf_section_value_find(cs, "nastype")) != NULL) {
656 if(strlen(nastype) >= sizeof(c->nastype)) {
657 radlog(L_ERR, "%s[%d]: nastype of length %u longer than the allowed maximum of %u",
658 filename, cf_section_lineno(cs),
659 strlen(nastype), sizeof(c->nastype) - 1);
665 if((login = cf_section_value_find(cs, "login")) != NULL) {
666 if(strlen(login) >= sizeof(c->login)) {
667 radlog(L_ERR, "%s[%d]: login of length %u longer than the allowed maximum of %u",
668 filename, cf_section_lineno(cs),
669 strlen(login), sizeof(c->login) - 1);
675 if((password = cf_section_value_find(cs, "password")) != NULL) {
676 if(strlen(password) >= sizeof(c->password)) {
677 radlog(L_ERR, "%s[%d]: password of length %u longer than the allowed maximum of %u",
678 filename, cf_section_lineno(cs),
679 strlen(password), sizeof(c->password) - 1);
686 * The size is fine.. Let's create the buffer
688 c = rad_malloc(sizeof(RADCLIENT));
689 memset(c, 0, sizeof(RADCLIENT));
698 mask_length = atoi(netmask + 1);
699 if ((mask_length < 0) || (mask_length > 32)) {
700 radlog(L_ERR, "%s[%d]: Invalid value '%s' for IP network mask.",
701 filename, cf_section_lineno(cs), netmask + 1);
707 if (mask_length == 0) {
710 c->netmask = ~0 << (32 - mask_length);
714 c->netmask = htonl(c->netmask);
717 c->ipaddr = ip_getaddr(hostnm);
718 if (c->ipaddr == INADDR_NONE) {
719 radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
720 filename, cf_section_lineno(cs), hostnm);
727 * Update the client name again...
731 c->ipaddr &= c->netmask;
732 strcpy(c->longname, hostnm);
734 ip_hostname(c->longname, sizeof(c->longname),
738 strcpy((char *)c->secret, secret);
739 strcpy(c->shortname, shortnm);
741 strcpy(c->nastype, nastype);
743 strcpy(c->login, login);
745 strcpy(c->password, password);
756 * Code for handling listening on multiple ports.
758 static rad_listen_t listen_inst;
759 static const char *listen_type = NULL;
761 static const CONF_PARSER listen_config[] = {
762 { "ipaddr", PW_TYPE_IPADDR,
763 offsetof(rad_listen_t,ipaddr), NULL, "0.0.0.0" },
765 { "port", PW_TYPE_INTEGER,
766 offsetof(rad_listen_t,port), NULL, "0" },
768 { "type", PW_TYPE_STRING_PTR,
769 0, &listen_type, "" },
771 { NULL, -1, 0, NULL, NULL } /* end the list */
774 static const LRAD_NAME_NUMBER listen_compare[] = {
775 { "auth", RAD_LISTEN_AUTH },
776 { "acct", RAD_LISTEN_ACCT },
782 * Free a linked list of listeners;
784 static void listen_free(rad_listen_t *list)
787 rad_listen_t *next = list->next;
790 * The code below may have eaten the FD.
792 if (list->fd >= 0) close(list->fd);
800 * Binds a listener to a socket.
802 static int listen_bind(rad_listen_t *this)
804 struct sockaddr salocal;
805 struct sockaddr_in *sa;
810 * If the port is zero, then it means the appropriate
811 * thing from /etc/services.
813 if (this->port == 0) {
816 switch (this->type) {
817 case RAD_LISTEN_AUTH:
818 svp = getservbyname ("radius", "udp");
820 this->port = ntohs(svp->s_port);
822 this->port = PW_AUTH_UDP_PORT;
826 case RAD_LISTEN_ACCT:
827 svp = getservbyname ("radacct", "udp");
829 this->port = ntohs(svp->s_port);
831 this->port = PW_ACCT_UDP_PORT;
836 radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
842 * Find it in the old list, AFTER updating the port. If
843 * it's there, use that, rather than creating a new
844 * socket. This allows HUP's to re-use the old sockets,
845 * which means that packets waiting in the socket queue
847 for (last = &mainconfig.listen;
849 last = &((*last)->next)) {
850 if ((this->ipaddr == (*last)->ipaddr) &&
851 (this->type == (*last)->type) &&
852 (this->port == (*last)->port)) {
853 this->fd = (*last)->fd;
862 this->fd = socket(AF_INET, SOCK_DGRAM, 0);
868 #ifdef WITH_UDPFROMTO
870 * Initialize udpfromto for all sockets.
872 if (udpfromto_init(this->fd) != 0) {
873 radlog(L_ERR|L_CONS, "ERROR: udpfromto init failed.");
877 sa = (struct sockaddr_in *) &salocal;
878 memset ((char *) sa, '\0', sizeof(salocal));
879 sa->sin_family = AF_INET;
880 sa->sin_addr.s_addr = this->ipaddr;
881 sa->sin_port = htons(this->port);
883 if (bind(this->fd, &salocal, sizeof(*sa)) < 0) {
893 static int last_proxy_port = 0;
896 * Externally visible function for creating a new proxy LISTENER.
898 * For now, don't take ipaddr or port.
900 int proxy_new_listener(void)
905 this = rad_malloc(sizeof(*this));
907 memset(this, 0, sizeof(*this));
909 this->ipaddr = mainconfig.myip;
910 this->type = RAD_LISTEN_PROXY;
913 * Proxying was not previously defined: die.
915 if (last_proxy_port == 0) {
921 * Keep going until we find an unused port.
923 for (port = last_proxy_port + 1; port < 64000; port++) {
925 if (listen_bind(this) == 0) {
928 last_proxy_port = port;
931 * Add the new listener to the list of
934 for (last = &mainconfig.listen;
936 last = &((*last)->next)) {
951 * Generate a list of listeners. Takes an input list of
952 * listeners, too, so we don't close sockets with waiting packets.
954 static int listen_init(const char *filename, rad_listen_t **head)
962 * Add to the end of the list.
964 for (last = head; *last != NULL; last = &((*last)->next)) {
969 * Find the first one (if any).
971 for (cs = cf_subsection_find_next(mainconfig.config,
974 cs = cf_subsection_find_next(mainconfig.config,
976 memset(&listen_inst, 0, sizeof(listen_inst));
979 * Fix errors for later.
981 if (cf_section_parse(cs, &listen_inst, listen_config) < 0) {
982 radlog(L_CONS|L_ERR, "%s[%d]: Error parsing listen section.",
983 filename, cf_section_lineno(cs));
988 listen_inst.type = lrad_str2int(listen_compare,
991 if (listen_inst.type == RAD_LISTEN_NONE) {
992 radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
993 filename, cf_section_lineno(cs));
997 this = rad_malloc(sizeof(*this));
998 memcpy(this, &listen_inst, sizeof(*this));
1001 * And bind it to the port.
1003 if (listen_bind(this) < 0) {
1004 radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s:%d",
1005 filename, cf_section_lineno(cs),
1006 ip_ntoa(buffer, this->ipaddr), this->port);
1012 last = &(this->next);
1016 * If we're proxying requests, open the proxy FD.
1017 * Otherwise, don't do anything.
1019 if (mainconfig.proxy_requests == TRUE) {
1030 * If there are no realms configured, don't
1031 * open the proxy port.
1033 for (realm = mainconfig.realms;
1035 realm = realm->next) {
1037 * Ignore LOCAL realms.
1039 if ((realm->ipaddr == htonl(INADDR_NONE)) &&
1040 (realm->acct_ipaddr == htonl(INADDR_NONE))) {
1046 * Loopback addresses
1048 if (realm->ipaddr == htonl(INADDR_LOOPBACK)) {
1053 if (realm->acct_ipaddr == htonl(INADDR_LOOPBACK)) {
1061 * No external realms. Don't open another port.
1063 if (num_realms == 0) {
1068 * All of the realms are localhost, don't open
1071 if (localhost && !otherhost) {
1072 proxy_ip = htonl(INADDR_LOOPBACK);
1075 * Multiple external realms, listen
1076 * on any address that will send packets.
1078 proxy_ip = htonl(INADDR_NONE);
1082 * Find the first authentication port,
1085 ipaddr = htonl(INADDR_NONE);
1086 for (auth = *head; auth != NULL; auth = auth->next) {
1088 * Listening on ANY, use that.
1090 if (ipaddr != htonl(INADDR_ANY)) {
1092 * Not set. Pick the first one.
1093 * Or, ANY, pick that.
1095 if ((ipaddr == htonl(INADDR_NONE)) ||
1096 (auth->ipaddr == htonl(INADDR_ANY))) {
1097 ipaddr = auth->ipaddr;
1100 * Else listening on multiple
1101 * IP's, use ANY for proxying.
1103 } else if (ipaddr != auth->ipaddr) {
1104 ipaddr = htonl(INADDR_ANY);
1107 if (auth->type == RAD_LISTEN_AUTH) {
1108 port = auth->port + 2;
1114 * Not found, pick an accounting port.
1116 if (port < 0) for (auth = *head; auth != NULL; auth = auth->next) {
1117 if (auth->type == RAD_LISTEN_ACCT) {
1118 port = auth->port + 1;
1124 * Still no port. Don't do anything.
1130 this = rad_malloc(sizeof(*this));
1131 memset(this, 0, sizeof(*this));
1134 * More checks to do the right thing.
1136 if (proxy_ip == htonl(INADDR_NONE)) {
1141 * Create the proxy socket.
1143 this->ipaddr = proxy_ip;
1144 this->type = RAD_LISTEN_PROXY;
1147 * Try to find a proxy port (value doesn't matter)
1149 for (this->port = port;
1152 if (listen_bind(this) == 0) {
1153 last_proxy_port = this->port;
1159 radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
1169 * Hack the OLD way of listening on a socket.
1171 static int old_listen_init(rad_listen_t **head)
1174 rad_listen_t *this, **last;
1177 * No "bind_address": all listen directives
1178 * are in the "listen" clauses.
1180 cp = cf_pair_find(mainconfig.config, "bind_address");
1185 this = rad_malloc(sizeof(*this));
1186 memset(this, 0, sizeof(*this));
1189 * Create the authentication socket.
1191 this->ipaddr = mainconfig.myip;
1192 this->type = RAD_LISTEN_AUTH;
1193 this->port = auth_port;
1195 if (listen_bind(this) < 0) {
1196 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", this->port);
1200 auth_port = this->port; /* may have been updated in listen_bind */
1202 last = &(this->next);
1205 * Open Accounting Socket.
1207 * If we haven't already gotten acct_port from /etc/services,
1208 * then make it auth_port + 1.
1210 this = rad_malloc(sizeof(*this));
1211 memset(this, 0, sizeof(*this));
1214 * Create the accounting socket.
1216 * The accounting port is always the authentication port + 1
1218 this->ipaddr = mainconfig.myip;
1219 this->type = RAD_LISTEN_ACCT;
1220 this->port = auth_port + 1;
1222 if (listen_bind(this) < 0) {
1223 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", this->port);
1233 #ifndef RADIUS_CONFIG
1234 #define RADIUS_CONFIG "radiusd.conf"
1237 CONF_SECTION *read_radius_conf_file(void)
1241 struct stat statbuf;
1243 if (stat(radius_dir, &statbuf) < 0) {
1244 radlog(L_ERR|L_CONS, "Errors reading %s: %s",
1245 radius_dir, strerror(errno));
1249 if ((statbuf.st_mode & S_IWOTH) != 0) {
1250 radlog(L_ERR|L_CONS, "Configuration directory %s is globally writable. Refusing to start due to insecure configuration.",
1256 if (0 && (statbuf.st_mode & S_IROTH) != 0) {
1257 radlog(L_ERR|L_CONS, "Configuration directory %s is globally readable. Refusing to start due to insecure configuration.",
1262 /* Lets go look for the new configuration files */
1263 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1264 if ((cs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
1269 * This allows us to figure out where, relative to
1270 * radiusd.conf, the other configuration files exist.
1272 cf_section_parse(cs, NULL, server_config);
1274 /* Initialize the dictionary */
1275 DEBUG2("read_config_files: reading dictionary");
1276 if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
1277 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
1279 cf_section_free(&cs);
1288 * Read config files.
1290 * This function can ONLY be called from the main server process.
1292 int read_mainconfig(int reload)
1294 struct rlimit core_limits;
1295 static int old_debug_level = -1;
1297 CONF_SECTION *cs, *oldcs;
1298 rad_listen_t *listener;
1299 RADCLIENT *c, *tail;
1302 radlog(L_INFO, "Starting - reading configuration files ...");
1304 radlog(L_INFO, "Reloading configuration files.");
1307 /* First read radiusd.conf */
1308 DEBUG2("reread_config: reading radiusd.conf");
1309 if ((cs = read_radius_conf_file()) == NULL) {
1311 (radlog_dir == NULL)) {
1312 radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
1314 radlog(L_ERR|L_CONS, "Errors reading %s/radiusd.conf: For more information, please read the tail end of %s", radius_dir, mainconfig.log_file);
1320 * Free the old configuration items, and replace them
1321 * with the new ones.
1323 * Note that where possible, we do atomic switch-overs,
1324 * to ensure that the pointers are always valid.
1326 oldcs = mainconfig.config;
1327 mainconfig.config = cs;
1328 cf_section_free(&oldcs);
1330 /* old-style naslist file */
1331 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
1332 DEBUG2("read_config_files: reading naslist");
1333 if (read_naslist_file(buffer) < 0) {
1334 radlog(L_ERR|L_CONS, "Errors reading naslist");
1337 /* old-style clients file */
1338 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CLIENTS);
1339 DEBUG2("read_config_files: reading clients");
1340 if (read_clients_file(buffer) < 0) {
1341 radlog(L_ERR|L_CONS, "Errors reading clients");
1346 * Add to that, the *new* list of clients.
1348 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1349 c = generate_clients(buffer, mainconfig.config);
1355 * The new list of clients takes precedence over the old one.
1357 for (tail = c; tail->next != NULL; tail = tail->next) {
1360 tail->next = mainconfig.clients;
1361 mainconfig.clients = c;
1363 /* old-style realms file */
1364 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
1365 DEBUG2("read_config_files: reading realms");
1366 if (read_realms_file(buffer) < 0) {
1367 radlog(L_ERR|L_CONS, "Errors reading realms");
1372 * If there isn't any realms it isn't fatal..
1374 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1375 if (generate_realms(buffer) < 0) {
1380 * Register the %{config:section.subsection} xlat function.
1382 xlat_register("config", xlat_config, NULL);
1385 * Set the libraries debugging flag to whatever the main
1386 * flag is. Note that on a SIGHUP, to turn the debugging
1387 * off, we do other magic.
1389 * Increase the debug level, if the configuration file
1390 * says to, OR, if we're decreasing the debug from what it
1391 * was before, allow that, too.
1393 if ((mainconfig.debug_level > debug_flag) ||
1394 (mainconfig.debug_level <= old_debug_level)) {
1395 debug_flag = mainconfig.debug_level;
1397 librad_debug = debug_flag;
1398 old_debug_level = mainconfig.debug_level;
1401 * Go update our behaviour, based on the configuration
1405 /* Get the current maximum for core files. */
1406 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
1407 radlog(L_ERR|L_CONS, "Failed to get current core limit: %s", strerror(errno));
1411 if (mainconfig.allow_core_dumps) {
1412 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
1413 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
1418 * If we're running as a daemon, and core
1419 * dumps are enabled, log that information.
1421 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
1422 radlog(L_INFO|L_CONS, "Core dumps are enabled.");
1424 } else if (!debug_flag) {
1426 * Not debugging. Set the core size to zero, to
1427 * prevent security breaches. i.e. People
1428 * reading passwords from the 'core' file.
1430 struct rlimit limits;
1432 limits.rlim_cur = 0;
1433 limits.rlim_max = core_limits.rlim_max;
1435 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
1436 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
1443 * The first time around, ensure that we can write to the
1448 * We need root to do mkdir() and chown(), so we
1449 * do this before giving up root.
1451 radlogdir_iswritable(mainconfig.uid_name);
1455 #ifdef HAVE_SYS_PRCTL_H
1456 #ifdef HAVE_PR_SET_DUMPABLE
1457 if (mainconfig.allow_core_dumps) {
1458 if (prctl(PR_SET_DUMPABLE, 1) < 0) {
1459 radlog(L_ERR|L_CONS,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
1467 * Sanity check the configuration for internal
1470 if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
1471 mainconfig.reject_delay = mainconfig.cleanup_delay;
1475 * Initialize the old "bind_address" and "port", first.
1478 if (old_listen_init(&listener) < 0) {
1483 * Read the list of listeners.
1485 snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
1486 if (listen_init(buffer, &listener) < 0) {
1491 radlog(L_ERR|L_CONS, "Server is not configured to listen on any ports. Exiting.");
1495 listen_free(mainconfig.listen);
1496 mainconfig.listen = listener;
1502 * Free the configuration.
1504 int free_mainconfig(void)
1507 * Clean up the configuration data
1510 cf_section_free(&mainconfig.config);
1511 realm_free(mainconfig.realms);
1512 clients_free(mainconfig.clients);
1513 read_naslist_file(NULL);
1516 listen_free(mainconfig.listen);
1517 paircompare_builtin_free();