ikev1: Handle queued TRANSACTION messages only after processing replies
[strongswan.git] / src / libimcv / plugins / imv_attestation / attest.c
1 /*
2 * Copyright (C) 2011-2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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 #define _GNU_SOURCE
17 #include <getopt.h>
18 #include <unistd.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <libgen.h>
23 #ifdef HAVE_SYSLOG
24 # include <syslog.h>
25 #endif
26
27 #include <library.h>
28 #include <utils/debug.h>
29
30 #include <imcv.h>
31 #include <pts/pts_meas_algo.h>
32
33 #include "attest_db.h"
34 #include "attest_usage.h"
35
36 /**
37 * global debug output variables
38 */
39 static int debug_level = 1;
40 static bool stderr_quiet = TRUE;
41
42 /**
43 * attest dbg function
44 */
45 static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
46 {
47 va_list args;
48
49 if (level <= debug_level)
50 {
51 if (!stderr_quiet)
52 {
53 va_start(args, fmt);
54 vfprintf(stderr, fmt, args);
55 fprintf(stderr, "\n");
56 va_end(args);
57 }
58
59 #ifdef HAVE_SYSLOG
60 {
61 int priority = LOG_INFO;
62 char buffer[8192];
63 char *current = buffer, *next;
64
65 /* write in memory buffer first */
66 va_start(args, fmt);
67 vsnprintf(buffer, sizeof(buffer), fmt, args);
68 va_end(args);
69
70 /* do a syslog with every line */
71 while (current)
72 {
73 next = strchr(current, '\n');
74 if (next)
75 {
76 *(next++) = '\0';
77 }
78 syslog(priority, "%s\n", current);
79 current = next;
80 }
81 }
82 #endif /* HAVE_SYSLOG */
83 }
84 }
85
86 /**
87 * global attestation database object
88 */
89 attest_db_t *attest;
90
91
92 /**
93 * atexit handler to close db on shutdown
94 */
95 static void cleanup(void)
96 {
97 attest->destroy(attest);
98 libimcv_deinit();
99 #ifdef HAVE_SYSLOG
100 closelog();
101 #endif
102 }
103
104 static void do_args(int argc, char *argv[])
105 {
106 enum {
107 OP_UNDEF,
108 OP_USAGE,
109 OP_KEYS,
110 OP_COMPONENTS,
111 OP_DEVICES,
112 OP_DIRECTORIES,
113 OP_FILES,
114 OP_HASHES,
115 OP_MEASUREMENTS,
116 OP_PACKAGES,
117 OP_PRODUCTS,
118 OP_SESSIONS,
119 OP_ADD,
120 OP_DEL,
121 } op = OP_UNDEF;
122
123 /* reinit getopt state */
124 optind = 0;
125
126 while (TRUE)
127 {
128 int c;
129
130 struct option long_opts[] = {
131 { "help", no_argument, NULL, 'h' },
132 { "components", no_argument, NULL, 'c' },
133 { "devices", no_argument, NULL, 'e' },
134 { "directories", no_argument, NULL, 'd' },
135 { "dirs", no_argument, NULL, 'd' },
136 { "files", no_argument, NULL, 'f' },
137 { "keys", no_argument, NULL, 'k' },
138 { "packages", no_argument, NULL, 'g' },
139 { "products", no_argument, NULL, 'p' },
140 { "hashes", no_argument, NULL, 'H' },
141 { "measurements", no_argument, NULL, 'm' },
142 { "sessions", no_argument, NULL, 's' },
143 { "add", no_argument, NULL, 'a' },
144 { "delete", no_argument, NULL, 'r' },
145 { "del", no_argument, NULL, 'r' },
146 { "remove", no_argument, NULL, 'r' },
147 { "aik", required_argument, NULL, 'A' },
148 { "blacklist", no_argument, NULL, 'B' },
149 { "component", required_argument, NULL, 'C' },
150 { "comp", required_argument, NULL, 'C' },
151 { "directory", required_argument, NULL, 'D' },
152 { "dir", required_argument, NULL, 'D' },
153 { "file", required_argument, NULL, 'F' },
154 { "package", required_argument, NULL, 'G' },
155 { "key", required_argument, NULL, 'K' },
156 { "measdir", required_argument, NULL, 'M' },
157 { "owner", required_argument, NULL, 'O' },
158 { "product", required_argument, NULL, 'P' },
159 { "relative", no_argument, NULL, 'R' },
160 { "rel", no_argument, NULL, 'R' },
161 { "sequence", required_argument, NULL, 'S' },
162 { "seq", required_argument, NULL, 'S' },
163 { "utc", no_argument, NULL, 'U' },
164 { "version", required_argument, NULL, 'V' },
165 { "security", no_argument, NULL, 'Y' },
166 { "sha1", no_argument, NULL, '1' },
167 { "sha256", no_argument, NULL, '2' },
168 { "sha384", no_argument, NULL, '3' },
169 { "did", required_argument, NULL, '4' },
170 { "fid", required_argument, NULL, '5' },
171 { "pid", required_argument, NULL, '6' },
172 { "cid", required_argument, NULL, '7' },
173 { "kid", required_argument, NULL, '8' },
174 { "gid", required_argument, NULL, '9' },
175 { 0,0,0,0 }
176 };
177
178 c = getopt_long(argc, argv, "", long_opts, NULL);
179 switch (c)
180 {
181 case EOF:
182 break;
183 case 'h':
184 op = OP_USAGE;
185 break;
186 case 'c':
187 op = OP_COMPONENTS;
188 continue;
189 case 'd':
190 op = OP_DIRECTORIES;
191 continue;
192 case 'e':
193 op = OP_DEVICES;
194 continue;
195 case 'f':
196 op = OP_FILES;
197 continue;
198 case 'g':
199 op = OP_PACKAGES;
200 continue;
201 case 'k':
202 op = OP_KEYS;
203 continue;
204 case 'p':
205 op = OP_PRODUCTS;
206 continue;
207 case 'H':
208 op = OP_HASHES;
209 continue;
210 case 'm':
211 op = OP_MEASUREMENTS;
212 continue;
213 case 's':
214 op = OP_SESSIONS;
215 continue;
216 case 'a':
217 op = OP_ADD;
218 continue;
219 case 'r':
220 op = OP_DEL;
221 continue;
222 case 'A':
223 {
224 certificate_t *aik_cert;
225 public_key_t *aik_key;
226 chunk_t aik;
227
228 aik_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
229 CERT_X509, BUILD_FROM_FILE, optarg, BUILD_END);
230 if (!aik_cert)
231 {
232 printf("AIK certificate '%s' could not be loaded\n", optarg);
233 exit(EXIT_FAILURE);
234 }
235 aik_key = aik_cert->get_public_key(aik_cert);
236 aik_cert->destroy(aik_cert);
237
238 if (!aik_key)
239 {
240 printf("AIK public key could not be retrieved\n");
241 exit(EXIT_FAILURE);
242 }
243 if (!aik_key->get_fingerprint(aik_key, KEYID_PUBKEY_INFO_SHA1,
244 &aik))
245 {
246 printf("AIK fingerprint could not be computed\n");
247 aik_key->destroy(aik_key);
248 exit(EXIT_FAILURE);
249 }
250 aik = chunk_clone(aik);
251 aik_key->destroy(aik_key);
252
253 if (!attest->set_key(attest, aik, op == OP_ADD))
254 {
255 exit(EXIT_FAILURE);
256 }
257 continue;
258 }
259 case 'B':
260 attest->set_package_state(attest, OS_PACKAGE_STATE_BLACKLIST);
261 continue;
262 case 'C':
263 if (!attest->set_component(attest, optarg, op == OP_ADD))
264 {
265 exit(EXIT_FAILURE);
266 }
267 continue;
268 case 'D':
269 if (!attest->set_directory(attest, optarg, op == OP_ADD))
270 {
271 exit(EXIT_FAILURE);
272 }
273 continue;
274 case 'F':
275 {
276 char *dir = path_dirname(optarg);
277 char *file = path_basename(optarg);
278
279 if (*dir != '.')
280 {
281 if (!attest->set_directory(attest, dir, op == OP_ADD))
282 {
283 free(file);
284 free(dir);
285 exit(EXIT_FAILURE);
286 }
287 }
288 free(dir);
289
290 if (!attest->set_file(attest, file, op == OP_ADD))
291 {
292 free(file);
293 exit(EXIT_FAILURE);
294 }
295 free(file);
296 continue;
297 }
298 case 'G':
299 if (!attest->set_package(attest, optarg, op == OP_ADD))
300 {
301 exit(EXIT_FAILURE);
302 }
303 continue;
304 case 'K':
305 {
306 chunk_t aik;
307
308 aik = chunk_from_hex(chunk_create(optarg, strlen(optarg)), NULL);
309 if (!attest->set_key(attest, aik, op == OP_ADD))
310 {
311 exit(EXIT_FAILURE);
312 }
313 continue;
314 }
315 case 'M':
316 if (!attest->set_meas_directory(attest, optarg))
317 {
318 exit(EXIT_FAILURE);
319 }
320 continue;
321 case 'O':
322 attest->set_owner(attest, optarg);
323 continue;
324 case 'P':
325 if (!attest->set_product(attest, optarg, op == OP_ADD))
326 {
327 exit(EXIT_FAILURE);
328 }
329 continue;
330 case 'R':
331 attest->set_relative(attest);
332 continue;
333 case 'S':
334 attest->set_sequence(attest, atoi(optarg));
335 continue;
336 case 'U':
337 attest->set_utc(attest);
338 continue;
339 case 'V':
340 if (!attest->set_version(attest, optarg))
341 {
342 exit(EXIT_FAILURE);
343 }
344 continue;
345 case 'Y':
346 attest->set_package_state(attest, OS_PACKAGE_STATE_SECURITY);
347 continue;
348 case '1':
349 attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
350 continue;
351 case '2':
352 attest->set_algo(attest, PTS_MEAS_ALGO_SHA256);
353 continue;
354 case '3':
355 attest->set_algo(attest, PTS_MEAS_ALGO_SHA384);
356 continue;
357 case '4':
358 if (!attest->set_did(attest, atoi(optarg)))
359 {
360 exit(EXIT_FAILURE);
361 }
362 continue;
363 case '5':
364 if (!attest->set_fid(attest, atoi(optarg)))
365 {
366 exit(EXIT_FAILURE);
367 }
368 continue;
369 case '6':
370 if (!attest->set_pid(attest, atoi(optarg)))
371 {
372 exit(EXIT_FAILURE);
373 }
374 continue;
375 case '7':
376 if (!attest->set_cid(attest, atoi(optarg)))
377 {
378 exit(EXIT_FAILURE);
379 }
380 continue;
381 case '8':
382 if (!attest->set_kid(attest, atoi(optarg)))
383 {
384 exit(EXIT_FAILURE);
385 }
386 continue;
387 case '9':
388 if (!attest->set_gid(attest, atoi(optarg)))
389 {
390 exit(EXIT_FAILURE);
391 }
392 continue;
393 }
394 break;
395 }
396
397 switch (op)
398 {
399 case OP_USAGE:
400 usage();
401 break;
402 case OP_PACKAGES:
403 attest->list_packages(attest);
404 break;
405 case OP_PRODUCTS:
406 attest->list_products(attest);
407 break;
408 case OP_KEYS:
409 attest->list_keys(attest);
410 break;
411 case OP_COMPONENTS:
412 attest->list_components(attest);
413 break;
414 case OP_DEVICES:
415 attest->list_devices(attest);
416 break;
417 case OP_DIRECTORIES:
418 attest->list_directories(attest);
419 break;
420 case OP_FILES:
421 attest->list_files(attest);
422 break;
423 case OP_HASHES:
424 attest->list_hashes(attest);
425 break;
426 case OP_MEASUREMENTS:
427 attest->list_measurements(attest);
428 break;
429 case OP_SESSIONS:
430 attest->list_sessions(attest);
431 break;
432 case OP_ADD:
433 attest->add(attest);
434 break;
435 case OP_DEL:
436 attest->delete(attest);
437 break;
438 default:
439 usage();
440 exit(EXIT_FAILURE);
441 }
442 }
443
444 int main(int argc, char *argv[])
445 {
446 char *uri;
447
448 /* enable attest debugging hook */
449 dbg = attest_dbg;
450 #ifdef HAVE_SYSLOG
451 openlog("attest", 0, LOG_DEBUG);
452 #endif
453
454 atexit(library_deinit);
455
456 /* initialize library */
457 if (!library_init(NULL, "attest"))
458 {
459 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
460 }
461 if (!lib->plugins->load(lib->plugins,
462 lib->settings->get_str(lib->settings, "attest.load", PLUGINS)))
463 {
464 exit(SS_RC_INITIALIZATION_FAILED);
465 }
466
467 uri = lib->settings->get_str(lib->settings, "attest.database", NULL);
468 if (!uri)
469 {
470 fprintf(stderr, "database URI attest.database not set.\n");
471 exit(SS_RC_INITIALIZATION_FAILED);
472 }
473 attest = attest_db_create(uri);
474 if (!attest)
475 {
476 exit(SS_RC_INITIALIZATION_FAILED);
477 }
478 atexit(cleanup);
479 libimcv_init(FALSE);
480
481 do_args(argc, argv);
482
483 exit(EXIT_SUCCESS);
484 }