Annotation of embedaddon/strongswan/src/libimcv/imv/imv_policy_manager.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2013-2015 Andreas Steffen
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "imv_policy_manager_usage.h"
! 17: #include "imv_workitem.h"
! 18:
! 19: #include <library.h>
! 20: #include <utils/debug.h>
! 21:
! 22: #include <tncif_names.h>
! 23:
! 24: #include <stdlib.h>
! 25: #include <stdio.h>
! 26: #include <time.h>
! 27:
! 28: /* The default policy group #1 is assumed to always exist */
! 29: #define DEFAULT_GROUP_ID 1
! 30:
! 31: /**
! 32: * global debug output variables
! 33: */
! 34: static int debug_level = 1;
! 35: static bool stderr_quiet = FALSE;
! 36:
! 37: /**
! 38: * attest dbg function
! 39: */
! 40: static void stderr_dbg(debug_t group, level_t level, char *fmt, ...)
! 41: {
! 42: va_list args;
! 43:
! 44: if (level <= debug_level)
! 45: {
! 46: if (!stderr_quiet)
! 47: {
! 48: va_start(args, fmt);
! 49: vfprintf(stderr, fmt, args);
! 50: fprintf(stderr, "\n");
! 51: va_end(args);
! 52: }
! 53: }
! 54: }
! 55:
! 56: /**
! 57: * Collect all enforcements by iterating up through parent groups
! 58: */
! 59: static bool iterate_enforcements(database_t *db, int device_id, int session_id,
! 60: int group_id)
! 61: {
! 62: int id, type, file, dir, arg_int, parent, policy, max_age;
! 63: int p_rec_fail, p_rec_noresult, e_rec_fail, e_rec_noresult, latest_rec;
! 64: bool latest_success;
! 65: char *argument;
! 66: time_t now;
! 67: enumerator_t *e, *e1, *e2;
! 68:
! 69: now = time(NULL);
! 70:
! 71: while (group_id)
! 72: {
! 73: e1 = db->query(db,
! 74: "SELECT e.id, p.type, p.argument, p.file, p.dir, p.rec_fail, "
! 75: "p.rec_noresult, e.policy, e.max_age, e.rec_fail, e.rec_noresult "
! 76: "FROM enforcements AS e JOIN policies as p ON e.policy = p.id "
! 77: "WHERE e.group_id = ?", DB_INT, group_id,
! 78: DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT,
! 79: DB_INT, DB_INT, DB_INT, DB_INT);
! 80: if (!e1)
! 81: {
! 82: return FALSE;
! 83: }
! 84: while (e1->enumerate(e1, &id, &type, &argument, &file, &dir,
! 85: &p_rec_fail, &p_rec_noresult, &policy, &max_age,
! 86: &e_rec_fail, &e_rec_noresult))
! 87: {
! 88: /* check if the latest measurement of the device was successful */
! 89: latest_success = FALSE;
! 90:
! 91: if (device_id)
! 92: {
! 93: e2 = db->query(db,
! 94: "SELECT r.rec FROM results AS r "
! 95: "JOIN sessions AS s ON s.id = r.session "
! 96: "WHERE r.policy = ? AND s.device = ? AND s.time > ? "
! 97: "ORDER BY s.time DESC",
! 98: DB_INT, policy, DB_INT, device_id,
! 99: DB_UINT, now - max_age, DB_INT);
! 100: if (!e2)
! 101: {
! 102: e1->destroy(e1);
! 103: return FALSE;
! 104: }
! 105: if (e2->enumerate(e2, &latest_rec) &&
! 106: latest_rec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
! 107: {
! 108: latest_success = TRUE;
! 109: }
! 110: e2->destroy(e2);
! 111: }
! 112:
! 113: if (latest_success)
! 114: {
! 115: /*skipping enforcement */
! 116: printf("skipping enforcement %d\n", id);
! 117: continue;
! 118: }
! 119:
! 120: /* determine arg_int */
! 121: switch ((imv_workitem_type_t)type)
! 122: {
! 123: case IMV_WORKITEM_FILE_REF_MEAS:
! 124: case IMV_WORKITEM_FILE_MEAS:
! 125: case IMV_WORKITEM_FILE_META:
! 126: arg_int = file;
! 127: break;
! 128: case IMV_WORKITEM_DIR_REF_MEAS:
! 129: case IMV_WORKITEM_DIR_MEAS:
! 130: case IMV_WORKITEM_DIR_META:
! 131: arg_int = dir;
! 132: break;
! 133: case IMV_WORKITEM_SWID_TAGS:
! 134: /* software [identifier] inventory by default */
! 135: arg_int = 0;
! 136:
! 137: /* software identifiers only? */
! 138: if (device_id && strchr(argument, 'R'))
! 139: {
! 140: /* get last EID in order to set earliest EID */
! 141: e2 = db->query(db,
! 142: "SELECT eid FROM swid_events where device == ? "
! 143: "ORDER BY eid DESC", DB_UINT, device_id, DB_INT);
! 144: if (e2)
! 145: {
! 146: if (e2->enumerate(e2, &arg_int))
! 147: {
! 148: arg_int++;
! 149: }
! 150: else
! 151: {
! 152: arg_int = 1;
! 153: }
! 154: e2->destroy(e2);
! 155: }
! 156: }
! 157: break;
! 158: default:
! 159: arg_int = 0;
! 160: }
! 161:
! 162: /* insert a workitem */
! 163: if (db->execute(db, NULL,
! 164: "INSERT INTO workitems (session, enforcement, type, arg_str, "
! 165: "arg_int, rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?, ?)",
! 166: DB_INT, session_id, DB_INT, id, DB_INT, type, DB_TEXT, argument,
! 167: DB_INT, arg_int, DB_INT, e_rec_fail ? e_rec_fail : p_rec_fail,
! 168: DB_INT, e_rec_noresult ? e_rec_noresult : p_rec_noresult) != 1)
! 169: {
! 170: e1->destroy(e1);
! 171: fprintf(stderr, "could not insert workitem\n");
! 172: return FALSE;
! 173: }
! 174: }
! 175: e1->destroy(e1);
! 176:
! 177: e = db->query(db,
! 178: "SELECT parent FROM groups WHERE id = ?",
! 179: DB_INT, group_id, DB_INT);
! 180: if (!e)
! 181: {
! 182: return FALSE;
! 183: }
! 184: if (e->enumerate(e, &parent))
! 185: {
! 186: group_id = parent;
! 187: }
! 188: else
! 189: {
! 190: fprintf(stderr, "group information not found\n");
! 191: group_id = 0;
! 192: }
! 193: e->destroy(e);
! 194: }
! 195: return TRUE;
! 196: }
! 197:
! 198: static bool policy_start(database_t *db, int session_id)
! 199: {
! 200: enumerator_t *e;
! 201: int device_id, product_id, gid, group_id = DEFAULT_GROUP_ID;
! 202: u_int created;
! 203:
! 204: /* get session data */
! 205: e = db->query(db,
! 206: "SELECT s.device, s.product, d.created FROM sessions AS s "
! 207: "LEFT JOIN devices AS d ON s.device = d.id WHERE s.id = ?",
! 208: DB_INT, session_id, DB_INT, DB_INT, DB_UINT);
! 209: if (!e || !e->enumerate(e, &device_id, &product_id, &created))
! 210: {
! 211: DESTROY_IF(e);
! 212: fprintf(stderr, "session %d not found\n", session_id);
! 213: return FALSE;
! 214: }
! 215: e->destroy(e);
! 216:
! 217: /* if a device ID with a creation date exists, get all group memberships */
! 218: if (device_id && created)
! 219: {
! 220: e = db->query(db,
! 221: "SELECT group_id FROM groups_members WHERE device_id = ?",
! 222: DB_INT, device_id, DB_INT);
! 223: if (!e)
! 224: {
! 225: return FALSE;
! 226: }
! 227: while (e->enumerate(e, &group_id))
! 228: {
! 229: if (!iterate_enforcements(db, device_id, session_id, group_id))
! 230: {
! 231: e->destroy(e);
! 232: return FALSE;
! 233: }
! 234: }
! 235: e->destroy(e);
! 236:
! 237: return TRUE;
! 238: }
! 239:
! 240: /* determine if a default product group exists */
! 241: e = db->query(db,
! 242: "SELECT group_id FROM groups_product_defaults "
! 243: "WHERE product_id = ?", DB_INT, product_id, DB_INT);
! 244: if (!e)
! 245: {
! 246: return FALSE;
! 247: }
! 248: if (e->enumerate(e, &gid))
! 249: {
! 250: group_id = gid;
! 251: }
! 252: e->destroy(e);
! 253:
! 254: if (device_id && !created)
! 255: {
! 256: /* assign a newly created device to a default group */
! 257: if (db->execute(db, NULL,
! 258: "INSERT INTO groups_members (device_id, group_id) "
! 259: "VALUES (?, ?)", DB_INT, device_id, DB_INT, group_id) != 1)
! 260: {
! 261: fprintf(stderr, "could not assign device to a default group\n");
! 262: return FALSE;
! 263: }
! 264:
! 265: /* set the creation date if it hasn't been set yet */
! 266: if (db->execute(db, NULL,
! 267: "UPDATE devices SET created = ? WHERE id = ?",
! 268: DB_UINT, time(NULL), DB_INT, device_id) != 1)
! 269: {
! 270: fprintf(stderr, "creation date of device could not be set\n");
! 271: return FALSE;
! 272: }
! 273: }
! 274:
! 275: return iterate_enforcements(db, device_id, session_id, group_id);
! 276: }
! 277:
! 278: static bool policy_stop(database_t *db, int session_id)
! 279: {
! 280: enumerator_t *e;
! 281: int rec, policy, final_rec, id_type;
! 282: chunk_t id_value;
! 283: char *result, *format, *ip_address = NULL;
! 284: char command[512];
! 285: bool success = TRUE;
! 286:
! 287: /* store all workitem results for this session in the results table */
! 288: e = db->query(db,
! 289: "SELECT w.rec_final, w.result, e.policy FROM workitems AS w "
! 290: "JOIN enforcements AS e ON w.enforcement = e.id "
! 291: "WHERE w.session = ? AND w.result IS NOT NULL",
! 292: DB_INT, session_id, DB_INT, DB_TEXT, DB_INT);
! 293: if (e)
! 294: {
! 295: while (e->enumerate(e, &rec, &result, &policy))
! 296: {
! 297: db->execute(db, NULL,
! 298: "INSERT INTO results (session, policy, rec, result) "
! 299: "VALUES (?, ?, ?, ?)", DB_INT, session_id, DB_INT, policy,
! 300: DB_INT, rec, DB_TEXT, result);
! 301: }
! 302: e->destroy(e);
! 303: }
! 304: else
! 305: {
! 306: success = FALSE;
! 307: }
! 308:
! 309: /* delete all workitems for this session from the database */
! 310: if (db->execute(db, NULL,
! 311: "DELETE FROM workitems WHERE session = ?",
! 312: DB_UINT, session_id) < 0)
! 313: {
! 314: success = FALSE;
! 315: }
! 316:
! 317: final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
! 318:
! 319: /* retrieve the final recommendation for this session */
! 320: e = db->query(db,
! 321: "SELECT rec FROM sessions WHERE id = ?",
! 322: DB_INT, session_id, DB_INT);
! 323: if (e)
! 324: {
! 325: if (!e->enumerate(e, &final_rec))
! 326: {
! 327: success = FALSE;
! 328: }
! 329: e->destroy(e);
! 330: }
! 331: else
! 332: {
! 333: success = FALSE;
! 334: }
! 335:
! 336: /* retrieve client IP address for this session */
! 337: e = db->query(db,
! 338: "SELECT i.type, i.value FROM identities AS i "
! 339: "JOIN sessions_identities AS si ON si.identity_id = i.id "
! 340: "WHERE si.session_id = ? AND (i.type = ? OR i.type = ?)",
! 341: DB_INT, session_id, DB_INT, TNC_ID_IPV4_ADDR, DB_INT,
! 342: TNC_ID_IPV6_ADDR, DB_INT, DB_BLOB);
! 343: if (e)
! 344: {
! 345: if (e->enumerate(e, &id_type, &id_value))
! 346: {
! 347: ip_address = strndup(id_value.ptr, id_value.len);
! 348: }
! 349: else
! 350: {
! 351: success = FALSE;
! 352: }
! 353: e->destroy(e);
! 354: }
! 355: else
! 356: {
! 357: success = FALSE;
! 358: }
! 359:
! 360: fprintf(stderr, "recommendation for access requestor %s is %N\n",
! 361: ip_address ? ip_address : "0.0.0.0",
! 362: TNC_IMV_Action_Recommendation_names, final_rec);
! 363:
! 364: if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
! 365: {
! 366: format = lib->settings->get_str(lib->settings,
! 367: "imv_policy_manager.command_allow", NULL);
! 368: }
! 369: else
! 370: {
! 371: format = lib->settings->get_str(lib->settings,
! 372: "imv_policy_manager.command_block", NULL);
! 373: }
! 374: if (format && ip_address)
! 375: {
! 376: /* the IP address can occur at most twice in the command string */
! 377: snprintf(command, sizeof(command), format, ip_address, ip_address);
! 378: success = system(command) == 0;
! 379: fprintf(stderr, "%s system command: %s\n",
! 380: success ? "successful" : "failed", command);
! 381: }
! 382: free(ip_address);
! 383:
! 384: return success;
! 385: }
! 386:
! 387: int main(int argc, char *argv[])
! 388: {
! 389: database_t *db;
! 390: char *uri;
! 391: int session_id;
! 392: bool start, success;
! 393:
! 394: /* enable attest debugging hook */
! 395: dbg = stderr_dbg;
! 396:
! 397: atexit(library_deinit);
! 398:
! 399: /* initialize library */
! 400: if (!library_init(NULL, "imv_policy_manager"))
! 401: {
! 402: exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
! 403: }
! 404: if (!lib->plugins->load(lib->plugins,
! 405: lib->settings->get_str(lib->settings, "imv_policy_manager.load",
! 406: "sqlite")))
! 407: {
! 408: exit(SS_RC_INITIALIZATION_FAILED);
! 409: }
! 410:
! 411: if (argc < 3)
! 412: {
! 413: usage();
! 414: exit(SS_RC_INITIALIZATION_FAILED);
! 415: }
! 416: if (streq(argv[1], "start"))
! 417: {
! 418: start = TRUE;
! 419: }
! 420: else if (streq(argv[1], "stop"))
! 421: {
! 422: start = FALSE;
! 423: }
! 424: else
! 425: {
! 426: usage();
! 427: exit(SS_RC_INITIALIZATION_FAILED);
! 428: }
! 429:
! 430: session_id = atoi(argv[2]);
! 431:
! 432: /* attach IMV database */
! 433: uri = lib->settings->get_str(lib->settings,
! 434: "imv_policy_manager.database",
! 435: lib->settings->get_str(lib->settings,
! 436: "charon.imcv.database",
! 437: lib->settings->get_str(lib->settings,
! 438: "libimcv.database", NULL)));
! 439: if (!uri)
! 440: {
! 441: fprintf(stderr, "database uri not defined.\n");
! 442: exit(SS_RC_INITIALIZATION_FAILED);
! 443: }
! 444:
! 445: db = lib->db->create(lib->db, uri);
! 446: if (!db)
! 447: {
! 448: fprintf(stderr, "opening database failed.\n");
! 449: exit(SS_RC_INITIALIZATION_FAILED);
! 450: }
! 451:
! 452: if (start)
! 453: {
! 454: success = policy_start(db, session_id);
! 455: }
! 456: else
! 457: {
! 458: success = policy_stop(db, session_id);
! 459: }
! 460: db->destroy(db);
! 461:
! 462: fprintf(stderr, "imv_policy_manager %s %s\n", start ? "start" : "stop",
! 463: success ? "successful" : "failed");
! 464:
! 465: exit(EXIT_SUCCESS);
! 466: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>