2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Reto Buerki
4 * Copyright (C) 2012 Adrian-Ken Rueegsegger
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include <sys/types.h>
32 #include <utils/backtrace.h>
33 #include <threading/thread.h>
36 #include "tkm_nonceg.h"
37 #include "tkm_diffie_hellman.h"
40 * PID file, in which charon-tkm stores its process id
42 static char *pidfile_name
= NULL
;
45 * Global reference to PID file (required to truncate, if undeletable)
47 static FILE *pidfile
= NULL
;
50 * Hook in library for debugging messages
52 extern void (*dbg
) (debug_t group
, level_t level
, char *fmt
, ...);
55 * Simple logging hook for library logs, using syslog output
57 static void dbg_syslog(debug_t group
, level_t level
, char *fmt
, ...)
65 /* write in memory buffer first */
66 vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
67 syslog(LOG_DAEMON
|LOG_INFO
, "00[%s] %s", debug_names
->names
[group
],
74 * Run the daemon and handle unix signals
80 /* handle SIGINT and SIGTERM in this handler */
82 sigaddset(&set
, SIGINT
);
83 sigaddset(&set
, SIGTERM
);
84 sigprocmask(SIG_BLOCK
, &set
, NULL
);
91 error
= sigwait(&set
, &sig
);
94 DBG1(DBG_DMN
, "error %d while waiting for a signal", error
);
101 DBG1(DBG_DMN
, "signal of type SIGINT received. Shutting down");
102 charon
->bus
->alert(charon
->bus
, ALERT_SHUTDOWN_SIGNAL
, sig
);
107 DBG1(DBG_DMN
, "signal of type SIGTERM received. Shutting down");
108 charon
->bus
->alert(charon
->bus
, ALERT_SHUTDOWN_SIGNAL
, sig
);
113 DBG1(DBG_DMN
, "unknown signal %d received. Ignored", sig
);
121 * Handle SIGSEGV/SIGILL signals raised by threads
123 static void segv_handler(int signal
)
125 backtrace_t
*backtrace
;
127 DBG1(DBG_DMN
, "thread %u received %d", thread_current_id(), signal
);
128 backtrace
= backtrace_create(2);
129 backtrace
->log(backtrace
, stderr
, TRUE
);
130 backtrace
->destroy(backtrace
);
132 DBG1(DBG_DMN
, "killing ourself, received critical signal");
139 static bool lookup_uid_gid()
142 if (!charon
->caps
->resolve_uid(charon
->caps
, IPSEC_USER
))
148 if (!charon
->caps
->resolve_gid(charon
->caps
, IPSEC_GROUP
))
157 * Check/create PID file, return TRUE if already running
159 static bool check_pidfile()
163 if (stat(pidfile_name
, &stb
) == 0)
165 pidfile
= fopen(pidfile_name
, "r");
171 memset(buf
, 0, sizeof(buf
));
172 if (fread(buf
, 1, sizeof(buf
), pidfile
))
174 buf
[sizeof(buf
) - 1] = '\0';
178 if (pid
&& kill(pid
, 0) == 0)
179 { /* such a process is running */
183 DBG1(DBG_DMN
, "removing pidfile '%s', process not running", pidfile_name
);
184 unlink(pidfile_name
);
187 /* create new pidfile */
188 pidfile
= fopen(pidfile_name
, "w");
191 ignore_result(fchown(fileno(pidfile
),
192 charon
->caps
->get_uid(charon
->caps
),
193 charon
->caps
->get_gid(charon
->caps
)));
194 fprintf(pidfile
, "%d\n", getpid());
201 * Delete/truncate the PID file
203 static void unlink_pidfile()
205 /* because unlinking the PID file may fail, we truncate it to ensure the
206 * daemon can be properly restarted. one probable cause for this is the
207 * combination of not running as root and the effective user lacking
208 * permissions on the parent dir(s) of the PID file */
211 ignore_result(ftruncate(fileno(pidfile
), 0));
214 unlink(pidfile_name
);
217 * Main function, starts TKM backend.
219 int main(int argc
, char *argv
[])
222 if (argc
> 0 && strlen(argv
[0]) > 0)
224 dmn_name
= basename(argv
[0]);
228 dmn_name
= "charon-tkm";
231 struct sigaction action
;
232 int status
= SS_RC_INITIALIZATION_FAILED
;
234 /* logging for library during initialization, as we have no bus yet */
237 /* initialize library */
238 if (!library_init(NULL
))
244 if (!libhydra_init(dmn_name
))
246 dbg_syslog(DBG_DMN
, 1, "initialization failed - aborting %s", dmn_name
);
252 if (!libcharon_init(dmn_name
))
254 dbg_syslog(DBG_DMN
, 1, "initialization failed - aborting %s", dmn_name
);
258 if (!lookup_uid_gid())
260 dbg_syslog(DBG_DMN
, 1, "invalid uid/gid - aborting %s", dmn_name
);
264 /* make sure we log to the DAEMON facility by default */
265 lib
->settings
->set_int(lib
->settings
, "%s.syslog.daemon.default",
266 lib
->settings
->get_int(lib
->settings
, "%s.syslog.daemon.default", 1,
267 dmn_name
), dmn_name
);
268 charon
->load_loggers(charon
, NULL
, FALSE
);
270 DBG1(DBG_DMN
, "Starting charon with TKM backend (strongSwan "VERSION
")");
272 /* register TKM specific plugins */
273 static plugin_feature_t features
[] = {
274 PLUGIN_REGISTER(NONCE_GEN
, tkm_nonceg_create
),
275 PLUGIN_PROVIDE(NONCE_GEN
),
276 PLUGIN_REGISTER(DH
, tkm_diffie_hellman_create
),
277 PLUGIN_PROVIDE(DH
, MODP_3072_BIT
),
278 PLUGIN_PROVIDE(DH
, MODP_4096_BIT
),
280 lib
->plugins
->add_static_features(lib
->plugins
, "tkm-backend", features
,
281 countof(features
), TRUE
);
283 /* initialize daemon */
284 if (!charon
->initialize(charon
, PLUGINS
))
286 DBG1(DBG_DMN
, "initialization failed - aborting %s", dmn_name
);
290 /* set global pidfile name depending on daemon name */
291 if (asprintf(&pidfile_name
, IPSEC_PIDDIR
"/%s.pid", dmn_name
) < 0)
293 DBG1(DBG_DMN
, "unable to set pidfile name - aborting %s", dmn_name
);
299 DBG1(DBG_DMN
, "%s already running (\"%s\" exists)", dmn_name
,
304 if (!charon
->caps
->drop(charon
->caps
))
306 DBG1(DBG_DMN
, "capability dropping failed - aborting %s", dmn_name
);
310 /* initialize TKM client */
313 DBG1(DBG_DMN
, "init of TKM client failed - aborting %s", dmn_name
);
317 /* add handler for SEGV and ILL,
318 * INT and TERM are handled by sigwait() in run() */
319 action
.sa_handler
= segv_handler
;
321 sigemptyset(&action
.sa_mask
);
322 sigaddset(&action
.sa_mask
, SIGINT
);
323 sigaddset(&action
.sa_mask
, SIGTERM
);
324 sigaction(SIGSEGV
, &action
, NULL
);
325 sigaction(SIGILL
, &action
, NULL
);
326 sigaction(SIGBUS
, &action
, NULL
);
327 action
.sa_handler
= SIG_IGN
;
328 sigaction(SIGPIPE
, &action
, NULL
);
330 pthread_sigmask(SIG_SETMASK
, &action
.sa_mask
, NULL
);
332 /* start daemon (i.e. the threads in the thread-pool) */
333 charon
->start(charon
);
335 /* main thread goes to run loop */