File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / charon-systemd / charon-systemd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 4 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    1: /*
    2:  * Copyright (C) 2006-2018 Tobias Brunner
    3:  * Copyright (C) 2005-2014 Martin Willi
    4:  * Copyright (C) 2006 Daniel Roethlisberger
    5:  * Copyright (C) 2005 Jan Hutter
    6:  * HSR Hochschule fuer Technik Rapperswil
    7:  * Copyright (C) 2014 revosec AG
    8:  *
    9:  * This program is free software; you can redistribute it and/or modify it
   10:  * under the terms of the GNU General Public License as published by the
   11:  * Free Software Foundation; either version 2 of the License, or (at your
   12:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
   13:  *
   14:  * This program is distributed in the hope that it will be useful, but
   15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   16:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   17:  * for more details.
   18:  */
   19: 
   20: #include <signal.h>
   21: #include <stdio.h>
   22: #include <pthread.h>
   23: #include <sys/stat.h>
   24: #include <sys/types.h>
   25: #include <sys/utsname.h>
   26: #include <unistd.h>
   27: #include <errno.h>
   28: 
   29: /* won't make sense from our logging hook */
   30: #define SD_JOURNAL_SUPPRESS_LOCATION
   31: #include <systemd/sd-daemon.h>
   32: #include <systemd/sd-journal.h>
   33: 
   34: #include <daemon.h>
   35: 
   36: #include <library.h>
   37: #include <utils/backtrace.h>
   38: #include <threading/thread.h>
   39: #include <threading/rwlock.h>
   40: 
   41: /**
   42:  * Default user and group
   43:  */
   44: #ifndef IPSEC_USER
   45: #define IPSEC_USER NULL
   46: #endif
   47: 
   48: #ifndef IPSEC_GROUP
   49: #define IPSEC_GROUP NULL
   50: #endif
   51: 
   52: /**
   53:  * hook in library for debugging messages
   54:  */
   55: extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
   56: 
   57: /**
   58:  * Logging hook for library logs, using stderr output
   59:  */
   60: static void dbg_stderr(debug_t group, level_t level, char *fmt, ...)
   61: {
   62: 	va_list args;
   63: 
   64: 	if (level <= 1)
   65: 	{
   66: 		va_start(args, fmt);
   67: 		fprintf(stderr, "00[%N] ", debug_names, group);
   68: 		vfprintf(stderr, fmt, args);
   69: 		fprintf(stderr, "\n");
   70: 		va_end(args);
   71: 	}
   72: }
   73: 
   74: typedef struct journal_logger_t journal_logger_t;
   75: 
   76: /**
   77:  * Logger implementation using systemd-journal
   78:  */
   79: struct journal_logger_t {
   80: 
   81: 	/**
   82: 	 * Public interface
   83: 	 */
   84: 	custom_logger_t public;
   85: 
   86: 	/**
   87: 	 * Configured loglevels
   88: 	 */
   89: 	level_t levels[DBG_MAX];
   90: 
   91: 	/**
   92: 	 * Lock for levels
   93: 	 */
   94: 	rwlock_t *lock;
   95: };
   96: 
   97: METHOD(logger_t, vlog, void,
   98: 	journal_logger_t *this, debug_t group, level_t level, int thread,
   99: 	ike_sa_t *ike_sa, const char *fmt, va_list args)
  100: {
  101: 	char buf[4096], *msg = buf;
  102: 	ssize_t len;
  103: 	va_list copy;
  104: 
  105: 	va_copy(copy, args);
  106: 	len = vsnprintf(msg, sizeof(buf), fmt, copy);
  107: 	va_end(copy);
  108: 
  109: 	if (len >= sizeof(buf))
  110: 	{
  111: 		len++;
  112: 		msg = malloc(len);
  113: 		va_copy(copy, args);
  114: 		len = vsnprintf(msg, len, fmt, copy);
  115: 		va_end(copy);
  116: 	}
  117: 	if (len > 0)
  118: 	{
  119: 		char unique[64] = "", name[256] = "";
  120: 		int priority;
  121: 
  122: 		if (ike_sa)
  123: 		{
  124: 			snprintf(unique, sizeof(unique), "IKE_SA_UNIQUE_ID=%u",
  125: 					 ike_sa->get_unique_id(ike_sa));
  126: 			if (ike_sa->get_peer_cfg(ike_sa))
  127: 			{
  128: 				snprintf(name, sizeof(name), "IKE_SA_NAME=%s",
  129: 						 ike_sa->get_name(ike_sa));
  130: 			}
  131: 		}
  132: 		switch (level)
  133: 		{
  134: 			case LEVEL_AUDIT:
  135: 				priority = LOG_NOTICE;
  136: 				break;
  137: 			case LEVEL_CTRL:
  138: 				priority = LOG_INFO;
  139: 				break;
  140: 			default:
  141: 				priority = LOG_DEBUG;
  142: 				break;
  143: 		}
  144: 		sd_journal_send(
  145: 			"MESSAGE=%s", msg,
  146: 			"MESSAGE_ID=57d2708c-d607-43bd-8c39-66bf%.8x",
  147: 				chunk_hash_static(chunk_from_str((char*)fmt)),
  148: 			"PRIORITY=%d", priority,
  149: 			"GROUP=%N", debug_names, group,
  150: 			"LEVEL=%d", level,
  151: 			"THREAD=%d", thread,
  152: 			unique[0] ? unique : NULL,
  153: 			name[0] ? name : NULL,
  154: 			NULL);
  155: 	}
  156: 	if (msg != buf)
  157: 	{
  158: 		free(msg);
  159: 	}
  160: }
  161: 
  162: METHOD(logger_t, get_level, level_t,
  163: 	journal_logger_t *this, debug_t group)
  164: {
  165: 	level_t level;
  166: 
  167: 	this->lock->read_lock(this->lock);
  168: 	level = this->levels[group];
  169: 	this->lock->unlock(this->lock);
  170: 
  171: 	return level;
  172: }
  173: 
  174: METHOD(custom_logger_t, set_level, void,
  175: 	journal_logger_t *this, debug_t group, level_t level)
  176: {
  177: 	this->lock->write_lock(this->lock);
  178: 	this->levels[group] = level;
  179: 	this->lock->unlock(this->lock);
  180: }
  181: 
  182: METHOD(custom_logger_t, logger_destroy, void,
  183: 	journal_logger_t *this)
  184: {
  185: 	this->lock->destroy(this->lock);
  186: 	free(this);
  187: }
  188: 
  189: static custom_logger_t *journal_logger_create(const char *name)
  190: {
  191: 	journal_logger_t *this;
  192: 
  193: 	INIT(this,
  194: 		.public = {
  195: 			.logger = {
  196: 				.vlog = _vlog,
  197: 				.get_level = _get_level,
  198: 			},
  199: 			.set_level = _set_level,
  200: 			.destroy = _logger_destroy,
  201: 		},
  202: 		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
  203: 	);
  204: 	return &this->public;
  205: }
  206: 
  207: /**
  208:  * Run the daemon and handle unix signals
  209:  */
  210: static int run()
  211: {
  212: 	sigset_t set;
  213: 
  214: 	sigemptyset(&set);
  215: 	sigaddset(&set, SIGHUP);
  216: 	sigaddset(&set, SIGTERM);
  217: 	sigprocmask(SIG_BLOCK, &set, NULL);
  218: 
  219: 	sd_notify(0, "READY=1\n");
  220: 
  221: 	while (TRUE)
  222: 	{
  223: 		int sig;
  224: 
  225: 		sig = sigwaitinfo(&set, NULL);
  226: 		if (sig == -1)
  227: 		{
  228: 			if (errno == EINTR)
  229: 			{	/* ignore signals we didn't wait for */
  230: 				continue;
  231: 			}
  232: 			DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno));
  233: 			return SS_RC_INITIALIZATION_FAILED;
  234: 		}
  235: 		switch (sig)
  236: 		{
  237: 			case SIGHUP:
  238: 			{
  239: 				DBG1(DBG_DMN, "signal of type SIGHUP received. Reloading "
  240: 					 "configuration");
  241: 				if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
  242: 				{
  243: 					charon->load_loggers(charon);
  244: 					lib->plugins->reload(lib->plugins, NULL);
  245: 				}
  246: 				else
  247: 				{
  248: 					DBG1(DBG_DMN, "reloading config failed, keeping old");
  249: 				}
  250: 				break;
  251: 			}
  252: 			case SIGTERM:
  253: 			{
  254: 				DBG1(DBG_DMN, "SIGTERM received, shutting down");
  255: 				charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
  256: 				return 0;
  257: 			}
  258: 		}
  259: 	}
  260: }
  261: 
  262: /**
  263:  * lookup UID and GID
  264:  */
  265: static bool lookup_uid_gid()
  266: {
  267: 	char *name;
  268: 
  269: 	name = lib->settings->get_str(lib->settings, "%s.user", IPSEC_USER,
  270: 								  lib->ns);
  271: 	if (name && !lib->caps->resolve_uid(lib->caps, name))
  272: 	{
  273: 		return FALSE;
  274: 	}
  275: 	name = lib->settings->get_str(lib->settings, "%s.group", IPSEC_GROUP,
  276: 								  lib->ns);
  277: 	if (name && !lib->caps->resolve_gid(lib->caps, name))
  278: 	{
  279: 		return FALSE;
  280: 	}
  281: 	return TRUE;
  282: }
  283: 
  284: #ifndef DISABLE_SIGNAL_HANDLER
  285: /**
  286:  * Handle SIGSEGV/SIGILL signals raised by threads
  287:  */
  288: static void segv_handler(int signal)
  289: {
  290: 	backtrace_t *backtrace;
  291: 
  292: 	DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
  293: 	backtrace = backtrace_create(2);
  294: 	backtrace->log(backtrace, NULL, TRUE);
  295: 	backtrace->log(backtrace, stderr, TRUE);
  296: 	backtrace->destroy(backtrace);
  297: 
  298: 	DBG1(DBG_DMN, "killing ourself, received critical signal");
  299: 	abort();
  300: }
  301: #endif /* DISABLE_SIGNAL_HANDLER */
  302: 
  303: /**
  304:  * Add namespace alias
  305:  */
  306: static void __attribute__ ((constructor))register_namespace()
  307: {
  308: 	/* inherit settings from charon */
  309: 	library_add_namespace("charon");
  310: }
  311: 
  312: /**
  313:  * Register journal logger
  314:  */
  315: static void __attribute__ ((constructor))register_logger()
  316: {
  317: 	register_custom_logger("journal", journal_logger_create);
  318: }
  319: 
  320: /**
  321:  * Main function, starts the daemon.
  322:  */
  323: int main(int argc, char *argv[])
  324: {
  325: 	struct sigaction action;
  326: 	struct utsname utsname;
  327: 	int status = SS_RC_INITIALIZATION_FAILED;
  328: 
  329: 	dbg = dbg_stderr;
  330: 
  331: 	if (uname(&utsname) != 0)
  332: 	{
  333: 		memset(&utsname, 0, sizeof(utsname));
  334: 	}
  335: 
  336: 	sd_notifyf(0, "STATUS=Starting charon-systemd, strongSwan %s, %s %s, %s",
  337: 			   VERSION, utsname.sysname, utsname.release, utsname.machine);
  338: 
  339: 	atexit(library_deinit);
  340: 	if (!library_init(NULL, "charon-systemd"))
  341: 	{
  342: 		sd_notifyf(0, "STATUS=libstrongswan initialization failed");
  343: 		return SS_RC_INITIALIZATION_FAILED;
  344: 	}
  345: 	if (lib->integrity &&
  346: 		!lib->integrity->check_file(lib->integrity, "charon-systemd", argv[0]))
  347: 	{
  348: 		sd_notifyf(0, "STATUS=integrity check of charon-systemd failed");
  349: 		return SS_RC_INITIALIZATION_FAILED;
  350: 	}
  351: 	if (!libcharon_init())
  352: 	{
  353: 		sd_notifyf(0, "STATUS=libcharon initialization failed");
  354: 		goto error;
  355: 	}
  356: 	if (!lookup_uid_gid())
  357: 	{
  358: 		sd_notifyf(0, "STATUS=unknown uid/gid");
  359: 		goto error;
  360: 	}
  361: 	/* we registered the journal logger as custom logger, which gets its
  362: 	 * settings from <ns>.customlog.journal, let it fallback to <ns>.journal */
  363: 	lib->settings->add_fallback(lib->settings, "%s.customlog.journal",
  364: 								"%s.journal", lib->ns);
  365: 	/* load the journal logger by default */
  366: 	lib->settings->set_default_str(lib->settings, "%s.journal.default", "1",
  367: 								   lib->ns);
  368: 
  369: 	charon->load_loggers(charon);
  370: 
  371: 	if (!charon->initialize(charon,
  372: 			lib->settings->get_str(lib->settings, "%s.load", PLUGINS, lib->ns)))
  373: 	{
  374: 		sd_notifyf(0, "STATUS=charon initialization failed");
  375: 		goto error;
  376: 	}
  377: 	lib->plugins->status(lib->plugins, LEVEL_CTRL);
  378: 
  379: 	if (!lib->caps->drop(lib->caps))
  380: 	{
  381: 		sd_notifyf(0, "STATUS=dropping capabilities failed");
  382: 		goto error;
  383: 	}
  384: 
  385: 	/* add handler for fatal signals,
  386: 	 * INT, TERM and HUP are handled by sigwaitinfo() in run() */
  387: 	action.sa_flags = 0;
  388: 	sigemptyset(&action.sa_mask);
  389: 	sigaddset(&action.sa_mask, SIGINT);
  390: 	sigaddset(&action.sa_mask, SIGTERM);
  391: 	sigaddset(&action.sa_mask, SIGHUP);
  392: 
  393: 	/* optionally let the external system handle fatal signals */
  394: #ifndef DISABLE_SIGNAL_HANDLER
  395: 	action.sa_handler = segv_handler;
  396: 	sigaction(SIGSEGV, &action, NULL);
  397: 	sigaction(SIGILL, &action, NULL);
  398: 	sigaction(SIGBUS, &action, NULL);
  399: #endif /* DISABLE_SIGNAL_HANDLER */
  400: 
  401: 	action.sa_handler = SIG_IGN;
  402: 	sigaction(SIGPIPE, &action, NULL);
  403: 
  404: 	pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
  405: 
  406: 	charon->start(charon);
  407: 
  408: 	sd_notifyf(0, "STATUS=charon-systemd running, strongSwan %s, %s %s, %s",
  409: 			   VERSION, utsname.sysname, utsname.release, utsname.machine);
  410: 
  411: 	status = run();
  412: 
  413: error:
  414: 	libcharon_deinit();
  415: 	return status;
  416: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>