2 * Copyright (C) 2012-2017 Tobias Brunner
3 * Copyright (C) 2012 Reto Buerki
4 * Copyright (C) 2012 Adrian-Ken Rueegsegger
5 * HSR 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>
34 #include <sa/keymat.h>
35 #include <credentials/credential_manager.h>
38 #include "tkm_nonceg.h"
39 #include "tkm_diffie_hellman.h"
40 #include "tkm_keymat.h"
41 #include "tkm_listener.h"
42 #include "tkm_kernel_ipsec.h"
43 #include "tkm_public_key.h"
45 #include "tkm_encoder.h"
48 * TKM bus listener for IKE authorize events.
50 static tkm_listener_t
*listener
;
55 static char *dmn_name
;
58 * PID file, in which charon-tkm stores its process id
60 static char *pidfile_name
= NULL
;
63 * Global reference to PID file (required to truncate, if undeletable)
65 static FILE *pidfile
= NULL
;
68 * Hook in library for debugging messages
70 extern void (*dbg
) (debug_t group
, level_t level
, char *fmt
, ...);
73 * Simple logging hook for library logs, using syslog output
75 static void dbg_syslog(debug_t group
, level_t level
, char *fmt
, ...)
83 /* write in memory buffer first */
84 vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
85 syslog(LOG_DAEMON
|LOG_INFO
, "00[%s] %s", debug_names
->names
[group
],
92 * Run the daemon and handle unix signals
98 /* handle SIGINT and SIGTERM in this handler */
100 sigaddset(&set
, SIGINT
);
101 sigaddset(&set
, SIGTERM
);
102 sigprocmask(SIG_BLOCK
, &set
, NULL
);
108 sig
= sigwaitinfo(&set
, NULL
);
112 { /* ignore signals we didn't wait for */
115 DBG1(DBG_DMN
, "waiting for signal failed: %s", strerror(errno
));
122 DBG1(DBG_DMN
, "signal of type SIGINT received. Shutting down");
123 charon
->bus
->alert(charon
->bus
, ALERT_SHUTDOWN_SIGNAL
, sig
);
128 DBG1(DBG_DMN
, "signal of type SIGTERM received. Shutting down");
129 charon
->bus
->alert(charon
->bus
, ALERT_SHUTDOWN_SIGNAL
, sig
);
136 #ifndef DISABLE_SIGNAL_HANDLER
138 * Handle SIGSEGV/SIGILL signals raised by threads
140 static void segv_handler(int signal
)
142 backtrace_t
*backtrace
;
144 DBG1(DBG_DMN
, "thread %u received %d", thread_current_id(), signal
);
145 backtrace
= backtrace_create(2);
146 backtrace
->log(backtrace
, stderr
, TRUE
);
147 backtrace
->destroy(backtrace
);
149 DBG1(DBG_DMN
, "killing ourself, received critical signal");
152 #endif /* DISABLE_SIGNAL_HANDLER */
157 static bool lookup_uid_gid()
160 if (!lib
->caps
->resolve_uid(lib
->caps
, IPSEC_USER
))
166 if (!lib
->caps
->resolve_gid(lib
->caps
, IPSEC_GROUP
))
175 * Check/create PID file, return TRUE if already running
177 static bool check_pidfile()
181 if (stat(pidfile_name
, &stb
) == 0)
183 pidfile
= fopen(pidfile_name
, "r");
189 memset(buf
, 0, sizeof(buf
));
190 if (fread(buf
, 1, sizeof(buf
), pidfile
))
192 buf
[sizeof(buf
) - 1] = '\0';
197 if (pid
&& pid
!= getpid() && kill(pid
, 0) == 0)
199 DBG1(DBG_DMN
, "%s already running ('%s' exists)", dmn_name
,
204 DBG1(DBG_DMN
, "removing pidfile '%s', process not running", pidfile_name
);
205 unlink(pidfile_name
);
208 /* create new pidfile */
209 pidfile
= fopen(pidfile_name
, "w");
214 fd
= fileno(pidfile
);
217 DBG1(DBG_DMN
, "unable to determine fd for '%s'", pidfile_name
);
220 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) == -1)
222 DBG1(DBG_LIB
, "setting FD_CLOEXEC for '%s' failed: %s",
223 pidfile_name
, strerror(errno
));
225 ignore_result(fchown(fd
,
226 lib
->caps
->get_uid(lib
->caps
),
227 lib
->caps
->get_gid(lib
->caps
)));
228 fprintf(pidfile
, "%d\n", getpid());
234 DBG1(DBG_DMN
, "unable to create pidfile '%s'", pidfile_name
);
240 * Delete/truncate the PID file
242 static void unlink_pidfile()
244 /* because unlinking the PID file may fail, we truncate it to ensure the
245 * daemon can be properly restarted. one probable cause for this is the
246 * combination of not running as root and the effective user lacking
247 * permissions on the parent dir(s) of the PID file */
250 ignore_result(ftruncate(fileno(pidfile
), 0));
252 unlink(pidfile_name
);
257 * Main function, starts TKM backend.
259 int main(int argc
, char *argv
[])
261 if (argc
> 0 && strlen(argv
[0]) > 0)
263 dmn_name
= basename(argv
[0]);
267 dmn_name
= "charon-tkm";
270 /* TKM credential set */
273 struct sigaction action
;
274 int status
= SS_RC_INITIALIZATION_FAILED
;
276 /* logging for library during initialization, as we have no bus yet */
279 /* initialize library */
280 if (!library_init(NULL
, dmn_name
))
286 if (!libcharon_init())
288 dbg_syslog(DBG_DMN
, 1, "initialization failed - aborting %s", dmn_name
);
292 if (!lookup_uid_gid())
294 dbg_syslog(DBG_DMN
, 1, "invalid uid/gid - aborting %s", dmn_name
);
298 /* the authorize hook currently does not support RFC 7427 signature auth */
299 lib
->settings
->set_bool(lib
->settings
, "%s.signature_authentication", FALSE
,
302 /* make sure we log to the DAEMON facility by default */
303 lib
->settings
->set_int(lib
->settings
, "%s.syslog.daemon.default",
304 lib
->settings
->get_int(lib
->settings
, "%s.syslog.daemon.default", 1,
305 dmn_name
), dmn_name
);
306 charon
->load_loggers(charon
);
308 DBG1(DBG_DMN
, "Starting charon with TKM backend (strongSwan "VERSION
")");
310 /* register TKM specific plugins */
311 static plugin_feature_t features
[] = {
312 PLUGIN_REGISTER(NONCE_GEN
, tkm_nonceg_create
),
313 PLUGIN_PROVIDE(NONCE_GEN
),
314 PLUGIN_REGISTER(PUBKEY
, tkm_public_key_load
, TRUE
),
315 PLUGIN_PROVIDE(PUBKEY
, KEY_RSA
),
316 PLUGIN_PROVIDE(PUBKEY_VERIFY
, SIGN_RSA_EMSA_PKCS1_SHA1
),
317 PLUGIN_PROVIDE(PUBKEY_VERIFY
, SIGN_RSA_EMSA_PKCS1_SHA2_256
),
318 PLUGIN_CALLBACK(kernel_ipsec_register
, tkm_kernel_ipsec_create
),
319 PLUGIN_PROVIDE(CUSTOM
, "kernel-ipsec"),
321 lib
->plugins
->add_static_features(lib
->plugins
, "tkm-backend", features
,
322 countof(features
), TRUE
, NULL
, NULL
);
324 if (!register_dh_mapping())
326 DBG1(DBG_DMN
, "no DH group mapping defined - aborting %s", dmn_name
);
330 /* register TKM keymat variant */
331 keymat_register_constructor(IKEV2
, (keymat_constructor_t
)tkm_keymat_create
);
333 /* initialize daemon */
334 if (!charon
->initialize(charon
, PLUGINS
))
336 DBG1(DBG_DMN
, "initialization failed - aborting %s", dmn_name
);
339 lib
->plugins
->status(lib
->plugins
, LEVEL_CTRL
);
341 /* set global pidfile name depending on daemon name */
342 if (asprintf(&pidfile_name
, IPSEC_PIDDIR
"/%s.pid", dmn_name
) < 0)
344 DBG1(DBG_DMN
, "unable to set pidfile name - aborting %s", dmn_name
);
353 if (!lib
->caps
->drop(lib
->caps
))
355 DBG1(DBG_DMN
, "capability dropping failed - aborting %s", dmn_name
);
359 /* initialize TKM client */
362 DBG1(DBG_DMN
, "init of TKM client failed - aborting %s", dmn_name
);
366 /* register TKM authorization hook */
367 listener
= tkm_listener_create();
368 charon
->bus
->add_listener(charon
->bus
, &listener
->listener
);
370 /* register TKM credential set */
371 creds
= tkm_cred_create();
372 lib
->credmgr
->add_set(lib
->credmgr
, (credential_set_t
*)creds
);
374 /* register TKM credential encoder */
375 lib
->encoding
->add_encoder(lib
->encoding
, tkm_encoder_encode
);
377 /* add handler for fatal signals,
378 * INT and TERM are handled by sigwaitinfo() in run() */
380 sigemptyset(&action
.sa_mask
);
381 sigaddset(&action
.sa_mask
, SIGINT
);
382 sigaddset(&action
.sa_mask
, SIGTERM
);
384 /* optionally let the external system handle fatal signals */
385 #ifndef DISABLE_SIGNAL_HANDLER
386 action
.sa_handler
= segv_handler
;
387 sigaction(SIGSEGV
, &action
, NULL
);
388 sigaction(SIGILL
, &action
, NULL
);
389 sigaction(SIGBUS
, &action
, NULL
);
390 #endif /* DISABLE_SIGNAL_HANDLER */
392 action
.sa_handler
= SIG_IGN
;
393 sigaction(SIGPIPE
, &action
, NULL
);
395 pthread_sigmask(SIG_SETMASK
, &action
.sa_mask
, NULL
);
397 /* start daemon (i.e. the threads in the thread-pool) */
398 charon
->start(charon
);
400 /* main thread goes to run loop */
404 charon
->bus
->remove_listener(charon
->bus
, &listener
->listener
);
405 listener
->destroy(listener
);
406 creds
->destroy(creds
);
407 lib
->encoding
->remove_encoder(lib
->encoding
, tkm_encoder_encode
);
410 destroy_dh_mapping();