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)) {
402 radlog(L_ERR, "%s[%d]: Host %s not found",
403 filename, cf_section_lineno(cs),
410 * Double check length, just to be sure!
412 if (strlen(authhost) >= sizeof(c->server)) {
413 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
414 filename, cf_section_lineno(cs),
415 (int) strlen(authhost),
416 (int) sizeof(c->server) - 1);
422 * No accthost means LOCAL
424 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
425 c->acct_ipaddr = htonl(INADDR_NONE);
428 if ((s = strchr(accthost, ':')) != NULL) {
430 c->acct_port = atoi(s);
432 c->acct_port = PW_ACCT_UDP_PORT;
434 if (strcmp(accthost, "LOCAL") == 0) {
436 * Local realms don't have an IP address,
439 c->acct_ipaddr = htonl(INADDR_NONE);
442 c->acct_ipaddr = ip_getaddr(accthost);
443 if (c->acct_ipaddr == htonl(INADDR_NONE)) {
444 radlog(L_ERR, "%s[%d]: Host %s not found",
445 filename, cf_section_lineno(cs),
451 if (strlen(accthost) >= sizeof(c->acct_server)) {
452 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
453 filename, cf_section_lineno(cs),
454 (int) strlen(accthost),
455 (int) sizeof(c->acct_server) - 1);
460 if (strlen(name2) >= sizeof(c->realm)) {
461 radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",
462 filename, cf_section_lineno(cs),
464 (int) sizeof(c->server) - 1);
468 strcpy(c->realm, name2);
469 if (authhost) strcpy(c->server, authhost);
470 if (accthost) strcpy(c->acct_server, accthost);
473 * If one or the other of authentication/accounting
474 * servers is set to LOCALHOST, then don't require
477 if ((c->ipaddr != htonl(INADDR_NONE)) ||
478 (c->acct_ipaddr != htonl(INADDR_NONE))) {
479 if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
480 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
481 filename, cf_section_lineno(cs), name2);
485 if (strlen(s) >= sizeof(c->secret)) {
486 radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
487 filename, cf_section_lineno(cs),
488 strlen(s), sizeof(c->secret) - 1);
491 strNcpy((char *)c->secret, s, sizeof(c->secret));
496 if ((cf_section_value_find(cs, "nostrip")) != NULL)
498 if ((cf_section_value_find(cs, "noacct")) != NULL)
500 if ((cf_section_value_find(cs, "trusted")) != NULL)
502 if ((cf_section_value_find(cs, "notrealm")) != NULL)
504 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
506 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
507 static const LRAD_NAME_NUMBER ldflags[] = {
509 { "round_robin", 1 },
513 c->ldflag = lrad_str2int(ldflags, t, -1);
514 if (c->ldflag == -1) {
515 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
516 filename, cf_section_lineno(cs),
522 c->ldflag = 0; /* non, make it fail-over */
525 c->acct_active = TRUE;
533 * And make these realms preferred over the ones
534 * in the 'realms' file.
536 *tail = mainconfig.realms;
537 mainconfig.realms = my_realms;
540 * Ensure that all of the flags agree for the realms.
542 * Yeah, it's O(N^2), but it's only once, and the
543 * maximum number of realms is small.
545 for(c = mainconfig.realms; c != NULL; c = c->next) {
549 * Check that we cannot load balance to LOCAL
550 * realms, as that doesn't make any sense.
552 if ((c->ldflag == 1) &&
553 ((c->ipaddr == htonl(INADDR_NONE)) ||
554 (c->acct_ipaddr == htonl(INADDR_NONE)))) {
555 radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
561 * Compare this realm to all others, to ensure
562 * that the configuration is consistent.
564 for (this = c->next; this != NULL; this = this->next) {
565 if (strcasecmp(c->realm, this->realm) != 0) {
570 * Same realm: Different load balancing
573 if (c->ldflag != this->ldflag) {
574 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
586 * Create the linked list of realms from the new configuration
587 * type. This way we don't have to change too much in the other
590 static RADCLIENT *generate_clients(const char *filename, CONF_SECTION *section)
594 char *hostnm, *secret, *shortnm, *netmask;
595 char *nastype, *login, *password;
599 for (cs = cf_subsection_find_next(section, NULL, "client");
601 cs = cf_subsection_find_next(section, cs, "client")) {
603 name2 = cf_section_name2(cs);
605 radlog(L_CONS|L_ERR, "%s[%d]: Missing client name",
606 filename, cf_section_lineno(cs));
611 * Check the lengths, we don't want any core dumps
615 if((secret = cf_section_value_find(cs, "secret")) == NULL) {
616 radlog(L_ERR, "%s[%d]: Missing secret for client: %s",
617 filename, cf_section_lineno(cs), name2);
622 if((shortnm = cf_section_value_find(cs, "shortname")) == NULL) {
623 radlog(L_ERR, "%s[%d]: Missing shortname for client: %s",
624 filename, cf_section_lineno(cs), name2);
629 netmask = strchr(hostnm, '/');
631 if (strlen(secret) >= sizeof(c->secret)) {
632 radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
633 filename, cf_section_lineno(cs),
634 strlen(secret), sizeof(c->secret) - 1);
639 if (strlen(shortnm) > sizeof(c->shortname)) {
640 radlog(L_ERR, "%s[%d]: Client short name of length %u is greater than the allowed maximum of %u.",
641 filename, cf_section_lineno(cs),
642 strlen(shortnm), sizeof(c->shortname) - 1);
647 if((nastype = cf_section_value_find(cs, "nastype")) != NULL) {
648 if(strlen(nastype) >= sizeof(c->nastype)) {
649 radlog(L_ERR, "%s[%d]: nastype of length %u longer than the allowed maximum of %u",
650 filename, cf_section_lineno(cs),
651 strlen(nastype), sizeof(c->nastype) - 1);
657 if((login = cf_section_value_find(cs, "login")) != NULL) {
658 if(strlen(login) >= sizeof(c->login)) {
659 radlog(L_ERR, "%s[%d]: login of length %u longer than the allowed maximum of %u",
660 filename, cf_section_lineno(cs),
661 strlen(login), sizeof(c->login) - 1);
667 if((password = cf_section_value_find(cs, "password")) != NULL) {
668 if(strlen(password) >= sizeof(c->password)) {
669 radlog(L_ERR, "%s[%d]: password of length %u longer than the allowed maximum of %u",
670 filename, cf_section_lineno(cs),
671 strlen(password), sizeof(c->password) - 1);
678 * The size is fine.. Let's create the buffer
680 c = rad_malloc(sizeof(RADCLIENT));
681 memset(c, 0, sizeof(RADCLIENT));
690 mask_length = atoi(netmask + 1);
691 if ((mask_length < 0) || (mask_length > 32)) {
692 radlog(L_ERR, "%s[%d]: Invalid value '%s' for IP network mask.",
693 filename, cf_section_lineno(cs), netmask + 1);
698 if (mask_length == 0) {
701 c->netmask = ~0 << (32 - mask_length);
705 c->netmask = htonl(c->netmask);
708 c->ipaddr = ip_getaddr(hostnm);
709 if (c->ipaddr == INADDR_NONE) {
710 radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
711 filename, cf_section_lineno(cs), hostnm);
717 * Update the client name again...
721 c->ipaddr &= c->netmask;
722 strcpy(c->longname, hostnm);
724 ip_hostname(c->longname, sizeof(c->longname),
728 strcpy((char *)c->secret, secret);
729 strcpy(c->shortname, shortnm);
731 strcpy(c->nastype, nastype);
733 strcpy(c->login, login);
735 strcpy(c->password, password);
746 * Code for handling listening on multiple ports.
748 static rad_listen_t listen_inst;
749 static const char *listen_type = NULL;
751 static const CONF_PARSER listen_config[] = {
752 { "ipaddr", PW_TYPE_IPADDR,
753 offsetof(rad_listen_t,ipaddr), NULL, "0.0.0.0" },
755 { "port", PW_TYPE_INTEGER,
756 offsetof(rad_listen_t,port), NULL, "0" },
758 { "type", PW_TYPE_STRING_PTR,
759 0, &listen_type, "" },
761 { NULL, -1, 0, NULL, NULL } /* end the list */
764 static const LRAD_NAME_NUMBER listen_compare[] = {
765 { "auth", RAD_LISTEN_AUTH },
766 { "acct", RAD_LISTEN_ACCT },
772 * Free a linked list of listeners;
774 static void listen_free(rad_listen_t *list)
777 rad_listen_t *next = list->next;
780 * The code below may have eaten the FD.
782 if (list->fd >= 0) close(list->fd);
790 * Binds a listener to a socket.
792 static int listen_bind(rad_listen_t *this)
794 struct sockaddr salocal;
795 struct sockaddr_in *sa;
800 * If the port is zero, then it means the appropriate
801 * thing from /etc/services.
803 if (this->port == 0) {
806 switch (this->type) {
807 case RAD_LISTEN_AUTH:
808 svp = getservbyname ("radius", "udp");
810 this->port = ntohs(svp->s_port);
812 this->port = PW_AUTH_UDP_PORT;
816 case RAD_LISTEN_ACCT:
817 svp = getservbyname ("radacct", "udp");
819 this->port = ntohs(svp->s_port);
821 this->port = PW_ACCT_UDP_PORT;
826 radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
832 * Find it in the old list, AFTER updating the port. If
833 * it's there, use that, rather than creating a new
834 * socket. This allows HUP's to re-use the old sockets,
835 * which means that packets waiting in the socket queue
837 for (last = &mainconfig.listen;
839 last = &((*last)->next)) {
840 if ((this->ipaddr == (*last)->ipaddr) &&
841 (this->type == (*last)->type) &&
842 (this->port == (*last)->port)) {
843 this->fd = (*last)->fd;
852 this->fd = socket(AF_INET, SOCK_DGRAM, 0);
858 #ifdef WITH_UDPFROMTO
860 * Initialize udpfromto for all sockets.
862 if (udpfromto_init(this->fd) != 0) {
863 radlog(L_ERR|L_CONS, "ERROR: udpfromto init failed.");
867 sa = (struct sockaddr_in *) &salocal;
868 memset ((char *) sa, '\0', sizeof(salocal));
869 sa->sin_family = AF_INET;
870 sa->sin_addr.s_addr = this->ipaddr;
871 sa->sin_port = htons(this->port);
873 if (bind(this->fd, &salocal, sizeof(*sa)) < 0) {
883 static int last_proxy_port = 0;
886 * Externally visible function for creating a new proxy LISTENER.
888 * For now, don't take ipaddr or port.
890 int proxy_new_listener(void)
895 this = rad_malloc(sizeof(*this));
897 memset(this, 0, sizeof(*this));
899 this->ipaddr = mainconfig.myip;
900 this->type = RAD_LISTEN_PROXY;
903 * Proxying was not previously defined: die.
905 if (last_proxy_port == 0) return -1;
908 * Keep going until we find an unused port.
910 for (port = last_proxy_port + 1; port < 64000; port++) {
912 if (listen_bind(this) == 0) {
915 last_proxy_port = port;
918 * Add the new listener to the list of
921 for (last = &mainconfig.listen;
923 last = &((*last)->next)) {
937 * Generate a list of listeners. Takes an input list of
938 * listeners, too, so we don't close sockets with waiting packets.
940 static int listen_init(const char *filename, rad_listen_t **head)
948 * Add to the end of the list.
950 for (last = head; *last != NULL; last = &((*last)->next)) {
955 * Find the first one (if any).
957 for (cs = cf_subsection_find_next(mainconfig.config,
960 cs = cf_subsection_find_next(mainconfig.config,
962 memset(&listen_inst, 0, sizeof(listen_inst));
965 * Fix errors for later.
967 if (cf_section_parse(cs, &listen_inst, listen_config) < 0) {
968 radlog(L_CONS|L_ERR, "%s[%d]: Error parsing listen section.",
969 filename, cf_section_lineno(cs));
974 listen_inst.type = lrad_str2int(listen_compare,
977 if (listen_inst.type == RAD_LISTEN_NONE) {
978 radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
979 filename, cf_section_lineno(cs));
983 this = rad_malloc(sizeof(*this));
984 memcpy(this, &listen_inst, sizeof(*this));
987 * And bind it to the port.
989 if (listen_bind(this) < 0) {
990 radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s:%d",
991 filename, cf_section_lineno(cs),
992 ip_ntoa(buffer, this->ipaddr), this->port);
998 last = &(this->next);
1002 * If we're proxying requests, open the proxy FD.
1003 * Otherwise, don't do anything.
1005 if (mainconfig.proxy_requests == TRUE) {
1016 * If there are no realms configured, don't
1017 * open the proxy port.
1019 for (realm = mainconfig.realms;
1021 realm = realm->next) {
1023 * Ignore LOCAL realms.
1025 if ((realm->ipaddr == htonl(INADDR_NONE)) &&
1026 (realm->acct_ipaddr == htonl(INADDR_NONE))) {
1032 * Loopback addresses
1034 if (realm->ipaddr == htonl(INADDR_LOOPBACK)) {
1039 if (realm->acct_ipaddr == htonl(INADDR_LOOPBACK)) {
1047 * No external realms. Don't open another port.
1049 if (num_realms == 0) {
1054 * All of the realms are localhost, don't open
1057 if (localhost && !otherhost) {
1058 proxy_ip = htonl(INADDR_LOOPBACK);
1061 * Multiple external realms, listen
1062 * on any address that will send packets.
1064 proxy_ip = htonl(INADDR_NONE);
1068 * Find the first authentication port,
1071 ipaddr = htonl(INADDR_NONE);
1072 for (auth = *head; auth != NULL; auth = auth->next) {
1074 * Listening on ANY, use that.
1076 if (ipaddr != htonl(INADDR_ANY)) {
1078 * Not set. Pick the first one.
1079 * Or, ANY, pick that.
1081 if ((ipaddr == htonl(INADDR_NONE)) ||
1082 (auth->ipaddr == htonl(INADDR_ANY))) {
1083 ipaddr = auth->ipaddr;
1086 * Else listening on multiple
1087 * IP's, use ANY for proxying.
1089 } else if (ipaddr != auth->ipaddr) {
1090 ipaddr = htonl(INADDR_ANY);
1093 if (auth->type == RAD_LISTEN_AUTH) {
1094 port = auth->port + 2;
1100 * Not found, pick an accounting port.
1102 if (port < 0) for (auth = *head; auth != NULL; auth = auth->next) {
1103 if (auth->type == RAD_LISTEN_ACCT) {
1104 port = auth->port + 1;
1110 * Still no port. Don't do anything.
1116 this = rad_malloc(sizeof(*this));
1117 memset(this, 0, sizeof(*this));
1120 * More checks to do the right thing.
1122 if (proxy_ip == htonl(INADDR_NONE)) {
1127 * Create the proxy socket.
1129 this->ipaddr = proxy_ip;
1130 this->type = RAD_LISTEN_PROXY;
1133 * Try to find a proxy port (value doesn't matter)
1135 for (this->port = port;
1138 if (listen_bind(this) == 0) {
1139 last_proxy_port = this->port;
1145 radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
1155 * Hack the OLD way of listening on a socket.
1157 static int old_listen_init(rad_listen_t **head)
1160 rad_listen_t *this, **last;
1163 * No "bind_address": all listen directives
1164 * are in the "listen" clauses.
1166 cp = cf_pair_find(mainconfig.config, "bind_address");
1171 this = rad_malloc(sizeof(*this));
1172 memset(this, 0, sizeof(*this));
1175 * Create the authentication socket.
1177 this->ipaddr = mainconfig.myip;
1178 this->type = RAD_LISTEN_AUTH;
1179 this->port = auth_port;
1181 if (listen_bind(this) < 0) {
1182 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", this->port);
1186 auth_port = this->port; /* may have been updated in listen_bind */
1188 last = &(this->next);
1191 * Open Accounting Socket.
1193 * If we haven't already gotten acct_port from /etc/services,
1194 * then make it auth_port + 1.
1196 this = rad_malloc(sizeof(*this));
1197 memset(this, 0, sizeof(*this));
1200 * Create the accounting socket.
1202 * The accounting port is always the authentication port + 1
1204 this->ipaddr = mainconfig.myip;
1205 this->type = RAD_LISTEN_ACCT;
1206 this->port = auth_port + 1;
1208 if (listen_bind(this) < 0) {
1209 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", this->port);
1219 #ifndef RADIUS_CONFIG
1220 #define RADIUS_CONFIG "radiusd.conf"
1223 CONF_SECTION *read_radius_conf_file(void)
1227 struct stat statbuf;
1229 if (stat(radius_dir, &statbuf) < 0) {
1230 radlog(L_ERR|L_CONS, "Errors reading %s: %s",
1231 radius_dir, strerror(errno));
1235 if ((statbuf.st_mode & S_IWOTH) != 0) {
1236 radlog(L_ERR|L_CONS, "Configuration directory %s is globally writable. Refusing to start due to insecure configuration.",
1242 if (0 && (statbuf.st_mode & S_IROTH) != 0) {
1243 radlog(L_ERR|L_CONS, "Configuration directory %s is globally readable. Refusing to start due to insecure configuration.",
1248 /* Lets go look for the new configuration files */
1249 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1250 if ((cs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
1255 * This allows us to figure out where, relative to
1256 * radiusd.conf, the other configuration files exist.
1258 cf_section_parse(cs, NULL, server_config);
1260 /* Initialize the dictionary */
1261 DEBUG2("read_config_files: reading dictionary");
1262 if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
1263 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
1265 cf_section_free(&cs);
1274 * Read config files.
1276 * This function can ONLY be called from the main server process.
1278 int read_mainconfig(int reload)
1280 struct rlimit core_limits;
1281 static int old_debug_level = -1;
1283 CONF_SECTION *cs, *oldcs;
1284 rad_listen_t *listener;
1285 RADCLIENT *c, *tail;
1288 radlog(L_INFO, "Starting - reading configuration files ...");
1290 radlog(L_INFO, "Reloading configuration files.");
1293 /* First read radiusd.conf */
1294 DEBUG2("reread_config: reading radiusd.conf");
1295 if ((cs = read_radius_conf_file()) == NULL) {
1297 (radlog_dir == NULL)) {
1298 radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
1300 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);
1306 * Free the old configuration items, and replace them
1307 * with the new ones.
1309 * Note that where possible, we do atomic switch-overs,
1310 * to ensure that the pointers are always valid.
1312 oldcs = mainconfig.config;
1313 mainconfig.config = cs;
1314 cf_section_free(&oldcs);
1316 /* old-style naslist file */
1317 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
1318 DEBUG2("read_config_files: reading naslist");
1319 if (read_naslist_file(buffer) < 0) {
1320 radlog(L_ERR|L_CONS, "Errors reading naslist");
1323 /* old-style clients file */
1324 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CLIENTS);
1325 DEBUG2("read_config_files: reading clients");
1326 if (read_clients_file(buffer) < 0) {
1327 radlog(L_ERR|L_CONS, "Errors reading clients");
1332 * Add to that, the *new* list of clients.
1334 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1335 c = generate_clients(buffer, mainconfig.config);
1341 * The new list of clients takes precedence over the old one.
1343 for (tail = c; tail->next != NULL; tail = tail->next) {
1346 tail->next = mainconfig.clients;
1347 mainconfig.clients = c;
1349 /* old-style realms file */
1350 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
1351 DEBUG2("read_config_files: reading realms");
1352 if (read_realms_file(buffer) < 0) {
1353 radlog(L_ERR|L_CONS, "Errors reading realms");
1358 * If there isn't any realms it isn't fatal..
1360 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1361 if (generate_realms(buffer) < 0) {
1366 * Register the %{config:section.subsection} xlat function.
1368 xlat_register("config", xlat_config, NULL);
1371 * Set the libraries debugging flag to whatever the main
1372 * flag is. Note that on a SIGHUP, to turn the debugging
1373 * off, we do other magic.
1375 * Increase the debug level, if the configuration file
1376 * says to, OR, if we're decreasing the debug from what it
1377 * was before, allow that, too.
1379 if ((mainconfig.debug_level > debug_flag) ||
1380 (mainconfig.debug_level <= old_debug_level)) {
1381 debug_flag = mainconfig.debug_level;
1383 librad_debug = debug_flag;
1384 old_debug_level = mainconfig.debug_level;
1387 * Go update our behaviour, based on the configuration
1391 /* Get the current maximum for core files. */
1392 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
1393 radlog(L_ERR|L_CONS, "Failed to get current core limit: %s", strerror(errno));
1397 if (mainconfig.allow_core_dumps) {
1398 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
1399 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
1404 * If we're running as a daemon, and core
1405 * dumps are enabled, log that information.
1407 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
1408 radlog(L_INFO|L_CONS, "Core dumps are enabled.");
1410 } else if (!debug_flag) {
1412 * Not debugging. Set the core size to zero, to
1413 * prevent security breaches. i.e. People
1414 * reading passwords from the 'core' file.
1416 struct rlimit limits;
1418 limits.rlim_cur = 0;
1419 limits.rlim_max = core_limits.rlim_max;
1421 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
1422 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
1429 * The first time around, ensure that we can write to the
1434 * We need root to do mkdir() and chown(), so we
1435 * do this before giving up root.
1437 radlogdir_iswritable(mainconfig.uid_name);
1441 #ifdef HAVE_SYS_PRCTL_H
1442 #ifdef HAVE_PR_SET_DUMPABLE
1443 if (mainconfig.allow_core_dumps) {
1444 if (prctl(PR_SET_DUMPABLE, 1) < 0) {
1445 radlog(L_ERR|L_CONS,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
1453 * Sanity check the configuration for internal
1456 if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
1457 mainconfig.reject_delay = mainconfig.cleanup_delay;
1461 * Initialize the old "bind_address" and "port", first.
1464 if (old_listen_init(&listener) < 0) {
1469 * Read the list of listeners.
1471 snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
1472 if (listen_init(buffer, &listener) < 0) {
1477 radlog(L_ERR|L_CONS, "Server is not configured to listen on any ports. Exiting.");
1481 listen_free(mainconfig.listen);
1482 mainconfig.listen = listener;
1488 * Free the configuration.
1490 int free_mainconfig(void)
1493 * Clean up the configuration data
1496 cf_section_free(&mainconfig.config);
1497 realm_free(mainconfig.realms);
1498 clients_free(mainconfig.clients);