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