Annotation of embedaddon/strongswan/src/libimcv/plugins/imv_attestation/attest_db.c, revision 1.1.1.2

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);
1.1.1.2 ! misho     340:        if (len > 1 && path_is_separator(dir[len-1]))
1.1       misho     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, &timestamp, 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", &timestamp, 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>