Load certificates from global suite configuration file
[strongswan.git] / src / conftest / conftest.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include <unistd.h>
17 #include <stdio.h>
18 #include <errno.h>
19 #include <signal.h>
20 #include <getopt.h>
21 #include <libgen.h>
22
23 #include "conftest.h"
24
25 #include <threading/thread.h>
26
27 /**
28 * Conftest globals struct
29 */
30 conftest_t *conftest;
31
32 /**
33 * Print usage information
34 */
35 static void usage(char *error)
36 {
37 FILE *out = stdout;
38
39 if (error)
40 {
41 out = stderr;
42 fprintf(out, "%s\n", error);
43 }
44 else
45 {
46 fprintf(out, "strongSwan %s conftest\n", VERSION);
47 }
48 fprintf(out, "Usage:\n");
49 fprintf(out, " --help show usage information\n");
50 fprintf(out, " --version show conftest version\n");
51 fprintf(out, " --suite <file> global testsuite configuration "
52 "(default: ./suite.conf)\n");
53 fprintf(out, " --test <file> test specific configuration\n");
54 }
55
56 /**
57 * Handle SIGSEGV/SIGILL signals raised by threads
58 */
59 static void segv_handler(int signal)
60 {
61 fprintf(stderr, "thread %u received %d\n", thread_current_id(), signal);
62 abort();
63 }
64
65 /**
66 * Load suite and test specific configurations
67 */
68 static bool load_configs(char *suite_file, char *test_file)
69 {
70 if (!test_file)
71 {
72 fprintf(stderr, "Missing test configuration file.\n");
73 return FALSE;
74 }
75 if (access(suite_file, R_OK) != 0)
76 {
77 fprintf(stderr, "Reading suite configuration file '%s' failed: %s.\n",
78 suite_file, strerror(errno));
79 return FALSE;
80 }
81 if (access(test_file, R_OK) != 0)
82 {
83 fprintf(stderr, "Reading test configuration file '%s' failed: %s.\n",
84 test_file, strerror(errno));
85 return FALSE;
86 }
87 conftest->suite = settings_create(suite_file);
88 conftest->test = settings_create(test_file);
89 suite_file = dirname(suite_file);
90 test_file = dirname(test_file);
91 conftest->suite_dir = strdup(suite_file);
92 conftest->test_dir = strdup(test_file);
93 return TRUE;
94 }
95
96 /**
97 * Load certificates from the confiuguration file
98 */
99 static bool load_certs()
100 {
101 enumerator_t *enumerator;
102 char *key, *value;
103 certificate_t *cert;
104
105 if (chdir(conftest->suite_dir) != 0)
106 {
107 fprintf(stderr, "opening suite directory '%s' failed",
108 conftest->suite_dir);
109 return FALSE;
110 }
111
112 enumerator = conftest->suite->create_key_value_enumerator(
113 conftest->suite, "certs.trusted");
114 while (enumerator->enumerate(enumerator, &key, &value))
115 {
116 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
117 BUILD_FROM_FILE, value, BUILD_END);
118 if (!cert)
119 {
120 fprintf(stderr, "loading trusted certificate "
121 "'%s' from '%s' failed\n", key, value);
122 enumerator->destroy(enumerator);
123 return FALSE;
124 }
125 conftest->creds->add_cert(conftest->creds, TRUE, cert);
126 }
127 enumerator->destroy(enumerator);
128
129 enumerator = conftest->suite->create_key_value_enumerator(
130 conftest->suite, "certs.untrusted");
131 while (enumerator->enumerate(enumerator, &key, &value))
132 {
133 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
134 BUILD_FROM_FILE, value, BUILD_END);
135 if (!cert)
136 {
137 fprintf(stderr, "loading untrusted certificate "
138 "'%s' from '%s' failed\n", key, value);
139 enumerator->destroy(enumerator);
140 return FALSE;
141 }
142 conftest->creds->add_cert(conftest->creds, FALSE, cert);
143 }
144 enumerator->destroy(enumerator);
145
146 return TRUE;
147 }
148
149 /**
150 * atexit() cleanup handler
151 */
152 static void cleanup()
153 {
154 DESTROY_IF(conftest->suite);
155 DESTROY_IF(conftest->test);
156 lib->credmgr->remove_set(lib->credmgr, &conftest->creds->set);
157 conftest->creds->destroy(conftest->creds);
158 free(conftest->suite_dir);
159 free(conftest->test_dir);
160 free(conftest);
161 libcharon_deinit();
162 libhydra_deinit();
163 library_deinit();
164 }
165
166 /**
167 * Main function, starts the conftest daemon.
168 */
169 int main(int argc, char *argv[])
170 {
171 struct sigaction action;
172 int status = 0;
173 sigset_t set;
174 int sig;
175 char *suite_file = "suite.conf", *test_file = NULL;
176 file_logger_t *logger;
177
178 if (!library_init(NULL))
179 {
180 library_deinit();
181 return SS_RC_LIBSTRONGSWAN_INTEGRITY;
182 }
183 if (!libhydra_init("conftest"))
184 {
185 libhydra_deinit();
186 library_deinit();
187 return SS_RC_INITIALIZATION_FAILED;
188 }
189 if (!libcharon_init())
190 {
191 libcharon_deinit();
192 libhydra_deinit();
193 library_deinit();
194 return SS_RC_INITIALIZATION_FAILED;
195 }
196
197 INIT(conftest,
198 .creds = mem_cred_create(),
199 );
200 logger = file_logger_create(stdout, NULL, FALSE);
201 logger->set_level(logger, DBG_ANY, LEVEL_CTRL);
202 charon->bus->add_listener(charon->bus, &logger->listener);
203 charon->file_loggers->insert_last(charon->file_loggers, logger);
204
205 lib->credmgr->add_set(lib->credmgr, &conftest->creds->set);
206 conftest->hooks = linked_list_create();
207
208 atexit(cleanup);
209
210 while (TRUE)
211 {
212 struct option long_opts[] = {
213 { "help", no_argument, NULL, 'h' },
214 { "version", no_argument, NULL, 'v' },
215 { "suite", required_argument, NULL, 's' },
216 { "test", required_argument, NULL, 't' },
217 { 0,0,0,0 }
218 };
219 switch (getopt_long(argc, argv, "", long_opts, NULL))
220 {
221 case EOF:
222 break;
223 case 'h':
224 usage(NULL);
225 return 0;
226 case 'v':
227 printf("strongSwan %s conftest\n", VERSION);
228 return 0;
229 case 's':
230 suite_file = optarg;
231 continue;
232 case 't':
233 test_file = optarg;
234 continue;
235 default:
236 usage("Invalid option.");
237 return 1;
238 }
239 break;
240 }
241
242 if (!load_configs(suite_file, test_file))
243 {
244 return 1;
245 }
246 if (!charon->initialize(charon))
247 {
248 return 1;
249 }
250 if (!load_certs(suite_file))
251 {
252 return 1;
253 }
254
255 /* set up thread specific handlers */
256 action.sa_handler = segv_handler;
257 action.sa_flags = 0;
258 sigemptyset(&action.sa_mask);
259 sigaddset(&action.sa_mask, SIGINT);
260 sigaddset(&action.sa_mask, SIGTERM);
261 sigaddset(&action.sa_mask, SIGHUP);
262 sigaction(SIGSEGV, &action, NULL);
263 sigaction(SIGILL, &action, NULL);
264 sigaction(SIGBUS, &action, NULL);
265 action.sa_handler = SIG_IGN;
266 sigaction(SIGPIPE, &action, NULL);
267 pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
268
269 /* start thread pool */
270 charon->start(charon);
271
272 /* handle SIGINT/SIGTERM in main thread */
273 sigemptyset(&set);
274 sigaddset(&set, SIGINT);
275 sigaddset(&set, SIGHUP);
276 sigaddset(&set, SIGTERM);
277 sigprocmask(SIG_BLOCK, &set, NULL);
278
279 while (sigwait(&set, &sig) == 0)
280 {
281 switch (sig)
282 {
283 case SIGINT:
284 case SIGTERM:
285 fprintf(stderr, "\nshutting down...\n");
286 break;
287 default:
288 continue;
289 }
290 break;
291 }
292 return status;
293 }