Show some uname() info during charon startup
[strongswan.git] / src / charon / charon.c
1 /*
2 * Copyright (C) 2006-2012 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
5 * Copyright (C) 2005 Jan Hutter
6 * Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include <stdio.h>
20 #ifdef HAVE_PRCTL
21 #include <sys/prctl.h>
22 #endif
23 #define _POSIX_PTHREAD_SEMANTICS /* for two param sigwait on OpenSolaris */
24 #include <signal.h>
25 #undef _POSIX_PTHREAD_SEMANTICS
26 #include <pthread.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <sys/utsname.h>
30 #include <syslog.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <getopt.h>
34 #include <pwd.h>
35 #include <grp.h>
36
37 #include <hydra.h>
38 #include <daemon.h>
39
40 #include <library.h>
41 #include <utils/backtrace.h>
42 #include <threading/thread.h>
43
44 #ifdef ANDROID
45 #include <private/android_filesystem_config.h> /* for AID_VPN */
46 #endif
47
48 #ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
49 #define LOG_AUTHPRIV LOG_AUTH
50 #endif
51
52 /**
53 * PID file, in which charon stores its process id
54 */
55 #define PID_FILE IPSEC_PIDDIR "/charon.pid"
56
57 /**
58 * Global reference to PID file (required to truncate, if undeletable)
59 */
60 static FILE *pidfile = NULL;
61
62 /**
63 * hook in library for debugging messages
64 */
65 extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
66
67 /**
68 * Logging hook for library logs, using stderr output
69 */
70 static void dbg_stderr(debug_t group, level_t level, char *fmt, ...)
71 {
72 va_list args;
73
74 if (level <= 1)
75 {
76 va_start(args, fmt);
77 fprintf(stderr, "00[%N] ", debug_names, group);
78 vfprintf(stderr, fmt, args);
79 fprintf(stderr, "\n");
80 va_end(args);
81 }
82 }
83
84 /**
85 * Run the daemon and handle unix signals
86 */
87 static void run()
88 {
89 sigset_t set;
90
91 /* handle SIGINT, SIGHUP ans SIGTERM in this handler */
92 sigemptyset(&set);
93 sigaddset(&set, SIGINT);
94 sigaddset(&set, SIGHUP);
95 sigaddset(&set, SIGTERM);
96 sigprocmask(SIG_BLOCK, &set, NULL);
97
98 while (TRUE)
99 {
100 int sig;
101 int error;
102
103 error = sigwait(&set, &sig);
104 if (error)
105 {
106 DBG1(DBG_DMN, "error %d while waiting for a signal", error);
107 return;
108 }
109 switch (sig)
110 {
111 case SIGHUP:
112 {
113 DBG1(DBG_DMN, "signal of type SIGHUP received. Reloading "
114 "configuration");
115 if (lib->settings->load_files(lib->settings, NULL, FALSE))
116 {
117 lib->plugins->reload(lib->plugins, NULL);
118 }
119 else
120 {
121 DBG1(DBG_DMN, "reloading config failed, keeping old");
122 }
123 break;
124 }
125 case SIGINT:
126 {
127 DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
128 charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
129 return;
130 }
131 case SIGTERM:
132 {
133 DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
134 charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
135 return;
136 }
137 default:
138 {
139 DBG1(DBG_DMN, "unknown signal %d received. Ignored", sig);
140 break;
141 }
142 }
143 }
144 }
145
146 /**
147 * drop daemon capabilities
148 */
149 static bool drop_capabilities()
150 {
151 #ifdef HAVE_PRCTL
152 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
153 #endif
154
155 if (setgid(charon->gid) != 0)
156 {
157 DBG1(DBG_DMN, "change to unprivileged group failed");
158 return FALSE;
159 }
160 if (setuid(charon->uid) != 0)
161 {
162 DBG1(DBG_DMN, "change to unprivileged user failed");
163 return FALSE;
164 }
165 if (!charon->drop_capabilities(charon))
166 {
167 DBG1(DBG_DMN, "unable to drop daemon capabilities");
168 return FALSE;
169 }
170 return TRUE;
171 }
172
173 /**
174 * lookup UID and GID
175 */
176 static bool lookup_uid_gid()
177 {
178 #ifdef IPSEC_USER
179 {
180 char buf[1024];
181 struct passwd passwd, *pwp;
182
183 if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
184 pwp == NULL)
185 {
186 DBG1(DBG_DMN, "resolving user '"IPSEC_USER"' failed");
187 return FALSE;
188 }
189 charon->uid = pwp->pw_uid;
190 }
191 #endif
192 #ifdef IPSEC_GROUP
193 {
194 char buf[1024];
195 struct group group, *grp;
196
197 if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
198 grp == NULL)
199 {
200 DBG1(DBG_DMN, "resolving group '"IPSEC_GROUP"' failed");
201 return FALSE;
202 }
203 charon->gid = grp->gr_gid;
204 }
205 #endif
206 #ifdef ANDROID
207 charon->uid = AID_VPN;
208 #endif
209 return TRUE;
210 }
211
212 /**
213 * Handle SIGSEGV/SIGILL signals raised by threads
214 */
215 static void segv_handler(int signal)
216 {
217 backtrace_t *backtrace;
218
219 DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
220 backtrace = backtrace_create(2);
221 backtrace->log(backtrace, stderr, TRUE);
222 backtrace->destroy(backtrace);
223
224 DBG1(DBG_DMN, "killing ourself, received critical signal");
225 abort();
226 }
227
228 /**
229 * Check/create PID file, return TRUE if already running
230 */
231 static bool check_pidfile()
232 {
233 struct stat stb;
234
235 if (stat(PID_FILE, &stb) == 0)
236 {
237 pidfile = fopen(PID_FILE, "r");
238 if (pidfile)
239 {
240 char buf[64];
241 pid_t pid = 0;
242
243 memset(buf, 0, sizeof(buf));
244 if (fread(buf, 1, sizeof(buf), pidfile))
245 {
246 buf[sizeof(buf) - 1] = '\0';
247 pid = atoi(buf);
248 }
249 fclose(pidfile);
250 if (pid && kill(pid, 0) == 0)
251 { /* such a process is running */
252 return TRUE;
253 }
254 }
255 DBG1(DBG_DMN, "removing pidfile '"PID_FILE"', process not running");
256 unlink(PID_FILE);
257 }
258
259 /* create new pidfile */
260 pidfile = fopen(PID_FILE, "w");
261 if (pidfile)
262 {
263 ignore_result(fchown(fileno(pidfile), charon->uid, charon->gid));
264 fprintf(pidfile, "%d\n", getpid());
265 fflush(pidfile);
266 }
267 return FALSE;
268 }
269
270 /**
271 * Delete/truncate the PID file
272 */
273 static void unlink_pidfile()
274 {
275 /* because unlinking the PID file may fail, we truncate it to ensure the
276 * daemon can be properly restarted. one probable cause for this is the
277 * combination of not running as root and the effective user lacking
278 * permissions on the parent dir(s) of the PID file */
279 if (pidfile)
280 {
281 ignore_result(ftruncate(fileno(pidfile), 0));
282 fclose(pidfile);
283 }
284 unlink(PID_FILE);
285 }
286
287 /**
288 * Initialize logging
289 */
290 static void initialize_loggers(bool use_stderr, level_t levels[])
291 {
292 sys_logger_t *sys_logger;
293 file_logger_t *file_logger;
294 enumerator_t *enumerator;
295 char *identifier, *facility, *filename;
296 int loggers_defined = 0;
297 debug_t group;
298 level_t def;
299 bool append, ike_name;
300 FILE *file;
301
302 /* setup sysloggers */
303 identifier = lib->settings->get_str(lib->settings,
304 "charon.syslog.identifier", NULL);
305 if (identifier)
306 { /* set identifier, which is prepended to each log line */
307 openlog(identifier, 0, 0);
308 }
309 enumerator = lib->settings->create_section_enumerator(lib->settings,
310 "charon.syslog");
311 while (enumerator->enumerate(enumerator, &facility))
312 {
313 loggers_defined++;
314
315 ike_name = lib->settings->get_bool(lib->settings,
316 "charon.syslog.%s.ike_name", FALSE, facility);
317 if (streq(facility, "daemon"))
318 {
319 sys_logger = sys_logger_create(LOG_DAEMON, ike_name);
320 }
321 else if (streq(facility, "auth"))
322 {
323 sys_logger = sys_logger_create(LOG_AUTHPRIV, ike_name);
324 }
325 else
326 {
327 continue;
328 }
329 def = lib->settings->get_int(lib->settings,
330 "charon.syslog.%s.default", 1, facility);
331 for (group = 0; group < DBG_MAX; group++)
332 {
333 sys_logger->set_level(sys_logger, group,
334 lib->settings->get_int(lib->settings,
335 "charon.syslog.%s.%N", def,
336 facility, debug_lower_names, group));
337 }
338 charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
339 charon->bus->add_logger(charon->bus, &sys_logger->logger);
340 }
341 enumerator->destroy(enumerator);
342
343 /* and file loggers */
344 enumerator = lib->settings->create_section_enumerator(lib->settings,
345 "charon.filelog");
346 while (enumerator->enumerate(enumerator, &filename))
347 {
348 loggers_defined++;
349 if (streq(filename, "stderr"))
350 {
351 file = stderr;
352 }
353 else if (streq(filename, "stdout"))
354 {
355 file = stdout;
356 }
357 else
358 {
359 append = lib->settings->get_bool(lib->settings,
360 "charon.filelog.%s.append", TRUE, filename);
361 file = fopen(filename, append ? "a" : "w");
362 if (file == NULL)
363 {
364 DBG1(DBG_DMN, "opening file %s for logging failed: %s",
365 filename, strerror(errno));
366 continue;
367 }
368 if (lib->settings->get_bool(lib->settings,
369 "charon.filelog.%s.flush_line", FALSE, filename))
370 {
371 setlinebuf(file);
372 }
373 }
374 file_logger = file_logger_create(file,
375 lib->settings->get_str(lib->settings,
376 "charon.filelog.%s.time_format", NULL, filename),
377 lib->settings->get_bool(lib->settings,
378 "charon.filelog.%s.ike_name", FALSE, filename));
379 def = lib->settings->get_int(lib->settings,
380 "charon.filelog.%s.default", 1, filename);
381 for (group = 0; group < DBG_MAX; group++)
382 {
383 file_logger->set_level(file_logger, group,
384 lib->settings->get_int(lib->settings,
385 "charon.filelog.%s.%N", def,
386 filename, debug_lower_names, group));
387 }
388 charon->file_loggers->insert_last(charon->file_loggers, file_logger);
389 charon->bus->add_logger(charon->bus, &file_logger->logger);
390
391 }
392 enumerator->destroy(enumerator);
393
394 /* set up legacy style default loggers provided via command-line */
395 if (!loggers_defined)
396 {
397 /* set up default stdout file_logger */
398 file_logger = file_logger_create(stdout, NULL, FALSE);
399 charon->file_loggers->insert_last(charon->file_loggers, file_logger);
400 /* set up default daemon sys_logger */
401 sys_logger = sys_logger_create(LOG_DAEMON, FALSE);
402 charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
403 for (group = 0; group < DBG_MAX; group++)
404 {
405 sys_logger->set_level(sys_logger, group, levels[group]);
406 if (use_stderr)
407 {
408 file_logger->set_level(file_logger, group, levels[group]);
409 }
410 }
411 charon->bus->add_logger(charon->bus, &file_logger->logger);
412 charon->bus->add_logger(charon->bus, &sys_logger->logger);
413
414 /* set up default auth sys_logger */
415 sys_logger = sys_logger_create(LOG_AUTHPRIV, FALSE);
416 sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
417 charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
418 charon->bus->add_logger(charon->bus, &sys_logger->logger);
419 }
420 }
421
422 /**
423 * print command line usage and exit
424 */
425 static void usage(const char *msg)
426 {
427 if (msg != NULL && *msg != '\0')
428 {
429 fprintf(stderr, "%s\n", msg);
430 }
431 fprintf(stderr, "Usage: charon\n"
432 " [--help]\n"
433 " [--version]\n"
434 " [--use-syslog]\n"
435 " [--debug-<type> <level>]\n"
436 " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|lib)\n"
437 " <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n"
438 " 2 = controlmore, 3 = raw, 4 = private)\n"
439 "\n"
440 );
441 }
442
443 /**
444 * Main function, starts the daemon.
445 */
446 int main(int argc, char *argv[])
447 {
448 struct sigaction action;
449 bool use_syslog = FALSE;
450 level_t levels[DBG_MAX];
451 int group, status = SS_RC_INITIALIZATION_FAILED;
452 struct utsname utsname;
453
454 /* logging for library during initialization, as we have no bus yet */
455 dbg = dbg_stderr;
456
457 /* initialize library */
458 if (!library_init(NULL))
459 {
460 library_deinit();
461 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
462 }
463
464 if (lib->integrity &&
465 !lib->integrity->check_file(lib->integrity, "charon", argv[0]))
466 {
467 dbg_stderr(DBG_DMN, 1, "integrity check of charon failed");
468 library_deinit();
469 exit(SS_RC_DAEMON_INTEGRITY);
470 }
471
472 if (!libhydra_init("charon"))
473 {
474 dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
475 libhydra_deinit();
476 library_deinit();
477 exit(SS_RC_INITIALIZATION_FAILED);
478 }
479
480 if (!libcharon_init("charon"))
481 {
482 dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
483 goto deinit;
484 }
485
486 /* use CTRL loglevel for default */
487 for (group = 0; group < DBG_MAX; group++)
488 {
489 levels[group] = LEVEL_CTRL;
490 }
491
492 /* handle arguments */
493 for (;;)
494 {
495 struct option long_opts[] = {
496 { "help", no_argument, NULL, 'h' },
497 { "version", no_argument, NULL, 'v' },
498 { "use-syslog", no_argument, NULL, 'l' },
499 /* TODO: handle "debug-all" */
500 { "debug-dmn", required_argument, &group, DBG_DMN },
501 { "debug-mgr", required_argument, &group, DBG_MGR },
502 { "debug-ike", required_argument, &group, DBG_IKE },
503 { "debug-chd", required_argument, &group, DBG_CHD },
504 { "debug-job", required_argument, &group, DBG_JOB },
505 { "debug-cfg", required_argument, &group, DBG_CFG },
506 { "debug-knl", required_argument, &group, DBG_KNL },
507 { "debug-net", required_argument, &group, DBG_NET },
508 { "debug-asn", required_argument, &group, DBG_ASN },
509 { "debug-enc", required_argument, &group, DBG_ENC },
510 { "debug-tnc", required_argument, &group, DBG_TNC },
511 { "debug-imc", required_argument, &group, DBG_IMC },
512 { "debug-imv", required_argument, &group, DBG_IMV },
513 { "debug-pts", required_argument, &group, DBG_PTS },
514 { "debug-tls", required_argument, &group, DBG_TLS },
515 { "debug-lib", required_argument, &group, DBG_LIB },
516 { 0,0,0,0 }
517 };
518
519 int c = getopt_long(argc, argv, "", long_opts, NULL);
520 switch (c)
521 {
522 case EOF:
523 break;
524 case 'h':
525 usage(NULL);
526 status = 0;
527 goto deinit;
528 case 'v':
529 printf("Linux strongSwan %s\n", VERSION);
530 status = 0;
531 goto deinit;
532 case 'l':
533 use_syslog = TRUE;
534 continue;
535 case 0:
536 /* option is in group */
537 levels[group] = atoi(optarg);
538 continue;
539 default:
540 usage("");
541 status = 1;
542 goto deinit;
543 }
544 break;
545 }
546
547 if (!lookup_uid_gid())
548 {
549 dbg_stderr(DBG_DMN, 1, "invalid uid/gid - aborting charon");
550 goto deinit;
551 }
552
553 initialize_loggers(!use_syslog, levels);
554
555 if (uname(&utsname) != 0)
556 {
557 memset(&utsname, 0, sizeof(utsname));
558 }
559 DBG1(DBG_DMN, "Starting IKE charon daemon (strongSwan "VERSION", %s %s, %s)",
560 utsname.sysname, utsname.release, utsname.machine);
561 if (lib->integrity)
562 {
563 DBG1(DBG_DMN, "integrity tests enabled:");
564 DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests");
565 DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests");
566 DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests");
567 DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
568 }
569
570 /* initialize daemon */
571 if (!charon->initialize(charon,
572 lib->settings->get_str(lib->settings, "charon.load", PLUGINS)))
573 {
574 DBG1(DBG_DMN, "initialization failed - aborting charon");
575 goto deinit;
576 }
577
578 if (check_pidfile())
579 {
580 DBG1(DBG_DMN, "charon already running (\""PID_FILE"\" exists)");
581 status = -1;
582 goto deinit;
583 }
584
585 if (!drop_capabilities())
586 {
587 DBG1(DBG_DMN, "capability dropping failed - aborting charon");
588 goto deinit;
589 }
590
591 /* add handler for SEGV and ILL,
592 * INT, TERM and HUP are handled by sigwait() in run() */
593 action.sa_handler = segv_handler;
594 action.sa_flags = 0;
595 sigemptyset(&action.sa_mask);
596 sigaddset(&action.sa_mask, SIGINT);
597 sigaddset(&action.sa_mask, SIGTERM);
598 sigaddset(&action.sa_mask, SIGHUP);
599 sigaction(SIGSEGV, &action, NULL);
600 sigaction(SIGILL, &action, NULL);
601 sigaction(SIGBUS, &action, NULL);
602 action.sa_handler = SIG_IGN;
603 sigaction(SIGPIPE, &action, NULL);
604
605 pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
606
607 /* start daemon (i.e. the threads in the thread-pool) */
608 charon->start(charon);
609
610 /* main thread goes to run loop */
611 run();
612
613 /* normal termination, cleanup and exit */
614 unlink_pidfile();
615 status = 0;
616
617 deinit:
618 libcharon_deinit();
619 libhydra_deinit();
620 library_deinit();
621 return status;
622 }
623