The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
radiusd.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: f4b8538c7c579bf72e7a8e4a5a7c7ee905de82f0 $
19 *
20 * @file radiusd.c
21 * @brief Main loop of the radius server.
22 *
23 * @copyright 2000-2018 The FreeRADIUS server project
24 * @copyright 1999,2000 Miquel van Smoorenburg (miquels@cistron.nl)
25 * @copyright 2000 Alan DeKok (aland@freeradius.org)
26 * @copyright 2000 Alan Curry (pacman-radius@cqc.com)
27 * @copyright 2000 Jeff Carneal (jeff@apex.net)
28 * @copyright 2000 Chad Miller (cmiller@surfsouth.com)
29 */
30RCSID("$Id: f4b8538c7c579bf72e7a8e4a5a7c7ee905de82f0 $")
31
32#include <freeradius-devel/server/base.h>
33#include <freeradius-devel/server/dependency.h>
34#include <freeradius-devel/server/map_proc.h>
35#include <freeradius-devel/server/module.h>
36#include <freeradius-devel/server/radmin.h>
37#include <freeradius-devel/server/snmp.h>
38#include <freeradius-devel/server/state.h>
39#include <freeradius-devel/server/virtual_servers.h>
40#include <freeradius-devel/util/debug.h>
41#include <freeradius-devel/util/size.h>
42#include <freeradius-devel/util/strerror.h>
43
44#include <freeradius-devel/tls/base.h>
45#include <freeradius-devel/tls/log.h>
46
47#include <freeradius-devel/unlang/base.h>
48
49#include <freeradius-devel/util/misc.h>
50#include <freeradius-devel/util/syserror.h>
51
52#ifdef HAVE_CAPABILITY_H
53#include <freeradius-devel/util/cap.h>
54#endif
55
56#include <fcntl.h>
57#include <signal.h>
58#include <sys/file.h>
59#include <sys/mman.h>
60
61#ifdef HAVE_GETOPT_H
62# include <getopt.h>
63#endif
64
65#ifdef HAVE_SYS_WAIT_H
66# include <sys/wait.h>
67#endif
68#ifndef WEXITSTATUS
69# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
70#endif
71#ifndef WIFEXITED
72# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
73#endif
74
75#ifdef HAVE_SYSTEMD
76# include <systemd/sd-daemon.h>
77#endif
78
79#ifdef WITH_TLS
80# include <freeradius-devel/tls/version.h>
81#endif
82
83char const *radiusd_version = RADIUSD_VERSION_BUILD("FreeRADIUS");
84static pid_t radius_pid;
85char const *program = NULL;
86
87/*
88 * Configuration items.
89 */
90
91/*
92 * Static functions.
93 */
94static void usage(int status);
95
96static void sig_fatal (int);
97#ifdef SIGHUP
98static void sig_hup (int);
99#endif
100
101/** Configure talloc debugging features
102 *
103 * @param[in] config The main config.
104 * @return
105 * - 1 on config conflict.
106 * - 0 on success.
107 * - -1 on error.
108 */
110{
111 if (config->spawn_workers) {
112 if (config->talloc_memory_report) {
113 fr_strerror_printf("talloc_memory_report requires single threaded mode (-s | -X)");
114 return 1;
115 }
116 return 0;
117 }
118
119 if (!config->talloc_memory_report) {
120 talloc_disable_null_tracking();
121 return 0;
122 }
123
124 talloc_enable_null_tracking();
125
126 return 0;
127}
128
129
130/** Create module and xlat per-thread instances
131 *
132 */
133static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
134{
135 if (modules_rlm_thread_instantiate(ctx, el) < 0) return -1;
136
137 if (virtual_servers_thread_instantiate(ctx, el) < 0) return -1;
138
139 if (xlat_thread_instantiate(ctx, el) < 0) return -1;
140#ifdef WITH_TLS
141 if (fr_openssl_thread_init(main_config->openssl_async_pool_init,
142 main_config->openssl_async_pool_max) < 0) return -1;
143#endif
144 return 0;
145}
146
147/** Explicitly cleanup module/xlat resources
148 *
149 */
150static void thread_detach(UNUSED void *uctx)
151{
153
155
157}
158
159#define EXIT_WITH_FAILURE \
160do { \
161 ret = EXIT_FAILURE; \
162 goto cleanup; \
163} while (0)
164
165#define EXIT_WITH_SUCCESS \
166do { \
167 ret = EXIT_SUCCESS; \
168 goto cleanup; \
169} while (0)
170
172
174{
176
177 (void) fr_timer_in(tl, tl, &fr_time_sync_ev, when, false, fr_time_sync_event, NULL);
178 (void) fr_time_sync();
179}
180
181#ifndef NDEBUG
182/** Encourage the server to exit after a period of time
183 *
184 * @param[in] tl The main loop.
185 * @param[in] now Current time. Should be 0, when adding the event.
186 * @param[in] uctx Pointer to a fr_time_delta_t indicating how long
187 * the server should run before exit.
188 */
189static void fr_exit_after(fr_timer_list_t *tl, fr_time_t now, void *uctx)
190{
191 static fr_timer_t *ev;
192
193 fr_time_delta_t exit_after = *(fr_time_delta_t *)uctx;
194
195 if (fr_time_eq(now, fr_time_wrap(0))) {
196 if (fr_timer_in(tl, tl, &ev, exit_after, false, fr_exit_after, uctx) < 0) {
197 PERROR("%s: Failed inserting exit event", program);
198 }
199 return;
200 }
201
203}
204#endif
205
206#ifdef HAVE_CAPABILITY_H
207#define DUMP_CAPABILITIES(_phase) \
208{ \
209 char *cap_str; \
210 if (fr_cap_set_to_str(talloc_autofree_context(), &cap_str) < 0) { \
211 PWARN("Failed retrieving %s capabilities", _phase); \
212 } else { \
213 INFO("%s capabilities: %s", _phase, cap_str); \
214 talloc_free(cap_str); \
215 } \
216}
217#else
218#define DUMP_CAPABILITIES(_phase)
219#endif
220
221/** Entry point for the daemon
222 *
223 * @hidecallgraph
224 */
225int main(int argc, char *argv[])
226{
227 int status;
228 int c;
229 bool display_version = false;
230 bool radmin = false;
231 int from_child[2] = {-1, -1};
232 fr_schedule_t *sc = NULL;
233 int ret = EXIT_SUCCESS;
234
235 TALLOC_CTX *global_ctx = NULL;
236 main_config_t *config = NULL;
237 bool talloc_memory_report = false;
238
239 bool raddb_dir_set = false;
240
241 size_t pool_size = 0;
242 void *pool_page_start = NULL;
243 size_t pool_page_len = 0;
244 bool do_mprotect;
245
246#ifndef NDEBUG
247 fr_time_delta_t exit_after = fr_time_delta_wrap(0);
248#endif
249 /*
250 * Must be called first, so the handler is called last
251 */
253
254 /*
255 * Setup talloc callbacks so we get useful errors
256 */
257 (void) fr_talloc_fault_setup();
258
259 /*
260 * Set some default values
261 */
262 program = strrchr(argv[0], FR_DIR_SEP);
263 if (!program) {
264 program = argv[0];
265 } else {
266 program++;
267 }
268
269 /*
270 * We probably don't want to free the talloc global_ctx context
271 * directly, so we'll allocate a new context beneath it, and
272 * free that before any leak reports.
273 */
274 {
275 char *env;
276
277 /*
278 * If a FR_GLOBAL_POOL value is provided and
279 * is of a valid size, we pre-allocate a global
280 * memory pool, and mprotect() it once we're done
281 * parsing the global config.
282 *
283 * This lets us catch stray writes into global
284 * memory.
285 */
286 env = getenv("FR_GLOBAL_POOL");
287 if (env) {
288 if (fr_size_from_str(&pool_size, &FR_SBUFF_IN(env, strlen(env))) < 0) {
289 fr_perror("%s: Invalid pool size string \"%s\"", program, env);
291 }
292
293 /*
294 * Pre-allocate a global memory pool for the static
295 * config to exist in. We mprotect() this later to
296 * catch any stray writes.
297 */
299 &pool_page_start, &pool_page_len, 0, pool_size);
300 do_mprotect = true;
301 } else {
302 global_ctx = talloc_new(talloc_autofree_context());
303 do_mprotect = false;
304 }
305
306 if (!global_ctx) {
307 fprintf(stderr, "Failed allocating global context\n");
309 }
310 }
311
312 /*
313 * Allocate the main config structure.
314 * It's allocated so we can hang talloced buffers off it.
315 */
317 if (!config) {
318 fprintf(stderr, "Failed allocating main config");
320 }
321
323
324 config->daemonize = true;
325 config->spawn_workers = true;
326
327 fr_debug_lvl = 0;
329
330 /*
331 * Don't put output anywhere until we get told a little
332 * more.
333 */
335 default_log.fd = -1;
338
339 /*
340 * Set the panic action and enable other debugging facilities
341 */
342 if (fr_fault_setup(global_ctx, getenv("PANIC_ACTION"), argv[0]) < 0) {
343 fr_perror("%s: Failed installing fault handlers... continuing", program);
344 }
345
346 /* Process the options. */
347 while ((c = getopt(argc, argv, "Cd:D:e:fhi:l:Mmn:p:PrsS:tTvxX")) != -1) switch (c) {
348 case 'C':
349 check_config = true;
350 config->spawn_workers = false;
351 config->daemonize = false;
352 break;
353
354 case 'd':
356 raddb_dir_set = true;
357 break;
358
359 case 'D':
361 break;
362
363#ifndef NDEBUG
364 case 'e':
365 exit_after = fr_time_delta_from_sec(atoi(optarg));
366 break;
367#endif
368
369 case 'f':
370 config->daemonize = false;
371 break;
372
373 case 'h':
374 usage(EXIT_SUCCESS);
375 break;
376
377 case 'l':
378 if (strcmp(optarg, "stdout") == 0) goto do_stdout;
379
380 config->log_file = talloc_typed_strdup(global_ctx, optarg);
383 default_log.fd = open(config->log_file, O_WRONLY | O_APPEND | O_CREAT, 0640);
384 if (default_log.fd < 0) {
385 fprintf(stderr, "%s: Failed to open log file %s: %s\n",
386 program, config->log_file, fr_syserror(errno));
388 }
389 break;
390
391 case 'm':
392 config->allow_multiple_procs = true;
393 break;
394
395 case 'M':
396 config->talloc_memory_report = true;
397 break;
398
399 case 'n':
401 break;
402
403 case 'P': /* Force the PID to be written, even in -f mode */
404 config->write_pid = true;
405 break;
406
407 case 'r': /* internal radmin-style control interface */
408 config->spawn_workers = false;
409 config->daemonize = false;
410 radmin = true;
411 break;
412
413 case 's': /* Single process mode */
414 config->spawn_workers = false;
415 config->daemonize = false;
416 break;
417
418 case 'S': /* Migration support */
419 if (main_config_parse_option(optarg) < 0) {
420 fprintf(stderr, "%s: Unknown configuration option '%s'\n",
421 program, optarg);
423 }
424 break;
425
426 case 't': /* no child threads */
427 config->spawn_workers = false;
428 break;
429
430 case 'T': /* enable timestamps */
432 break;
433
434 case 'v':
435 display_version = true;
436 break;
437
438 case 'X':
439 config->spawn_workers = false;
440 config->daemonize = false;
441 fr_debug_lvl += 2;
443
444 do_stdout:
446 default_log.fd = STDOUT_FILENO;
447 break;
448
449 case 'x':
450 fr_debug_lvl++;
452 break;
453
454 default:
455 usage(EXIT_FAILURE);
456 break;
457 }
458
459 /*
460 * Allow the configuration directory to be set from an
461 * environment variable. This allows tests to change the
462 * configuration directory without changing the scripts
463 * being executed.
464 */
465 if (!raddb_dir_set) {
466 char const *raddb_dir = getenv("FREERADIUS_CONFIG_DIR");
467
468 if (raddb_dir) main_config_raddb_dir_set(config, raddb_dir);
469 }
470
471 /*
472 * We've now got enough information to check to see
473 * if another process is running with the same config.
474 */
475 config->debug_level = fr_debug_lvl;
476
477 /*
478 * Mismatch between the binary and the libraries it depends on.
479 */
481 fr_perror("%s", program);
483 }
484
486
487#ifdef WITH_TLS
488 /*
489 * Mismatch between build time OpenSSL and linked SSL, better to die
490 * here than segfault later.
491 */
493
494 /*
495 * Initialising OpenSSL once, here, is safer than having individual modules do it.
496 * Must be called before display_version to ensure relevant engines are loaded.
497 *
498 * fr_openssl_init() must be called before *ANY* OpenSSL functions are used, which is why
499 * it's called so early.
500 */
501 if (fr_openssl_init() < 0) EXIT_WITH_FAILURE;
502#endif
503
504 /*
505 * According to the talloc peeps, no two threads may modify any part of
506 * a ctx tree with a common root without synchronisation.
507 *
508 * So we can't run with a null context and threads.
509 */
510 if (talloc_config_set(config) != 0) {
511 fr_perror("%s", program);
513 }
514
515 /*
516 * Better here, so it doesn't matter whether we get passed -xv or -vx.
517 */
518 if (display_version) {
519 if (fr_debug_lvl == 0) fr_debug_lvl = 1;
521 default_log.fd = STDOUT_FILENO;
522
523 INFO("%s - %s", program, radiusd_version);
526 }
527
529
530 /*
531 * Under linux CAP_SYS_PTRACE is usually only available before setuid/setguid,
532 * so we need to check whether we can attach before calling those functions
533 * (in main_config_init()).
534 */
536
537 /*
538 * Write the PID always if we're running as a daemon.
539 */
540 if (config->daemonize) config->write_pid = true;
541
542 /*
543 * Initialize the DL infrastructure, which is used by the
544 * config file parser. Note that we pass an empty path
545 * here, as we haven't yet read the configuration file.
546 */
547 modules_init(NULL);
548
549 /*
550 * Initialise the top level dictionary hashes which hold
551 * the protocols.
552 */
553 if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
554 fr_perror("%s", program);
556 }
557
558#ifdef WITH_TLS
559 if (fr_tls_dict_init() < 0) {
560 fr_perror("%s", program);
562 }
563#endif
564
565 /*
566 * Setup the global structures for module lists
567 */
568 if (modules_rlm_init() < 0) {
569 fr_perror("%s", program);
571 }
572
573 if (virtual_servers_init() < 0) {
574 fr_perror("%s", program);
576 }
577
578 /*
579 * Load dictionary attributes used
580 * for requests.
581 */
582 if (request_global_init() < 0) {
583 fr_perror("%s", program);
585 }
586
587 /*
588 * Read the configuration files, BEFORE doing anything else.
589 */
591
592 if (!config->suppress_secrets) default_log.suppress_secrets = false;
593
594 /*
595 * Check we're the only process using this config.
596 */
597 if (!config->allow_multiple_procs) {
599 case 0: /* No other processes running */
600 break;
601
602 case -1: /* Permissions error - fail open */
603 PWARN("%s: Process concurrency checks disabled", program);
604 break;
605
606 case 1:
607 default: /* All other errors */
608 fr_perror("%s", program);
610 }
611 }
612
613 /*
614 * Set panic_action from the main config if one wasn't specified in the
615 * environment.
616 */
617 if (config->panic_action && !getenv("PANIC_ACTION") &&
618 (fr_fault_setup(global_ctx, config->panic_action, argv[0]) < 0)) {
619 fr_perror("%s: Failed configuring panic action", program);
621 }
622
623 /*
624 * This is very useful in figuring out why the panic_action didn't fire.
625 */
627
628 /*
629 * Track configuration versions. This lets us know if the configuration changed.
630 */
631 if (fr_debug_lvl) {
632 uint8_t digest[16];
633
634 cf_md5_final(digest);
635
636 digest[6] &= 0x0f; /* ver is 0b0100 at bits 48:51 */
637 digest[6] |= 0x40;
638 digest[8] &= ~0xc0; /* var is 0b10 at bits 64:65 */
639 digest[8] |= 0x80;
640
641 /*
642 * UUIDv4 format: 4-2-2-2-6
643 */
644 INFO("Configuration version: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
645 digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
646 digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
647 }
648
649 /*
650 * Call this again now we've loaded the configuration. Yes I know...
651 */
652 if (talloc_config_set(config) < 0) {
653 fr_perror("%s", program);
655 }
656
657 /*
658 * Check for vulnerabilities in the version of libssl were linked against.
659 */
660#ifdef WITH_TLS
661# ifdef ENABLE_OPENSSL_VERSION_CHECK
662 if (fr_openssl_version_check(config->allow_vulnerable_openssl) < 0) EXIT_WITH_FAILURE;
663# endif
664
665 /*
666 * Toggle FIPS mode
667 */
668 if (config->openssl_fips_mode_is_set &&
669 (fr_openssl_fips_mode(config->openssl_fips_mode) < 0)) EXIT_WITH_FAILURE;
670#endif
671
672 /*
673 * The systemd watchdog enablement must be checked before we
674 * daemonize, but the watchdog notifications can come from any
675 * process.
676 */
677#ifdef HAVE_SYSTEMD_WATCHDOG
678 if (!check_config) main_loop_set_sd_watchdog_interval();
679#else
680 /*
681 * If the default systemd unit file is used, but the server wasn't
682 * built with support for systemd, the status returned by systemctl
683 * will stay permanently as "activating".
684 *
685 * We detect this condition and warn about it here, using the
686 * presence of the NOTIFY_SOCKET environmental variable to determine
687 * whether we're running under systemd.
688 */
689 if (getenv("NOTIFY_SOCKET")) INFO("Built without support for systemd watchdog, but running under systemd");
690#endif
691
692 /*
693 * Don't allow radmin when checking the config.
694 */
695 if (check_config) radmin = false;
696
697 if (fr_radmin_start(config, radmin) < 0) EXIT_WITH_FAILURE;
698
699 /*
700 * Disconnect from session
701 */
702 if (config->daemonize) {
703 pid_t pid;
704 int devnull;
705
706 DUMP_CAPABILITIES("pre-fork");
707
708 /*
709 * Really weird things happen if we leave stdin open and call things like
710 * system() later.
711 */
712 devnull = open("/dev/null", O_RDWR);
713 if (devnull < 0) {
714 ERROR("Failed opening /dev/null: %s", fr_syserror(errno));
716 }
717 dup2(devnull, STDIN_FILENO);
718
719 close(devnull);
720
721 if (pipe(from_child) != 0) {
722 ERROR("Couldn't open pipe for child status: %s", fr_syserror(errno));
724 }
725
726 pid = fork();
727 if (pid < 0) {
728 ERROR("Couldn't fork: %s", fr_syserror(errno));
730 }
731
732 /*
733 * The parent exits, so the child can run in the background.
734 *
735 * As the child can still encounter an error during initialisation
736 * we do a blocking read on a pipe between it and the parent.
737 *
738 * Just before entering the event loop the child will send a success
739 * or failure message to the parent, via the pipe.
740 */
741 if (pid > 0) {
742 uint8_t child_ret;
743 int stat_loc;
744
745 /* So the pipe is correctly widowed if the child exits */
746 close(from_child[1]);
747
748 /*
749 * The child writes a 0x01 byte on success, and closes
750 * the pipe on error.
751 */
752 if ((read(from_child[0], &child_ret, 1) < 0)) child_ret = 0;
753
754 /* For cleanliness... */
755 close(from_child[0]);
756
757 /* Don't turn children into zombies */
758 if (child_ret == 0) {
759 waitpid(pid, &stat_loc, WNOHANG);
761 }
762
763#ifdef HAVE_SYSTEMD
764 /*
765 * Update the systemd MAINPID to be our child,
766 * as the parent is about to exit.
767 */
768 sd_notifyf(0, "MAINPID=%lu", (unsigned long)pid);
769#endif
770
771 goto cleanup;
772 /*
773 * The child needs to increment the semaphore as the parent
774 * is going to exit, and it will decrement the semaphore.
775 */
776 } else if (pid == 0) {
778 PWARN("%s: Failed incrementing exclusive proc semaphore in child", program);
779 }
780 }
781
782 /* so the pipe is correctly widowed if the parent exits?! */
783 close(from_child[0]);
784#ifdef HAVE_SETSID
785 setsid();
786#endif
787
788 DUMP_CAPABILITIES("post-fork");
789 } else {
790 DUMP_CAPABILITIES("pre-suid-down");
791 }
792
793 /*
794 * Ensure that we're using the CORRECT pid after forking, NOT the one
795 * we started with.
796 */
797 radius_pid = getpid();
798
799 /*
800 * Initialise the interpreter, registering operations.
801 */
803
805
806 /*
807 * Everything seems to have loaded OK, exit gracefully.
808 */
809 if (check_config) {
810 DEBUG("Configuration appears to be OK");
811 goto cleanup;
812 }
813
814 /*
815 * Initialise the SNMP stats structures
816 */
817 if (fr_snmp_init() < 0) {
818 PERROR("Failed initialising SNMP");
820 }
821
822 /*
823 * Initialize the global event loop which handles things like
824 * systemd.
825 *
826 * This has to be done post-fork in case we're using kqueue, where the
827 * queue isn't inherited by the child process.
828 */
829 if (main_loop_init() < 0) {
830 PERROR("Failed initialising main event loop");
832 }
833
834 /*
835 * Start the network / worker threads.
836 */
837 {
838 fr_event_list_t *el = NULL;
839 fr_schedule_config_t *schedule;
840
841 schedule = talloc_zero(global_ctx, fr_schedule_config_t);
842 schedule->max_workers = config->max_workers;
843 schedule->max_networks = config->max_networks;
844 schedule->stats_interval = config->stats_interval;
845
846 schedule->network.max_outstanding = config->worker.max_requests;
847 schedule->worker = config->worker;
848
849 /*
850 * Single server mode: use the global event list.
851 * Otherwise, each network thread will create
852 * its own event list.
853 */
854 if (!config->spawn_workers) {
856 }
857
858 /*
859 * Fix spurious messages
860 */
864 if (!sc) {
865 PERROR("Failed starting the scheduler");
867 }
868
869 /*
870 * Tell the virtual servers to open their sockets.
871 */
873 }
874
875 /*
876 * At this point, no one has any business *ever* going
877 * back to root uid.
878 */
880
881 DUMP_CAPABILITIES("post-suid-down");
882
883 /*
884 * Dropping down may change the RLIMIT_CORE value, so
885 * reset it back to what to should be here.
886 */
888
889 /*
890 * If we're debugging, then a CTRL-C will cause the server to die
891 * immediately. Use SIGTERM to shut down the server cleanly in
892 * that case.
893 */
894 if (fr_set_signal(SIGINT, sig_fatal) < 0) {
895 set_signal_error:
896 PERROR("Failed installing signal handler");
898 }
899
900#ifdef SIGQUIT
901 if (fr_set_signal(SIGQUIT, sig_fatal) < 0) goto set_signal_error;
902#endif
903
904 /*
905 * Now that we've set everything up, we can install the signal
906 * handlers. Before this, if we get any signal, we don't know
907 * what to do, so we might as well do the default, and die.
908 */
909#ifdef SIGPIPE
910 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
911 ERROR("Failed ignoring SIGPIPE: %s", fr_syserror(errno));
912 goto cleanup;
913 }
914#endif
915
916 if (fr_set_signal(SIGHUP, sig_hup) < 0) goto set_signal_error;
917 if (fr_set_signal(SIGTERM, sig_fatal) < 0) goto set_signal_error;
918
919 /*
920 * Write the PID after we've forked, so that we write the correct one.
921 */
922 if (config->write_pid) {
923 FILE *fp;
924
925 fp = fopen(config->pid_file, "w");
926 if (fp != NULL) {
927 /*
928 * @fixme What about following symlinks,
929 * and having it over-write a normal file?
930 */
931 fprintf(fp, "%d\n", (int) radius_pid);
932 fclose(fp);
933 } else {
934 ERROR("Failed creating PID file %s: %s", config->pid_file, fr_syserror(errno));
936 }
937 }
938
939 trigger_exec(NULL, NULL, "server.start", false, NULL);
940
941 /*
942 * Inform the parent (who should still be waiting) that the rest of
943 * initialisation went OK, and that it should exit with a 0 status.
944 * If we don't get this far, then we just close the pipe on exit, and the
945 * parent gets a read failure.
946 */
947 if (config->daemonize) {
948 if (write(from_child[1], "\001", 1) < 0) {
949 WARN("Failed informing parent of successful start: %s",
950 fr_syserror(errno));
951 }
952 close(from_child[1]);
953 }
954
955 /*
956 * Clear the libfreeradius error buffer.
957 */
959
960 /*
961 * Prevent anything from modifying the dictionaries
962 * they're now immutable.
963 */
965
966 /*
967 * Protect global memory - If something attempts
968 * to write to this memory we get a SIGBUS.
969 */
970 if (do_mprotect) {
971 if (mprotect(pool_page_start, pool_page_len, PROT_READ) < 0) {
972 PERROR("Protecting global memory failed: %s", fr_syserror(errno));
974 }
975 DEBUG("Global memory protected");
976 }
977
979#ifndef NDEBUG
980 if (fr_time_delta_ispos(exit_after)) fr_exit_after(main_loop_event_list()->tl, fr_time_wrap(0), &exit_after);
981#endif
982 /*
983 * Process requests until HUP or exit.
984 */
985 INFO("Ready to process requests"); /* we were actually ready a while ago, but oh well */
986 while ((status = main_loop_start()) == 0x80) {
988 }
989
990 /*
991 * Ignore the TERM signal: we're about to die.
992 */
993 if (unlikely(signal(SIGTERM, SIG_IGN) == SIG_ERR)) {
994 ERROR("Failed blocking SIGTERM, we may receive spurious signals: %s",
995 fr_syserror(errno));
996 }
997
998 /*
999 * Unprotect global memory
1000 */
1001 if (do_mprotect) {
1002 if (mprotect(pool_page_start, pool_page_len,
1003 PROT_READ | PROT_WRITE) < 0) {
1004 PERROR("Unprotecting global memory failed: %s", fr_syserror(errno));
1006 }
1007 DEBUG("Global memory unprotected");
1008 }
1009
1010 if (status < 0) {
1011 PERROR("Exiting due to internal error");
1012 ret = EXIT_FAILURE;
1013 } else {
1014 INFO("Exiting normally");
1015 ret = EXIT_SUCCESS;
1016 }
1017
1019
1020 /*
1021 * Fire signal and stop triggers after ignoring SIGTERM, so handlers are
1022 * not killed with the rest of the process group, below.
1023 */
1024 if (status == 2) trigger_exec(NULL, NULL, "server.signal.term", true, NULL);
1025 trigger_exec(NULL, NULL, "server.stop", false, NULL);
1026
1027 /*
1028 * Stop the scheduler, this signals the network and worker threads
1029 * to exit gracefully. fr_schedule_destroy only returns once all
1030 * threads have been joined.
1031 */
1032 (void) fr_schedule_destroy(&sc);
1033
1034 /*
1035 * We're exiting, so we can delete the PID file.
1036 * (If it doesn't exist, we can ignore the error returned by unlink)
1037 */
1038 if (config->daemonize) {
1039 DEBUG3("Unlinking PID file %s", config->pid_file);
1040 unlink(config->pid_file);
1041 }
1042
1043 /*
1044 * Free memory in an explicit and consistent order
1045 *
1046 * We could let everything be freed by the global_ctx
1047 * context, but in some cases there are odd interactions
1048 * with destructors that may cause double frees and
1049 * SEGVs.
1050 */
1051 if (!config->spawn_workers) {
1053
1056 }
1057
1059
1060 /*
1061 * Send a TERM signal to all associated processes
1062 * (including us, which gets ignored.)
1063 *
1064 * This _shouldn't_ be needed, but may help with
1065 * processes created by the exec code or triggers.
1066 */
1067 if (config->spawn_workers) {
1068 INFO("All threads have exited, sending SIGTERM to remaining children");
1069
1070 /*
1071 * If pid is negative, but not -1, sig
1072 * shall be sent to all processes
1073 * (excluding an unspecified set of system processes)
1074 * whose process group ID is equal to the absolute value
1075 * of pid, and for which the process has permission
1076 * to send a signal.
1077 */
1078 kill(-getpgid(radius_pid), SIGTERM);
1079 }
1080
1081 /*
1082 * Remove the semaphore, allowing other processes
1083 * to start. We do this before the cleanup label
1084 * as the parent process MUST NOT call this
1085 * function as it exits, otherwise the semaphore
1086 * is removed and there's no exclusivity.
1087 */
1089
1090cleanup:
1091 /*
1092 * This may not have been done earlier if we're
1093 * exiting due to a startup error.
1094 */
1095 (void) fr_schedule_destroy(&sc);
1096
1097 /*
1098 * Ensure all thread local memory is cleaned up
1099 * before we start cleaning up global resources.
1100 * This is necessary for single threaded mode
1101 * to ensure that thread local resources that
1102 * depend on global resources are freed at the
1103 * appropriate time.
1104 */
1106
1107 server_free();
1108
1109#ifdef WITH_TLS
1110 fr_openssl_free(); /* Cleanup any memory alloced by OpenSSL and placed into globals */
1111#endif
1112
1113 if (config) talloc_memory_report = config->talloc_memory_report; /* Grab this before we free the config */
1114
1115 /*
1116 * Virtual servers need to be freed before modules
1117 * as state entries containing data with module-specific
1118 * destructors may exist.
1119 */
1121
1122 /*
1123 * Free modules, this needs to be done explicitly
1124 * because some libraries used by modules use atexit
1125 * handlers registered after ours, and they may deinit
1126 * themselves before we free the modules and cause
1127 * crashes on exit.
1128 */
1130
1131#ifdef WITH_TLS
1132 fr_tls_dict_free();
1133#endif
1134
1135 /*
1136 * And now nothing should be left anywhere except the
1137 * parsed configuration items.
1138 */
1140
1141 /*
1142 * Cleanup everything else
1143 */
1144 if (talloc_free(global_ctx) < 0) {
1145#ifndef NDEBUG
1146 fr_perror("program");
1147 ret = EXIT_FAILURE;
1148#endif
1149 }
1150
1151 /*
1152 * Anything not cleaned up by the above is allocated in
1153 * the NULL top level context, and is likely leaked memory.
1154 */
1155 if (talloc_memory_report) fr_log_talloc_report(NULL);
1156
1157 /*
1158 * If we're running under LSAN, try and SUID back up so
1159 * we don't inteferere with the onexit() handler.
1160 */
1162 fr_strerror_clear(); /* clear error buffer */
1163
1164 /*
1165 * Ensure our atexit handlers run before any other
1166 * atexit handlers registered by third party libraries.
1167 */
1169
1170 return ret;
1171}
1172
1173/*
1174 * Display the syntax for starting this program.
1175 */
1176static NEVER_RETURNS void usage(int status)
1177{
1178 FILE *output = status ? stderr : stdout;
1179
1180 fprintf(output, "Usage: %s [options]\n", program);
1181 fprintf(output, "Options:\n");
1182 fprintf(output, " -C Check configuration and exit.\n");
1183 fprintf(stderr, " -d <raddb> Set configuration directory (defaults to " RADDBDIR ").\n");
1184 fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
1185#ifndef NDEBUG
1186 fprintf(output, " -e <seconds> Exit after the specified number of seconds. Useful for diagnosing \"crash-on-exit\" issues.\n");
1187#endif
1188 fprintf(output, " -f Run as a foreground process, not a daemon.\n");
1189 fprintf(output, " -h Print this help message.\n");
1190 fprintf(output, " -l <log_file> Logging output will be written to this file.\n");
1191#ifndef NDEBUG
1192 fprintf(output, " -L <size> When running in memory debug mode, set a hard limit on talloced memory\n");
1193#endif
1194 fprintf(output, " -n <name> Read raddb/name.conf instead of raddb/%s.conf.\n", program);
1195 fprintf(output, " -m Allow multiple processes reading the same %s.conf to exist simultaneously.\n", program);
1196#ifndef NDEBUG
1197 fprintf(output, " -M Enable talloc memory debugging, and issue a memory report when the server terminates\n");
1198#endif
1199 fprintf(output, " -P Always write out PID, even with -f.\n");
1200 fprintf(output, " -s Do not spawn child processes to handle requests (same as -ft).\n");
1201 fprintf(output, " -S <flag> Set migration flags to assist with upgrades from version 3. Flags are:\n\n");
1202 fprintf(output, " rewrite_update=no Use the old v3 interpreter for 'update' sections.\n");
1203 fprintf(output, " forbid_update=yes Error if the old v3 'update' section is used.\n");
1204 fprintf(output, " v3_enum_names=yes Do not use '::' as the prefix for enumeration names,\n");
1205 fprintf(output, " AND require '&' for all attribute names.\n");
1206 fprintf(output, " -t Disable threads.\n");
1207 fprintf(output, " -T Prepend timestamps to log messages.\n");
1208 fprintf(output, " -v Print server version information.\n");
1209 fprintf(output, " -X Turn on full debugging (similar to -tfxxl stdout).\n");
1210 fprintf(output, " -x Turn on additional debugging (-xx gives more debugging).\n");
1211 fr_exit(status);
1212}
1213
1214
1215/*
1216 * We got a fatal signal.
1217 */
1218static void sig_fatal(int sig)
1219{
1220 static int last_sig;
1221
1222 if (getpid() != radius_pid) _exit(sig);
1223
1224 /*
1225 * Suppress duplicate signals.
1226 *
1227 * For some reason on macOS we get multiple signals
1228 * for the same event (SIGINT).
1229 *
1230 * ...this also fixes the problem of the user hammering
1231 * Ctrl-C and causing ungraceful exits as we try and
1232 * write out signals to a pipe that's already closed.
1233 */
1234 if (sig == last_sig) return;
1235 last_sig = sig;
1236
1237 switch (sig) {
1238 case SIGTERM:
1240 break;
1241
1242 case SIGINT:
1243#ifdef SIGQUIT
1244 case SIGQUIT:
1245#endif
1247 break;
1248
1249 default:
1250 fr_exit(sig);
1251 }
1252}
1253
1254#ifdef SIGHUP
1255/*
1256 * We got the hangup signal.
1257 * Re-read the configuration files.
1258 */
1259static void sig_hup(UNUSED int sig)
1260{
1261 reset_signal(SIGHUP, sig_hup);
1262
1264}
1265#endif
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
Definition atexit.c:160
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition atexit.c:286
#define fr_atexit_thread_trigger_all(...)
Definition atexit.h:233
void fr_radmin_stop(void)
Definition radmin.c:1101
int fr_radmin_start(main_config_t *config, bool cli)
Definition radmin.c:1064
#define RCSID(id)
Definition build.h:485
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:315
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
bool check_config
Definition cf_file.c:62
void cf_md5_final(uint8_t *digest)
Definition cf_file.c:3184
char const * fr_debug_state_to_msg(fr_debug_state_t state)
Return current value of debug_state.
Definition debug.c:541
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition debug.c:1147
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
Definition debug.c:890
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition debug.c:1242
int fr_get_lsan_state(void)
Definition debug.c:261
void fr_debug_state_store(void)
Should be run before using setuid or setgid to get useful results.
Definition debug.c:521
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition debug.c:1223
fr_debug_state_t fr_debug_state
Whether we're attached to by a debugger.
Definition debug.c:104
#define fr_exit(_x)
Exit, producing a log message in debug builds.
Definition debug.h:228
void dependency_version_print(void)
Definition dependency.c:375
int rad_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition dependency.c:70
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:114
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir)
Initialise the global protocol hashes.
Definition dict_util.c:4394
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
Definition dict_util.c:4587
void fr_dict_global_ctx_read_only(void)
Mark all dictionaries and the global dictionary ctx as read only.
Definition dict_util.c:4505
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4612
uint32_t max_outstanding
Definition network.h:46
int server_init(CONF_SECTION *cs, char const *dict_dir, fr_dict_t *dict)
Initialize src/lib/server/.
Definition base.c:42
void server_free(void)
Free src/lib/server/.
Definition base.c:130
#define PERROR(_fmt,...)
Definition log.h:228
#define DEBUG3(_fmt,...)
Definition log.h:266
#define PWARN(_fmt,...)
Definition log.h:227
void rad_suid_up(void)
Definition util.c:880
bool rad_suid_is_down_permanent(void)
Return whether we've permanently dropped root privileges.
Definition util.c:901
void(*)(int) reset_signal(int signo, void(*func)(int))
Definition util.c:47
void rad_suid_down_permanent(void)
Definition util.c:889
int unlang_global_init(void)
Definition base.c:133
waitpid(reap->pid_ev->pid, &status, 0)
talloc_free(reap)
void fr_event_loop_exit(fr_event_list_t *el, int code)
Signal an event loop exit with the specified code.
Definition event.c:2372
Stores all information relating to an event list.
Definition event.c:377
int fr_debug_lvl
Definition log.c:40
static FILE * devnull
File handle for /dev/null.
Definition log.c:56
fr_log_t default_log
Definition log.c:288
@ L_DST_NULL
Discard log messages.
Definition log.h:83
@ L_DST_FILES
Log to a file on disk.
Definition log.h:79
@ L_DST_STDOUT
Log to stdout.
Definition log.h:78
@ L_TIMESTAMP_ON
Always log timestamps.
Definition log.h:90
int main_config_parse_option(char const *value)
int main_config_free(main_config_t **config)
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
void main_config_raddb_dir_set(main_config_t *config, char const *name)
Set the global radius config directory.
void main_config_exclusive_proc_done(UNUSED main_config_t const *config)
Clean up the semaphore when the main config is freed.
void main_config_hup(main_config_t *config)
int main_config_exclusive_proc(main_config_t *config)
Check to see if we're the only process using this configuration file (or PID file if specified)
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
Set the server name.
int main_config_init(main_config_t *config)
main_config_t const * main_config
Main server configuration.
Definition main_config.c:58
int main_config_exclusive_proc_child(UNUSED main_config_t const *config)
Increment the semaphore in the child process so that it's not released when the parent exits.
void main_config_dict_dir_set(main_config_t *config, char const *name)
Set the global dictionary directory.
Main server configuration.
Definition main_config.h:51
int main_loop_start(void)
Definition main_loop.c:194
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
Definition main_loop.c:164
void main_loop_signal_raise(int flag)
Definition main_loop.c:78
int main_loop_init(void)
Initialise the main event loop, setting up signal handlers.
Definition main_loop.c:253
void main_loop_free(void)
Definition main_loop.c:189
@ RADIUS_SIGNAL_SELF_HUP
Definition main_loop.h:36
@ RADIUS_SIGNAL_SELF_TERM
Definition main_loop.h:37
unsigned char uint8_t
int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
Definition misc.c:47
void modules_rlm_thread_detach(void)
Frees thread-specific data for all registered backend modules.
Definition module_rlm.c:949
int modules_rlm_free(void)
Cleanup all global structures.
int modules_rlm_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Allocates thread-specific data for all registered backend modules.
Definition module_rlm.c:962
int modules_rlm_init(void)
Initialise the module list structure.
static const conf_parser_t config[]
Definition base.c:183
#define WARN(fmt,...)
Definition radclient.h:47
#define INFO(fmt,...)
Definition radict.c:54
int main(int argc, char *argv[])
Entry point for the daemon.
Definition radiusd.c:225
static void thread_detach(UNUSED void *uctx)
Explicitly cleanup module/xlat resources.
Definition radiusd.c:150
static void fr_exit_after(fr_timer_list_t *tl, fr_time_t now, void *uctx)
Encourage the server to exit after a period of time.
Definition radiusd.c:189
static void fr_time_sync_event(fr_timer_list_t *tl, UNUSED fr_time_t now, UNUSED void *uctx)
Definition radiusd.c:173
#define DUMP_CAPABILITIES(_phase)
Definition radiusd.c:218
#define EXIT_WITH_SUCCESS
Definition radiusd.c:165
char const * radiusd_version
Definition radiusd.c:83
static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
Create module and xlat per-thread instances.
Definition radiusd.c:133
static int talloc_config_set(main_config_t *config)
Configure talloc debugging features.
Definition radiusd.c:109
static void sig_fatal(int)
Definition radiusd.c:1218
static pid_t radius_pid
Definition radiusd.c:84
#define EXIT_WITH_FAILURE
Definition radiusd.c:159
static fr_timer_t * fr_time_sync_ev
Definition radiusd.c:171
char const * program
Definition radiusd.c:85
static bool cleanup
Definition radsniff.c:60
int request_global_init(void)
Definition request.c:589
#define FR_SBUFF_IN(_start, _len_or_end)
fr_schedule_t * fr_schedule_create(TALLOC_CTX *ctx, fr_event_list_t *el, fr_log_t *logger, fr_log_lvl_t lvl, fr_schedule_thread_instantiate_t worker_thread_instantiate, fr_schedule_thread_detach_t worker_thread_detach, fr_schedule_config_t *config)
Create a scheduler and spawn the child threads.
Definition schedule.c:466
int fr_schedule_destroy(fr_schedule_t **sc_to_free)
Destroy a scheduler, and tell its child threads to exit.
Definition schedule.c:768
The scheduler.
Definition schedule.c:125
fr_network_config_t network
configuration for each network;
Definition schedule.h:68
uint32_t max_workers
number of network threads
Definition schedule.h:65
fr_worker_config_t worker
configuration for each worker
Definition schedule.h:67
fr_time_delta_t stats_interval
print channel statistics
Definition schedule.h:70
uint32_t max_networks
number of network threads
Definition schedule.h:64
Signals that can be sent to a request.
fr_slen_t fr_size_from_str(size_t *out, fr_sbuff_t *in)
Parse a size string with optional unit.
Definition size.c:40
static const uchar sc[16]
Definition smbdes.c:115
int fr_snmp_init(void)
Initialise the tree of SNMP map structures used to attach callbacks to OIDs.
Definition snmp.c:1130
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition module.c:1904
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
fr_log_dst_t dst
Log destination.
Definition log.h:97
int fd
File descriptor to write messages to.
Definition log.h:112
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
Definition log.h:110
bool suppress_secrets
suppress secrets when printing to this destination
Definition log.h:108
char const * file
Path to log file.
Definition log.h:113
bool print_level
sometimes we don't want log levels printed
Definition log.h:106
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
static TALLOC_CTX * global_ctx
Definition talloc.c:32
TALLOC_CTX * talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, size_t *end_len, unsigned int headers, size_t size)
Return a page aligned talloc memory pool.
Definition talloc.c:308
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:441
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:51
int fr_time_sync(void)
Get a new fr_time_monotonic_to_realtime value.
Definition time.c:102
int fr_time_start(void)
Initialize the local time.
Definition time.c:150
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_delta_wrap(_time)
Definition time.h:152
#define fr_time_wrap(_time)
Definition time.h:145
#define fr_time_delta_ispos(_a)
Definition time.h:290
#define fr_time_eq(_a, _b)
Definition time.h:241
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
An event timer list.
Definition timer.c:49
A timer event.
Definition timer.c:75
#define fr_timer_in(...)
Definition timer.h:86
int fr_openssl_version_consistent(void)
Definition version.c:246
int trigger_exec(unlang_interpret_t *intp, CONF_SECTION const *cs, char const *name, bool rate_limit, fr_pair_list_t *args)
Execute a trigger - call an executable to process an event.
Definition trigger.c:228
close(uq->fd)
static fr_event_list_t * el
void xlat_thread_detach(void)
Destroy any thread specific xlat instances.
Definition xlat_inst.c:487
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
Definition xlat_inst.c:442
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:732
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:576
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition version.c:40
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81
int virtual_servers_open(fr_schedule_t *sc)
Open all the listen sockets.
void virtual_servers_thread_detach(void)
Free thread-specific data for all process modules and listeners.
int virtual_servers_init(void)
Performs global initialisation for the virtual server code.
int virtual_servers_free(void)
int virtual_servers_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Perform thread instantiation for all process modules and listeners.