]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libimcv/plugins/imv_attestation/attest_db.c
imv-attestation: Don't use comma to separate statements
[thirdparty/strongswan.git] / src / libimcv / plugins / imv_attestation / attest_db.c
CommitLineData
e881ee23 1/*
60da0153 2 * Copyright (C) 2011-2017 Andreas Steffen
e881ee23
AS
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
b8db66de
AS
16#define _GNU_SOURCE
17
18#include <stdio.h>
19#include <libgen.h>
20#include <time.h>
21
29645621
AS
22#include <tncif_names.h>
23
e881ee23
AS
24#include "attest_db.h"
25
d6fb2cc6 26#include "imcv.h"
358dbe48 27#include "pts/pts_meas_algo.h"
0f236aac 28#include "pts/pts_file_meas.h"
6b55276a 29#include "pts/components/pts_comp_func_name.h"
72631301 30
358dbe48 31#define IMA_MAX_NAME_LEN 255
72631301 32#define DEVICE_MAX_LEN 20
358dbe48 33
e881ee23
AS
34typedef struct private_attest_db_t private_attest_db_t;
35
36/**
37 * Private data of an attest_db_t object.
38 */
39struct private_attest_db_t {
40
41 /**
42 * Public members of attest_db_state_t
43 */
44 attest_db_t public;
45
46 /**
f2a521e7 47 * Component Functional Name to be queried
e881ee23 48 */
f2a521e7 49 pts_comp_func_name_t *cfn;
e881ee23
AS
50
51 /**
f2a521e7 52 * Primary key of the Component Functional Name to be queried
e881ee23 53 */
f2a521e7 54 int cid;
e881ee23
AS
55
56 /**
f2a521e7 57 * TRUE if Component Functional Name has been set
e881ee23 58 */
f2a521e7
AS
59 bool comp_set;
60
61 /**
62 * Directory containing the Measurement file to be queried
63 */
64 char *dir;
65
66 /**
67 * Primary key of the directory to be queried
68 */
69 int did;
70
e881ee23
AS
71 /**
72 * Measurement file to be queried
73 */
74 char *file;
75
76 /**
77 * Primary key of measurement file to be queried
78 */
79 int fid;
80
37a73b9c
AS
81 /**
82 * Directory where file measurement are to be taken
83 */
84 char *meas_dir;
85
e881ee23 86 /**
f2a521e7 87 * AIK to be queried
e881ee23 88 */
f2a521e7 89 chunk_t key;
e881ee23
AS
90
91 /**
f2a521e7 92 * Primary key of the AIK to be queried
e881ee23 93 */
f2a521e7 94 int kid;
e881ee23
AS
95
96 /**
f2a521e7 97 * TRUE if AIK has been set
e881ee23 98 */
f2a521e7 99 bool key_set;
e881ee23 100
1bb6a086
AS
101 /**
102 * Software package to be queried
103 */
104 char *package;
105
106 /**
107 * Primary key of software package to be queried
108 */
109 int gid;
110
111 /**
112 * TRUE if package has been set
113 */
114 bool package_set;
115
d37abe0f 116 /**
f2a521e7 117 * Software product to be queried
d37abe0f 118 */
f2a521e7 119 char *product;
d37abe0f
AS
120
121 /**
f2a521e7 122 * Primary key of software product to be queried
d37abe0f 123 */
f2a521e7 124 int pid;
d37abe0f
AS
125
126 /**
f2a521e7 127 * TRUE if product has been set
d37abe0f 128 */
f2a521e7 129 bool product_set;
d37abe0f 130
1bb6a086
AS
131 /**
132 * Software package version to be queried
133 */
134 char *version;
135
60da0153
AS
136 /**
137 * Primary key of software package version to be queried
138 */
139 int vid;
140
1bb6a086
AS
141 /**
142 * TRUE if version has been set
143 */
144 bool version_set;
145
0f236aac
AS
146 /**
147 * TRUE if relative filenames are to be used
148 */
149 bool relative;
150
81ee269d
AS
151 /**
152 * TRUE if dates are to be displayed in UTC
153 */
154 bool utc;
155
1bb6a086 156 /**
71c7b435 157 * Package security or blacklist state
1bb6a086 158 */
71c7b435 159 os_package_state_t package_state;
1bb6a086 160
e0c66beb
AS
161 /**
162 * Sequence number for ordering entries
163 */
164 int seq_no;
165
e881ee23
AS
166 /**
167 * File measurement hash algorithm
168 */
169 pts_meas_algorithms_t algo;
170
f2a521e7
AS
171 /**
172 * Optional owner (user/host name)
173 */
174 char *owner;
175
e881ee23
AS
176 /**
177 * Attestation database
178 */
179 database_t *db;
180
181};
182
d37abe0f
AS
183char* print_cfn(pts_comp_func_name_t *cfn)
184{
185 static char buf[BUF_LEN];
186 char flags[8];
187 int type, vid, name, qualifier, n;
188 enum_name_t *names, *types;
189
f1889ca3 190 vid = cfn->get_vendor_id(cfn);
d37abe0f
AS
191 name = cfn->get_name(cfn);
192 qualifier = cfn->get_qualifier(cfn);
193 n = snprintf(buf, BUF_LEN, "0x%06x/0x%08x-0x%02x", vid, name, qualifier);
194
d6fb2cc6
AS
195 names = imcv_pts_components->get_comp_func_names(imcv_pts_components, vid);
196 types = imcv_pts_components->get_qualifier_type_names(imcv_pts_components,
197 vid);
198 type = imcv_pts_components->get_qualifier(imcv_pts_components, cfn, flags);
d37abe0f
AS
199 if (names && types)
200 {
201 n = snprintf(buf + n, BUF_LEN - n, " %N/%N [%s] %N",
202 pen_names, vid, names, name, flags, types, type);
203 }
204 return buf;
205}
206
0731d41c
MW
207/**
208 * Get the directory separator to append to a path
209 */
210static const char* get_separator(const char *path)
211{
212 if (streq(path, DIRECTORY_SEPARATOR))
213 { /* root directory on Unix file system, no separator */
214 return "";
215 }
216 else
217 { /* non-root or Windows path, use system specific separator */
218 return DIRECTORY_SEPARATOR;
219 }
220}
221
f2a521e7
AS
222METHOD(attest_db_t, set_component, bool,
223 private_attest_db_t *this, char *comp, bool create)
e881ee23
AS
224{
225 enumerator_t *e;
f2a521e7
AS
226 char *pos1, *pos2;
227 int vid, name, qualifier;
228 pts_comp_func_name_t *cfn;
e881ee23 229
f2a521e7 230 if (this->comp_set)
e881ee23 231 {
f2a521e7 232 printf("component has already been set\n");
e881ee23
AS
233 return FALSE;
234 }
e881ee23 235
f2a521e7
AS
236 /* parse component string */
237 pos1 = strchr(comp, '/');
238 pos2 = strchr(comp, '-');
239 if (!pos1 || !pos2)
240 {
241 printf("component string must have the form \"vendor_id/name-qualifier\"\n");
242 return FALSE;
243 }
244 vid = atoi(comp);
245 name = atoi(pos1 + 1);
246 qualifier = atoi(pos2 + 1);
247 cfn = pts_comp_func_name_create(vid, name, qualifier);
248
249 e = this->db->query(this->db,
250 "SELECT id FROM components "
251 "WHERE vendor_id = ? AND name = ? AND qualifier = ?",
e0c66beb 252 DB_UINT, vid, DB_INT, name, DB_INT, qualifier, DB_INT);
e881ee23
AS
253 if (e)
254 {
f2a521e7 255 if (e->enumerate(e, &this->cid))
e881ee23 256 {
f2a521e7
AS
257 this->comp_set = TRUE;
258 this->cfn = cfn;
e881ee23 259 }
e881ee23
AS
260 e->destroy(e);
261 }
f2a521e7 262 if (this->comp_set)
f4159ff8
AS
263 {
264 return TRUE;
265 }
266
267 if (!create)
268 {
f2a521e7
AS
269 printf("component '%s' not found in database\n", print_cfn(cfn));
270 cfn->destroy(cfn);
2b28a131 271 return FALSE;
f4159ff8
AS
272 }
273
274 /* Add a new database entry */
f2a521e7
AS
275 this->comp_set = this->db->execute(this->db, &this->cid,
276 "INSERT INTO components (vendor_id, name, qualifier) "
277 "VALUES (?, ?, ?)",
278 DB_INT, vid, DB_INT, name, DB_INT, qualifier) == 1;
f4159ff8 279
f2a521e7
AS
280 printf("component '%s' %sinserted into database\n", print_cfn(cfn),
281 this->comp_set ? "" : "could not be ");
282 if (this->comp_set)
283 {
284 this->cfn = cfn;
285 }
286 else
287 {
288 cfn->destroy(cfn);
289 }
290 return this->comp_set;
291}
f4159ff8 292
f2a521e7
AS
293METHOD(attest_db_t, set_cid, bool,
294 private_attest_db_t *this, int cid)
295{
296 enumerator_t *e;
297 int vid, name, qualifier;
298
299 if (this->comp_set)
300 {
301 printf("component has already been set\n");
302 return FALSE;
303 }
304 this->cid = cid;
305
306 e = this->db->query(this->db, "SELECT vendor_id, name, qualifier "
307 "FROM components WHERE id = ?",
e0c66beb 308 DB_UINT, cid, DB_INT, DB_INT, DB_INT);
f2a521e7
AS
309 if (e)
310 {
311 if (e->enumerate(e, &vid, &name, &qualifier))
312 {
313 this->cfn = pts_comp_func_name_create(vid, name, qualifier);
314 this->comp_set = TRUE;
315 }
316 else
317 {
318 printf("no component found with cid %d\n", cid);
319 }
320 e->destroy(e);
321 }
322 return this->comp_set;
e881ee23
AS
323}
324
f2a521e7
AS
325METHOD(attest_db_t, set_directory, bool,
326 private_attest_db_t *this, char *dir, bool create)
e881ee23
AS
327{
328 enumerator_t *e;
1f179c63 329 int did;
0f236aac 330 size_t len;
e881ee23 331
1f179c63 332 if (this->did)
e881ee23 333 {
f2a521e7 334 printf("directory has already been set\n");
e881ee23
AS
335 return FALSE;
336 }
0f236aac 337
0731d41c 338 /* remove trailing '/' or '\' character if not root directory */
0f236aac 339 len = strlen(dir);
0731d41c 340 if (len > 1 && dir[len-1] == DIRECTORY_SEPARATOR[0])
0f236aac
AS
341 {
342 dir[len-1] = '\0';
343 }
f2a521e7 344 this->dir = strdup(dir);
e881ee23 345
f2a521e7 346 e = this->db->query(this->db,
1f179c63 347 "SELECT id FROM directories WHERE path = ?",
f2a521e7 348 DB_TEXT, dir, DB_INT);
e881ee23
AS
349 if (e)
350 {
1f179c63 351 if (e->enumerate(e, &did))
e881ee23 352 {
1f179c63 353 this->did = did;
f2a521e7
AS
354 }
355 e->destroy(e);
356 }
1f179c63 357 if (this->did)
f2a521e7
AS
358 {
359 return TRUE;
360 }
361
362 if (!create)
363 {
364 printf("directory '%s' not found in database\n", dir);
365 return FALSE;
366 }
367
368 /* Add a new database entry */
1f179c63
AS
369 if (1 == this->db->execute(this->db, &did,
370 "INSERT INTO directories (path) VALUES (?)", DB_TEXT, dir))
371 {
372 this->did = did;
373 }
f2a521e7 374 printf("directory '%s' %sinserted into database\n", dir,
1f179c63 375 this->did ? "" : "could not be ");
f2a521e7 376
1f179c63 377 return this->did > 0;
f2a521e7
AS
378}
379
380METHOD(attest_db_t, set_did, bool,
381 private_attest_db_t *this, int did)
382{
383 enumerator_t *e;
384 char *dir;
385
1f179c63 386 if (this->did)
f2a521e7
AS
387 {
388 printf("directory has already been set\n");
389 return FALSE;
390 }
f2a521e7 391
1f179c63 392 e = this->db->query(this->db, "SELECT path FROM directories WHERE id = ?",
e0c66beb 393 DB_UINT, did, DB_TEXT);
f2a521e7
AS
394 if (e)
395 {
396 if (e->enumerate(e, &dir))
397 {
f2a521e7 398 this->dir = strdup(dir);
1f179c63 399 this->did = did;
e881ee23
AS
400 }
401 else
402 {
f2a521e7 403 printf("no directory found with did %d\n", did);
e881ee23
AS
404 }
405 e->destroy(e);
406 }
1f179c63 407 return this->did > 0;
e881ee23
AS
408}
409
410METHOD(attest_db_t, set_file, bool,
f4159ff8 411 private_attest_db_t *this, char *file, bool create)
e881ee23 412{
1f179c63 413 int fid;
e881ee23
AS
414 enumerator_t *e;
415
1f179c63 416 if (this->file)
e881ee23
AS
417 {
418 printf("file has already been set\n");
419 return FALSE;
420 }
421 this->file = strdup(file);
422
1f179c63
AS
423 if (!this->did)
424 {
425 return TRUE;
426 }
1f179c63
AS
427 e = this->db->query(this->db, "SELECT id FROM files "
428 "WHERE dir = ? AND name = ?",
429 DB_INT, this->did, DB_TEXT, file, DB_INT);
e881ee23
AS
430 if (e)
431 {
1f179c63 432 if (e->enumerate(e, &fid))
e881ee23 433 {
1f179c63 434 this->fid = fid;
e881ee23 435 }
e881ee23
AS
436 e->destroy(e);
437 }
1f179c63 438 if (this->fid)
f4159ff8
AS
439 {
440 return TRUE;
441 }
442
443 if (!create)
444 {
0731d41c
MW
445 printf("file '%s%s%s' not found in database\n",
446 this->dir, get_separator(this->dir), file);
2b28a131 447 return FALSE;
f4159ff8
AS
448 }
449
450 /* Add a new database entry */
1f179c63
AS
451 if (1 == this->db->execute(this->db, &fid,
452 "INSERT INTO files (dir, name) VALUES (?, ?)",
453 DB_INT, this->did, DB_TEXT, file))
454 {
455 this->fid = fid;
456 }
0731d41c
MW
457 printf("file '%s%s%s' %sinserted into database\n", this->dir,
458 get_separator(this->dir), file, this->fid ? "" : "could not be ");
f4159ff8 459
1f179c63 460 return this->fid > 0;
e881ee23
AS
461}
462
463METHOD(attest_db_t, set_fid, bool,
464 private_attest_db_t *this, int fid)
465{
466 enumerator_t *e;
1f179c63 467 int did;
e881ee23
AS
468 char *file;
469
1f179c63 470 if (this->fid)
e881ee23
AS
471 {
472 printf("file has already been set\n");
473 return FALSE;
474 }
e881ee23 475
1f179c63
AS
476 e = this->db->query(this->db, "SELECT dir, name FROM files WHERE id = ?",
477 DB_UINT, fid, DB_INT, DB_TEXT);
e881ee23
AS
478 if (e)
479 {
1f179c63 480 if (e->enumerate(e, &did, &file))
e881ee23 481 {
1f179c63
AS
482 if (did)
483 {
484 set_did(this, did);
485 }
e881ee23 486 this->file = strdup(file);
1f179c63 487 this->fid = fid;
e881ee23
AS
488 }
489 else
490 {
491 printf("no file found with fid %d\n", fid);
492 }
493 e->destroy(e);
494 }
1f179c63 495 return this->fid > 0;
e881ee23
AS
496}
497
37a73b9c
AS
498METHOD(attest_db_t, set_meas_directory, bool,
499 private_attest_db_t *this, char *dir)
500{
501 size_t len;
502
503 /* remove trailing '/' character if not root directory */
504 len = strlen(dir);
505 if (len > 1 && dir[len-1] == '/')
506 {
507 dir[len-1] = '\0';
508 }
509 this->meas_dir = strdup(dir);
510
511 return TRUE;
512}
513
f2a521e7 514METHOD(attest_db_t, set_key, bool,
cb4da3f6 515 private_attest_db_t *this, chunk_t key, bool create)
e881ee23
AS
516{
517 enumerator_t *e;
f2a521e7 518 char *owner;
e881ee23 519
f2a521e7 520 if (this->key_set)
e881ee23 521 {
f2a521e7 522 printf("key has already been set\n");
e881ee23
AS
523 return FALSE;
524 }
cb4da3f6 525 this->key = key;
e881ee23 526
f2a521e7
AS
527 e = this->db->query(this->db, "SELECT id, owner FROM keys WHERE keyid= ?",
528 DB_BLOB, this->key, DB_INT, DB_TEXT);
e881ee23
AS
529 if (e)
530 {
f2a521e7 531 if (e->enumerate(e, &this->kid, &owner))
e881ee23 532 {
cb4da3f6 533 free(this->owner);
f2a521e7
AS
534 this->owner = strdup(owner);
535 this->key_set = TRUE;
e881ee23 536 }
e881ee23
AS
537 e->destroy(e);
538 }
f2a521e7 539 if (this->key_set)
f4159ff8
AS
540 {
541 return TRUE;
542 }
543
544 if (!create)
545 {
f2a521e7 546 printf("key '%#B' not found in database\n", &this->key);
2b28a131 547 return FALSE;
f4159ff8
AS
548 }
549
550 /* Add a new database entry */
f2a521e7
AS
551 if (!this->owner)
552 {
553 this->owner = strdup("");
554 }
555 this->key_set = this->db->execute(this->db, &this->kid,
556 "INSERT INTO keys (keyid, owner) VALUES (?, ?)",
557 DB_BLOB, this->key, DB_TEXT, this->owner) == 1;
f4159ff8 558
f2a521e7
AS
559 printf("key '%#B' %sinserted into database\n", &this->key,
560 this->key_set ? "" : "could not be ");
f4159ff8 561
f2a521e7 562 return this->key_set;
e881ee23 563
f2a521e7
AS
564};
565
566METHOD(attest_db_t, set_kid, bool,
567 private_attest_db_t *this, int kid)
e881ee23
AS
568{
569 enumerator_t *e;
f2a521e7
AS
570 chunk_t key;
571 char *owner;
e881ee23 572
f2a521e7 573 if (this->key_set)
e881ee23 574 {
f2a521e7 575 printf("key has already been set\n");
e881ee23
AS
576 return FALSE;
577 }
f2a521e7 578 this->kid = kid;
e881ee23 579
f2a521e7 580 e = this->db->query(this->db, "SELECT keyid, owner FROM keys WHERE id = ?",
e0c66beb 581 DB_UINT, kid, DB_BLOB, DB_TEXT);
e881ee23
AS
582 if (e)
583 {
f2a521e7 584 if (e->enumerate(e, &key, &owner))
e881ee23 585 {
f2a521e7
AS
586 this->owner = strdup(owner);
587 this->key = chunk_clone(key);
588 this->key_set = TRUE;
e881ee23
AS
589 }
590 else
591 {
f2a521e7 592 printf("no key found with kid %d\n", kid);
e881ee23
AS
593 }
594 e->destroy(e);
595 }
f2a521e7 596 return this->key_set;
e881ee23 597
f2a521e7
AS
598};
599
600METHOD(attest_db_t, set_product, bool,
601 private_attest_db_t *this, char *product, bool create)
d37abe0f
AS
602{
603 enumerator_t *e;
d37abe0f 604
f2a521e7 605 if (this->product_set)
d37abe0f 606 {
f2a521e7 607 printf("product has already been set\n");
d37abe0f
AS
608 return FALSE;
609 }
f2a521e7 610 this->product = strdup(product);
d37abe0f 611
f2a521e7
AS
612 e = this->db->query(this->db, "SELECT id FROM products WHERE name = ?",
613 DB_TEXT, product, DB_INT);
d37abe0f
AS
614 if (e)
615 {
f2a521e7 616 if (e->enumerate(e, &this->pid))
d37abe0f 617 {
f2a521e7 618 this->product_set = TRUE;
d37abe0f
AS
619 }
620 e->destroy(e);
621 }
f2a521e7 622 if (this->product_set)
d37abe0f
AS
623 {
624 return TRUE;
625 }
626
627 if (!create)
628 {
f2a521e7 629 printf("product '%s' not found in database\n", product);
d37abe0f
AS
630 return FALSE;
631 }
632
633 /* Add a new database entry */
f2a521e7
AS
634 this->product_set = this->db->execute(this->db, &this->pid,
635 "INSERT INTO products (name) VALUES (?)",
636 DB_TEXT, product) == 1;
d37abe0f 637
f2a521e7
AS
638 printf("product '%s' %sinserted into database\n", product,
639 this->product_set ? "" : "could not be ");
640
641 return this->product_set;
d37abe0f
AS
642}
643
f2a521e7
AS
644METHOD(attest_db_t, set_pid, bool,
645 private_attest_db_t *this, int pid)
d37abe0f
AS
646{
647 enumerator_t *e;
f2a521e7 648 char *product;
d37abe0f 649
f2a521e7 650 if (this->product_set)
d37abe0f 651 {
f2a521e7 652 printf("product has already been set\n");
d37abe0f
AS
653 return FALSE;
654 }
f2a521e7 655 this->pid = pid;
d37abe0f 656
f2a521e7 657 e = this->db->query(this->db, "SELECT name FROM products WHERE id = ?",
e0c66beb 658 DB_UINT, pid, DB_TEXT);
d37abe0f
AS
659 if (e)
660 {
f2a521e7 661 if (e->enumerate(e, &product))
d37abe0f 662 {
f2a521e7
AS
663 this->product = strdup(product);
664 this->product_set = TRUE;
d37abe0f
AS
665 }
666 else
667 {
f2a521e7 668 printf("no product found with pid %d in database\n", pid);
d37abe0f
AS
669 }
670 e->destroy(e);
671 }
f2a521e7 672 return this->product_set;
d37abe0f
AS
673}
674
1bb6a086
AS
675METHOD(attest_db_t, set_package, bool,
676 private_attest_db_t *this, char *package, bool create)
677{
678 enumerator_t *e;
679
680 if (this->package_set)
681 {
682 printf("package has already been set\n");
683 return FALSE;
684 }
685 this->package = strdup(package);
686
687 e = this->db->query(this->db, "SELECT id FROM packages WHERE name = ?",
688 DB_TEXT, package, DB_INT);
689 if (e)
690 {
691 if (e->enumerate(e, &this->gid))
692 {
693 this->package_set = TRUE;
694 }
695 e->destroy(e);
696 }
697 if (this->package_set)
698 {
699 return TRUE;
700 }
701
702 if (!create)
703 {
704 printf("package '%s' not found in database\n", package);
705 return FALSE;
706 }
707
708 /* Add a new database entry */
709 this->package_set = this->db->execute(this->db, &this->gid,
710 "INSERT INTO packages (name) VALUES (?)",
711 DB_TEXT, package) == 1;
712
713 printf("package '%s' %sinserted into database\n", package,
714 this->package_set ? "" : "could not be ");
715
716 return this->package_set;
717}
718
719METHOD(attest_db_t, set_gid, bool,
720 private_attest_db_t *this, int gid)
721{
722 enumerator_t *e;
723 char *package;
724
725 if (this->package_set)
726 {
727 printf("package has already been set\n");
728 return FALSE;
729 }
730 this->gid = gid;
731
732 e = this->db->query(this->db, "SELECT name FROM packages WHERE id = ?",
733 DB_UINT, gid, DB_TEXT);
734 if (e)
735 {
736 if (e->enumerate(e, &package))
737 {
738 this->package = strdup(package);
739 this->package_set = TRUE;
740 }
741 else
742 {
743 printf("no package found with gid %d in database\n", gid);
744 }
745 e->destroy(e);
746 }
747 return this->package_set;
748}
749
750METHOD(attest_db_t, set_version, bool,
751 private_attest_db_t *this, char *version)
752{
753 if (this->version_set)
754 {
755 printf("version has already been set\n");
756 return FALSE;
757 }
758 this->version = strdup(version);
759 this->version_set = TRUE;
760
761 return TRUE;
762}
763
764
e881ee23
AS
765METHOD(attest_db_t, set_algo, void,
766 private_attest_db_t *this, pts_meas_algorithms_t algo)
767{
768 this->algo = algo;
769}
770
0f236aac
AS
771METHOD(attest_db_t, set_relative, void,
772 private_attest_db_t *this)
773{
774 this->relative = TRUE;
775}
776
71c7b435
AS
777METHOD(attest_db_t, set_package_state, void,
778 private_attest_db_t *this, os_package_state_t package_state)
1bb6a086 779{
71c7b435 780 this->package_state = package_state;
1bb6a086
AS
781}
782
e0c66beb
AS
783METHOD(attest_db_t, set_sequence, void,
784 private_attest_db_t *this, int seq_no)
785{
786 this->seq_no = seq_no;
787}
788
f2a521e7
AS
789METHOD(attest_db_t, set_owner, void,
790 private_attest_db_t *this, char *owner)
791{
792 free(this->owner);
793 this->owner = strdup(owner);
794}
795
81ee269d
AS
796METHOD(attest_db_t, set_utc, void,
797 private_attest_db_t *this)
798{
799 this->utc = TRUE;
800}
801
6b55276a
AS
802METHOD(attest_db_t, list_components, void,
803 private_attest_db_t *this)
804{
805 enumerator_t *e;
6b55276a 806 pts_comp_func_name_t *cfn;
e0c66beb 807 int seq_no, cid, vid, name, qualifier, count = 0;
6b55276a 808
f2a521e7 809 if (this->kid)
6b55276a
AS
810 {
811 e = this->db->query(this->db,
e0c66beb 812 "SELECT kc.seq_no, c.id, c.vendor_id, c.name, c.qualifier "
6b55276a 813 "FROM components AS c "
f2a521e7 814 "JOIN key_component AS kc ON c.id = kc.component "
e0c66beb
AS
815 "WHERE kc.key = ? ORDER BY kc.seq_no",
816 DB_UINT, this->kid, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
817 if (e)
818 {
819 while (e->enumerate(e, &cid, &seq_no, &vid, &name, &qualifier))
820 {
821 cfn = pts_comp_func_name_create(vid, name, qualifier);
822 printf("%4d: #%-2d %s\n", seq_no, cid, print_cfn(cfn));
823 cfn->destroy(cfn);
824 count++;
825 }
826 e->destroy(e);
827 printf("%d component%s found for key %#B\n", count,
828 (count == 1) ? "" : "s", &this->key);
829 }
6b55276a
AS
830 }
831 else
832 {
833 e = this->db->query(this->db,
834 "SELECT id, vendor_id, name, qualifier FROM components "
835 "ORDER BY vendor_id, name, qualifier",
836 DB_INT, DB_INT, DB_INT, DB_INT);
e0c66beb 837 if (e)
6b55276a 838 {
e0c66beb
AS
839 while (e->enumerate(e, &cid, &vid, &name, &qualifier))
840 {
841 cfn = pts_comp_func_name_create(vid, name, qualifier);
842 printf("%4d: %s\n", cid, print_cfn(cfn));
843 cfn->destroy(cfn);
844 count++;
845 }
846 e->destroy(e);
847 printf("%d component%s found\n", count, (count == 1) ? "" : "s");
6b55276a 848 }
6b55276a
AS
849 }
850}
851
ac6dd7d4
AS
852METHOD(attest_db_t, list_devices, void,
853 private_attest_db_t *this)
854{
c88104aa 855 enumerator_t *e, *e_ar;
72631301 856 chunk_t ar_id_value = chunk_empty;
20f90d71 857 char *product, *device, *description;
7b6cc33e 858 time_t timestamp;
20f90d71 859 int id, last_id = 0, ar_id = 0, last_ar_id = 0, device_count = 0, trusted;
29645621 860 int session_id, rec;
b12c53ce 861 uint32_t ar_id_type;
29645621 862 u_int tstamp;
ac6dd7d4
AS
863
864 e = this->db->query(this->db,
20f90d71
AS
865 "SELECT d.id, d.value, d.trusted, d.description, "
866 "s.id, s.time, s.identity, s.rec, p.name "
b8db66de
AS
867 "FROM devices AS d "
868 "JOIN sessions AS s ON d.id = s.device "
869 "JOIN products AS p ON p.id = s.product "
20f90d71
AS
870 "ORDER BY d.value, s.time DESC", DB_INT, DB_TEXT, DB_INT, DB_TEXT,
871 DB_INT, DB_UINT, DB_INT, DB_INT, DB_TEXT);
7b6cc33e 872
ac6dd7d4
AS
873 if (e)
874 {
20f90d71
AS
875 while (e->enumerate(e, &id, &device, &trusted, &description,
876 &session_id, &tstamp, &ar_id, &rec, &product))
ac6dd7d4 877 {
7b6cc33e
AS
878 if (id != last_id)
879 {
20f90d71
AS
880 printf("%4d: %s %s - %s - %s\n", id, trusted ? "+" : "-",
881 device, product, description);
7b6cc33e
AS
882 device_count++;
883 last_id = id;
884 }
2b61f7ba 885 timestamp = tstamp;
19ce03be 886 printf("%4d: %T", session_id, &timestamp, this->utc);
a1bc67d6 887 if (ar_id)
c88104aa 888 {
a1bc67d6 889 if (ar_id != last_ar_id)
c88104aa 890 {
a1bc67d6 891 chunk_free(&ar_id_value);
c88104aa 892 e_ar = this->db->query(this->db,
b8db66de 893 "SELECT type, value FROM identities "
a1bc67d6
AS
894 "WHERE id = ?", DB_INT, ar_id, DB_INT, DB_BLOB);
895 if (e_ar)
c88104aa 896 {
a1bc67d6 897 e_ar->enumerate(e_ar, &ar_id_type, &ar_id_value);
6c998b8b 898 ar_id_value = chunk_clone(ar_id_value);
a1bc67d6 899 e_ar->destroy(e_ar);
c88104aa 900 }
c88104aa 901 }
a1bc67d6 902 if (ar_id_value.len)
c88104aa 903 {
f2e6a67e 904 printf(" %.*s", (int)ar_id_value.len, ar_id_value.ptr);
c88104aa 905 }
6c998b8b 906 last_ar_id = ar_id;
c88104aa 907 }
29645621 908 printf(" - %N\n", TNC_IMV_Action_Recommendation_names, rec);
ac6dd7d4
AS
909 }
910 e->destroy(e);
a1bc67d6 911 free(ar_id_value.ptr);
c88104aa 912
7b6cc33e
AS
913 printf("%d device%s found\n", device_count,
914 (device_count == 1) ? "" : "s");
ac6dd7d4
AS
915 }
916}
917
f2a521e7
AS
918METHOD(attest_db_t, list_keys, void,
919 private_attest_db_t *this)
920{
921 enumerator_t *e;
922 chunk_t keyid;
923 char *owner;
924 int kid, count = 0;
925
926 if (this->cid)
927 {
928 e = this->db->query(this->db,
929 "SELECT k.id, k.keyid, k.owner FROM keys AS k "
930 "JOIN key_component AS kc ON k.id = kc.key "
931 "WHERE kc.component = ? ORDER BY k.keyid",
e0c66beb 932 DB_UINT, this->cid, DB_INT, DB_BLOB, DB_TEXT);
f2a521e7
AS
933 if (e)
934 {
935 while (e->enumerate(e, &kid, &keyid, &owner))
936 {
0f236aac 937 printf("%4d: %#B '%s'\n", kid, &keyid, owner);
f2a521e7
AS
938 count++;
939 }
940 e->destroy(e);
941 }
942 }
943 else
944 {
945 e = this->db->query(this->db, "SELECT id, keyid, owner FROM keys "
946 "ORDER BY keyid",
947 DB_INT, DB_BLOB, DB_TEXT);
948 if (e)
949 {
950 while (e->enumerate(e, &kid, &keyid, &owner))
951 {
0f236aac 952 printf("%4d: %#B '%s'\n", kid, &keyid, owner);
f2a521e7
AS
953 count++;
954 }
955 e->destroy(e);
956 }
957 }
958
959 printf("%d key%s found", count, (count == 1) ? "" : "s");
960 if (this->comp_set)
961 {
962 printf(" for component '%s'", print_cfn(this->cfn));
963 }
964 printf("\n");
965}
966
e881ee23
AS
967METHOD(attest_db_t, list_files, void,
968 private_attest_db_t *this)
969{
970 enumerator_t *e;
1f179c63
AS
971 char *dir, *file;
972 int did, last_did = 0, fid, count = 0;
e881ee23 973
1f179c63 974 if (this->did)
e881ee23
AS
975 {
976 e = this->db->query(this->db,
1f179c63
AS
977 "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
978 DB_INT, this->did, DB_INT, DB_TEXT);
dac97629
AS
979 if (e)
980 {
1f179c63 981 while (e->enumerate(e, &fid, &file))
dac97629 982 {
60da0153 983 printf("%6d: %s\n", fid, file);
dac97629
AS
984 count++;
985 }
986 e->destroy(e);
987 }
1f179c63
AS
988 printf("%d file%s found in directory '%s'\n", count,
989 (count == 1) ? "" : "s", this->dir);
e881ee23
AS
990 }
991 else
992 {
993 e = this->db->query(this->db,
1f179c63
AS
994 "SELECT d.id, d.path, f.id, f.name FROM files AS f "
995 "JOIN directories AS d ON f.dir = d.id "
996 "ORDER BY d.path, f.name",
997 DB_INT, DB_TEXT, DB_INT, DB_TEXT);
dac97629 998 if (e)
e881ee23 999 {
1f179c63 1000 while (e->enumerate(e, &did, &dir, &fid, &file))
dac97629 1001 {
1f179c63
AS
1002 if (did != last_did)
1003 {
60da0153 1004 printf("%6d: %s\n", did, dir);
1f179c63
AS
1005 last_did = did;
1006 }
60da0153 1007 printf("%6d: %s\n", fid, file);
dac97629
AS
1008 count++;
1009 }
1010 e->destroy(e);
e881ee23 1011 }
1f179c63 1012 printf("%d file%s found\n", count, (count == 1) ? "" : "s");
dac97629 1013 }
1f179c63 1014}
e881ee23 1015
1f179c63
AS
1016METHOD(attest_db_t, list_directories, void,
1017 private_attest_db_t *this)
1018{
1019 enumerator_t *e;
1020 char *dir;
1021 int did, count = 0;
1022
1023 if (this->file)
dac97629 1024 {
1f179c63
AS
1025 e = this->db->query(this->db,
1026 "SELECT d.id, d.path FROM directories AS d "
1027 "JOIN files AS f ON f.dir = d.id WHERE f.name = ? "
1028 "ORDER BY path", DB_TEXT, this->file, DB_INT, DB_TEXT);
1029 if (e)
1030 {
1031 while (e->enumerate(e, &did, &dir))
1032 {
1033 printf("%4d: %s\n", did, dir);
1034 count++;
1035 }
1036 e->destroy(e);
1037 }
1038 printf("%d director%s found containing file '%s'\n", count,
1039 (count == 1) ? "y" : "ies", this->file);
1040 }
1041 else
1042 {
1043 e = this->db->query(this->db,
1044 "SELECT id, path FROM directories ORDER BY path",
1045 DB_INT, DB_TEXT);
1046 if (e)
1047 {
1048 while (e->enumerate(e, &did, &dir))
1049 {
1050 printf("%4d: %s\n", did, dir);
1051 count++;
1052 }
1053 e->destroy(e);
1054 }
1055 printf("%d director%s found\n", count, (count == 1) ? "y" : "ies");
e881ee23
AS
1056 }
1057}
1058
1bb6a086
AS
1059METHOD(attest_db_t, list_packages, void,
1060 private_attest_db_t *this)
1061{
1062 enumerator_t *e;
1063 char *package, *version;
71c7b435
AS
1064 os_package_state_t package_state;
1065 int blacklist, security, gid, gid_old = 0, spaces, count = 0, t;
9fab0a58 1066 time_t timestamp;
1bb6a086
AS
1067
1068 if (this->pid)
1069 {
1070 e = this->db->query(this->db,
71c7b435
AS
1071 "SELECT p.id, p.name, "
1072 "v.release, v.security, v.blacklist, v.time "
d598f2db
AS
1073 "FROM packages AS p JOIN versions AS v ON v.package = p.id "
1074 "WHERE v.product = ? ORDER BY p.name, v.release",
71c7b435
AS
1075 DB_INT, this->pid,
1076 DB_INT, DB_TEXT, DB_TEXT, DB_INT, DB_INT, DB_INT);
1bb6a086
AS
1077 if (e)
1078 {
71c7b435
AS
1079 while (e->enumerate(e, &gid, &package,
1080 &version, &security, &blacklist, &t))
1bb6a086
AS
1081 {
1082 if (gid != gid_old)
1083 {
90741863 1084 printf("%5d: %s,", gid, package);
1bb6a086
AS
1085 gid_old = gid;
1086 }
1087 else
1088 {
90741863 1089 spaces = 8 + strlen(package);
1bb6a086
AS
1090 while (spaces--)
1091 {
1092 printf(" ");
1093 }
1094 }
9fab0a58 1095 timestamp = t;
71c7b435
AS
1096 if (blacklist)
1097 {
1098 package_state = OS_PACKAGE_STATE_BLACKLIST;
1099 }
1100 else
1101 {
1102 package_state = security ? OS_PACKAGE_STATE_SECURITY :
1103 OS_PACKAGE_STATE_UPDATE;
1104 }
9fab0a58 1105 printf(" %T (%s)%N\n", &timestamp, this->utc, version,
71c7b435 1106 os_package_state_names, package_state);
1bb6a086
AS
1107 count++;
1108 }
1109 e->destroy(e);
1110 }
1111 }
1112 else
1113 {
1114 e = this->db->query(this->db, "SELECT id, name FROM packages "
1115 "ORDER BY name",
1116 DB_INT, DB_TEXT);
1117 if (e)
1118 {
1119 while (e->enumerate(e, &gid, &package))
1120 {
1121 printf("%4d: %s\n", gid, package);
1122 count++;
1123 }
1124 e->destroy(e);
1125 }
1126 }
1127
1128 printf("%d package%s found", count, (count == 1) ? "" : "s");
1129 if (this->product_set)
1130 {
1131 printf(" for product '%s'", this->product);
1132 }
1133 printf("\n");
1134}
1135
e881ee23
AS
1136METHOD(attest_db_t, list_products, void,
1137 private_attest_db_t *this)
1138{
1139 enumerator_t *e;
1140 char *product;
dac97629 1141 int pid, meas, meta, count = 0;
e881ee23
AS
1142
1143 if (this->fid)
1144 {
1145 e = this->db->query(this->db,
dac97629
AS
1146 "SELECT p.id, p.name, pf.measurement, pf.metadata "
1147 "FROM products AS p "
e881ee23 1148 "JOIN product_file AS pf ON p.id = pf.product "
0ee1fe15 1149 "WHERE pf.file = ? ORDER BY p.name",
e0c66beb 1150 DB_UINT, this->fid, DB_INT, DB_TEXT, DB_INT, DB_INT);
dac97629
AS
1151 if (e)
1152 {
1153 while (e->enumerate(e, &pid, &product, &meas, &meta))
1154 {
0f236aac 1155 printf("%4d: |%s%s| %s\n", pid, meas ? "M":" ", meta ? "T":" ",
dac97629
AS
1156 product);
1157 count++;
1158 }
1159 e->destroy(e);
1160 }
e881ee23
AS
1161 }
1162 else
1163 {
1164 e = this->db->query(this->db, "SELECT id, name FROM products "
1165 "ORDER BY name",
1166 DB_INT, DB_TEXT);
dac97629 1167 if (e)
e881ee23 1168 {
dac97629
AS
1169 while (e->enumerate(e, &pid, &product))
1170 {
0f236aac 1171 printf("%4d: %s\n", pid, product);
dac97629
AS
1172 count++;
1173 }
1174 e->destroy(e);
e881ee23 1175 }
dac97629 1176 }
e881ee23 1177
dac97629 1178 printf("%d product%s found", count, (count == 1) ? "" : "s");
1f179c63 1179 if (this->fid)
dac97629
AS
1180 {
1181 printf(" for file '%s'", this->file);
e881ee23 1182 }
dac97629 1183 printf("\n");
e881ee23
AS
1184}
1185
b8db66de
AS
1186METHOD(attest_db_t, list_hashes, void,
1187 private_attest_db_t *this)
e881ee23
AS
1188{
1189 enumerator_t *e;
60da0153 1190 char *file, *dir, *product, *hash;
b8db66de 1191 int id, fid, fid_old = 0, did, did_old = 0, pid, pid_old = 0, count = 0;
e881ee23 1192
b8db66de 1193 if (this->pid && this->fid && this->did)
e881ee23 1194 {
60da0153
AS
1195 printf("%6d: %s\n", this->did, this->dir);
1196 printf("%6d: %s\n", this->fid, this->file);
e881ee23 1197 e = this->db->query(this->db,
60da0153
AS
1198 "SELECT h.id, h.hash FROM file_hashes AS h "
1199 "JOIN versions AS v ON h.version = v.id "
1200 "WHERE h.algo = ? AND h.file = ? AND v.product = ?",
b8db66de 1201 DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->pid,
60da0153 1202 DB_INT, DB_TEXT);
e881ee23
AS
1203 if (e)
1204 {
b8db66de 1205 while (e->enumerate(e, &id, &hash))
e881ee23 1206 {
60da0153 1207 printf("%6d: %s\n", id, hash);
b8db66de 1208 count++;
e881ee23
AS
1209 }
1210 e->destroy(e);
b8db66de
AS
1211
1212 printf("%d %N value%s found for product '%s'\n", count,
1213 pts_meas_algorithm_names, this->algo,
1214 (count == 1) ? "" : "s", this->product);
e881ee23
AS
1215 }
1216 }
b8db66de 1217 else if (this->pid && this->file)
645f55eb
AS
1218 {
1219 e = this->db->query(this->db,
b8db66de
AS
1220 "SELECT h.id, h.hash, f.id, d.id, d.path "
1221 "FROM file_hashes AS h "
1222 "JOIN files AS f ON h.file = f.id "
1223 "JOIN directories AS d ON f.dir = d.id "
60da0153
AS
1224 "JOIN versions AS v ON h.version = v.id "
1225 "WHERE h.algo = ? AND v.product = ? AND f.name = ? "
b8db66de
AS
1226 "ORDER BY d.path, f.name, h.hash",
1227 DB_INT, this->algo, DB_INT, this->pid, DB_TEXT, this->file,
60da0153 1228 DB_INT, DB_TEXT, DB_INT, DB_INT, DB_TEXT);
645f55eb
AS
1229 if (e)
1230 {
b8db66de 1231 while (e->enumerate(e, &id, &hash, &fid, &did, &dir))
645f55eb 1232 {
b8db66de 1233 if (did != did_old)
645f55eb 1234 {
60da0153 1235 printf("%6d: %s\n", did, dir);
b8db66de
AS
1236 did_old = did;
1237 }
1238 if (fid != fid_old)
1239 {
60da0153 1240 printf("%6d: %s\n", fid, this->file);
b8db66de 1241 fid_old = fid;
645f55eb 1242 }
60da0153 1243 printf("%6d: %s\n", id, hash);
645f55eb
AS
1244 count++;
1245 }
1246 e->destroy(e);
1247
1248 printf("%d %N value%s found for product '%s'\n", count,
358dbe48 1249 pts_meas_algorithm_names, this->algo,
645f55eb
AS
1250 (count == 1) ? "" : "s", this->product);
1251 }
1252 }
b8db66de 1253 else if (this->pid && this->did)
f4263eae 1254 {
60da0153 1255 printf("%6d: %s\n", this->did, this->dir);
f4263eae 1256 e = this->db->query(this->db,
b8db66de
AS
1257 "SELECT h.id, h.hash, f.id, f.name "
1258 "FROM file_hashes AS h "
1259 "JOIN files AS f ON h.file = f.id "
60da0153
AS
1260 "JOIN versions AS v ON h.version = v.id "
1261 "WHERE h.algo = ? AND v.product = ? AND f.dir = ? "
b8db66de
AS
1262 "ORDER BY f.name, h.hash",
1263 DB_INT, this->algo, DB_INT, this->pid, DB_INT, this->did,
60da0153 1264 DB_INT, DB_TEXT, DB_INT, DB_TEXT);
f4263eae
AS
1265 if (e)
1266 {
b8db66de 1267 while (e->enumerate(e, &id, &hash, &fid, &file))
f4263eae 1268 {
b8db66de
AS
1269 if (fid != fid_old)
1270 {
60da0153 1271 printf("%6d: %s\n", fid, file);
b8db66de
AS
1272 fid_old = fid;
1273 }
60da0153 1274 printf("%6d: %s\n", id, hash);
f4263eae
AS
1275 count++;
1276 }
1277 e->destroy(e);
1278
1279 printf("%d %N value%s found for product '%s'\n", count,
1280 pts_meas_algorithm_names, this->algo,
1281 (count == 1) ? "" : "s", this->product);
f4263eae
AS
1282 }
1283 }
645f55eb 1284 else if (this->pid)
e881ee23
AS
1285 {
1286 e = this->db->query(this->db,
b8db66de
AS
1287 "SELECT h.id, h.hash, f.id, f.name, d.id, d.path "
1288 "FROM file_hashes AS h "
1289 "JOIN files AS f ON h.file = f.id "
1290 "JOIN directories AS d ON f.dir = d.id "
60da0153
AS
1291 "JOIN versions AS v ON h.version = v.id "
1292 "WHERE h.algo = ? AND v.product = ? "
b8db66de
AS
1293 "ORDER BY d.path, f.name, h.hash",
1294 DB_INT, this->algo, DB_INT, this->pid,
60da0153 1295 DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
e881ee23
AS
1296 if (e)
1297 {
b8db66de 1298 while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir))
e881ee23 1299 {
b8db66de 1300 if (did != did_old)
e881ee23 1301 {
60da0153 1302 printf("%6d: %s\n", did, dir);
e881ee23
AS
1303 did_old = did;
1304 }
b8db66de
AS
1305 if (fid != fid_old)
1306 {
60da0153 1307 printf("%6d: %s\n", fid, file);
b8db66de
AS
1308 fid_old = fid;
1309 }
60da0153 1310 printf("%6d: %s\n", id, hash);
e881ee23
AS
1311 count++;
1312 }
1313 e->destroy(e);
1314
1315 printf("%d %N value%s found for product '%s'\n", count,
358dbe48 1316 pts_meas_algorithm_names, this->algo,
e881ee23
AS
1317 (count == 1) ? "" : "s", this->product);
1318 }
1319 }
b8db66de 1320 else if (this->fid && this->did)
e881ee23
AS
1321 {
1322 e = this->db->query(this->db,
b8db66de 1323 "SELECT h.id, h.hash, p.id, p.name FROM file_hashes AS h "
60da0153
AS
1324 "JOIN versions AS v ON h.version = v.id "
1325 "JOIN products AS p ON v.product = p.id "
b8db66de
AS
1326 "WHERE h.algo = ? AND h.file = ? "
1327 "ORDER BY p.name, h.hash",
1328 DB_INT, this->algo, DB_INT, this->fid,
60da0153 1329 DB_INT, DB_TEXT, DB_INT, DB_TEXT);
e881ee23
AS
1330 if (e)
1331 {
b8db66de 1332 while (e->enumerate(e, &id, &hash, &pid, &product))
e881ee23 1333 {
b8db66de
AS
1334 if (pid != pid_old)
1335 {
60da0153 1336 printf("%6d: %s\n", pid, product);
b8db66de
AS
1337 pid_old = pid;
1338 }
60da0153 1339 printf("%6d: %s\n", id, hash);
e881ee23
AS
1340 count++;
1341 }
1342 e->destroy(e);
1343
b8db66de
AS
1344 printf("%d %N value%s found for file '%s%s%s'\n", count,
1345 pts_meas_algorithm_names, this->algo,
0ee1fe15 1346 (count == 1) ? "" : "s", this->dir,
0731d41c 1347 get_separator(this->dir), this->file);
b8db66de
AS
1348 }
1349 }
1350 else if (this->file)
1351 {
1352 e = this->db->query(this->db,
1353 "SELECT h.id, h.hash, f.id, d.id, d.path, p.id, p.name "
1354 "FROM file_hashes AS h "
1355 "JOIN files AS f ON h.file = f.id "
1356 "JOIN directories AS d ON f.dir = d.id "
60da0153
AS
1357 "JOIN versions AS v ON h.version = v.id "
1358 "JOIN products AS p ON v.product = p.id "
b8db66de
AS
1359 "WHERE h.algo = ? AND f.name = ? "
1360 "ORDER BY d.path, f.name, p.name, h.hash",
1361 DB_INT, this->algo, DB_TEXT, this->file,
60da0153 1362 DB_INT, DB_TEXT, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
b8db66de
AS
1363 if (e)
1364 {
1365 while (e->enumerate(e, &id, &hash, &fid, &did, &dir, &pid, &product))
1366 {
1367 if (did != did_old)
1368 {
60da0153 1369 printf("%6d: %s\n", did, dir);
b8db66de
AS
1370 did_old = did;
1371 }
1372 if (fid != fid_old)
1373 {
60da0153 1374 printf("%6d: %s\n", fid, this->file);
b8db66de
AS
1375 fid_old = fid;
1376 pid_old = 0;
1377 }
1378 if (pid != pid_old)
1379 {
60da0153 1380 printf("%6d: %s\n", pid, product);
b8db66de
AS
1381 pid_old = pid;
1382 }
60da0153 1383 printf("%6d: %s\n", id, hash);
b8db66de
AS
1384 count++;
1385 }
1386 e->destroy(e);
1387
1388 printf("%d %N value%s found\n", count, pts_meas_algorithm_names,
1389 this->algo, (count == 1) ? "" : "s");
1390 }
1391
1392 }
1393 else if (this->did)
1394 {
1395 e = this->db->query(this->db,
1396 "SELECT h.id, h.hash, f.id, f.name, p.id, p.name "
1397 "FROM file_hashes AS h "
1398 "JOIN files AS f ON h.file = f.id "
60da0153
AS
1399 "JOIN versions AS v ON h.version = v.id "
1400 "JOIN products AS p ON v.product = p.id "
b8db66de
AS
1401 "WHERE h.algo = ? AND f.dir = ? "
1402 "ORDER BY f.name, p.name, h.hash",
1403 DB_INT, this->algo, DB_INT, this->did,
60da0153 1404 DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
b8db66de
AS
1405 if (e)
1406 {
1407 while (e->enumerate(e, &id, &hash, &fid, &file, &pid, &product))
1408 {
1409 if (fid != fid_old)
1410 {
60da0153 1411 printf("%6d: %s\n", fid, file);
b8db66de
AS
1412 fid_old = fid;
1413 pid_old = 0;
1414 }
1415 if (pid != pid_old)
1416 {
60da0153 1417 printf("%6d: %s\n", pid, product);
b8db66de
AS
1418 pid_old = pid;
1419 }
60da0153 1420 printf("%6d: %s\n", id, hash);
b8db66de
AS
1421 count++;
1422 }
1423 e->destroy(e);
1424
1425 printf("%d %N value%s found for directory '%s'\n", count,
1426 pts_meas_algorithm_names, this->algo,
1427 (count == 1) ? "" : "s", this->dir);
e881ee23
AS
1428 }
1429 }
1430 else
1431 {
1432 e = this->db->query(this->db,
b8db66de
AS
1433 "SELECT h.id, h.hash, f.id, f.name, d.id, d.path, p.id, p.name "
1434 "FROM file_hashes AS h "
1435 "JOIN files AS f ON h.file = f.id "
1436 "JOIN directories AS d ON f.dir = d.id "
60da0153
AS
1437 "JOIN versions AS v ON h.version = v.id "
1438 "JOIN products AS p on v.product = p.id "
b8db66de
AS
1439 "WHERE h.algo = ? "
1440 "ORDER BY d.path, f.name, p.name, h.hash",
60da0153 1441 DB_INT, this->algo, DB_INT, DB_TEXT, DB_INT, DB_TEXT,
b8db66de 1442 DB_INT, DB_TEXT, DB_INT, DB_TEXT);
e881ee23
AS
1443 if (e)
1444 {
b8db66de
AS
1445 while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir, &pid,
1446 &product))
e881ee23 1447 {
b8db66de 1448 if (did != did_old)
e881ee23 1449 {
60da0153 1450 printf("%6d: %s\n", did, dir);
b8db66de
AS
1451 did_old = did;
1452 }
1453 if (fid != fid_old)
1454 {
60da0153 1455 printf("%6d: %s\n", fid, file);
e881ee23 1456 fid_old = fid;
b8db66de
AS
1457 pid_old = 0;
1458 }
1459 if (pid != pid_old)
1460 {
60da0153 1461 printf("%6d: %s\n", pid, product);
b8db66de 1462 pid_old = pid;
e881ee23 1463 }
60da0153 1464 printf("%6d: %s\n", id, hash);
e881ee23
AS
1465 count++;
1466 }
1467 e->destroy(e);
1468
358dbe48
AS
1469 printf("%d %N value%s found\n", count, pts_meas_algorithm_names,
1470 this->algo, (count == 1) ? "" : "s");
e881ee23
AS
1471 }
1472 }
e881ee23
AS
1473}
1474
f2a521e7
AS
1475METHOD(attest_db_t, list_measurements, void,
1476 private_attest_db_t *this)
1477{
1478 enumerator_t *e;
1479 chunk_t hash, keyid;
1480 pts_comp_func_name_t *cfn;
1481 char *owner;
1482 int seq_no, pcr, vid, name, qualifier;
1483 int cid, cid_old = 0, kid, kid_old = 0, count = 0;
1484
1485 if (this->kid && this->cid)
1486 {
1487 e = this->db->query(this->db,
1488 "SELECT ch.seq_no, ch.pcr, ch.hash, k.owner "
1489 "FROM component_hashes AS ch "
1490 "JOIN keys AS k ON k.id = ch.key "
1491 "WHERE ch.algo = ? AND ch.key = ? AND ch.component = ? "
1492 "ORDER BY seq_no",
e0c66beb 1493 DB_INT, this->algo, DB_UINT, this->kid, DB_UINT, this->cid,
f2a521e7
AS
1494 DB_INT, DB_INT, DB_BLOB, DB_TEXT);
1495 if (e)
1496 {
1497 while (e->enumerate(e, &seq_no, &pcr, &hash, &owner))
1498 {
1499 if (this->kid != kid_old)
1500 {
0f236aac 1501 printf("%4d: %#B '%s'\n", this->kid, &this->key, owner);
f2a521e7
AS
1502 kid_old = this->kid;
1503 }
e0c66beb 1504 printf("%7d %02d %#B\n", seq_no, pcr, &hash);
f2a521e7
AS
1505 count++;
1506 }
1507 e->destroy(e);
1508
1509 printf("%d %N value%s found for component '%s'\n", count,
358dbe48 1510 pts_meas_algorithm_names, this->algo,
f2a521e7
AS
1511 (count == 1) ? "" : "s", print_cfn(this->cfn));
1512 }
1513 }
1514 else if (this->cid)
1515 {
1516 e = this->db->query(this->db,
1517 "SELECT ch.seq_no, ch.pcr, ch.hash, k.id, k.keyid, k.owner "
1518 "FROM component_hashes AS ch "
1519 "JOIN keys AS k ON k.id = ch.key "
1520 "WHERE ch.algo = ? AND ch.component = ? "
1521 "ORDER BY keyid, seq_no",
e0c66beb 1522 DB_INT, this->algo, DB_UINT, this->cid,
f2a521e7
AS
1523 DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB, DB_TEXT);
1524 if (e)
1525 {
1526 while (e->enumerate(e, &seq_no, &pcr, &hash, &kid, &keyid, &owner))
1527 {
1528 if (kid != kid_old)
1529 {
0f236aac 1530 printf("%4d: %#B '%s'\n", kid, &keyid, owner);
f2a521e7
AS
1531 kid_old = kid;
1532 }
e0c66beb 1533 printf("%7d %02d %#B\n", seq_no, pcr, &hash);
f2a521e7
AS
1534 count++;
1535 }
1536 e->destroy(e);
1537
1538 printf("%d %N value%s found for component '%s'\n", count,
358dbe48 1539 pts_meas_algorithm_names, this->algo,
f2a521e7
AS
1540 (count == 1) ? "" : "s", print_cfn(this->cfn));
1541 }
1542
1543 }
1544 else if (this->kid)
1545 {
1546 e = this->db->query(this->db,
1547 "SELECT ch.seq_no, ch.pcr, ch.hash, "
1548 "c.id, c.vendor_id, c.name, c.qualifier "
1549 "FROM component_hashes AS ch "
1550 "JOIN components AS c ON c.id = ch.component "
1551 "WHERE ch.algo = ? AND ch.key = ? "
1552 "ORDER BY vendor_id, name, qualifier, seq_no",
e0c66beb 1553 DB_INT, this->algo, DB_UINT, this->kid, DB_INT, DB_INT, DB_BLOB,
1b9c613b 1554 DB_INT, DB_INT, DB_INT, DB_INT);
f2a521e7
AS
1555 if (e)
1556 {
1557 while (e->enumerate(e, &seq_no, &pcr, &hash, &cid, &vid, &name,
1558 &qualifier))
1559 {
1560 if (cid != cid_old)
1561 {
1562 cfn = pts_comp_func_name_create(vid, name, qualifier);
0f236aac 1563 printf("%4d: %s\n", cid, print_cfn(cfn));
f2a521e7
AS
1564 cfn->destroy(cfn);
1565 cid_old = cid;
1566 }
1567 printf("%5d %02d %#B\n", seq_no, pcr, &hash);
1568 count++;
1569 }
1570 e->destroy(e);
1571
1572 printf("%d %N value%s found for key %#B '%s'\n", count,
358dbe48 1573 pts_meas_algorithm_names, this->algo,
f2a521e7
AS
1574 (count == 1) ? "" : "s", &this->key, this->owner);
1575 }
1576 }
1577}
1578
b8db66de
AS
1579METHOD(attest_db_t, list_sessions, void,
1580 private_attest_db_t *this)
1581{
1582 enumerator_t *e;
72631301
AS
1583 chunk_t identity;
1584 char *product, *device;
1585 int session_id, conn_id, rec, device_len;
b8db66de
AS
1586 time_t created;
1587 u_int t;
1588
1589 e = this->db->query(this->db,
29645621
AS
1590 "SELECT s.id, s.time, s.connection, s.rec, p.name, d.value, i.value "
1591 "FROM sessions AS s "
1592 "LEFT JOIN products AS p ON s.product = p.id "
1593 "LEFT JOIN devices AS d ON s.device = d.id "
1594 "LEFT JOIN identities AS i ON s.identity = i.id "
1595 "ORDER BY s.time DESC",
72631301 1596 DB_INT, DB_UINT, DB_INT, DB_INT, DB_TEXT, DB_TEXT, DB_BLOB);
b8db66de
AS
1597 if (e)
1598 {
29645621
AS
1599 while (e->enumerate(e, &session_id, &t, &conn_id, &rec, &product,
1600 &device, &identity))
b8db66de
AS
1601 {
1602 created = t;
1603 product = product ? product : "-";
72631301
AS
1604 device = strlen(device) ? device : "-";
1605 device_len = min(strlen(device), DEVICE_MAX_LEN);
b8db66de 1606 identity = identity.len ? identity : chunk_from_str("-");
97980127 1607 printf("%4d: %T %2d %-20s %.*s%*s%.*s - %N\n", session_id, &created,
24f59868 1608 this->utc, conn_id, product, device_len, device,
a00ac1d9
TB
1609 DEVICE_MAX_LEN - device_len + 1, " ", (int)identity.len,
1610 identity.ptr, TNC_IMV_Action_Recommendation_names, rec);
b8db66de
AS
1611 }
1612 e->destroy(e);
1613 }
1614}
1615
1616/**
1617 * Insert a file hash into the database
1618 */
1619static bool insert_file_hash(private_attest_db_t *this,
1620 pts_meas_algorithms_t algo,
37a73b9c 1621 chunk_t measurement, int fid,
b8db66de 1622 int *hashes_added, int *hashes_updated)
358dbe48
AS
1623{
1624 enumerator_t *e;
60da0153
AS
1625 uint8_t hex_measurement_buf[2*HASH_SIZE_SHA512 + 1];
1626 uint8_t *hex_hash_buf;
1627 chunk_t hex_hash, hex_measurement;
358dbe48 1628 char *label;
37a73b9c 1629 bool insert = TRUE, update = FALSE;
358dbe48
AS
1630
1631 label = "could not be created";
1632
1633 e = this->db->query(this->db,
60da0153
AS
1634 "SELECT hash FROM file_hashes "
1635 "WHERE algo = ? AND file = ? AND version = ?",
1636 DB_INT, algo, DB_UINT, fid, DB_UINT, this->vid, DB_TEXT);
37a73b9c 1637
358dbe48
AS
1638 if (!e)
1639 {
1640 printf("file_hashes query failed\n");
1641 return FALSE;
1642 }
60da0153 1643 hex_measurement = chunk_to_hex(measurement, hex_measurement_buf, FALSE);
37a73b9c 1644
60da0153 1645 while (e->enumerate(e, &hex_hash_buf))
358dbe48 1646 {
37a73b9c 1647 update = TRUE;
60da0153 1648 hex_hash = chunk_from_str(hex_hash_buf);
37a73b9c 1649
60da0153 1650 if (chunk_equals(hex_measurement, hex_hash))
f0d4756e
AS
1651 {
1652 label = "exists and equals";
37a73b9c
AS
1653 insert = FALSE;
1654 break;
f0d4756e 1655 }
358dbe48 1656 }
37a73b9c
AS
1657 e->destroy(e);
1658
1659 if (insert)
358dbe48
AS
1660 {
1661 if (this->db->execute(this->db, NULL,
1662 "INSERT INTO file_hashes "
60da0153
AS
1663 "(file, version, algo, hash) "
1664 "VALUES (?, ?, ?, ?)",
1665 DB_UINT, fid, DB_UINT, this->vid,
1666 DB_INT, algo, DB_TEXT, hex_measurement) != 1)
37a73b9c
AS
1667 {
1668 printf("file_hash insertion failed\n");
1669 return FALSE;
1670 }
1671 if (update)
1672 {
1673 label = "updated";
1674 (*hashes_updated)++;
1675 }
1676 else
358dbe48
AS
1677 {
1678 label = "created";
1679 (*hashes_added)++;
1680 }
1681 }
37a73b9c 1682 printf(" %#B - %s\n", &measurement, label);
358dbe48
AS
1683 return TRUE;
1684}
1685
60da0153
AS
1686/**
1687 * Add a package version
1688 */
1689static bool add_version(private_attest_db_t *this)
1690{
1691 int vid, security_old, security, blacklist_old, blacklist;
1692 time_t t = time(NULL);
1693 enumerator_t *e;
1694 bool success;
1695
1696 security = this->package_state == OS_PACKAGE_STATE_SECURITY;
1697 blacklist = this->package_state == OS_PACKAGE_STATE_BLACKLIST;
1698
1699 e = this->db->query(this->db,
1700 "SELECT id, security, blacklist FROM versions "
1701 "WHERE package = ? AND product = ? AND release = ?",
1702 DB_UINT, this->gid, DB_UINT, this->pid, DB_TEXT, this->version,
1703 DB_INT, DB_INT, DB_INT, DB_INT);
1704 if (e)
1705 {
1706 if (e->enumerate(e, &vid, &security_old, &blacklist_old))
1707 {
1708 this->vid = vid;
1709 }
1710 e->destroy(e);
1711 }
1712 if (this->vid)
1713 {
1714 if (security != security_old || blacklist != blacklist_old)
1715 {
1716 /* update security and/or blacklist flag */
1717 success = this->db->execute(this->db, NULL, "UPDATE versions "
1718 "SET security = ?, blacklist = ?, time = ? WHERE id = ?",
1719 DB_INT, security, DB_INT, blacklist, DB_INT, t,
1720 DB_INT, this->vid) == 1;
1721
1722 printf("'%s' package %s (%s)%N %s updated in database\n",
1723 this->product, this->package, this->version,
1724 os_package_state_names, this->package_state,
1725 success ? "" : "could not be ");
1726 }
1727 else
1728 {
1729 success = TRUE;
1730
1731 printf("'%s' package %s (%s)%N exists in database\n",
1732 this->product, this->package, this->version,
1733 os_package_state_names, this->package_state);
1734 }
1735 return success;
1736 }
1737
1738 /* create a new version */
1739 success = this->db->execute(this->db, NULL,
1740 "INSERT INTO versions "
1741 "(package, product, release, security, blacklist, time) "
1742 "VALUES (?, ?, ?, ?, ?, ?)",
1743 DB_UINT, this->gid, DB_INT, this->pid, DB_TEXT,
1744 this->version, DB_INT, security, DB_INT, blacklist,
1745 DB_INT, t) == 1;
1746
1747 printf("'%s' package %s (%s)%N %sinserted into database\n",
1748 this->product, this->package, this->version,
1749 os_package_state_names, this->package_state,
1750 success ? "" : "could not be ");
1751
1752 return success;
1753}
1754
b8db66de
AS
1755/**
1756 * Add hash measurement for a single file or all files in a directory
1757 */
1758static bool add_hash(private_attest_db_t *this)
f4159ff8 1759{
0731d41c
MW
1760 char *pathname, *filename, *label;
1761 const char *sep;
b8db66de 1762 pts_file_meas_t *measurements;
37a73b9c 1763 chunk_t measurement;
b8db66de 1764 hasher_t *hasher = NULL;
b8db66de 1765 int fid, files_added = 0, hashes_added = 0, hashes_updated = 0;
b8db66de
AS
1766 enumerator_t *enumerator, *e;
1767
37a73b9c 1768 if (!this->meas_dir)
b8db66de 1769 {
37a73b9c 1770 this->meas_dir = strdup(this->dir);
b8db66de 1771 }
0731d41c 1772 sep = get_separator(this->meas_dir);
358dbe48 1773
b8db66de
AS
1774 if (this->fid)
1775 {
1776 /* build pathname from directory path and relative filename */
37a73b9c 1777 if (asprintf(&pathname, "%s%s%s", this->meas_dir, sep, this->file) == -1)
0f236aac
AS
1778 {
1779 return FALSE;
1780 }
b8db66de
AS
1781 measurements = pts_file_meas_create_from_path(0, pathname, FALSE,
1782 TRUE, this->algo);
1783 free(pathname);
1784 }
1785 else
1786 {
37a73b9c 1787 measurements = pts_file_meas_create_from_path(0, this->meas_dir, TRUE,
b8db66de
AS
1788 TRUE, this->algo);
1789 }
1790 if (!measurements)
1791 {
1792 printf("file measurement failed\n");
1793 DESTROY_IF(hasher);
1794 return FALSE;
1795 }
1796
1797 enumerator = measurements->create_enumerator(measurements);
1798 while (enumerator->enumerate(enumerator, &filename, &measurement))
1799 {
1800 if (this->fid)
0f236aac 1801 {
b8db66de
AS
1802 /* a single file already exists */
1803 filename = this->file;
1804 fid = this->fid;
1805 label = "exists";
0f236aac 1806 }
b8db66de 1807 else
0f236aac
AS
1808 {
1809 /* retrieve or create filename */
1810 label = "could not be created";
1811
1812 e = this->db->query(this->db,
b8db66de
AS
1813 "SELECT id FROM files WHERE name = ? AND dir = ?",
1814 DB_TEXT, filename, DB_INT, this->did, DB_INT);
0f236aac
AS
1815 if (!e)
1816 {
1817 printf("files query failed\n");
1818 break;
1819 }
1820 if (e->enumerate(e, &fid))
1821 {
1822 label = "exists";
1823 }
1824 else
1825 {
1826 if (this->db->execute(this->db, &fid,
b8db66de
AS
1827 "INSERT INTO files (name, dir) VALUES (?, ?)",
1828 DB_TEXT, filename, DB_INT, this->did) == 1)
0f236aac
AS
1829 {
1830 label = "created";
1831 files_added++;
1832 }
1833 }
1834 e->destroy(e);
b8db66de
AS
1835 }
1836 printf("%4d: %s - %s\n", fid, filename, label);
0f236aac 1837
b8db66de 1838 /* compute file measurement hash */
37a73b9c 1839 if (!insert_file_hash(this, this->algo, measurement, fid,
b8db66de
AS
1840 &hashes_added, &hashes_updated))
1841 {
1842 break;
1843 }
b8db66de
AS
1844 }
1845 enumerator->destroy(enumerator);
1846
37a73b9c
AS
1847 printf("%d measurements, added %d new files, %d file hashes, "
1848 "updated %d file hashes\n",
1849 measurements->get_file_count(measurements),
1850 files_added, hashes_added, hashes_updated);
b8db66de
AS
1851 measurements->destroy(measurements);
1852
1853 return TRUE;
1854}
1855
1856METHOD(attest_db_t, add, bool,
1857 private_attest_db_t *this)
1858{
60da0153
AS
1859 /* insert package version */
1860 if (this->version_set && this->gid && this->pid)
1861 {
1862 if (!add_version(this))
1863 {
1864 return FALSE;
1865 }
1866 }
b8db66de 1867
b8db66de
AS
1868 /* add directory or file hash measurement for a given product */
1869 if (this->did && this->pid)
1870 {
1871 return add_hash(this);
0f236aac 1872 }
1bb6a086 1873
60da0153 1874 return FALSE;
f4159ff8
AS
1875}
1876
1877METHOD(attest_db_t, delete, bool,
1878 private_attest_db_t *this)
1879{
2b28a131 1880 bool success;
1f179c63
AS
1881 int id, count = 0;
1882 char *name;
1883 enumerator_t *e;
2b28a131 1884
838f683c
AS
1885 /* delete a file measurement hash for a given product */
1886 if (this->algo && this->pid && this->fid)
1887 {
1888 success = this->db->execute(this->db, NULL,
60da0153
AS
1889 "DELETE FROM file_hashes AS h "
1890 "JOIN versions AS v ON h.version = v.id "
1891 "WHERE h.algo = ? AND v.product = ? AND h.file = ?",
838f683c 1892 DB_UINT, this->algo, DB_UINT, this->pid,
b8db66de 1893 DB_UINT, this->fid) > 0;
838f683c 1894
0731d41c
MW
1895 printf("%4d: %s%s%s\n", this->fid, this->dir, get_separator(this->dir),
1896 this->file);
838f683c
AS
1897 printf("%N value for product '%s' %sdeleted from database\n",
1898 pts_meas_algorithm_names, this->algo, this->product,
1899 success ? "" : "could not be ");
1900
1901 return success;
1902 }
1903
fa1baac3 1904 /* delete product/file entries */
2b28a131
AS
1905 if (this->pid && (this->fid || this->did))
1906 {
fa1baac3
AS
1907 success = this->db->execute(this->db, NULL,
1908 "DELETE FROM product_file "
1909 "WHERE product = ? AND file = ?",
1910 DB_UINT, this->pid,
1911 DB_UINT, this->fid ? this->fid : this->did) > 0;
1912
1913 printf("product/file pair (%d/%d) %sdeleted from database\n",
1914 this->pid, this->fid ? this->fid : this->did,
1915 success ? "" : "could not be ");
1916
1917 return success;
2b28a131
AS
1918 }
1919
f2a521e7 1920 if (this->cid)
2b28a131
AS
1921 {
1922 success = this->db->execute(this->db, NULL,
f2a521e7
AS
1923 "DELETE FROM components WHERE id = ?",
1924 DB_UINT, this->cid) > 0;
2b28a131 1925
f2a521e7
AS
1926 printf("component '%s' %sdeleted from database\n", print_cfn(this->cfn),
1927 success ? "" : "could not be ");
1928 return success;
1929 }
1930
1f179c63 1931 if (this->fid)
f2a521e7
AS
1932 {
1933 success = this->db->execute(this->db, NULL,
1f179c63
AS
1934 "DELETE FROM files WHERE id = ?",
1935 DB_UINT, this->fid) > 0;
f2a521e7 1936
1f179c63 1937 printf("file '%s%s%s' %sdeleted from database\n", this->dir,
0731d41c 1938 get_separator(this->dir), this->file,
2b28a131
AS
1939 success ? "" : "could not be ");
1940 return success;
1941 }
1942
1f179c63 1943 if (this->did)
2b28a131 1944 {
1f179c63
AS
1945 e = this->db->query(this->db,
1946 "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
1947 DB_INT, this->did, DB_INT, DB_TEXT);
1948 if (e)
1949 {
1950 while (e->enumerate(e, &id, &name))
1951 {
1952 printf("%4d: %s\n", id, name);
1953 count++;
1954 }
1955 e->destroy(e);
2b28a131 1956
1f179c63
AS
1957 if (count)
1958 {
1959 printf("%d dependent file%s found, "
1960 "directory '%s' could not deleted\n",
1961 count, (count == 1) ? "" : "s", this->dir);
1962 return FALSE;
1963 }
1964 }
1965 success = this->db->execute(this->db, NULL,
1966 "DELETE FROM directories WHERE id = ?",
1967 DB_UINT, this->did) > 0;
1968 printf("directory '%s' %sdeleted from database\n", this->dir,
2b28a131
AS
1969 success ? "" : "could not be ");
1970 return success;
1971 }
1972
f2a521e7 1973 if (this->kid)
2b28a131
AS
1974 {
1975 success = this->db->execute(this->db, NULL,
f2a521e7
AS
1976 "DELETE FROM keys WHERE id = ?",
1977 DB_UINT, this->kid) > 0;
2b28a131 1978
f2a521e7 1979 printf("key %#B %sdeleted from database\n", &this->key,
2b28a131
AS
1980 success ? "" : "could not be ");
1981 return success;
1982 }
f2a521e7 1983 if (this->pid)
d37abe0f
AS
1984 {
1985 success = this->db->execute(this->db, NULL,
f2a521e7
AS
1986 "DELETE FROM products WHERE id = ?",
1987 DB_UINT, this->pid) > 0;
d37abe0f 1988
f2a521e7 1989 printf("product '%s' %sdeleted from database\n", this->product,
d37abe0f
AS
1990 success ? "" : "could not be ");
1991 return success;
1992 }
1993
2b28a131 1994 printf("empty delete command\n");
f4159ff8
AS
1995 return FALSE;
1996}
1997
e881ee23
AS
1998METHOD(attest_db_t, destroy, void,
1999 private_attest_db_t *this)
2000{
2001 DESTROY_IF(this->db);
d37abe0f 2002 DESTROY_IF(this->cfn);
1bb6a086 2003 free(this->package);
e881ee23 2004 free(this->product);
1bb6a086 2005 free(this->version);
e881ee23
AS
2006 free(this->file);
2007 free(this->dir);
37a73b9c 2008 free(this->meas_dir);
f2a521e7
AS
2009 free(this->owner);
2010 free(this->key.ptr);
e881ee23
AS
2011 free(this);
2012}
2013
2014/**
2015 * Described in header.
2016 */
2017attest_db_t *attest_db_create(char *uri)
2018{
2019 private_attest_db_t *this;
2020
2021 INIT(this,
2022 .public = {
d37abe0f
AS
2023 .set_component = _set_component,
2024 .set_cid = _set_cid,
f2a521e7
AS
2025 .set_directory = _set_directory,
2026 .set_did = _set_did,
2027 .set_file = _set_file,
2028 .set_fid = _set_fid,
37a73b9c 2029 .set_meas_directory = _set_meas_directory,
f2a521e7
AS
2030 .set_key = _set_key,
2031 .set_kid = _set_kid,
1bb6a086
AS
2032 .set_package = _set_package,
2033 .set_gid = _set_gid,
f2a521e7
AS
2034 .set_product = _set_product,
2035 .set_pid = _set_pid,
1bb6a086 2036 .set_version = _set_version,
e881ee23 2037 .set_algo = _set_algo,
0f236aac 2038 .set_relative = _set_relative,
71c7b435 2039 .set_package_state = _set_package_state,
e0c66beb 2040 .set_sequence = _set_sequence,
f2a521e7 2041 .set_owner = _set_owner,
81ee269d 2042 .set_utc = _set_utc,
1bb6a086 2043 .list_packages = _list_packages,
e881ee23
AS
2044 .list_products = _list_products,
2045 .list_files = _list_files,
1f179c63 2046 .list_directories = _list_directories,
6b55276a 2047 .list_components = _list_components,
ac6dd7d4 2048 .list_devices = _list_devices,
f2a521e7 2049 .list_keys = _list_keys,
e881ee23 2050 .list_hashes = _list_hashes,
f2a521e7 2051 .list_measurements = _list_measurements,
b8db66de 2052 .list_sessions = _list_sessions,
f4159ff8
AS
2053 .add = _add,
2054 .delete = _delete,
e881ee23
AS
2055 .destroy = _destroy,
2056 },
e881ee23
AS
2057 .db = lib->db->create(lib->db, uri),
2058 );
2059
2060 if (!this->db)
2061 {
2062 fprintf(stderr, "opening database failed.\n");
2063 destroy(this);
2064 return NULL;
2065 }
2066
2067 return &this->public;
2068}