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>
32 * Conftest globals struct
37 * Print usage information
39 static void usage(FILE *out
)
41 fprintf(out
, "Usage:\n");
42 fprintf(out
, " --help show usage information\n");
43 fprintf(out
, " --version show conftest version\n");
44 fprintf(out
, " --suite <file> global testsuite configuration "
45 "(default: ./suite.conf)\n");
46 fprintf(out
, " --test <file> test specific configuration\n");
50 * Handle SIGSEGV/SIGILL signals raised by threads
52 static void segv_handler(int signal
)
54 fprintf(stderr
, "thread %u received %d\n", thread_current_id(), signal
);
59 * Load suite and test specific configurations
61 static bool load_configs(char *suite_file
, char *test_file
)
65 fprintf(stderr
, "Missing test configuration file.\n");
68 if (access(suite_file
, R_OK
) != 0)
70 fprintf(stderr
, "Reading suite configuration file '%s' failed: %s.\n",
71 suite_file
, strerror(errno
));
74 if (access(test_file
, R_OK
) != 0)
76 fprintf(stderr
, "Reading test configuration file '%s' failed: %s.\n",
77 test_file
, strerror(errno
));
80 conftest
->suite
= settings_create(suite_file
);
81 conftest
->test
= settings_create(test_file
);
82 suite_file
= dirname(suite_file
);
83 test_file
= dirname(test_file
);
84 conftest
->suite_dir
= strdup(suite_file
);
85 conftest
->test_dir
= strdup(test_file
);
90 * Load certificates from the confiuguration file
92 static bool load_certs(settings_t
*settings
, char *dir
)
94 enumerator_t
*enumerator
;
95 char *key
, *value
, wd
[PATH_MAX
];
98 if (getcwd(wd
, sizeof(wd
)) == NULL
)
100 fprintf(stderr
, "getting cwd failed: %s\n", strerror(errno
));
105 fprintf(stderr
, "opening directory '%s' failed: %s\n",
106 dir
, strerror(errno
));
110 enumerator
= settings
->create_key_value_enumerator(settings
, "certs.trusted");
111 while (enumerator
->enumerate(enumerator
, &key
, &value
))
113 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
114 BUILD_FROM_FILE
, value
, BUILD_END
);
117 fprintf(stderr
, "loading trusted certificate "
118 "'%s' from '%s' failed\n", key
, value
);
119 enumerator
->destroy(enumerator
);
122 conftest
->creds
->add_cert(conftest
->creds
, TRUE
, cert
);
124 enumerator
->destroy(enumerator
);
126 enumerator
= settings
->create_key_value_enumerator(settings
, "certs.untrusted");
127 while (enumerator
->enumerate(enumerator
, &key
, &value
))
129 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
130 BUILD_FROM_FILE
, value
, BUILD_END
);
133 fprintf(stderr
, "loading untrusted certificate "
134 "'%s' from '%s' failed\n", key
, value
);
135 enumerator
->destroy(enumerator
);
138 conftest
->creds
->add_cert(conftest
->creds
, FALSE
, cert
);
140 enumerator
->destroy(enumerator
);
144 fprintf(stderr
, "opening directory '%s' failed: %s\n",
145 wd
, strerror(errno
));
152 * Load private keys from the confiuguration file
154 static bool load_keys(settings_t
*settings
, char *dir
)
156 enumerator_t
*enumerator
;
157 char *type
, *value
, wd
[PATH_MAX
];
161 if (getcwd(wd
, sizeof(wd
)) == NULL
)
163 fprintf(stderr
, "getting cwd failed: %s\n", strerror(errno
));
168 fprintf(stderr
, "opening directory '%s' failed: %s\n",
169 dir
, strerror(errno
));
173 enumerator
= settings
->create_key_value_enumerator(settings
, "keys");
174 while (enumerator
->enumerate(enumerator
, &type
, &value
))
176 if (strcaseeq(type
, "ecdsa"))
178 key_type
= KEY_ECDSA
;
180 else if (strcaseeq(type
, "rsa"))
186 fprintf(stderr
, "unkown key type: '%s'\n", type
);
187 enumerator
->destroy(enumerator
);
190 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
191 BUILD_FROM_FILE
, value
, BUILD_END
);
194 fprintf(stderr
, "loading %s key from '%s' failed\n", type
, value
);
195 enumerator
->destroy(enumerator
);
198 conftest
->creds
->add_key(conftest
->creds
, key
);
200 enumerator
->destroy(enumerator
);
204 fprintf(stderr
, "opening directory '%s' failed: %s\n",
205 wd
, strerror(errno
));
212 * Load configured hooks
214 static bool load_hooks()
216 enumerator_t
*enumerator
;
218 hook_t
*(*create
)(void);
221 enumerator
= conftest
->test
->create_section_enumerator(conftest
->test
,
223 while (enumerator
->enumerate(enumerator
, &name
))
225 snprintf(buf
, sizeof(buf
), "%s_hook_create", name
);
226 create
= dlsym(RTLD_DEFAULT
, buf
);
232 conftest
->hooks
->insert_last(conftest
->hooks
, hook
);
233 charon
->bus
->add_listener(charon
->bus
, &hook
->listener
);
238 fprintf(stderr
, "dlsym() for hook '%s' failed: %s\n", name
, dlerror());
239 enumerator
->destroy(enumerator
);
243 enumerator
->destroy(enumerator
);
248 * atexit() cleanup handler
250 static void cleanup()
254 DESTROY_IF(conftest
->suite
);
255 DESTROY_IF(conftest
->test
);
256 lib
->credmgr
->remove_set(lib
->credmgr
, &conftest
->creds
->set
);
257 conftest
->creds
->destroy(conftest
->creds
);
258 while (conftest
->hooks
->remove_last(conftest
->hooks
,
259 (void**)&hook
) == SUCCESS
)
261 charon
->bus
->remove_listener(charon
->bus
, &hook
->listener
);
264 conftest
->hooks
->destroy(conftest
->hooks
);
265 if (conftest
->config
)
267 charon
->backends
->remove_backend(charon
->backends
,
268 &conftest
->config
->backend
);
269 conftest
->config
->destroy(conftest
->config
);
271 free(conftest
->suite_dir
);
272 free(conftest
->test_dir
);
280 * Main function, starts the conftest daemon.
282 int main(int argc
, char *argv
[])
284 struct sigaction action
;
288 char *suite_file
= "suite.conf", *test_file
= NULL
;
289 file_logger_t
*logger
;
291 if (!library_init(NULL
))
294 return SS_RC_LIBSTRONGSWAN_INTEGRITY
;
296 if (!libhydra_init("conftest"))
300 return SS_RC_INITIALIZATION_FAILED
;
302 if (!libcharon_init())
307 return SS_RC_INITIALIZATION_FAILED
;
311 .creds
= mem_cred_create(),
313 logger
= file_logger_create(stdout
, NULL
, FALSE
);
314 logger
->set_level(logger
, DBG_ANY
, LEVEL_CTRL
);
315 charon
->bus
->add_listener(charon
->bus
, &logger
->listener
);
316 charon
->file_loggers
->insert_last(charon
->file_loggers
, logger
);
318 lib
->credmgr
->add_set(lib
->credmgr
, &conftest
->creds
->set
);
319 conftest
->hooks
= linked_list_create();
320 conftest
->config
= config_create();
326 struct option long_opts
[] = {
327 { "help", no_argument
, NULL
, 'h' },
328 { "version", no_argument
, NULL
, 'v' },
329 { "suite", required_argument
, NULL
, 's' },
330 { "test", required_argument
, NULL
, 't' },
333 switch (getopt_long(argc
, argv
, "", long_opts
, NULL
))
341 printf("strongSwan %s conftest\n", VERSION
);
356 if (!load_configs(suite_file
, test_file
))
360 if (!charon
->initialize(charon
))
364 if (!load_certs(conftest
->suite
, suite_file
) ||
365 !load_certs(conftest
->test
, test_file
))
369 if (!load_keys(conftest
->suite
, suite_file
) ||
370 !load_keys(conftest
->test
, test_file
))
378 charon
->backends
->add_backend(charon
->backends
, &conftest
->config
->backend
);
379 conftest
->config
->load(conftest
->config
, conftest
->suite
);
380 conftest
->config
->load(conftest
->config
, conftest
->test
);
382 /* set up thread specific handlers */
383 action
.sa_handler
= segv_handler
;
385 sigemptyset(&action
.sa_mask
);
386 sigaddset(&action
.sa_mask
, SIGINT
);
387 sigaddset(&action
.sa_mask
, SIGTERM
);
388 sigaddset(&action
.sa_mask
, SIGHUP
);
389 sigaction(SIGSEGV
, &action
, NULL
);
390 sigaction(SIGILL
, &action
, NULL
);
391 sigaction(SIGBUS
, &action
, NULL
);
392 action
.sa_handler
= SIG_IGN
;
393 sigaction(SIGPIPE
, &action
, NULL
);
394 pthread_sigmask(SIG_SETMASK
, &action
.sa_mask
, NULL
);
396 /* start thread pool */
397 charon
->start(charon
);
399 /* handle SIGINT/SIGTERM in main thread */
401 sigaddset(&set
, SIGINT
);
402 sigaddset(&set
, SIGHUP
);
403 sigaddset(&set
, SIGTERM
);
404 sigprocmask(SIG_BLOCK
, &set
, NULL
);
406 while (sigwait(&set
, &sig
) == 0)
412 fprintf(stderr
, "\nshutting down...\n");