2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 #include "hooks/hook.h"
29 #include <threading/thread.h>
30 #include <credentials/certificates/x509.h>
33 * Conftest globals struct
38 * Print usage information
40 static void usage(FILE *out
)
42 fprintf(out
, "Usage:\n");
43 fprintf(out
, " --help show usage information\n");
44 fprintf(out
, " --version show conftest version\n");
45 fprintf(out
, " --suite <file> global testsuite configuration "
46 "(default: ./suite.conf)\n");
47 fprintf(out
, " --test <file> test specific configuration\n");
51 * Handle SIGSEGV/SIGILL signals raised by threads
53 static void segv_handler(int signal
)
55 fprintf(stderr
, "thread %u received %d\n", thread_current_id(), signal
);
60 * Load suite and test specific configurations
62 static bool load_configs(char *suite_file
, char *test_file
)
66 fprintf(stderr
, "Missing test configuration file.\n");
69 if (access(suite_file
, R_OK
) != 0)
71 fprintf(stderr
, "Reading suite configuration file '%s' failed: %s.\n",
72 suite_file
, strerror(errno
));
75 if (access(test_file
, R_OK
) != 0)
77 fprintf(stderr
, "Reading test configuration file '%s' failed: %s.\n",
78 test_file
, strerror(errno
));
81 conftest
->test
= settings_create(suite_file
);
82 conftest
->test
->load_files(conftest
->test
, test_file
, TRUE
);
83 conftest
->suite_dir
= strdup(dirname(suite_file
));
88 * Load trusted/untrusted certificates
90 static bool load_cert(settings_t
*settings
, bool trusted
)
92 enumerator_t
*enumerator
;
95 enumerator
= settings
->create_key_value_enumerator(settings
,
96 trusted ?
"certs.trusted" : "certs.untrusted");
97 while (enumerator
->enumerate(enumerator
, &key
, &value
))
99 certificate_t
*cert
= NULL
;
101 if (strncaseeq(key
, "x509", strlen("x509")))
103 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
104 CERT_X509
, BUILD_FROM_FILE
, value
, BUILD_END
);
106 else if (strncaseeq(key
, "crl", strlen("crl")))
108 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
109 CERT_X509_CRL
, BUILD_FROM_FILE
, value
, BUILD_END
);
113 fprintf(stderr
, "certificate type '%s' not supported\n", key
);
114 enumerator
->destroy(enumerator
);
119 fprintf(stderr
, "loading %strusted certificate '%s' from '%s' "
120 "failed\n", trusted ?
"" : "un", key
, value
);
121 enumerator
->destroy(enumerator
);
124 conftest
->creds
->add_cert(conftest
->creds
, trusted
, cert
);
126 enumerator
->destroy(enumerator
);
131 * Load certificates from the confiuguration file
133 static bool load_certs(settings_t
*settings
, char *dir
)
137 if (getcwd(wd
, sizeof(wd
)) == NULL
)
139 fprintf(stderr
, "getting cwd failed: %s\n", strerror(errno
));
144 fprintf(stderr
, "opening directory '%s' failed: %s\n",
145 dir
, strerror(errno
));
149 if (!load_cert(settings
, TRUE
) ||
150 !load_cert(settings
, FALSE
))
157 fprintf(stderr
, "opening directory '%s' failed: %s\n",
158 wd
, strerror(errno
));
165 * Load private keys from the confiuguration file
167 static bool load_keys(settings_t
*settings
, char *dir
)
169 enumerator_t
*enumerator
;
170 char *type
, *value
, wd
[PATH_MAX
];
174 if (getcwd(wd
, sizeof(wd
)) == NULL
)
176 fprintf(stderr
, "getting cwd failed: %s\n", strerror(errno
));
181 fprintf(stderr
, "opening directory '%s' failed: %s\n",
182 dir
, strerror(errno
));
186 enumerator
= settings
->create_key_value_enumerator(settings
, "keys");
187 while (enumerator
->enumerate(enumerator
, &type
, &value
))
189 if (strncaseeq(type
, "ecdsa", strlen("ecdsa")))
191 key_type
= KEY_ECDSA
;
193 else if (strncaseeq(type
, "rsa", strlen("rsa")))
199 fprintf(stderr
, "unknown key type: '%s'\n", type
);
200 enumerator
->destroy(enumerator
);
203 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
204 BUILD_FROM_FILE
, value
, BUILD_END
);
207 fprintf(stderr
, "loading %s key from '%s' failed\n", type
, value
);
208 enumerator
->destroy(enumerator
);
211 conftest
->creds
->add_key(conftest
->creds
, key
);
213 enumerator
->destroy(enumerator
);
217 fprintf(stderr
, "opening directory '%s' failed: %s\n",
218 wd
, strerror(errno
));
225 * Load certificate distribution points
227 static void load_cdps(settings_t
*settings
)
229 enumerator_t
*enumerator
;
230 identification_t
*id
;
231 char *ca
, *uri
, *section
;
232 certificate_type_t type
;
235 enumerator
= settings
->create_section_enumerator(settings
, "cdps");
236 while (enumerator
->enumerate(enumerator
, §ion
))
238 if (strncaseeq(section
, "crl", strlen("crl")))
240 type
= CERT_X509_CRL
;
242 else if (strncaseeq(section
, "ocsp", strlen("ocsp")))
244 type
= CERT_X509_OCSP_RESPONSE
;
248 fprintf(stderr
, "unknown cdp type '%s', ignored\n", section
);
252 uri
= settings
->get_str(settings
, "cdps.%s.uri", NULL
, section
);
253 ca
= settings
->get_str(settings
, "cdps.%s.ca", NULL
, section
);
256 fprintf(stderr
, "cdp '%s' misses ca/uri, ignored\n", section
);
259 x509
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
260 CERT_X509
, BUILD_FROM_FILE
, ca
, BUILD_END
);
263 fprintf(stderr
, "loading cdp '%s' ca failed, ignored\n", section
);
266 id
= identification_create_from_encoding(ID_KEY_ID
,
267 x509
->get_subjectKeyIdentifier(x509
));
268 conftest
->creds
->add_cdp(conftest
->creds
, type
, id
, uri
);
269 DESTROY_IF((certificate_t
*)x509
);
272 enumerator
->destroy(enumerator
);
276 * Load configured hooks
278 static bool load_hooks()
280 enumerator_t
*enumerator
;
281 char *name
, *pos
, buf
[64];
282 hook_t
*(*create
)(char*);
285 enumerator
= conftest
->test
->create_section_enumerator(conftest
->test
,
287 while (enumerator
->enumerate(enumerator
, &name
))
289 pos
= strchr(name
, '-');
292 snprintf(buf
, sizeof(buf
), "%.*s_hook_create", (int)(pos
- name
),
297 snprintf(buf
, sizeof(buf
), "%s_hook_create", name
);
299 create
= dlsym(RTLD_DEFAULT
, buf
);
305 conftest
->hooks
->insert_last(conftest
->hooks
, hook
);
306 charon
->bus
->add_listener(charon
->bus
, &hook
->listener
);
311 fprintf(stderr
, "dlsym() for hook '%s' failed: %s\n", name
, dlerror());
312 enumerator
->destroy(enumerator
);
316 enumerator
->destroy(enumerator
);
321 * atexit() cleanup handler
323 static void cleanup()
327 DESTROY_IF(conftest
->test
);
328 lib
->credmgr
->remove_set(lib
->credmgr
, &conftest
->creds
->set
);
329 conftest
->creds
->destroy(conftest
->creds
);
330 DESTROY_IF(conftest
->actions
);
331 while (conftest
->hooks
->remove_last(conftest
->hooks
,
332 (void**)&hook
) == SUCCESS
)
334 charon
->bus
->remove_listener(charon
->bus
, &hook
->listener
);
337 conftest
->hooks
->destroy(conftest
->hooks
);
338 if (conftest
->config
)
340 if (charon
->backends
)
342 charon
->backends
->remove_backend(charon
->backends
,
343 &conftest
->config
->backend
);
345 conftest
->config
->destroy(conftest
->config
);
347 free(conftest
->suite_dir
);
355 * Load log levels for a logger from section
357 static void load_log_levels(file_logger_t
*logger
, char *section
)
362 def
= conftest
->test
->get_int(conftest
->test
, "log.%s.default", 1, section
);
363 for (group
= 0; group
< DBG_MAX
; group
++)
365 logger
->set_level(logger
, group
,
366 conftest
->test
->get_int(conftest
->test
, "log.%s.%N", def
,
367 section
, debug_lower_names
, group
));
372 * Load logger configuration
374 static void load_loggers(file_logger_t
*logger
)
376 enumerator_t
*enumerator
;
380 load_log_levels(logger
, "stdout");
382 enumerator
= conftest
->test
->create_section_enumerator(conftest
->test
, "log");
383 while (enumerator
->enumerate(enumerator
, §ion
))
385 if (!streq(section
, "stdout"))
387 file
= fopen(section
, "w");
390 fprintf(stderr
, "opening file %s for logging failed: %s",
391 section
, strerror(errno
));
394 logger
= file_logger_create(file
, NULL
, FALSE
);
395 load_log_levels(logger
, section
);
396 charon
->bus
->add_logger(charon
->bus
, &logger
->logger
);
397 charon
->file_loggers
->insert_last(charon
->file_loggers
, logger
);
400 enumerator
->destroy(enumerator
);
404 * Main function, starts the conftest daemon.
406 int main(int argc
, char *argv
[])
408 struct sigaction action
;
412 char *suite_file
= "suite.conf", *test_file
= NULL
;
413 file_logger_t
*logger
;
415 if (!library_init(NULL
))
418 return SS_RC_LIBSTRONGSWAN_INTEGRITY
;
420 if (!libhydra_init("conftest"))
424 return SS_RC_INITIALIZATION_FAILED
;
426 if (!libcharon_init("conftest"))
431 return SS_RC_INITIALIZATION_FAILED
;
435 .creds
= mem_cred_create(),
438 logger
= file_logger_create(stdout
, NULL
, FALSE
);
439 logger
->set_level(logger
, DBG_ANY
, LEVEL_CTRL
);
440 charon
->bus
->add_logger(charon
->bus
, &logger
->logger
);
441 charon
->file_loggers
->insert_last(charon
->file_loggers
, logger
);
443 lib
->credmgr
->add_set(lib
->credmgr
, &conftest
->creds
->set
);
444 conftest
->hooks
= linked_list_create();
445 conftest
->config
= config_create();
451 struct option long_opts
[] = {
452 { "help", no_argument
, NULL
, 'h' },
453 { "version", no_argument
, NULL
, 'v' },
454 { "suite", required_argument
, NULL
, 's' },
455 { "test", required_argument
, NULL
, 't' },
458 switch (getopt_long(argc
, argv
, "", long_opts
, NULL
))
466 printf("strongSwan %s conftest\n", VERSION
);
481 if (!load_configs(suite_file
, test_file
))
485 load_loggers(logger
);
487 if (!lib
->plugins
->load(lib
->plugins
, NULL
,
488 conftest
->test
->get_str(conftest
->test
, "preload", "")))
492 if (!charon
->initialize(charon
, PLUGINS
))
496 if (!load_certs(conftest
->test
, conftest
->suite_dir
))
500 if (!load_keys(conftest
->test
, conftest
->suite_dir
))
504 load_cdps(conftest
->test
);
509 charon
->backends
->add_backend(charon
->backends
, &conftest
->config
->backend
);
510 conftest
->config
->load(conftest
->config
, conftest
->test
);
511 conftest
->actions
= actions_create();
513 /* set up thread specific handlers */
514 action
.sa_handler
= segv_handler
;
516 sigemptyset(&action
.sa_mask
);
517 sigaddset(&action
.sa_mask
, SIGINT
);
518 sigaddset(&action
.sa_mask
, SIGTERM
);
519 sigaddset(&action
.sa_mask
, SIGHUP
);
520 sigaction(SIGSEGV
, &action
, NULL
);
521 sigaction(SIGILL
, &action
, NULL
);
522 sigaction(SIGBUS
, &action
, NULL
);
523 action
.sa_handler
= SIG_IGN
;
524 sigaction(SIGPIPE
, &action
, NULL
);
525 pthread_sigmask(SIG_SETMASK
, &action
.sa_mask
, NULL
);
527 /* start thread pool */
528 charon
->start(charon
);
530 /* handle SIGINT/SIGTERM in main thread */
532 sigaddset(&set
, SIGINT
);
533 sigaddset(&set
, SIGHUP
);
534 sigaddset(&set
, SIGTERM
);
535 sigprocmask(SIG_BLOCK
, &set
, NULL
);
537 while (sigwait(&set
, &sig
) == 0)
543 fprintf(stderr
, "\nshutting down...\n");