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