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