bffb2e5c15ce9214715939d74cd3813feaf93d58
[freeradius.git] / src / main / radiusd.c
1 /*
2  * radiusd.c    Main loop of the radius server.
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000-2012  The FreeRADIUS server project
21  * Copyright 1999,2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  * Copyright 2000  Alan Curry <pacman-radius@cqc.com>
24  * Copyright 2000  Jeff Carneal <jeff@apex.net>
25  * Copyright 2000  Chad Miller <cmiller@surfsouth.com>
26  */
27
28 RCSID("$Id$")
29
30 #include <freeradius-devel/radiusd.h>
31 #include <freeradius-devel/modules.h>
32 #include <freeradius-devel/rad_assert.h>
33
34 #include <sys/file.h>
35
36 #include <fcntl.h>
37 #include <ctype.h>
38
39 #ifdef HAVE_GETOPT_H
40 #       include <getopt.h>
41 #endif
42
43 #ifdef HAVE_SYS_WAIT_H
44 #       include <sys/wait.h>
45 #endif
46 #ifndef WEXITSTATUS
47 #       define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
48 #endif
49 #ifndef WIFEXITED
50 #       define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
51 #endif
52
53 /*
54  *  Global variables.
55  */
56 char const *progname = NULL;
57 char const *radius_dir = NULL;
58 char const *radacct_dir = NULL;
59 char const *radlog_dir = NULL;
60 char const *radlib_dir = NULL;
61 bool log_stripped_names;
62 log_debug_t debug_flag = 0;
63 bool check_config = false;
64
65 char const *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION_STRING
66 #ifdef RADIUSD_VERSION_COMMIT
67 " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")"
68 #endif
69 ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
70
71 pid_t radius_pid;
72
73 /*
74  *  Configuration items.
75  */
76
77 /*
78  *      Static functions.
79  */
80 static void usage(int);
81
82 static void sig_fatal (int);
83 #ifdef SIGHUP
84 static void sig_hup (int);
85 #endif
86
87 /*
88  *      The main guy.
89  */
90 int main(int argc, char *argv[])
91 {
92         int rcode = EXIT_SUCCESS;
93         int status;
94         int argval;
95         bool spawn_flag = true;
96         bool write_pid = false;
97         bool display_version = false;
98         int flag = 0;
99         int from_child[2] = {-1, -1};
100
101         /*
102          *      We probably don't want to free the talloc autofree context
103          *      directly, so we'll allocate a new context beneath it, and
104          *      free that before any leak reports.
105          */
106         TALLOC_CTX *autofree = talloc_init("main");
107
108         /*
109          *      If the server was built with debugging enabled always install
110          *      the basic fatal signal handlers.
111          */
112 #ifndef NDEBUG
113         if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) {
114                 fr_perror("radiusd");
115                 exit(EXIT_FAILURE);
116         }
117 #endif
118
119 #ifdef OSFC2
120         set_auth_parameters(argc,argv);
121 #endif
122
123         if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
124                 progname = argv[0];
125         else
126                 progname++;
127
128 #ifdef WIN32
129         {
130                 WSADATA wsaData;
131                 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
132                         fprintf(stderr, "%s: Unable to initialize socket library.\n", progname);
133                         exit(EXIT_FAILURE);
134                 }
135         }
136 #endif
137
138         debug_flag = 0;
139         set_radius_dir(autofree, RADIUS_DIR);
140
141         /*
142          *      Ensure that the configuration is initialized.
143          */
144         memset(&main_config, 0, sizeof(main_config));
145         main_config.myip.af = AF_UNSPEC;
146         main_config.port = 0;
147         main_config.name = "radiusd";
148         main_config.daemonize = true;
149
150         /*
151          *      Don't put output anywhere until we get told a little
152          *      more.
153          */
154         default_log.dst = L_DST_NULL;
155         default_log.fd = -1;
156         main_config.log_file = NULL;
157
158         /*  Process the options.  */
159         while ((argval = getopt(argc, argv, "Cd:D:fhi:l:mMn:p:PstvxX")) != EOF) {
160
161                 switch(argval) {
162                         case 'C':
163                                 check_config = true;
164                                 spawn_flag = false;
165                                 main_config.daemonize = false;
166                                 break;
167
168                         case 'd':
169                                 set_radius_dir(autofree, optarg);
170                                 break;
171
172                         case 'D':
173                                 main_config.dictionary_dir = talloc_typed_strdup(NULL, optarg);
174                                 break;
175
176                         case 'f':
177                                 main_config.daemonize = false;
178                                 break;
179
180                         case 'h':
181                                 usage(0);
182                                 break;
183
184                         case 'l':
185                                 if (strcmp(optarg, "stdout") == 0) {
186                                         goto do_stdout;
187                                 }
188                                 main_config.log_file = strdup(optarg);
189                                 default_log.dst = L_DST_FILES;
190                                 default_log.fd = open(main_config.log_file,
191                                                             O_WRONLY | O_APPEND | O_CREAT, 0640);
192                                 if (default_log.fd < 0) {
193                                         fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", main_config.log_file, fr_syserror(errno));
194                                         exit(EXIT_FAILURE);
195                                 }
196                                 fr_log_fp = fdopen(default_log.fd, "a");
197                                 break;
198
199                         case 'i':
200                                 if (ip_hton(&main_config.myip, AF_UNSPEC, optarg, false) < 0) {
201                                         fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
202                                         exit(EXIT_FAILURE);
203                                 }
204                                 flag |= 1;
205                                 break;
206
207                         case 'n':
208                                 main_config.name = optarg;
209                                 break;
210
211                         case 'm':
212                                 main_config.debug_memory = true;
213                                 break;
214
215                         case 'M':
216                                 main_config.memory_report = true;
217                                 main_config.debug_memory = true;
218                                 break;
219
220                         case 'p':
221                         {
222                                 unsigned long port;
223
224                                 port = strtoul(optarg, 0, 10);
225                                 if ((port == 0) || (port > UINT16_MAX)) {
226                                         fprintf(stderr, "radiusd: Invalid port number \"%s\"\n", optarg);
227                                         exit(EXIT_FAILURE);
228                                 }
229
230                                 main_config.port = (uint16_t) port;
231                                 flag |= 2;
232                         }
233                                 break;
234
235                         case 'P':
236                                 /* Force the PID to be written, even in -f mode */
237                                 write_pid = true;
238                                 break;
239
240                         case 's':       /* Single process mode */
241                                 spawn_flag = false;
242                                 main_config.daemonize = false;
243                                 break;
244
245                         case 't':       /* no child threads */
246                                 spawn_flag = false;
247                                 break;
248
249                         case 'v':
250                                 display_version = true;
251                                 break;
252
253                         case 'X':
254                                 spawn_flag = false;
255                                 main_config.daemonize = false;
256                                 debug_flag += 2;
257                                 main_config.log_auth = true;
258                                 main_config.log_auth_badpass = true;
259                                 main_config.log_auth_goodpass = true;
260                 do_stdout:
261                                 fr_log_fp = stdout;
262                                 default_log.dst = L_DST_STDOUT;
263                                 default_log.fd = STDOUT_FILENO;
264                                 break;
265
266                         case 'x':
267                                 debug_flag++;
268                                 break;
269
270                         default:
271                                 usage(1);
272                                 break;
273                 }
274         }
275
276         /*
277          *      Mismatch between the binary and the libraries it depends on
278          */
279         if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
280                 fr_perror("radiusd");
281                 exit(EXIT_FAILURE);
282         }
283
284         if (rad_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
285                 exit(EXIT_FAILURE);
286         }
287
288         /*
289          *      Mismatch between build time OpenSSL and linked SSL,
290          *      better to die here than segfault later.
291          */
292 #ifdef HAVE_OPENSSL_CRYPTO_H
293         if (ssl_check_consistency() < 0) {
294                 exit(EXIT_FAILURE);
295         }
296 #endif
297
298         if (flag && (flag != 0x03)) {
299                 fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
300                 exit(EXIT_FAILURE);
301         }
302
303         /*
304          *      Better here, so it doesn't matter whether we get passed
305          *      -xv or -vx.
306          */
307         if (display_version) {
308                 /* Don't print timestamps */
309                 debug_flag += 2;
310                 fr_log_fp = stdout;
311                 default_log.dst = L_DST_STDOUT;
312                 default_log.fd = STDOUT_FILENO;
313
314                 version();
315                 exit(EXIT_SUCCESS);
316         }
317
318         if (debug_flag) {
319                 version();
320         }
321
322         /*
323          *  Initialising OpenSSL once, here, is safer than having individual
324          *  modules do it.
325          */
326 #ifdef HAVE_OPENSSL_CRYPTO_H
327         tls_global_init();
328 #endif
329
330         /*
331          *  Initialize any event loops just enough so module instantiations
332          *  can add fd/event to them, but do not start them yet.
333          */
334         if (!radius_event_init(autofree)) {
335                 exit(EXIT_FAILURE);
336         }
337
338         /*  Read the configuration files, BEFORE doing anything else.  */
339         if (main_config_init() < 0) {
340                 exit(EXIT_FAILURE);
341         }
342
343         /*  Check for vulnerabilities in the version of libssl were linked against */
344 #ifdef HAVE_OPENSSL_CRYPTO_H
345         if (tls_global_version_check(main_config.allow_vulnerable_openssl) < 0) {
346                 exit(EXIT_FAILURE);
347         }
348 #endif
349
350         /*
351          *  Load the modules
352          */
353         if (modules_init(main_config.config) < 0) {
354                 exit(EXIT_FAILURE);
355         }
356
357         /* Set the panic action (if required) */
358         if (main_config.panic_action &&
359 #ifndef NDEBUG
360             !getenv("PANIC_ACTION") &&
361 #endif
362             (fr_fault_setup(main_config.panic_action, argv[0]) < 0)) {
363                 fr_perror("radiusd");
364                 exit(EXIT_FAILURE);
365         }
366
367 #ifndef __MINGW32__
368
369
370         /*
371          *  Disconnect from session
372          */
373         if (main_config.daemonize) {
374                 pid_t pid;
375                 int devnull;
376
377                 /*
378                  *  Really weird things happen if we leave stdin open and call things like
379                  *  system() later.
380                  */
381                 devnull = open("/dev/null", O_RDWR);
382                 if (devnull < 0) {
383                         ERROR("Failed opening /dev/null: %s", fr_syserror(errno));
384                         exit(EXIT_FAILURE);
385                 }
386                 dup2(devnull, STDIN_FILENO);
387
388                 close(devnull);
389
390                 if (pipe(from_child) != 0) {
391                         ERROR("Couldn't open pipe for child status: %s", fr_syserror(errno));
392                         exit(EXIT_FAILURE);
393                 }
394
395                 pid = fork();
396                 if (pid < 0) {
397                         ERROR("Couldn't fork: %s", fr_syserror(errno));
398                         exit(EXIT_FAILURE);
399                 }
400
401                 /*
402                  *  The parent exits, so the child can run in the background.
403                  *
404                  *  As the child can still encounter an error during initialisation
405                  *  we do a blocking read on a pipe between it and the parent.
406                  *
407                  *  Just before entering the event loop the child will send a success
408                  *  or failure message to the parent, via the pipe.
409                  */
410                 if (pid > 0) {
411                         uint8_t ret = 0;
412                         int stat_loc;
413
414                         /* So the pipe is correctly widowed if the child exits */
415                         close(from_child[1]);
416
417                         /*
418                          *      The child writes a 0x01 byte on
419                          *      success, and closes the pipe on error.
420                          */
421                         if ((read(from_child[0], &ret, 1) < 0)) {
422                                 ret = 0;
423                         }
424
425                         /* For cleanliness... */
426                         close(from_child[0]);
427
428                         /* Don't turn children into zombies */
429                         if (!ret) {
430                                 waitpid(pid, &stat_loc, WNOHANG);
431                                 exit(EXIT_FAILURE);
432                         }
433
434                         exit(EXIT_SUCCESS);
435                 }
436
437                 /* so the pipe is correctly widowed if the parent exits?! */
438                 close(from_child[0]);
439 #  ifdef HAVE_SETSID
440                 setsid();
441 #  endif
442         }
443 #endif
444
445         /*
446          *      Ensure that we're using the CORRECT pid after forking,
447          *      NOT the one we started with.
448          */
449         radius_pid = getpid();
450
451         /*
452          *      Redirect stderr/stdout as appropriate.
453          */
454         if (radlog_init(&default_log, main_config.daemonize) < 0) {
455                 ERROR("%s", fr_strerror());
456                 exit(EXIT_FAILURE);
457         }
458
459         /*
460          *      Start the event loop(s) and threads.
461          */
462         radius_event_start(main_config.config, spawn_flag);
463
464         /*
465          *      Now that we've set everything up, we can install the signal
466          *      handlers.  Before this, if we get any signal, we don't know
467          *      what to do, so we might as well do the default, and die.
468          */
469 #ifdef SIGPIPE
470         signal(SIGPIPE, SIG_IGN);
471 #endif
472
473         if ((fr_set_signal(SIGHUP, sig_hup) < 0) ||
474             (fr_set_signal(SIGTERM, sig_fatal) < 0)) {
475                 ERROR("%s", fr_strerror());
476                 exit(EXIT_FAILURE);
477         }
478
479         /*
480          *      If we're debugging, then a CTRL-C will cause the
481          *      server to die immediately.  Use SIGTERM to shut down
482          *      the server cleanly in that case.
483          */
484         if (main_config.debug_memory || (debug_flag == 0)) {
485                 if ((fr_set_signal(SIGINT, sig_fatal) < 0)
486 #ifdef SIGQUIT
487                 || (fr_set_signal(SIGQUIT, sig_fatal) < 0)
488 #endif
489                 ) {
490                         ERROR("%s", fr_strerror());
491                         exit(EXIT_FAILURE);
492                 }
493         }
494
495         /*
496          *      Everything seems to have loaded OK, exit gracefully.
497          */
498         if (check_config) {
499                 DEBUG("Configuration appears to be OK");
500
501                 /* for -C -m|-M */
502                 if (main_config.debug_memory) {
503                         goto cleanup;
504                 }
505
506                 exit(EXIT_SUCCESS);
507         }
508
509 #ifdef WITH_STATS
510         radius_stats_init(0);
511 #endif
512
513         /*
514          *      Write the PID always if we're running as a daemon.
515          */
516         if (main_config.daemonize) write_pid = true;
517
518         /*
519          *      Write the PID after we've forked, so that we write the
520          *      correct one.
521          */
522         if (write_pid) {
523                 FILE *fp;
524
525                 fp = fopen(main_config.pid_file, "w");
526                 if (fp != NULL) {
527                         /*
528                          *      FIXME: What about following symlinks,
529                          *      and having it over-write a normal file?
530                          */
531                         fprintf(fp, "%d\n", (int) radius_pid);
532                         fclose(fp);
533                 } else {
534                         ERROR("Failed creating PID file %s: %s\n",
535                                main_config.pid_file, fr_syserror(errno));
536                         exit(EXIT_FAILURE);
537                 }
538         }
539
540         exec_trigger(NULL, NULL, "server.start", false);
541
542         /*
543          *      Inform the parent (who should still be waiting) that
544          *      the rest of initialisation went OK, and that it should
545          *      exit with a 0 status.  If we don't get this far, then
546          *      we just close the pipe on exit, and the parent gets a
547          *      read failure.
548          */
549         if (main_config.daemonize) {
550                 if (write(from_child[1], "\001", 1) < 0) {
551                         WARN("Failed informing parent of successful start: %s",
552                              fr_syserror(errno));
553                 }
554                 close(from_child[1]);
555         }
556
557         /*
558          *      Clear the libfreeradius error buffer
559          */
560         fr_strerror();
561
562         /*
563          *      Process requests until HUP or exit.
564          */
565         while ((status = radius_event_process()) == 0x80) {
566 #ifdef WITH_STATS
567                 radius_stats_init(1);
568 #endif
569                 main_config_hup();
570         }
571         if (status < 0) {
572                 ERROR("Exiting due to internal error: %s", fr_strerror());
573                 rcode = EXIT_FAILURE;
574         } else {
575                 INFO("Exiting normally");
576         }
577
578         exec_trigger(NULL, NULL, "server.stop", false);
579
580         /*
581          *      Ignore the TERM signal: we're
582          *      about to die.
583          */
584         signal(SIGTERM, SIG_IGN);
585
586         /*
587          *      Send a TERM signal to all
588          *      associated processes
589          *      (including us, which gets
590          *      ignored.)
591          */
592 #ifndef __MINGW32__
593         if (spawn_flag) kill(-radius_pid, SIGTERM);
594 #endif
595
596         /*
597          *      We're exiting, so we can delete the PID
598          *      file.  (If it doesn't exist, we can ignore
599          *      the error returned by unlink)
600          */
601         if (main_config.daemonize) {
602                 unlink(main_config.pid_file);
603         }
604
605         radius_event_free();
606
607 cleanup:
608         /*
609          *      Detach any modules.
610          */
611         modules_free();
612
613         xlat_free();            /* modules may have xlat's */
614
615         /*
616          *      Free the configuration items.
617          */
618         main_config_free();
619
620 #ifdef WIN32
621         WSACleanup();
622 #endif
623
624 #ifdef HAVE_OPENSSL_CRYPTO_H
625         tls_global_cleanup();
626 #endif
627
628         /*
629          *      So we don't see autofreed memory in the talloc report
630          */
631         talloc_free(autofree);
632
633         if (main_config.memory_report) {
634                 INFO("Allocated memory at time of report:");
635                 fr_log_talloc_report(NULL);
636         }
637
638         return rcode;
639 }
640
641
642 /*
643  *  Display the syntax for starting this program.
644  */
645 static void NEVER_RETURNS usage(int status)
646 {
647         FILE *output = status?stderr:stdout;
648
649         fprintf(output, "Usage: %s [options]\n", progname);
650         fprintf(output, "Options:\n");
651         fprintf(output, "  -C            Check configuration and exit.\n");
652         fprintf(stderr, "  -d <raddb>    Set configuration directory (defaults to " RADDBDIR ").\n");
653         fprintf(stderr, "  -D <dictdir>  Set main dictionary directory (defaults to " DICTDIR ").\n");
654         fprintf(output, "  -f            Run as a foreground process, not a daemon.\n");
655         fprintf(output, "  -h            Print this help message.\n");
656         fprintf(output, "  -i <ipaddr>   Listen on ipaddr ONLY.\n");
657         fprintf(output, "  -l <log_file> Logging output will be written to this file.\n");
658         fprintf(output, "  -m            On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
659         fprintf(output, "  -n <name>     Read raddb/name.conf instead of raddb/radiusd.conf.\n");
660         fprintf(output, "  -p <port>     Listen on port ONLY.\n");
661         fprintf(output, "  -P            Always write out PID, even with -f.\n");
662         fprintf(output, "  -s            Do not spawn child processes to handle requests.\n");
663         fprintf(output, "  -t            Disable threads.\n");
664         fprintf(output, "  -v            Print server version information.\n");
665         fprintf(output, "  -X            Turn on full debugging.\n");
666         fprintf(output, "  -x            Turn on additional debugging. (-xx gives more debugging).\n");
667         exit(status);
668 }
669
670
671 /*
672  *      We got a fatal signal.
673  */
674 static void sig_fatal(int sig)
675 {
676         if (getpid() != radius_pid) _exit(sig);
677
678         switch(sig) {
679         case SIGTERM:
680                 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
681                 break;
682
683         case SIGINT:
684 #ifdef SIGQUIT
685         case SIGQUIT:
686 #endif
687                 if (main_config.debug_memory || main_config.memory_report) {
688                         radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
689                         break;
690                 }
691                 /* FALL-THROUGH */
692
693         default:
694                 _exit(sig);
695         }
696 }
697
698 #ifdef SIGHUP
699 /*
700  *  We got the hangup signal.
701  *  Re-read the configuration files.
702  */
703 static void sig_hup(UNUSED int sig)
704 {
705         reset_signal(SIGHUP, sig_hup);
706
707         radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
708 }
709 #endif