181c6fb8a9eff51223b72d424ec3fc54e92b332e
[strongswan.git] / src / charon-tkm / src / charon-tkm.c
1 /*
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
6 *
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>.
11 *
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
15 * for more details.
16 */
17
18 #define _GNU_SOURCE
19
20 #include <stdio.h>
21 #include <syslog.h>
22 #include <signal.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <libgen.h>
27 #include <fcntl.h>
28 #include <errno.h>
29
30 #include <daemon.h>
31 #include <library.h>
32 #include <utils/backtrace.h>
33 #include <threading/thread.h>
34 #include <sa/keymat.h>
35 #include <credentials/credential_manager.h>
36
37 #include "tkm.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"
44 #include "tkm_cred.h"
45 #include "tkm_encoder.h"
46 #include "tkm_spi_generator.h"
47
48 /**
49 * TKM bus listener for IKE authorize events.
50 */
51 static tkm_listener_t *listener;
52
53 /**
54 * Name of the daemon
55 */
56 static char *dmn_name;
57
58 /**
59 * PID file, in which charon-tkm stores its process id
60 */
61 static char *pidfile_name = NULL;
62
63 /**
64 * Global reference to PID file (required to truncate, if undeletable)
65 */
66 static FILE *pidfile = NULL;
67
68 /**
69 * Hook in library for debugging messages
70 */
71 extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
72
73 /**
74 * Simple logging hook for library logs, using syslog output
75 */
76 static void dbg_syslog(debug_t group, level_t level, char *fmt, ...)
77 {
78 if (level <= 1)
79 {
80 char buffer[8192];
81 va_list args;
82
83 va_start(args, fmt);
84 /* write in memory buffer first */
85 vsnprintf(buffer, sizeof(buffer), fmt, args);
86 syslog(LOG_DAEMON|LOG_INFO, "00[%s] %s", debug_names->names[group],
87 buffer);
88 va_end(args);
89 }
90 }
91
92 /**
93 * Run the daemon and handle unix signals
94 */
95 static void run()
96 {
97 sigset_t set;
98
99 /* handle SIGINT and SIGTERM in this handler */
100 sigemptyset(&set);
101 sigaddset(&set, SIGINT);
102 sigaddset(&set, SIGTERM);
103 sigprocmask(SIG_BLOCK, &set, NULL);
104
105 while (TRUE)
106 {
107 int sig;
108
109 sig = sigwaitinfo(&set, NULL);
110 if (sig == -1)
111 {
112 if (errno == EINTR)
113 { /* ignore signals we didn't wait for */
114 continue;
115 }
116 DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno));
117 return;
118 }
119 switch (sig)
120 {
121 case SIGINT:
122 {
123 DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
124 charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
125 return;
126 }
127 case SIGTERM:
128 {
129 DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
130 charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
131 return;
132 }
133 }
134 }
135 }
136
137 /**
138 * Handle SIGSEGV/SIGILL signals raised by threads
139 */
140 static void segv_handler(int signal)
141 {
142 backtrace_t *backtrace;
143
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);
148
149 DBG1(DBG_DMN, "killing ourself, received critical signal");
150 abort();
151 }
152
153 /**
154 * Lookup UID and GID
155 */
156 static bool lookup_uid_gid()
157 {
158 #ifdef IPSEC_USER
159 if (!lib->caps->resolve_uid(lib->caps, IPSEC_USER))
160 {
161 return FALSE;
162 }
163 #endif
164 #ifdef IPSEC_GROUP
165 if (!lib->caps->resolve_gid(lib->caps, IPSEC_GROUP))
166 {
167 return FALSE;
168 }
169 #endif
170 return TRUE;
171 }
172
173 /**
174 * Check/create PID file, return TRUE if already running
175 */
176 static bool check_pidfile()
177 {
178 struct stat stb;
179
180 if (stat(pidfile_name, &stb) == 0)
181 {
182 pidfile = fopen(pidfile_name, "r");
183 if (pidfile)
184 {
185 char buf[64];
186 pid_t pid = 0;
187
188 memset(buf, 0, sizeof(buf));
189 if (fread(buf, 1, sizeof(buf), pidfile))
190 {
191 buf[sizeof(buf) - 1] = '\0';
192 pid = atoi(buf);
193 }
194 fclose(pidfile);
195 pidfile = NULL;
196 if (pid && pid != getpid() && kill(pid, 0) == 0)
197 {
198 DBG1(DBG_DMN, "%s already running ('%s' exists)", dmn_name,
199 pidfile_name);
200 return TRUE;
201 }
202 }
203 DBG1(DBG_DMN, "removing pidfile '%s', process not running", pidfile_name);
204 unlink(pidfile_name);
205 }
206
207 /* create new pidfile */
208 pidfile = fopen(pidfile_name, "w");
209 if (pidfile)
210 {
211 int fd;
212
213 fd = fileno(pidfile);
214 if (fd == -1)
215 {
216 DBG1(DBG_DMN, "unable to determine fd for '%s'", pidfile_name);
217 return TRUE;
218 }
219 if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
220 {
221 DBG1(DBG_LIB, "setting FD_CLOEXEC for '%s' failed: %s",
222 pidfile_name, strerror(errno));
223 }
224 ignore_result(fchown(fd,
225 lib->caps->get_uid(lib->caps),
226 lib->caps->get_gid(lib->caps)));
227 fprintf(pidfile, "%d\n", getpid());
228 fflush(pidfile);
229 return FALSE;
230 }
231 else
232 {
233 DBG1(DBG_DMN, "unable to create pidfile '%s'", pidfile_name);
234 return TRUE;
235 }
236 }
237
238 /**
239 * Delete/truncate the PID file
240 */
241 static void unlink_pidfile()
242 {
243 /* because unlinking the PID file may fail, we truncate it to ensure the
244 * daemon can be properly restarted. one probable cause for this is the
245 * combination of not running as root and the effective user lacking
246 * permissions on the parent dir(s) of the PID file */
247 if (pidfile)
248 {
249 ignore_result(ftruncate(fileno(pidfile), 0));
250 fclose(pidfile);
251 unlink(pidfile_name);
252 }
253 }
254
255 /**
256 * Main function, starts TKM backend.
257 */
258 int main(int argc, char *argv[])
259 {
260 if (argc > 0 && strlen(argv[0]) > 0)
261 {
262 dmn_name = basename(argv[0]);
263 }
264 else
265 {
266 dmn_name = "charon-tkm";
267 }
268
269 /* TKM credential set */
270 tkm_cred_t *creds;
271
272 struct sigaction action;
273 int status = SS_RC_INITIALIZATION_FAILED;
274
275 /* logging for library during initialization, as we have no bus yet */
276 dbg = dbg_syslog;
277
278 /* initialize library */
279 if (!library_init(NULL, dmn_name))
280 {
281 library_deinit();
282 exit(status);
283 }
284
285 if (!libcharon_init())
286 {
287 dbg_syslog(DBG_DMN, 1, "initialization failed - aborting %s", dmn_name);
288 goto deinit;
289 }
290
291 if (!lookup_uid_gid())
292 {
293 dbg_syslog(DBG_DMN, 1, "invalid uid/gid - aborting %s", dmn_name);
294 goto deinit;
295 }
296
297 /* the authorize hook currently does not support RFC 7427 signature auth */
298 lib->settings->set_bool(lib->settings, "%s.signature_authentication", FALSE,
299 dmn_name);
300
301 /* make sure we log to the DAEMON facility by default */
302 lib->settings->set_int(lib->settings, "%s.syslog.daemon.default",
303 lib->settings->get_int(lib->settings, "%s.syslog.daemon.default", 1,
304 dmn_name), dmn_name);
305 charon->load_loggers(charon);
306
307 DBG1(DBG_DMN, "Starting charon with TKM backend (strongSwan "VERSION")");
308
309 /* register TKM specific plugins */
310 static plugin_feature_t features[] = {
311 PLUGIN_REGISTER(NONCE_GEN, tkm_nonceg_create),
312 PLUGIN_PROVIDE(NONCE_GEN),
313 PLUGIN_REGISTER(PUBKEY, tkm_public_key_load, TRUE),
314 PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
315 PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1),
316 PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_256),
317 PLUGIN_CALLBACK(kernel_ipsec_register, tkm_kernel_ipsec_create),
318 PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
319 PLUGIN_CALLBACK(tkm_spi_generator_register, NULL),
320 PLUGIN_PROVIDE(CUSTOM, "tkm-spi-generator"),
321 PLUGIN_DEPENDS(CUSTOM, "libcharon-sa-managers"),
322 };
323 lib->plugins->add_static_features(lib->plugins, "tkm-backend", features,
324 countof(features), TRUE, NULL, NULL);
325
326 if (!register_dh_mapping())
327 {
328 DBG1(DBG_DMN, "no DH group mapping defined - aborting %s", dmn_name);
329 goto deinit;
330 }
331
332 /* register TKM keymat variant */
333 keymat_register_constructor(IKEV2, (keymat_constructor_t)tkm_keymat_create);
334
335 /* initialize daemon */
336 if (!charon->initialize(charon, PLUGINS))
337 {
338 DBG1(DBG_DMN, "initialization failed - aborting %s", dmn_name);
339 goto deinit;
340 }
341 lib->plugins->status(lib->plugins, LEVEL_CTRL);
342
343 /* set global pidfile name depending on daemon name */
344 if (asprintf(&pidfile_name, IPSEC_PIDDIR"/%s.pid", dmn_name) < 0)
345 {
346 DBG1(DBG_DMN, "unable to set pidfile name - aborting %s", dmn_name);
347 goto deinit;
348 };
349
350 if (check_pidfile())
351 {
352 goto deinit;
353 }
354
355 if (!lib->caps->drop(lib->caps))
356 {
357 DBG1(DBG_DMN, "capability dropping failed - aborting %s", dmn_name);
358 goto deinit;
359 }
360
361 /* initialize TKM client */
362 if (!tkm_init())
363 {
364 DBG1(DBG_DMN, "init of TKM client failed - aborting %s", dmn_name);
365 goto deinit;
366 }
367
368 /* register TKM authorization hook */
369 listener = tkm_listener_create();
370 charon->bus->add_listener(charon->bus, &listener->listener);
371
372 /* register TKM credential set */
373 creds = tkm_cred_create();
374 lib->credmgr->add_set(lib->credmgr, (credential_set_t*)creds);
375
376 /* register TKM credential encoder */
377 lib->encoding->add_encoder(lib->encoding, tkm_encoder_encode);
378
379 /* add handler for SEGV and ILL,
380 * INT and TERM are handled by sigwaitinfo() in run() */
381 action.sa_handler = segv_handler;
382 action.sa_flags = 0;
383 sigemptyset(&action.sa_mask);
384 sigaddset(&action.sa_mask, SIGINT);
385 sigaddset(&action.sa_mask, SIGTERM);
386 sigaction(SIGSEGV, &action, NULL);
387 sigaction(SIGILL, &action, NULL);
388 sigaction(SIGBUS, &action, NULL);
389 action.sa_handler = SIG_IGN;
390 sigaction(SIGPIPE, &action, NULL);
391
392 pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
393
394 /* start daemon (i.e. the threads in the thread-pool) */
395 charon->start(charon);
396
397 /* main thread goes to run loop */
398 run();
399
400 status = 0;
401 charon->bus->remove_listener(charon->bus, &listener->listener);
402 listener->destroy(listener);
403 creds->destroy(creds);
404 lib->encoding->remove_encoder(lib->encoding, tkm_encoder_encode);
405
406 deinit:
407 destroy_dh_mapping();
408 libcharon_deinit();
409 tkm_deinit();
410 unlink_pidfile();
411 free(pidfile_name);
412 library_deinit();
413 return status;
414 }