Annotation of embedaddon/strongswan/src/libimcv/pts/pts_file_meas.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2011 Sansar Choinyambuu
        !             3:  * Copyright (C) 2014 Andreas Steffen
        !             4:  * HSR Hochschule fuer Technik Rapperswil
        !             5:  *
        !             6:  * This program is free software; you can redistribute it and/or modify it
        !             7:  * under the terms of the GNU General Public License as published by the
        !             8:  * Free Software Foundation; either version 2 of the License, or (at your
        !             9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            10:  *
        !            11:  * This program is distributed in the hope that it will be useful, but
        !            12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            14:  * for more details.
        !            15:  */
        !            16: 
        !            17: #include "pts_file_meas.h"
        !            18: 
        !            19: #include <collections/linked_list.h>
        !            20: #include <utils/debug.h>
        !            21: 
        !            22: #include <sys/stat.h>
        !            23: #include <libgen.h>
        !            24: #include <errno.h>
        !            25: 
        !            26: typedef struct private_pts_file_meas_t private_pts_file_meas_t;
        !            27: 
        !            28: /**
        !            29:  * Private data of a pts_file_meas_t object.
        !            30:  *
        !            31:  */
        !            32: struct private_pts_file_meas_t {
        !            33: 
        !            34:        /**
        !            35:         * Public pts_file_meas_t interface.
        !            36:         */
        !            37:        pts_file_meas_t public;
        !            38: 
        !            39:        /**
        !            40:         * ID of PTS File Measurement Request
        !            41:         */
        !            42:        uint16_t request_id;
        !            43: 
        !            44:        /**
        !            45:         * List of File Measurements
        !            46:         */
        !            47:        linked_list_t *list;
        !            48: };
        !            49: 
        !            50: typedef struct entry_t entry_t;
        !            51: 
        !            52: /**
        !            53:  * PTS File Measurement entry
        !            54:  */
        !            55: struct entry_t {
        !            56:        char     *filename;
        !            57:        chunk_t  measurement;
        !            58: };
        !            59: 
        !            60: /**
        !            61:  * Free an entry_t object
        !            62:  */
        !            63: static void free_entry(entry_t *entry)
        !            64: {
        !            65:        if (entry)
        !            66:        {
        !            67:                free(entry->filename);
        !            68:                free(entry->measurement.ptr);
        !            69:                free(entry);
        !            70:        }
        !            71: }
        !            72: 
        !            73: METHOD(pts_file_meas_t, get_request_id, uint16_t,
        !            74:        private_pts_file_meas_t *this)
        !            75: {
        !            76:        return this->request_id;
        !            77: }
        !            78: 
        !            79: METHOD(pts_file_meas_t, get_file_count, int,
        !            80:        private_pts_file_meas_t *this)
        !            81: {
        !            82:        return this->list->get_count(this->list);
        !            83: }
        !            84: 
        !            85: METHOD(pts_file_meas_t, add, void,
        !            86:        private_pts_file_meas_t *this, char *filename, chunk_t measurement)
        !            87: {
        !            88:        entry_t *entry;
        !            89: 
        !            90:        entry = malloc_thing(entry_t);
        !            91:        entry->filename = strdup(filename);
        !            92:        entry->measurement = chunk_clone(measurement);
        !            93: 
        !            94:        this->list->insert_last(this->list, entry);
        !            95: }
        !            96: 
        !            97: CALLBACK(entry_filter, bool,
        !            98:        void *null, enumerator_t *orig, va_list args)
        !            99: {
        !           100:        entry_t *entry;
        !           101:        chunk_t *measurement;
        !           102:        char **filename;
        !           103: 
        !           104:        VA_ARGS_VGET(args, filename, measurement);
        !           105: 
        !           106:        if (orig->enumerate(orig, &entry))
        !           107:        {
        !           108:                *filename = entry->filename;
        !           109:                *measurement = entry->measurement;
        !           110:                return TRUE;
        !           111:        }
        !           112:        return FALSE;
        !           113: }
        !           114: 
        !           115: METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
        !           116:        private_pts_file_meas_t *this)
        !           117: {
        !           118:        return enumerator_create_filter(this->list->create_enumerator(this->list),
        !           119:                                                                        entry_filter, NULL, NULL);
        !           120: }
        !           121: 
        !           122: METHOD(pts_file_meas_t, check, bool,
        !           123:        private_pts_file_meas_t *this, pts_database_t *pts_db, int pid,
        !           124:        pts_meas_algorithms_t algo)
        !           125: {
        !           126:        enumerator_t *enumerator, *e;
        !           127:        entry_t *entry;
        !           128:        chunk_t hash;
        !           129:        int count_ok = 0, count_not_found = 0, count_differ = 0;
        !           130:        status_t status;
        !           131: 
        !           132:        enumerator = this->list->create_enumerator(this->list);
        !           133:        while (enumerator->enumerate(enumerator, &entry))
        !           134:        {
        !           135:                status = NOT_FOUND;
        !           136: 
        !           137:                e = pts_db->create_file_meas_enumerator(pts_db, pid, algo,
        !           138:                                                                                                entry->filename);
        !           139:                if (e)
        !           140:                {
        !           141:                        while (e->enumerate(e, &hash))
        !           142:                        {
        !           143:                                if (chunk_equals(entry->measurement, hash))
        !           144:                                {
        !           145:                                        status = SUCCESS;
        !           146:                                        break;
        !           147:                                }
        !           148:                                else
        !           149:                                {
        !           150:                                        status = VERIFY_ERROR;
        !           151:                                }
        !           152:                        }
        !           153:                        e->destroy(e);
        !           154:                }
        !           155:                else
        !           156:                {
        !           157:                        status = FAILED;
        !           158:                }
        !           159: 
        !           160:                switch (status)
        !           161:                {
        !           162:                        case SUCCESS:
        !           163:                                DBG3(DBG_PTS, "  %#B for '%s' is ok", &entry->measurement,
        !           164:                                                                                                           entry->filename);
        !           165:                                count_ok++;
        !           166:                                break;
        !           167:                        case NOT_FOUND:
        !           168:                                DBG2(DBG_PTS, "  %#B for '%s' not found", &entry->measurement,
        !           169:                                                                                                                   entry->filename);
        !           170:                                count_not_found++;
        !           171:                                break;
        !           172:                        case VERIFY_ERROR:
        !           173:                                DBG1(DBG_PTS, "  %#B for '%s' differs", &entry->measurement,
        !           174:                                                                                                                 entry->filename);
        !           175:                                count_differ++;
        !           176:                                break;
        !           177:                        case FAILED:
        !           178:                        default:
        !           179:                                DBG1(DBG_PTS, "  %#B for '%s' failed", &entry->measurement,
        !           180:                                                                                                                entry->filename);
        !           181:                }
        !           182:        }
        !           183:        enumerator->destroy(enumerator);
        !           184: 
        !           185:        DBG1(DBG_PTS, "%d measurements, %d ok, %d not found, %d differ",
        !           186:                 this->list->get_count(this->list),
        !           187:                 count_ok, count_not_found, count_differ);
        !           188:        return TRUE;
        !           189: }
        !           190: 
        !           191: METHOD(pts_file_meas_t, verify, bool,
        !           192:        private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
        !           193: {
        !           194:        int fid, fid_last = 0;
        !           195:        char *filename;
        !           196:        uint8_t measurement_buf[HASH_SIZE_SHA512], *hex_meas_buf;
        !           197:        chunk_t measurement, hex_meas;
        !           198:        entry_t *entry;
        !           199:        enumerator_t *enumerator = NULL;
        !           200:        bool found = FALSE, match = FALSE, success = TRUE;
        !           201: 
        !           202:        while (e_hash->enumerate(e_hash, &fid, &filename, &hex_meas_buf))
        !           203:        {
        !           204:                if (fid != fid_last)
        !           205:                {
        !           206:                        if (found && !match)
        !           207:                        {
        !           208:                                /* no matching hash value found for last filename */
        !           209:                                success = FALSE;
        !           210:                                DBG1(DBG_PTS, "  %#B for '%s' is incorrect",
        !           211:                                         &entry->measurement, entry->filename);
        !           212:                                enumerator->destroy(enumerator);
        !           213:                        }
        !           214: 
        !           215:                        /* get a new filename from the database */
        !           216:                        found = FALSE;
        !           217:                        match = FALSE;
        !           218:                        fid_last = fid;
        !           219: 
        !           220:                        /**
        !           221:                         * check if we find an entry for this filename
        !           222:                         * in the PTS measurement list
        !           223:                        */
        !           224:                        enumerator = this->list->create_enumerator(this->list);
        !           225:                        while (enumerator->enumerate(enumerator, &entry))
        !           226:                        {
        !           227:                                if (!is_dir || streq(filename, entry->filename))
        !           228:                                {
        !           229:                                        found = TRUE;
        !           230:                                        break;
        !           231:                                }
        !           232:                        }
        !           233: 
        !           234:                        /* no PTS measurement returned for this filename */
        !           235:                        if (!found)
        !           236:                        {
        !           237:                                success = FALSE;
        !           238:                                DBG1(DBG_PTS, "  no measurement found for '%s'", filename);
        !           239:                                enumerator->destroy(enumerator);
        !           240:                        }
        !           241:                }
        !           242: 
        !           243:                if (found && !match)
        !           244:                {
        !           245:                        hex_meas = chunk_from_str(hex_meas_buf);
        !           246:                        measurement = chunk_from_hex(hex_meas, measurement_buf);
        !           247: 
        !           248:                        if (chunk_equals(measurement, entry->measurement))
        !           249:                        {
        !           250:                                match = TRUE;
        !           251:                                DBG2(DBG_PTS, "  %#B for '%s' is ok",
        !           252:                                         &entry->measurement, entry->filename);
        !           253:                                enumerator->destroy(enumerator);
        !           254:                        }
        !           255:                }
        !           256:        }
        !           257: 
        !           258:        if (found && !match)
        !           259:        {
        !           260:                /* no matching hash value found for the very last filename */
        !           261:                success = FALSE;
        !           262:                DBG1(DBG_PTS, "  %#B for '%s' is incorrect",
        !           263:                         &entry->measurement, entry->filename);
        !           264:                        enumerator->destroy(enumerator);
        !           265:        }
        !           266: 
        !           267:        return success;
        !           268: }
        !           269: 
        !           270: METHOD(pts_file_meas_t, destroy, void,
        !           271:        private_pts_file_meas_t *this)
        !           272: {
        !           273:        this->list->destroy_function(this->list, (void *)free_entry);
        !           274:        free(this);
        !           275: }
        !           276: 
        !           277: /**
        !           278:  * See header
        !           279:  */
        !           280: pts_file_meas_t *pts_file_meas_create(uint16_t request_id)
        !           281: {
        !           282:        private_pts_file_meas_t *this;
        !           283: 
        !           284:        INIT(this,
        !           285:                .public = {
        !           286:                        .get_request_id = _get_request_id,
        !           287:                        .get_file_count = _get_file_count,
        !           288:                        .add = _add,
        !           289:                        .create_enumerator = _create_enumerator,
        !           290:                        .check = _check,
        !           291:                        .verify = _verify,
        !           292:                        .destroy = _destroy,
        !           293:                },
        !           294:                .request_id = request_id,
        !           295:                .list = linked_list_create(),
        !           296:        );
        !           297: 
        !           298:        return &this->public;
        !           299: }
        !           300: 
        !           301: /**
        !           302:  * Hash a file with a given absolute pathname
        !           303:  */
        !           304: static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash)
        !           305: {
        !           306:        u_char buffer[4096];
        !           307:        size_t bytes_read;
        !           308:        bool success = TRUE;
        !           309:        FILE *file;
        !           310: 
        !           311:        file = fopen(pathname, "rb");
        !           312:        if (!file)
        !           313:        {
        !           314:                DBG1(DBG_PTS,"  file '%s' can not be opened, %s", pathname,
        !           315:                         strerror(errno));
        !           316:                return FALSE;
        !           317:        }
        !           318:        while (TRUE)
        !           319:        {
        !           320:                bytes_read = fread(buffer, 1, sizeof(buffer), file);
        !           321:                if (bytes_read > 0)
        !           322:                {
        !           323:                        if (!hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL))
        !           324:                        {
        !           325:                                DBG1(DBG_PTS, "  hasher increment error");
        !           326:                                success = FALSE;
        !           327:                                break;
        !           328:                        }
        !           329:                }
        !           330:                else
        !           331:                {
        !           332:                        if (!hasher->get_hash(hasher, chunk_empty, hash))
        !           333:                        {
        !           334:                                DBG1(DBG_PTS, "  hasher finalize error");
        !           335:                                success = FALSE;
        !           336:                        }
        !           337:                        break;
        !           338:                }
        !           339:        }
        !           340:        fclose(file);
        !           341: 
        !           342:        return success;
        !           343: }
        !           344: 
        !           345: /**
        !           346:  * See header
        !           347:  */
        !           348: pts_file_meas_t *pts_file_meas_create_from_path(uint16_t request_id,
        !           349:                                                        char *pathname, bool is_dir, bool use_rel_name,
        !           350:                                                        pts_meas_algorithms_t alg)
        !           351: {
        !           352:        private_pts_file_meas_t *this;
        !           353:        hash_algorithm_t hash_alg;
        !           354:        hasher_t *hasher;
        !           355:        u_char hash[HASH_SIZE_SHA384];
        !           356:        chunk_t measurement;
        !           357:        char* filename;
        !           358:        bool success = TRUE;
        !           359: 
        !           360:        /* Create a hasher and a hash measurement buffer */
        !           361:        hash_alg = pts_meas_algo_to_hash(alg);
        !           362:        hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
        !           363:        if (!hasher)
        !           364:        {
        !           365:                DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
        !           366:                return NULL;
        !           367:        }
        !           368:        measurement = chunk_create(hash, hasher->get_hash_size(hasher));
        !           369:        this = (private_pts_file_meas_t*)pts_file_meas_create(request_id);
        !           370: 
        !           371:        if (is_dir)
        !           372:        {
        !           373:                enumerator_t *enumerator;
        !           374:                char *rel_name, *abs_name;
        !           375:                struct stat st;
        !           376: 
        !           377:                enumerator = enumerator_create_directory(pathname);
        !           378:                if (!enumerator)
        !           379:                {
        !           380:                        DBG1(DBG_PTS, "  directory '%s' can not be opened, %s", pathname,
        !           381:                                 strerror(errno));
        !           382:                        success = FALSE;
        !           383:                        goto end;
        !           384:                }
        !           385:                while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
        !           386:                {
        !           387:                        /* measure regular files only */
        !           388:                        if (S_ISREG(st.st_mode) && *rel_name != '.')
        !           389:                        {
        !           390:                                if (!hash_file(hasher, abs_name, hash))
        !           391:                                {
        !           392:                                        continue;
        !           393:                                }
        !           394:                                filename = use_rel_name ? rel_name : abs_name;
        !           395:                                DBG2(DBG_PTS, "  %#B for '%s'", &measurement, filename);
        !           396:                                add(this, filename, measurement);
        !           397:                        }
        !           398:                }
        !           399:                enumerator->destroy(enumerator);
        !           400:        }
        !           401:        else
        !           402:        {
        !           403:                if (!hash_file(hasher, pathname, hash))
        !           404:                {
        !           405:                        success = FALSE;
        !           406:                        goto end;
        !           407:                }
        !           408:                filename = use_rel_name ? path_basename(pathname) : strdup(pathname);
        !           409:                DBG2(DBG_PTS, "  %#B for '%s'", &measurement, filename);
        !           410:                add(this, filename, measurement);
        !           411:                free(filename);
        !           412:        }
        !           413: 
        !           414: end:
        !           415:        hasher->destroy(hasher);
        !           416:        if (success)
        !           417:        {
        !           418:                return &this->public;
        !           419:        }
        !           420:        else
        !           421:        {
        !           422:                destroy(this);
        !           423:                return NULL;
        !           424:        }
        !           425: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>