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>