Annotation of embedaddon/strongswan/src/libimcv/plugins/imv_attestation/attest_db.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2011-2017 Andreas Steffen
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #define _GNU_SOURCE
17:
18: #include <stdio.h>
19: #include <libgen.h>
20: #include <time.h>
21:
22: #include <tncif_names.h>
23:
24: #include "attest_db.h"
25:
26: #include "imcv.h"
27: #include "pts/pts_meas_algo.h"
28: #include "pts/pts_file_meas.h"
29: #include "pts/components/pts_comp_func_name.h"
30:
31: #define IMA_MAX_NAME_LEN 255
32: #define DEVICE_MAX_LEN 20
33:
34: typedef struct private_attest_db_t private_attest_db_t;
35:
36: /**
37: * Private data of an attest_db_t object.
38: */
39: struct private_attest_db_t {
40:
41: /**
42: * Public members of attest_db_state_t
43: */
44: attest_db_t public;
45:
46: /**
47: * Component Functional Name to be queried
48: */
49: pts_comp_func_name_t *cfn;
50:
51: /**
52: * Primary key of the Component Functional Name to be queried
53: */
54: int cid;
55:
56: /**
57: * TRUE if Component Functional Name has been set
58: */
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:
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:
81: /**
82: * Directory where file measurement are to be taken
83: */
84: char *meas_dir;
85:
86: /**
87: * AIK to be queried
88: */
89: chunk_t key;
90:
91: /**
92: * Primary key of the AIK to be queried
93: */
94: int kid;
95:
96: /**
97: * TRUE if AIK has been set
98: */
99: bool key_set;
100:
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:
116: /**
117: * Software product to be queried
118: */
119: char *product;
120:
121: /**
122: * Primary key of software product to be queried
123: */
124: int pid;
125:
126: /**
127: * TRUE if product has been set
128: */
129: bool product_set;
130:
131: /**
132: * Software package version to be queried
133: */
134: char *version;
135:
136: /**
137: * Primary key of software package version to be queried
138: */
139: int vid;
140:
141: /**
142: * TRUE if version has been set
143: */
144: bool version_set;
145:
146: /**
147: * TRUE if relative filenames are to be used
148: */
149: bool relative;
150:
151: /**
152: * TRUE if dates are to be displayed in UTC
153: */
154: bool utc;
155:
156: /**
157: * Package security or blacklist state
158: */
159: os_package_state_t package_state;
160:
161: /**
162: * Sequence number for ordering entries
163: */
164: int seq_no;
165:
166: /**
167: * File measurement hash algorithm
168: */
169: pts_meas_algorithms_t algo;
170:
171: /**
172: * Optional owner (user/host name)
173: */
174: char *owner;
175:
176: /**
177: * Attestation database
178: */
179: database_t *db;
180:
181: };
182:
183: char* 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:
190: vid = cfn->get_vendor_id(cfn);
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:
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);
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:
207: /**
208: * Get the directory separator to append to a path
209: */
210: static 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:
222: METHOD(attest_db_t, set_component, bool,
223: private_attest_db_t *this, char *comp, bool create)
224: {
225: enumerator_t *e;
226: char *pos1, *pos2;
227: int vid, name, qualifier;
228: pts_comp_func_name_t *cfn;
229:
230: if (this->comp_set)
231: {
232: printf("component has already been set\n");
233: return FALSE;
234: }
235:
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 = ?",
252: DB_UINT, vid, DB_INT, name, DB_INT, qualifier, DB_INT);
253: if (e)
254: {
255: if (e->enumerate(e, &this->cid))
256: {
257: this->comp_set = TRUE;
258: this->cfn = cfn;
259: }
260: e->destroy(e);
261: }
262: if (this->comp_set)
263: {
264: return TRUE;
265: }
266:
267: if (!create)
268: {
269: printf("component '%s' not found in database\n", print_cfn(cfn));
270: cfn->destroy(cfn);
271: return FALSE;
272: }
273:
274: /* Add a new database entry */
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;
279:
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: }
292:
293: METHOD(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 = ?",
308: DB_UINT, cid, DB_INT, DB_INT, DB_INT);
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;
323: }
324:
325: METHOD(attest_db_t, set_directory, bool,
326: private_attest_db_t *this, char *dir, bool create)
327: {
328: enumerator_t *e;
329: int did;
330: size_t len;
331:
332: if (this->did)
333: {
334: printf("directory has already been set\n");
335: return FALSE;
336: }
337:
338: /* remove trailing '/' or '\' character if not root directory */
339: len = strlen(dir);
340: if (len > 1 && dir[len-1] == DIRECTORY_SEPARATOR[0])
341: {
342: dir[len-1] = '\0';
343: }
344: this->dir = strdup(dir);
345:
346: e = this->db->query(this->db,
347: "SELECT id FROM directories WHERE path = ?",
348: DB_TEXT, dir, DB_INT);
349: if (e)
350: {
351: if (e->enumerate(e, &did))
352: {
353: this->did = did;
354: }
355: e->destroy(e);
356: }
357: if (this->did)
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 */
369: if (1 == this->db->execute(this->db, &did,
370: "INSERT INTO directories (path) VALUES (?)", DB_TEXT, dir))
371: {
372: this->did = did;
373: }
374: printf("directory '%s' %sinserted into database\n", dir,
375: this->did ? "" : "could not be ");
376:
377: return this->did > 0;
378: }
379:
380: METHOD(attest_db_t, set_did, bool,
381: private_attest_db_t *this, int did)
382: {
383: enumerator_t *e;
384: char *dir;
385:
386: if (this->did)
387: {
388: printf("directory has already been set\n");
389: return FALSE;
390: }
391:
392: e = this->db->query(this->db, "SELECT path FROM directories WHERE id = ?",
393: DB_UINT, did, DB_TEXT);
394: if (e)
395: {
396: if (e->enumerate(e, &dir))
397: {
398: this->dir = strdup(dir);
399: this->did = did;
400: }
401: else
402: {
403: printf("no directory found with did %d\n", did);
404: }
405: e->destroy(e);
406: }
407: return this->did > 0;
408: }
409:
410: METHOD(attest_db_t, set_file, bool,
411: private_attest_db_t *this, char *file, bool create)
412: {
413: int fid;
414: enumerator_t *e;
415:
416: if (this->file)
417: {
418: printf("file has already been set\n");
419: return FALSE;
420: }
421: this->file = strdup(file);
422:
423: if (!this->did)
424: {
425: return TRUE;
426: }
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);
430: if (e)
431: {
432: if (e->enumerate(e, &fid))
433: {
434: this->fid = fid;
435: }
436: e->destroy(e);
437: }
438: if (this->fid)
439: {
440: return TRUE;
441: }
442:
443: if (!create)
444: {
445: printf("file '%s%s%s' not found in database\n",
446: this->dir, get_separator(this->dir), file);
447: return FALSE;
448: }
449:
450: /* Add a new database entry */
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: }
457: printf("file '%s%s%s' %sinserted into database\n", this->dir,
458: get_separator(this->dir), file, this->fid ? "" : "could not be ");
459:
460: return this->fid > 0;
461: }
462:
463: METHOD(attest_db_t, set_fid, bool,
464: private_attest_db_t *this, int fid)
465: {
466: enumerator_t *e;
467: int did;
468: char *file;
469:
470: if (this->fid)
471: {
472: printf("file has already been set\n");
473: return FALSE;
474: }
475:
476: e = this->db->query(this->db, "SELECT dir, name FROM files WHERE id = ?",
477: DB_UINT, fid, DB_INT, DB_TEXT);
478: if (e)
479: {
480: if (e->enumerate(e, &did, &file))
481: {
482: if (did)
483: {
484: set_did(this, did);
485: }
486: this->file = strdup(file);
487: this->fid = fid;
488: }
489: else
490: {
491: printf("no file found with fid %d\n", fid);
492: }
493: e->destroy(e);
494: }
495: return this->fid > 0;
496: }
497:
498: METHOD(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:
514: METHOD(attest_db_t, set_key, bool,
515: private_attest_db_t *this, chunk_t key, bool create)
516: {
517: enumerator_t *e;
518: char *owner;
519:
520: if (this->key_set)
521: {
522: printf("key has already been set\n");
523: return FALSE;
524: }
525: this->key = key;
526:
527: e = this->db->query(this->db, "SELECT id, owner FROM keys WHERE keyid= ?",
528: DB_BLOB, this->key, DB_INT, DB_TEXT);
529: if (e)
530: {
531: if (e->enumerate(e, &this->kid, &owner))
532: {
533: free(this->owner);
534: this->owner = strdup(owner);
535: this->key_set = TRUE;
536: }
537: e->destroy(e);
538: }
539: if (this->key_set)
540: {
541: return TRUE;
542: }
543:
544: if (!create)
545: {
546: printf("key '%#B' not found in database\n", &this->key);
547: return FALSE;
548: }
549:
550: /* Add a new database entry */
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;
558:
559: printf("key '%#B' %sinserted into database\n", &this->key,
560: this->key_set ? "" : "could not be ");
561:
562: return this->key_set;
563:
564: };
565:
566: METHOD(attest_db_t, set_kid, bool,
567: private_attest_db_t *this, int kid)
568: {
569: enumerator_t *e;
570: chunk_t key;
571: char *owner;
572:
573: if (this->key_set)
574: {
575: printf("key has already been set\n");
576: return FALSE;
577: }
578: this->kid = kid;
579:
580: e = this->db->query(this->db, "SELECT keyid, owner FROM keys WHERE id = ?",
581: DB_UINT, kid, DB_BLOB, DB_TEXT);
582: if (e)
583: {
584: if (e->enumerate(e, &key, &owner))
585: {
586: this->owner = strdup(owner);
587: this->key = chunk_clone(key);
588: this->key_set = TRUE;
589: }
590: else
591: {
592: printf("no key found with kid %d\n", kid);
593: }
594: e->destroy(e);
595: }
596: return this->key_set;
597:
598: };
599:
600: METHOD(attest_db_t, set_product, bool,
601: private_attest_db_t *this, char *product, bool create)
602: {
603: enumerator_t *e;
604:
605: if (this->product_set)
606: {
607: printf("product has already been set\n");
608: return FALSE;
609: }
610: this->product = strdup(product);
611:
612: e = this->db->query(this->db, "SELECT id FROM products WHERE name = ?",
613: DB_TEXT, product, DB_INT);
614: if (e)
615: {
616: if (e->enumerate(e, &this->pid))
617: {
618: this->product_set = TRUE;
619: }
620: e->destroy(e);
621: }
622: if (this->product_set)
623: {
624: return TRUE;
625: }
626:
627: if (!create)
628: {
629: printf("product '%s' not found in database\n", product);
630: return FALSE;
631: }
632:
633: /* Add a new database entry */
634: this->product_set = this->db->execute(this->db, &this->pid,
635: "INSERT INTO products (name) VALUES (?)",
636: DB_TEXT, product) == 1;
637:
638: printf("product '%s' %sinserted into database\n", product,
639: this->product_set ? "" : "could not be ");
640:
641: return this->product_set;
642: }
643:
644: METHOD(attest_db_t, set_pid, bool,
645: private_attest_db_t *this, int pid)
646: {
647: enumerator_t *e;
648: char *product;
649:
650: if (this->product_set)
651: {
652: printf("product has already been set\n");
653: return FALSE;
654: }
655: this->pid = pid;
656:
657: e = this->db->query(this->db, "SELECT name FROM products WHERE id = ?",
658: DB_UINT, pid, DB_TEXT);
659: if (e)
660: {
661: if (e->enumerate(e, &product))
662: {
663: this->product = strdup(product);
664: this->product_set = TRUE;
665: }
666: else
667: {
668: printf("no product found with pid %d in database\n", pid);
669: }
670: e->destroy(e);
671: }
672: return this->product_set;
673: }
674:
675: METHOD(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:
719: METHOD(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:
750: METHOD(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:
765: METHOD(attest_db_t, set_algo, void,
766: private_attest_db_t *this, pts_meas_algorithms_t algo)
767: {
768: this->algo = algo;
769: }
770:
771: METHOD(attest_db_t, set_relative, void,
772: private_attest_db_t *this)
773: {
774: this->relative = TRUE;
775: }
776:
777: METHOD(attest_db_t, set_package_state, void,
778: private_attest_db_t *this, os_package_state_t package_state)
779: {
780: this->package_state = package_state;
781: }
782:
783: METHOD(attest_db_t, set_sequence, void,
784: private_attest_db_t *this, int seq_no)
785: {
786: this->seq_no = seq_no;
787: }
788:
789: METHOD(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:
796: METHOD(attest_db_t, set_utc, void,
797: private_attest_db_t *this)
798: {
799: this->utc = TRUE;
800: }
801:
802: METHOD(attest_db_t, list_components, void,
803: private_attest_db_t *this)
804: {
805: enumerator_t *e;
806: pts_comp_func_name_t *cfn;
807: int seq_no, cid, vid, name, qualifier, count = 0;
808:
809: if (this->kid)
810: {
811: e = this->db->query(this->db,
812: "SELECT kc.seq_no, c.id, c.vendor_id, c.name, c.qualifier "
813: "FROM components AS c "
814: "JOIN key_component AS kc ON c.id = kc.component "
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: }
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);
837: if (e)
838: {
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");
848: }
849: }
850: }
851:
852: METHOD(attest_db_t, list_devices, void,
853: private_attest_db_t *this)
854: {
855: enumerator_t *e, *e_ar;
856: chunk_t ar_id_value = chunk_empty;
857: char *product, *device, *description;
858: time_t timestamp;
859: int id, last_id = 0, ar_id = 0, last_ar_id = 0, device_count = 0, trusted;
860: int session_id, rec;
861: uint32_t ar_id_type;
862: u_int tstamp;
863:
864: e = this->db->query(this->db,
865: "SELECT d.id, d.value, d.trusted, d.description, "
866: "s.id, s.time, s.identity, s.rec, p.name "
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 "
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);
872:
873: if (e)
874: {
875: while (e->enumerate(e, &id, &device, &trusted, &description,
876: &session_id, &tstamp, &ar_id, &rec, &product))
877: {
878: if (id != last_id)
879: {
880: printf("%4d: %s %s - %s - %s\n", id, trusted ? "+" : "-",
881: device, product, description);
882: device_count++;
883: last_id = id;
884: }
885: timestamp = tstamp;
886: printf("%4d: %T", session_id, ×tamp, this->utc);
887: if (ar_id)
888: {
889: if (ar_id != last_ar_id)
890: {
891: chunk_free(&ar_id_value);
892: e_ar = this->db->query(this->db,
893: "SELECT type, value FROM identities "
894: "WHERE id = ?", DB_INT, ar_id, DB_INT, DB_BLOB);
895: if (e_ar)
896: {
897: e_ar->enumerate(e_ar, &ar_id_type, &ar_id_value);
898: ar_id_value = chunk_clone(ar_id_value);
899: e_ar->destroy(e_ar);
900: }
901: }
902: if (ar_id_value.len)
903: {
904: printf(" %.*s", (int)ar_id_value.len, ar_id_value.ptr);
905: }
906: last_ar_id = ar_id;
907: }
908: printf(" - %N\n", TNC_IMV_Action_Recommendation_names, rec);
909: }
910: e->destroy(e);
911: free(ar_id_value.ptr);
912:
913: printf("%d device%s found\n", device_count,
914: (device_count == 1) ? "" : "s");
915: }
916: }
917:
918: METHOD(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",
932: DB_UINT, this->cid, DB_INT, DB_BLOB, DB_TEXT);
933: if (e)
934: {
935: while (e->enumerate(e, &kid, &keyid, &owner))
936: {
937: printf("%4d: %#B '%s'\n", kid, &keyid, owner);
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: {
952: printf("%4d: %#B '%s'\n", kid, &keyid, owner);
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:
967: METHOD(attest_db_t, list_files, void,
968: private_attest_db_t *this)
969: {
970: enumerator_t *e;
971: char *dir, *file;
972: int did, last_did = 0, fid, count = 0;
973:
974: if (this->did)
975: {
976: e = this->db->query(this->db,
977: "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
978: DB_INT, this->did, DB_INT, DB_TEXT);
979: if (e)
980: {
981: while (e->enumerate(e, &fid, &file))
982: {
983: printf("%6d: %s\n", fid, file);
984: count++;
985: }
986: e->destroy(e);
987: }
988: printf("%d file%s found in directory '%s'\n", count,
989: (count == 1) ? "" : "s", this->dir);
990: }
991: else
992: {
993: e = this->db->query(this->db,
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);
998: if (e)
999: {
1000: while (e->enumerate(e, &did, &dir, &fid, &file))
1001: {
1002: if (did != last_did)
1003: {
1004: printf("%6d: %s\n", did, dir);
1005: last_did = did;
1006: }
1007: printf("%6d: %s\n", fid, file);
1008: count++;
1009: }
1010: e->destroy(e);
1011: }
1012: printf("%d file%s found\n", count, (count == 1) ? "" : "s");
1013: }
1014: }
1015:
1016: METHOD(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)
1024: {
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");
1056: }
1057: }
1058:
1059: METHOD(attest_db_t, list_packages, void,
1060: private_attest_db_t *this)
1061: {
1062: enumerator_t *e;
1063: char *package, *version;
1064: os_package_state_t package_state;
1065: int blacklist, security, gid, gid_old = 0, spaces, count = 0, t;
1066: time_t timestamp;
1067:
1068: if (this->pid)
1069: {
1070: e = this->db->query(this->db,
1071: "SELECT p.id, p.name, "
1072: "v.release, v.security, v.blacklist, v.time "
1073: "FROM packages AS p JOIN versions AS v ON v.package = p.id "
1074: "WHERE v.product = ? ORDER BY p.name, v.release",
1075: DB_INT, this->pid,
1076: DB_INT, DB_TEXT, DB_TEXT, DB_INT, DB_INT, DB_INT);
1077: if (e)
1078: {
1079: while (e->enumerate(e, &gid, &package,
1080: &version, &security, &blacklist, &t))
1081: {
1082: if (gid != gid_old)
1083: {
1084: printf("%5d: %s,", gid, package);
1085: gid_old = gid;
1086: }
1087: else
1088: {
1089: spaces = 8 + strlen(package);
1090: while (spaces--)
1091: {
1092: printf(" ");
1093: }
1094: }
1095: timestamp = t;
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: }
1105: printf(" %T (%s)%N\n", ×tamp, this->utc, version,
1106: os_package_state_names, package_state);
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:
1136: METHOD(attest_db_t, list_products, void,
1137: private_attest_db_t *this)
1138: {
1139: enumerator_t *e;
1140: char *product;
1141: int pid, meas, meta, count = 0;
1142:
1143: if (this->fid)
1144: {
1145: e = this->db->query(this->db,
1146: "SELECT p.id, p.name, pf.measurement, pf.metadata "
1147: "FROM products AS p "
1148: "JOIN product_file AS pf ON p.id = pf.product "
1149: "WHERE pf.file = ? ORDER BY p.name",
1150: DB_UINT, this->fid, DB_INT, DB_TEXT, DB_INT, DB_INT);
1151: if (e)
1152: {
1153: while (e->enumerate(e, &pid, &product, &meas, &meta))
1154: {
1155: printf("%4d: |%s%s| %s\n", pid, meas ? "M":" ", meta ? "T":" ",
1156: product);
1157: count++;
1158: }
1159: e->destroy(e);
1160: }
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);
1167: if (e)
1168: {
1169: while (e->enumerate(e, &pid, &product))
1170: {
1171: printf("%4d: %s\n", pid, product);
1172: count++;
1173: }
1174: e->destroy(e);
1175: }
1176: }
1177:
1178: printf("%d product%s found", count, (count == 1) ? "" : "s");
1179: if (this->fid)
1180: {
1181: printf(" for file '%s'", this->file);
1182: }
1183: printf("\n");
1184: }
1185:
1186: METHOD(attest_db_t, list_hashes, void,
1187: private_attest_db_t *this)
1188: {
1189: enumerator_t *e;
1190: char *file, *dir, *product, *hash;
1191: int id, fid, fid_old = 0, did, did_old = 0, pid, pid_old = 0, count = 0;
1192:
1193: if (this->pid && this->fid && this->did)
1194: {
1195: printf("%6d: %s\n", this->did, this->dir);
1196: printf("%6d: %s\n", this->fid, this->file);
1197: e = this->db->query(this->db,
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 = ?",
1201: DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->pid,
1202: DB_INT, DB_TEXT);
1203: if (e)
1204: {
1205: while (e->enumerate(e, &id, &hash))
1206: {
1207: printf("%6d: %s\n", id, hash);
1208: count++;
1209: }
1210: e->destroy(e);
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);
1215: }
1216: }
1217: else if (this->pid && this->file)
1218: {
1219: e = this->db->query(this->db,
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 "
1224: "JOIN versions AS v ON h.version = v.id "
1225: "WHERE h.algo = ? AND v.product = ? AND f.name = ? "
1226: "ORDER BY d.path, f.name, h.hash",
1227: DB_INT, this->algo, DB_INT, this->pid, DB_TEXT, this->file,
1228: DB_INT, DB_TEXT, DB_INT, DB_INT, DB_TEXT);
1229: if (e)
1230: {
1231: while (e->enumerate(e, &id, &hash, &fid, &did, &dir))
1232: {
1233: if (did != did_old)
1234: {
1235: printf("%6d: %s\n", did, dir);
1236: did_old = did;
1237: }
1238: if (fid != fid_old)
1239: {
1240: printf("%6d: %s\n", fid, this->file);
1241: fid_old = fid;
1242: }
1243: printf("%6d: %s\n", id, hash);
1244: count++;
1245: }
1246: e->destroy(e);
1247:
1248: printf("%d %N value%s found for product '%s'\n", count,
1249: pts_meas_algorithm_names, this->algo,
1250: (count == 1) ? "" : "s", this->product);
1251: }
1252: }
1253: else if (this->pid && this->did)
1254: {
1255: printf("%6d: %s\n", this->did, this->dir);
1256: e = this->db->query(this->db,
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 "
1260: "JOIN versions AS v ON h.version = v.id "
1261: "WHERE h.algo = ? AND v.product = ? AND f.dir = ? "
1262: "ORDER BY f.name, h.hash",
1263: DB_INT, this->algo, DB_INT, this->pid, DB_INT, this->did,
1264: DB_INT, DB_TEXT, DB_INT, DB_TEXT);
1265: if (e)
1266: {
1267: while (e->enumerate(e, &id, &hash, &fid, &file))
1268: {
1269: if (fid != fid_old)
1270: {
1271: printf("%6d: %s\n", fid, file);
1272: fid_old = fid;
1273: }
1274: printf("%6d: %s\n", id, hash);
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);
1282: }
1283: }
1284: else if (this->pid)
1285: {
1286: e = this->db->query(this->db,
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 "
1291: "JOIN versions AS v ON h.version = v.id "
1292: "WHERE h.algo = ? AND v.product = ? "
1293: "ORDER BY d.path, f.name, h.hash",
1294: DB_INT, this->algo, DB_INT, this->pid,
1295: DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
1296: if (e)
1297: {
1298: while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir))
1299: {
1300: if (did != did_old)
1301: {
1302: printf("%6d: %s\n", did, dir);
1303: did_old = did;
1304: }
1305: if (fid != fid_old)
1306: {
1307: printf("%6d: %s\n", fid, file);
1308: fid_old = fid;
1309: }
1310: printf("%6d: %s\n", id, hash);
1311: count++;
1312: }
1313: e->destroy(e);
1314:
1315: printf("%d %N value%s found for product '%s'\n", count,
1316: pts_meas_algorithm_names, this->algo,
1317: (count == 1) ? "" : "s", this->product);
1318: }
1319: }
1320: else if (this->fid && this->did)
1321: {
1322: e = this->db->query(this->db,
1323: "SELECT h.id, h.hash, p.id, p.name FROM file_hashes AS h "
1324: "JOIN versions AS v ON h.version = v.id "
1325: "JOIN products AS p ON v.product = p.id "
1326: "WHERE h.algo = ? AND h.file = ? "
1327: "ORDER BY p.name, h.hash",
1328: DB_INT, this->algo, DB_INT, this->fid,
1329: DB_INT, DB_TEXT, DB_INT, DB_TEXT);
1330: if (e)
1331: {
1332: while (e->enumerate(e, &id, &hash, &pid, &product))
1333: {
1334: if (pid != pid_old)
1335: {
1336: printf("%6d: %s\n", pid, product);
1337: pid_old = pid;
1338: }
1339: printf("%6d: %s\n", id, hash);
1340: count++;
1341: }
1342: e->destroy(e);
1343:
1344: printf("%d %N value%s found for file '%s%s%s'\n", count,
1345: pts_meas_algorithm_names, this->algo,
1346: (count == 1) ? "" : "s", this->dir,
1347: get_separator(this->dir), this->file);
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 "
1357: "JOIN versions AS v ON h.version = v.id "
1358: "JOIN products AS p ON v.product = p.id "
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,
1362: DB_INT, DB_TEXT, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
1363: if (e)
1364: {
1365: while (e->enumerate(e, &id, &hash, &fid, &did, &dir, &pid, &product))
1366: {
1367: if (did != did_old)
1368: {
1369: printf("%6d: %s\n", did, dir);
1370: did_old = did;
1371: }
1372: if (fid != fid_old)
1373: {
1374: printf("%6d: %s\n", fid, this->file);
1375: fid_old = fid;
1376: pid_old = 0;
1377: }
1378: if (pid != pid_old)
1379: {
1380: printf("%6d: %s\n", pid, product);
1381: pid_old = pid;
1382: }
1383: printf("%6d: %s\n", id, hash);
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 "
1399: "JOIN versions AS v ON h.version = v.id "
1400: "JOIN products AS p ON v.product = p.id "
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,
1404: DB_INT, DB_TEXT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
1405: if (e)
1406: {
1407: while (e->enumerate(e, &id, &hash, &fid, &file, &pid, &product))
1408: {
1409: if (fid != fid_old)
1410: {
1411: printf("%6d: %s\n", fid, file);
1412: fid_old = fid;
1413: pid_old = 0;
1414: }
1415: if (pid != pid_old)
1416: {
1417: printf("%6d: %s\n", pid, product);
1418: pid_old = pid;
1419: }
1420: printf("%6d: %s\n", id, hash);
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);
1428: }
1429: }
1430: else
1431: {
1432: e = this->db->query(this->db,
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 "
1437: "JOIN versions AS v ON h.version = v.id "
1438: "JOIN products AS p on v.product = p.id "
1439: "WHERE h.algo = ? "
1440: "ORDER BY d.path, f.name, p.name, h.hash",
1441: DB_INT, this->algo, DB_INT, DB_TEXT, DB_INT, DB_TEXT,
1442: DB_INT, DB_TEXT, DB_INT, DB_TEXT);
1443: if (e)
1444: {
1445: while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir, &pid,
1446: &product))
1447: {
1448: if (did != did_old)
1449: {
1450: printf("%6d: %s\n", did, dir);
1451: did_old = did;
1452: }
1453: if (fid != fid_old)
1454: {
1455: printf("%6d: %s\n", fid, file);
1456: fid_old = fid;
1457: pid_old = 0;
1458: }
1459: if (pid != pid_old)
1460: {
1461: printf("%6d: %s\n", pid, product);
1462: pid_old = pid;
1463: }
1464: printf("%6d: %s\n", id, hash);
1465: count++;
1466: }
1467: e->destroy(e);
1468:
1469: printf("%d %N value%s found\n", count, pts_meas_algorithm_names,
1470: this->algo, (count == 1) ? "" : "s");
1471: }
1472: }
1473: }
1474:
1475: METHOD(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",
1493: DB_INT, this->algo, DB_UINT, this->kid, DB_UINT, this->cid,
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: {
1501: printf("%4d: %#B '%s'\n", this->kid, &this->key, owner);
1502: kid_old = this->kid;
1503: }
1504: printf("%7d %02d %#B\n", seq_no, pcr, &hash);
1505: count++;
1506: }
1507: e->destroy(e);
1508:
1509: printf("%d %N value%s found for component '%s'\n", count,
1510: pts_meas_algorithm_names, this->algo,
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",
1522: DB_INT, this->algo, DB_UINT, this->cid,
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: {
1530: printf("%4d: %#B '%s'\n", kid, &keyid, owner);
1531: kid_old = kid;
1532: }
1533: printf("%7d %02d %#B\n", seq_no, pcr, &hash);
1534: count++;
1535: }
1536: e->destroy(e);
1537:
1538: printf("%d %N value%s found for component '%s'\n", count,
1539: pts_meas_algorithm_names, this->algo,
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",
1553: DB_INT, this->algo, DB_UINT, this->kid, DB_INT, DB_INT, DB_BLOB,
1554: DB_INT, DB_INT, DB_INT, DB_INT);
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);
1563: printf("%4d: %s\n", cid, print_cfn(cfn));
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,
1573: pts_meas_algorithm_names, this->algo,
1574: (count == 1) ? "" : "s", &this->key, this->owner);
1575: }
1576: }
1577: }
1578:
1579: METHOD(attest_db_t, list_sessions, void,
1580: private_attest_db_t *this)
1581: {
1582: enumerator_t *e;
1583: chunk_t identity;
1584: char *product, *device;
1585: int session_id, conn_id, rec, device_len;
1586: time_t created;
1587: u_int t;
1588:
1589: e = this->db->query(this->db,
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",
1596: DB_INT, DB_UINT, DB_INT, DB_INT, DB_TEXT, DB_TEXT, DB_BLOB);
1597: if (e)
1598: {
1599: while (e->enumerate(e, &session_id, &t, &conn_id, &rec, &product,
1600: &device, &identity))
1601: {
1602: created = t;
1603: product = product ? product : "-";
1604: device = strlen(device) ? device : "-";
1605: device_len = min(strlen(device), DEVICE_MAX_LEN);
1606: identity = identity.len ? identity : chunk_from_str("-");
1607: printf("%4d: %T %2d %-20s %.*s%*s%.*s - %N\n", session_id, &created,
1608: this->utc, conn_id, product, device_len, device,
1609: DEVICE_MAX_LEN - device_len + 1, " ", (int)identity.len,
1610: identity.ptr, TNC_IMV_Action_Recommendation_names, rec);
1611: }
1612: e->destroy(e);
1613: }
1614: }
1615:
1616: /**
1617: * Insert a file hash into the database
1618: */
1619: static bool insert_file_hash(private_attest_db_t *this,
1620: pts_meas_algorithms_t algo,
1621: chunk_t measurement, int fid,
1622: int *hashes_added, int *hashes_updated)
1623: {
1624: enumerator_t *e;
1625: uint8_t hex_measurement_buf[2*HASH_SIZE_SHA512 + 1];
1626: uint8_t *hex_hash_buf;
1627: chunk_t hex_hash, hex_measurement;
1628: char *label;
1629: bool insert = TRUE, update = FALSE;
1630:
1631: label = "could not be created";
1632:
1633: e = this->db->query(this->db,
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);
1637:
1638: if (!e)
1639: {
1640: printf("file_hashes query failed\n");
1641: return FALSE;
1642: }
1643: hex_measurement = chunk_to_hex(measurement, hex_measurement_buf, FALSE);
1644:
1645: while (e->enumerate(e, &hex_hash_buf))
1646: {
1647: update = TRUE;
1648: hex_hash = chunk_from_str(hex_hash_buf);
1649:
1650: if (chunk_equals(hex_measurement, hex_hash))
1651: {
1652: label = "exists and equals";
1653: insert = FALSE;
1654: break;
1655: }
1656: }
1657: e->destroy(e);
1658:
1659: if (insert)
1660: {
1661: if (this->db->execute(this->db, NULL,
1662: "INSERT INTO file_hashes "
1663: "(file, version, algo, hash) "
1664: "VALUES (?, ?, ?, ?)",
1665: DB_UINT, fid, DB_UINT, this->vid,
1666: DB_INT, algo, DB_TEXT, hex_measurement) != 1)
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
1677: {
1678: label = "created";
1679: (*hashes_added)++;
1680: }
1681: }
1682: printf(" %#B - %s\n", &measurement, label);
1683: return TRUE;
1684: }
1685:
1686: /**
1687: * Add a package version
1688: */
1689: static 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:
1755: /**
1756: * Add hash measurement for a single file or all files in a directory
1757: */
1758: static bool add_hash(private_attest_db_t *this)
1759: {
1760: char *pathname, *filename, *label;
1761: const char *sep;
1762: pts_file_meas_t *measurements;
1763: chunk_t measurement;
1764: hasher_t *hasher = NULL;
1765: int fid, files_added = 0, hashes_added = 0, hashes_updated = 0;
1766: enumerator_t *enumerator, *e;
1767:
1768: if (!this->meas_dir)
1769: {
1770: this->meas_dir = strdup(this->dir);
1771: }
1772: sep = get_separator(this->meas_dir);
1773:
1774: if (this->fid)
1775: {
1776: /* build pathname from directory path and relative filename */
1777: if (asprintf(&pathname, "%s%s%s", this->meas_dir, sep, this->file) == -1)
1778: {
1779: return FALSE;
1780: }
1781: measurements = pts_file_meas_create_from_path(0, pathname, FALSE,
1782: TRUE, this->algo);
1783: free(pathname);
1784: }
1785: else
1786: {
1787: measurements = pts_file_meas_create_from_path(0, this->meas_dir, TRUE,
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)
1801: {
1802: /* a single file already exists */
1803: filename = this->file;
1804: fid = this->fid;
1805: label = "exists";
1806: }
1807: else
1808: {
1809: /* retrieve or create filename */
1810: label = "could not be created";
1811:
1812: e = this->db->query(this->db,
1813: "SELECT id FROM files WHERE name = ? AND dir = ?",
1814: DB_TEXT, filename, DB_INT, this->did, DB_INT);
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,
1827: "INSERT INTO files (name, dir) VALUES (?, ?)",
1828: DB_TEXT, filename, DB_INT, this->did) == 1)
1829: {
1830: label = "created";
1831: files_added++;
1832: }
1833: }
1834: e->destroy(e);
1835: }
1836: printf("%4d: %s - %s\n", fid, filename, label);
1837:
1838: /* compute file measurement hash */
1839: if (!insert_file_hash(this, this->algo, measurement, fid,
1840: &hashes_added, &hashes_updated))
1841: {
1842: break;
1843: }
1844: }
1845: enumerator->destroy(enumerator);
1846:
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);
1851: measurements->destroy(measurements);
1852:
1853: return TRUE;
1854: }
1855:
1856: METHOD(attest_db_t, add, bool,
1857: private_attest_db_t *this)
1858: {
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: }
1867:
1868: /* add directory or file hash measurement for a given product */
1869: if (this->did && this->pid)
1870: {
1871: return add_hash(this);
1872: }
1873:
1874: return FALSE;
1875: }
1876:
1877: METHOD(attest_db_t, delete, bool,
1878: private_attest_db_t *this)
1879: {
1880: bool success;
1881: int id, count = 0;
1882: char *name;
1883: enumerator_t *e;
1884:
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,
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 = ?",
1892: DB_UINT, this->algo, DB_UINT, this->pid,
1893: DB_UINT, this->fid) > 0;
1894:
1895: printf("%4d: %s%s%s\n", this->fid, this->dir, get_separator(this->dir),
1896: this->file);
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:
1904: /* delete product/file entries */
1905: if (this->pid && (this->fid || this->did))
1906: {
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;
1918: }
1919:
1920: if (this->cid)
1921: {
1922: success = this->db->execute(this->db, NULL,
1923: "DELETE FROM components WHERE id = ?",
1924: DB_UINT, this->cid) > 0;
1925:
1926: printf("component '%s' %sdeleted from database\n", print_cfn(this->cfn),
1927: success ? "" : "could not be ");
1928: return success;
1929: }
1930:
1931: if (this->fid)
1932: {
1933: success = this->db->execute(this->db, NULL,
1934: "DELETE FROM files WHERE id = ?",
1935: DB_UINT, this->fid) > 0;
1936:
1937: printf("file '%s%s%s' %sdeleted from database\n", this->dir,
1938: get_separator(this->dir), this->file,
1939: success ? "" : "could not be ");
1940: return success;
1941: }
1942:
1943: if (this->did)
1944: {
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);
1956:
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,
1969: success ? "" : "could not be ");
1970: return success;
1971: }
1972:
1973: if (this->kid)
1974: {
1975: success = this->db->execute(this->db, NULL,
1976: "DELETE FROM keys WHERE id = ?",
1977: DB_UINT, this->kid) > 0;
1978:
1979: printf("key %#B %sdeleted from database\n", &this->key,
1980: success ? "" : "could not be ");
1981: return success;
1982: }
1983: if (this->pid)
1984: {
1985: success = this->db->execute(this->db, NULL,
1986: "DELETE FROM products WHERE id = ?",
1987: DB_UINT, this->pid) > 0;
1988:
1989: printf("product '%s' %sdeleted from database\n", this->product,
1990: success ? "" : "could not be ");
1991: return success;
1992: }
1993:
1994: printf("empty delete command\n");
1995: return FALSE;
1996: }
1997:
1998: METHOD(attest_db_t, destroy, void,
1999: private_attest_db_t *this)
2000: {
2001: DESTROY_IF(this->db);
2002: DESTROY_IF(this->cfn);
2003: free(this->package);
2004: free(this->product);
2005: free(this->version);
2006: free(this->file);
2007: free(this->dir);
2008: free(this->meas_dir);
2009: free(this->owner);
2010: free(this->key.ptr);
2011: free(this);
2012: }
2013:
2014: /**
2015: * Described in header.
2016: */
2017: attest_db_t *attest_db_create(char *uri)
2018: {
2019: private_attest_db_t *this;
2020:
2021: INIT(this,
2022: .public = {
2023: .set_component = _set_component,
2024: .set_cid = _set_cid,
2025: .set_directory = _set_directory,
2026: .set_did = _set_did,
2027: .set_file = _set_file,
2028: .set_fid = _set_fid,
2029: .set_meas_directory = _set_meas_directory,
2030: .set_key = _set_key,
2031: .set_kid = _set_kid,
2032: .set_package = _set_package,
2033: .set_gid = _set_gid,
2034: .set_product = _set_product,
2035: .set_pid = _set_pid,
2036: .set_version = _set_version,
2037: .set_algo = _set_algo,
2038: .set_relative = _set_relative,
2039: .set_package_state = _set_package_state,
2040: .set_sequence = _set_sequence,
2041: .set_owner = _set_owner,
2042: .set_utc = _set_utc,
2043: .list_packages = _list_packages,
2044: .list_products = _list_products,
2045: .list_files = _list_files,
2046: .list_directories = _list_directories,
2047: .list_components = _list_components,
2048: .list_devices = _list_devices,
2049: .list_keys = _list_keys,
2050: .list_hashes = _list_hashes,
2051: .list_measurements = _list_measurements,
2052: .list_sessions = _list_sessions,
2053: .add = _add,
2054: .delete = _delete,
2055: .destroy = _destroy,
2056: },
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>