Use Botan 2.18.0 for tests
[strongswan.git] / src / libcharon / daemon.c
1 /*
2 * Copyright (C) 2006-2017 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
5 * Copyright (C) 2005 Jan Hutter
6 * HSR 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 /*
20 * Copyright (C) 2016 secunet Security Networks AG
21 * Copyright (C) 2016 Thomas Egerer
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
42 #include <stdio.h>
43 #include <sys/types.h>
44 #include <unistd.h>
45 #include <time.h>
46 #include <errno.h>
47
48 #ifdef HAVE_SYSLOG
49 #include <syslog.h>
50 #endif
51
52 #include "daemon.h"
53
54 #include <library.h>
55 #include <bus/listeners/sys_logger.h>
56 #include <bus/listeners/file_logger.h>
57 #include <collections/array.h>
58 #include <plugins/plugin_feature.h>
59 #include <kernel/kernel_handler.h>
60 #include <processing/jobs/start_action_job.h>
61 #include <threading/mutex.h>
62
63 #ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
64 #define LOG_AUTHPRIV LOG_AUTH
65 #endif
66
67 typedef struct private_daemon_t private_daemon_t;
68
69 /**
70 * Private additions to daemon_t, contains threads and internal functions.
71 */
72 struct private_daemon_t {
73 /**
74 * Public members of daemon_t.
75 */
76 daemon_t public;
77
78 /**
79 * Handler for kernel events
80 */
81 kernel_handler_t *kernel_handler;
82
83 /**
84 * A list of installed loggers (as logger_entry_t*)
85 */
86 linked_list_t *loggers;
87
88 /**
89 * Cached log levels for default loggers
90 */
91 level_t *levels;
92
93 /**
94 * Whether to log to stdout/err by default
95 */
96 bool to_stderr;
97
98 /**
99 * Identifier used for syslog (in the openlog call)
100 */
101 char *syslog_identifier;
102
103 /**
104 * Mutex for configured loggers
105 */
106 mutex_t *mutex;
107
108 /**
109 * Integrity check failed?
110 */
111 bool integrity_failed;
112
113 /**
114 * Number of times we have been initialized
115 */
116 refcount_t ref;
117 };
118
119 /**
120 * Register plugins if built statically
121 */
122 #ifdef STATIC_PLUGIN_CONSTRUCTORS
123 #include "plugin_constructors.c"
124 #endif
125
126 /**
127 * One and only instance of the daemon.
128 */
129 daemon_t *charon;
130
131 /**
132 * hook in library for debugging messages
133 */
134 extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
135
136 /**
137 * we store the previous debug function so we can reset it
138 */
139 static void (*dbg_old) (debug_t group, level_t level, char *fmt, ...);
140
141 /**
142 * Logging hook for library logs, spreads debug message over bus
143 */
144 static void dbg_bus(debug_t group, level_t level, char *fmt, ...)
145 {
146 va_list args;
147
148 va_start(args, fmt);
149 charon->bus->vlog(charon->bus, group, level, fmt, args);
150 va_end(args);
151 }
152
153 /**
154 * Data for registered custom loggers
155 */
156 typedef struct {
157 /**
158 * Name of the custom logger (also used for loglevel configuration)
159 */
160 char *name;
161
162 /**
163 * Constructor to be called for custom logger creation
164 */
165 custom_logger_constructor_t constructor;
166
167 } custom_logger_entry_t;
168
169 #define MAX_CUSTOM_LOGGERS 10
170
171 /**
172 * Static array for logger registration using __attribute__((constructor))
173 */
174 static custom_logger_entry_t custom_loggers[MAX_CUSTOM_LOGGERS];
175 static int custom_logger_count;
176
177 /**
178 * Described in header
179 */
180 void register_custom_logger(char *name,
181 custom_logger_constructor_t constructor)
182 {
183 if (custom_logger_count < MAX_CUSTOM_LOGGERS - 1)
184 {
185 custom_loggers[custom_logger_count].name = name;
186 custom_loggers[custom_logger_count].constructor = constructor;
187 custom_logger_count++;
188 }
189 else
190 {
191 fprintf(stderr, "failed to register custom logger, please increase "
192 "MAX_CUSTOM_LOGGERS");
193 }
194 }
195
196 /**
197 * Types of supported loggers
198 */
199 typedef enum {
200 /**
201 * Syslog logger instance
202 */
203 SYS_LOGGER,
204
205 /**
206 * File logger instance
207 */
208 FILE_LOGGER,
209
210 /**
211 * Custom logger instance
212 */
213 CUSTOM_LOGGER,
214
215 } logger_type_t;
216
217 /**
218 * Some metadata about configured loggers
219 */
220 typedef struct {
221 /**
222 * Target of the logger (syslog facility or filename)
223 */
224 char *target;
225
226 /**
227 * Type of logger
228 */
229 logger_type_t type;
230
231 /**
232 * The actual logger
233 */
234 union {
235 sys_logger_t *sys;
236 file_logger_t *file;
237 custom_logger_t *custom;
238 } logger;
239
240 } logger_entry_t;
241
242 /**
243 * Destroy a logger entry
244 */
245 static void logger_entry_destroy(logger_entry_t *this)
246 {
247 switch (this->type)
248 {
249 case FILE_LOGGER:
250 DESTROY_IF(this->logger.file);
251 break;
252 case SYS_LOGGER:
253 DESTROY_IF(this->logger.sys);
254 break;
255 case CUSTOM_LOGGER:
256 DESTROY_IF(this->logger.custom);
257 break;
258 }
259 free(this->target);
260 free(this);
261 }
262
263 /**
264 * Unregister and destroy a logger entry
265 */
266 static void logger_entry_unregister_destroy(logger_entry_t *this)
267 {
268 switch (this->type)
269 {
270 case FILE_LOGGER:
271 charon->bus->remove_logger(charon->bus, &this->logger.file->logger);
272 break;
273 case SYS_LOGGER:
274 charon->bus->remove_logger(charon->bus, &this->logger.sys->logger);
275 break;
276 case CUSTOM_LOGGER:
277 charon->bus->remove_logger(charon->bus,
278 &this->logger.custom->logger);
279 break;
280 }
281 logger_entry_destroy(this);
282 }
283
284 CALLBACK(logger_entry_match, bool,
285 logger_entry_t *this, va_list args)
286 {
287 logger_type_t type;
288 char *target;
289
290 VA_ARGS_VGET(args, target, type);
291 return this->type == type && streq(this->target, target);
292 }
293
294 /**
295 * Handle configured syslog identifier
296 *
297 * mutex must be locked when calling this function
298 */
299 static void handle_syslog_identifier(private_daemon_t *this)
300 {
301 #ifdef HAVE_SYSLOG
302 char *identifier;
303
304 identifier = lib->settings->get_str(lib->settings, "%s.syslog.identifier",
305 NULL, lib->ns);
306 if (identifier)
307 { /* set identifier, which is prepended to each log line */
308 if (!this->syslog_identifier ||
309 !streq(identifier, this->syslog_identifier))
310 {
311 closelog();
312 this->syslog_identifier = identifier;
313 openlog(this->syslog_identifier, 0, 0);
314 }
315 }
316 else if (this->syslog_identifier)
317 {
318 closelog();
319 this->syslog_identifier = NULL;
320 }
321 #endif /* HAVE_SYSLOG */
322 }
323
324 /**
325 * Convert the given string into a syslog facility, returns -1 if the facility
326 * is not supported
327 */
328 static int get_syslog_facility(char *facility)
329 {
330 #ifdef HAVE_SYSLOG
331 if (streq(facility, "daemon"))
332 {
333 return LOG_DAEMON;
334 }
335 else if (streq(facility, "auth"))
336 {
337 return LOG_AUTHPRIV;
338 }
339 #endif /* HAVE_SYSLOG */
340 return -1;
341 }
342
343 /**
344 * Returns an existing or newly created logger entry (if found, it is removed
345 * from the given linked list of existing loggers)
346 */
347 static logger_entry_t *get_logger_entry(char *target, logger_type_t type,
348 linked_list_t *existing,
349 custom_logger_constructor_t constructor)
350 {
351 logger_entry_t *entry;
352
353 if (!existing->find_first(existing, logger_entry_match, (void**)&entry,
354 target, type))
355 {
356 INIT(entry,
357 .target = strdup(target),
358 .type = type,
359 );
360 switch (type)
361 {
362 case FILE_LOGGER:
363 entry->logger.file = file_logger_create(target);
364 break;
365 case SYS_LOGGER:
366 #ifdef HAVE_SYSLOG
367 entry->logger.sys = sys_logger_create(
368 get_syslog_facility(target));
369 break;
370 #else
371 free(entry);
372 return NULL;
373 #endif /* HAVE_SYSLOG */
374 case CUSTOM_LOGGER:
375 if (constructor)
376 {
377 entry->logger.custom = constructor(target);
378 }
379 if (!entry->logger.custom)
380 {
381 free(entry);
382 return NULL;
383 }
384 break;
385 }
386 }
387 else
388 {
389 existing->remove(existing, entry, NULL);
390 }
391 return entry;
392 }
393
394 /**
395 * Create or reuse a syslog logger
396 */
397 static sys_logger_t *add_sys_logger(private_daemon_t *this, char *facility,
398 linked_list_t *current_loggers)
399 {
400 logger_entry_t *entry;
401
402 entry = get_logger_entry(facility, SYS_LOGGER, current_loggers, NULL);
403 if (entry)
404 {
405 this->loggers->insert_last(this->loggers, entry);
406 }
407 return entry ? entry->logger.sys : NULL;
408 }
409
410 /**
411 * Create or reuse a file logger
412 */
413 static file_logger_t *add_file_logger(private_daemon_t *this, char *filename,
414 linked_list_t *current_loggers)
415 {
416 logger_entry_t *entry;
417
418 entry = get_logger_entry(filename, FILE_LOGGER, current_loggers, NULL);
419 if (entry)
420 {
421 this->loggers->insert_last(this->loggers, entry);
422 }
423 return entry ? entry->logger.file : NULL;
424 }
425
426 /**
427 * Create or reuse a custom logger
428 */
429 static custom_logger_t *add_custom_logger(private_daemon_t *this,
430 custom_logger_entry_t *custom,
431 linked_list_t *current_loggers)
432 {
433 logger_entry_t *entry;
434
435 entry = get_logger_entry(custom->name, CUSTOM_LOGGER, current_loggers,
436 custom->constructor);
437 if (entry)
438 {
439 this->loggers->insert_last(this->loggers, entry);
440 }
441 return entry ? entry->logger.custom : NULL;
442 }
443
444 /**
445 * Load the given syslog logger configured in strongswan.conf
446 */
447 static void load_sys_logger(private_daemon_t *this, char *facility,
448 linked_list_t *current_loggers)
449 {
450 sys_logger_t *sys_logger;
451 debug_t group;
452 level_t def;
453 bool ike_name, log_level;
454
455 if (get_syslog_facility(facility) == -1)
456 {
457 return;
458 }
459
460 sys_logger = add_sys_logger(this, facility, current_loggers);
461 if (!sys_logger)
462 {
463 return;
464 }
465
466 ike_name = lib->settings->get_bool(lib->settings, "%s.syslog.%s.ike_name",
467 FALSE, lib->ns, facility);
468 log_level = lib->settings->get_bool(lib->settings, "%s.syslog.%s.log_level",
469 FALSE, lib->ns, facility);
470
471 sys_logger->set_options(sys_logger, ike_name, log_level);
472
473 def = lib->settings->get_int(lib->settings, "%s.syslog.%s.default", 1,
474 lib->ns, facility);
475 for (group = 0; group < DBG_MAX; group++)
476 {
477 sys_logger->set_level(sys_logger, group,
478 lib->settings->get_int(lib->settings, "%s.syslog.%s.%N", def,
479 lib->ns, facility, debug_lower_names, group));
480 }
481 charon->bus->add_logger(charon->bus, &sys_logger->logger);
482 }
483
484 /**
485 * Load the given file logger configured in strongswan.conf
486 */
487 static void load_file_logger(private_daemon_t *this, char *section,
488 linked_list_t *current_loggers)
489 {
490 file_logger_t *file_logger;
491 debug_t group;
492 level_t def;
493 bool add_ms, ike_name, log_level, flush_line, append;
494 char *time_format, *filename;
495
496 time_format = lib->settings->get_str(lib->settings,
497 "%s.filelog.%s.time_format", NULL, lib->ns, section);
498 add_ms = lib->settings->get_bool(lib->settings,
499 "%s.filelog.%s.time_add_ms", FALSE, lib->ns, section);
500 ike_name = lib->settings->get_bool(lib->settings,
501 "%s.filelog.%s.ike_name", FALSE, lib->ns, section);
502 log_level = lib->settings->get_bool(lib->settings,
503 "%s.filelog.%s.log_level", FALSE, lib->ns, section);
504 flush_line = lib->settings->get_bool(lib->settings,
505 "%s.filelog.%s.flush_line", FALSE, lib->ns, section);
506 append = lib->settings->get_bool(lib->settings,
507 "%s.filelog.%s.append", TRUE, lib->ns, section);
508 filename = lib->settings->get_str(lib->settings,
509 "%s.filelog.%s.path", section, lib->ns, section);
510
511 file_logger = add_file_logger(this, filename, current_loggers);
512 if (!file_logger)
513 {
514 return;
515 }
516
517 file_logger->set_options(file_logger, time_format, add_ms, ike_name,
518 log_level);
519 file_logger->open(file_logger, flush_line, append);
520
521 def = lib->settings->get_int(lib->settings, "%s.filelog.%s.default", 1,
522 lib->ns, section);
523 for (group = 0; group < DBG_MAX; group++)
524 {
525 file_logger->set_level(file_logger, group,
526 lib->settings->get_int(lib->settings, "%s.filelog.%s.%N", def,
527 lib->ns, section, debug_lower_names, group));
528 }
529 charon->bus->add_logger(charon->bus, &file_logger->logger);
530 }
531
532 /**
533 * Load the given custom logger configured in strongswan.conf
534 */
535 static void load_custom_logger(private_daemon_t *this,
536 custom_logger_entry_t *entry,
537 linked_list_t *current_loggers)
538 {
539 custom_logger_t *custom_logger;
540 debug_t group;
541 level_t def;
542
543 custom_logger = add_custom_logger(this, entry, current_loggers);
544 if (!custom_logger)
545 {
546 return;
547 }
548
549 def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1,
550 lib->ns, entry->name);
551 for (group = 0; group < DBG_MAX; group++)
552 {
553 custom_logger->set_level(custom_logger, group,
554 lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def,
555 lib->ns, entry->name, debug_lower_names, group));
556 }
557 if (custom_logger->reload)
558 {
559 custom_logger->reload(custom_logger);
560 }
561 charon->bus->add_logger(charon->bus, &custom_logger->logger);
562 }
563
564 METHOD(daemon_t, load_loggers, void,
565 private_daemon_t *this)
566 {
567 enumerator_t *enumerator;
568 linked_list_t *current_loggers;
569 char *target;
570 int i;
571
572 this->mutex->lock(this->mutex);
573 handle_syslog_identifier(this);
574 current_loggers = this->loggers;
575 this->loggers = linked_list_create();
576 enumerator = lib->settings->create_section_enumerator(lib->settings,
577 "%s.syslog", lib->ns);
578 while (enumerator->enumerate(enumerator, &target))
579 {
580 load_sys_logger(this, target, current_loggers);
581 }
582 enumerator->destroy(enumerator);
583
584 enumerator = lib->settings->create_section_enumerator(lib->settings,
585 "%s.filelog", lib->ns);
586 while (enumerator->enumerate(enumerator, &target))
587 {
588 load_file_logger(this, target, current_loggers);
589 }
590 enumerator->destroy(enumerator);
591
592 for (i = 0; i < custom_logger_count; ++i)
593 {
594 load_custom_logger(this, &custom_loggers[i], current_loggers);
595 }
596
597 if (!this->loggers->get_count(this->loggers) && this->levels)
598 { /* setup legacy style default loggers configured via command-line */
599 file_logger_t *file_logger;
600 sys_logger_t *sys_logger;
601 debug_t group;
602
603 sys_logger = add_sys_logger(this, "daemon", current_loggers);
604 file_logger = add_file_logger(this, "stdout", current_loggers);
605 file_logger->open(file_logger, FALSE, FALSE);
606
607 for (group = 0; group < DBG_MAX; group++)
608 {
609 if (sys_logger)
610 {
611 sys_logger->set_level(sys_logger, group, this->levels[group]);
612 }
613 if (this->to_stderr)
614 {
615 file_logger->set_level(file_logger, group, this->levels[group]);
616 }
617 }
618 if (sys_logger)
619 {
620 charon->bus->add_logger(charon->bus, &sys_logger->logger);
621 }
622 charon->bus->add_logger(charon->bus, &file_logger->logger);
623
624 sys_logger = add_sys_logger(this, "auth", current_loggers);
625 if (sys_logger)
626 {
627 sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
628 charon->bus->add_logger(charon->bus, &sys_logger->logger);
629 }
630 }
631 /* unregister and destroy any unused remaining loggers */
632 current_loggers->destroy_function(current_loggers,
633 (void*)logger_entry_unregister_destroy);
634 this->mutex->unlock(this->mutex);
635 }
636
637 METHOD(daemon_t, set_default_loggers, void,
638 private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
639 {
640 debug_t group;
641
642 this->mutex->lock(this->mutex);
643 if (!levels)
644 {
645 free(this->levels);
646 this->levels = NULL;
647 }
648 else
649 {
650 if (!this->levels)
651 {
652 this->levels = calloc(sizeof(level_t), DBG_MAX);
653 }
654 for (group = 0; group < DBG_MAX; group++)
655 {
656 this->levels[group] = levels[group];
657 }
658 this->to_stderr = to_stderr;
659 }
660 this->mutex->unlock(this->mutex);
661 }
662
663 METHOD(daemon_t, set_level, void,
664 private_daemon_t *this, debug_t group, level_t level)
665 {
666 enumerator_t *enumerator;
667 logger_entry_t *entry;
668
669 /* we set the loglevel on ALL loggers */
670 this->mutex->lock(this->mutex);
671 enumerator = this->loggers->create_enumerator(this->loggers);
672 while (enumerator->enumerate(enumerator, &entry))
673 {
674 switch (entry->type)
675 {
676 case FILE_LOGGER:
677 entry->logger.file->set_level(entry->logger.file, group, level);
678 charon->bus->add_logger(charon->bus,
679 &entry->logger.file->logger);
680 break;
681 case SYS_LOGGER:
682 entry->logger.sys->set_level(entry->logger.sys, group, level);
683 charon->bus->add_logger(charon->bus,
684 &entry->logger.sys->logger);
685 break;
686 case CUSTOM_LOGGER:
687 entry->logger.custom->set_level(entry->logger.custom, group,
688 level);
689 charon->bus->add_logger(charon->bus,
690 &entry->logger.custom->logger);
691 break;
692 }
693 }
694 enumerator->destroy(enumerator);
695 this->mutex->unlock(this->mutex);
696 }
697
698 /**
699 * Clean up all daemon resources
700 */
701 static void destroy(private_daemon_t *this)
702 {
703 /* terminate all idle threads */
704 lib->processor->set_threads(lib->processor, 0);
705 /* make sure nobody waits for a DNS query */
706 lib->hosts->flush(lib->hosts);
707 /* close all IKE_SAs */
708 if (this->public.ike_sa_manager)
709 {
710 this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
711 }
712 if (this->public.traps)
713 {
714 this->public.traps->flush(this->public.traps);
715 }
716 if (this->public.shunts)
717 {
718 this->public.shunts->flush(this->public.shunts);
719 }
720 if (this->public.sender)
721 {
722 this->public.sender->flush(this->public.sender);
723 }
724
725 /* cancel all threads and wait for their termination */
726 lib->processor->cancel(lib->processor);
727
728 #ifdef ME
729 DESTROY_IF(this->public.connect_manager);
730 DESTROY_IF(this->public.mediation_manager);
731 #endif /* ME */
732 /* make sure the cache and scheduler are clear before unloading plugins */
733 lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
734 lib->scheduler->flush(lib->scheduler);
735 lib->plugins->unload(lib->plugins);
736 DESTROY_IF(this->public.attributes);
737 DESTROY_IF(this->kernel_handler);
738 DESTROY_IF(this->public.traps);
739 DESTROY_IF(this->public.shunts);
740 DESTROY_IF(this->public.redirect);
741 DESTROY_IF(this->public.controller);
742 DESTROY_IF(this->public.eap);
743 DESTROY_IF(this->public.xauth);
744 DESTROY_IF(this->public.backends);
745 DESTROY_IF(this->public.socket);
746 DESTROY_IF(this->public.kernel);
747
748 /* rehook library logging, shutdown logging */
749 dbg = dbg_old;
750 DESTROY_IF(this->public.bus);
751 this->loggers->destroy_function(this->loggers, (void*)logger_entry_destroy);
752 this->mutex->destroy(this->mutex);
753 free(this->levels);
754 free(this);
755 }
756
757 /**
758 * Run a set of configured scripts
759 */
760 static void run_scripts(private_daemon_t *this, char *verb)
761 {
762 struct {
763 char *name;
764 char *path;
765 } *script;
766 array_t *scripts = NULL;
767 enumerator_t *enumerator;
768 char *key, *value, *pos, buf[1024];
769 FILE *cmd;
770
771 /* copy the scripts so we don't hold any locks while executing them */
772 enumerator = lib->settings->create_key_value_enumerator(lib->settings,
773 "%s.%s-scripts", lib->ns, verb);
774 while (enumerator->enumerate(enumerator, &key, &value))
775 {
776 INIT(script,
777 .name = key,
778 .path = value,
779 );
780 array_insert_create(&scripts, ARRAY_TAIL, script);
781 }
782 enumerator->destroy(enumerator);
783
784 enumerator = array_create_enumerator(scripts);
785 while (enumerator->enumerate(enumerator, &script))
786 {
787 DBG1(DBG_DMN, "executing %s script '%s' (%s)", verb, script->name,
788 script->path);
789 cmd = popen(script->path, "r");
790 if (!cmd)
791 {
792 DBG1(DBG_DMN, "executing %s script '%s' (%s) failed: %s",
793 verb, script->name, script->path, strerror(errno));
794 }
795 else
796 {
797 while (TRUE)
798 {
799 if (!fgets(buf, sizeof(buf), cmd))
800 {
801 if (ferror(cmd))
802 {
803 DBG1(DBG_DMN, "reading from %s script '%s' (%s) failed",
804 verb, script->name, script->path);
805 }
806 break;
807 }
808 else
809 {
810 pos = buf + strlen(buf);
811 if (pos > buf && pos[-1] == '\n')
812 {
813 pos[-1] = '\0';
814 }
815 DBG1(DBG_DMN, "%s: %s", script->name, buf);
816 }
817 }
818 pclose(cmd);
819 }
820 free(script);
821 }
822 enumerator->destroy(enumerator);
823 array_destroy(scripts);
824 }
825
826 METHOD(daemon_t, start, void,
827 private_daemon_t *this)
828 {
829 /* start the engine, go multithreaded */
830 lib->processor->set_threads(lib->processor,
831 lib->settings->get_int(lib->settings, "%s.threads",
832 DEFAULT_THREADS, lib->ns));
833
834 run_scripts(this, "start");
835 }
836
837 /**
838 * Initialize/deinitialize sender and receiver
839 */
840 static bool sender_receiver_cb(void *plugin, plugin_feature_t *feature,
841 bool reg, private_daemon_t *this)
842 {
843 if (reg)
844 {
845 this->public.receiver = receiver_create();
846 if (!this->public.receiver)
847 {
848 return FALSE;
849 }
850 this->public.sender = sender_create();
851 }
852 else
853 {
854 DESTROY_IF(this->public.receiver);
855 DESTROY_IF(this->public.sender);
856 }
857 return TRUE;
858 }
859
860 /**
861 * Initialize/deinitialize IKE_SA/CHILD_SA managers
862 */
863 static bool sa_managers_cb(void *plugin, plugin_feature_t *feature,
864 bool reg, private_daemon_t *this)
865 {
866 if (reg)
867 {
868 this->public.ike_sa_manager = ike_sa_manager_create();
869 if (!this->public.ike_sa_manager)
870 {
871 return FALSE;
872 }
873 this->public.child_sa_manager = child_sa_manager_create();
874 }
875 else
876 {
877 DESTROY_IF(this->public.ike_sa_manager);
878 DESTROY_IF(this->public.child_sa_manager);
879 }
880 return TRUE;
881 }
882
883 METHOD(daemon_t, initialize, bool,
884 private_daemon_t *this, char *plugins)
885 {
886 plugin_feature_t features[] = {
887 PLUGIN_PROVIDE(CUSTOM, "libcharon"),
888 PLUGIN_DEPENDS(NONCE_GEN),
889 PLUGIN_DEPENDS(CUSTOM, "libcharon-sa-managers"),
890 PLUGIN_DEPENDS(CUSTOM, "libcharon-receiver"),
891 PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
892 PLUGIN_DEPENDS(CUSTOM, "kernel-net"),
893 PLUGIN_CALLBACK((plugin_feature_callback_t)sender_receiver_cb, this),
894 PLUGIN_PROVIDE(CUSTOM, "libcharon-receiver"),
895 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
896 PLUGIN_DEPENDS(RNG, RNG_STRONG),
897 PLUGIN_DEPENDS(CUSTOM, "socket"),
898 PLUGIN_CALLBACK((plugin_feature_callback_t)sa_managers_cb, this),
899 PLUGIN_PROVIDE(CUSTOM, "libcharon-sa-managers"),
900 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
901 PLUGIN_DEPENDS(RNG, RNG_WEAK),
902 };
903 lib->plugins->add_static_features(lib->plugins, lib->ns, features,
904 countof(features), TRUE, NULL, NULL);
905
906 /* load plugins, further infrastructure may need it */
907 if (!lib->plugins->load(lib->plugins, plugins))
908 {
909 return FALSE;
910 }
911
912 /* Queue start_action job */
913 lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
914
915 #ifdef ME
916 this->public.connect_manager = connect_manager_create();
917 if (this->public.connect_manager == NULL)
918 {
919 return FALSE;
920 }
921 this->public.mediation_manager = mediation_manager_create();
922 #endif /* ME */
923
924 return TRUE;
925 }
926
927 /**
928 * Create the daemon.
929 */
930 private_daemon_t *daemon_create()
931 {
932 private_daemon_t *this;
933
934 INIT(this,
935 .public = {
936 .initialize = _initialize,
937 .start = _start,
938 .load_loggers = _load_loggers,
939 .set_default_loggers = _set_default_loggers,
940 .set_level = _set_level,
941 .bus = bus_create(),
942 },
943 .loggers = linked_list_create(),
944 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
945 .ref = 1,
946 );
947 charon = &this->public;
948 this->public.kernel = kernel_interface_create();
949 this->public.attributes = attribute_manager_create();
950 this->public.controller = controller_create();
951 this->public.eap = eap_manager_create();
952 this->public.xauth = xauth_manager_create();
953 this->public.backends = backend_manager_create();
954 this->public.socket = socket_manager_create();
955 this->public.traps = trap_manager_create();
956 this->public.shunts = shunt_manager_create();
957 this->public.redirect = redirect_manager_create();
958 this->kernel_handler = kernel_handler_create();
959
960 return this;
961 }
962
963 /**
964 * Described in header.
965 */
966 void libcharon_deinit()
967 {
968 private_daemon_t *this = (private_daemon_t*)charon;
969
970 if (!this || !ref_put(&this->ref))
971 { /* have more users */
972 return;
973 }
974
975 run_scripts(this, "stop");
976
977 destroy(this);
978 charon = NULL;
979 }
980
981 /**
982 * Described in header.
983 */
984 bool libcharon_init()
985 {
986 private_daemon_t *this;
987
988 if (charon)
989 { /* already initialized, increase refcount */
990 this = (private_daemon_t*)charon;
991 ref_get(&this->ref);
992 return !this->integrity_failed;
993 }
994
995 this = daemon_create();
996
997 /* for uncritical pseudo random numbers */
998 srandom(time(NULL) + getpid());
999
1000 /* set up hook to log dbg message in library via charons message bus */
1001 dbg_old = dbg;
1002 dbg = dbg_bus;
1003
1004 if (lib->integrity &&
1005 !lib->integrity->check(lib->integrity, "libcharon", libcharon_init))
1006 {
1007 dbg(DBG_DMN, 1, "integrity check of libcharon failed");
1008 this->integrity_failed = TRUE;
1009 }
1010 return !this->integrity_failed;
1011 }