Annotation of embedaddon/strongswan/src/libimcv/plugins/imv_os/imv_os_agent.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: #define _GNU_SOURCE
! 17: #include <stdio.h>
! 18:
! 19: #include "imv_os_agent.h"
! 20: #include "imv_os_state.h"
! 21: #include "imv_os_database.h"
! 22:
! 23: #include <imcv.h>
! 24: #include <imv/imv_agent.h>
! 25: #include <imv/imv_msg.h>
! 26: #include <generic/generic_attr_bool.h>
! 27: #include <generic/generic_attr_string.h>
! 28: #include <ietf/ietf_attr.h>
! 29: #include <ietf/ietf_attr_attr_request.h>
! 30: #include <ietf/ietf_attr_installed_packages.h>
! 31: #include <ietf/ietf_attr_numeric_version.h>
! 32: #include <ietf/ietf_attr_op_status.h>
! 33: #include <ietf/ietf_attr_pa_tnc_error.h>
! 34: #include <ietf/ietf_attr_product_info.h>
! 35: #include <ietf/ietf_attr_remediation_instr.h>
! 36: #include <ietf/ietf_attr_string_version.h>
! 37: #include <ita/ita_attr.h>
! 38: #include <ita/ita_attr_get_settings.h>
! 39: #include <ita/ita_attr_settings.h>
! 40: #include "tcg/seg/tcg_seg_attr_max_size.h"
! 41: #include "tcg/seg/tcg_seg_attr_seg_env.h"
! 42:
! 43: #include <tncif_names.h>
! 44: #include <tncif_pa_subtypes.h>
! 45:
! 46: #include <pen/pen.h>
! 47: #include <utils/debug.h>
! 48:
! 49: #define INSTALLED_PACKAGES_MAX_ATTR_SIZE 100000000
! 50:
! 51: typedef struct private_imv_os_agent_t private_imv_os_agent_t;
! 52: typedef enum imv_os_attr_t imv_os_attr_t;
! 53:
! 54: /* Subscribed PA-TNC message subtypes */
! 55: static pen_type_t msg_types[] = {
! 56: { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM }
! 57: };
! 58:
! 59: static char unknown_source_str[] = "install_non_market_apps";
! 60:
! 61: /**
! 62: * Flag set when corresponding attribute has been received
! 63: */
! 64: enum imv_os_attr_t {
! 65: IMV_OS_ATTR_PRODUCT_INFORMATION = (1<<0),
! 66: IMV_OS_ATTR_STRING_VERSION = (1<<1),
! 67: IMV_OS_ATTR_NUMERIC_VERSION = (1<<2),
! 68: IMV_OS_ATTR_OPERATIONAL_STATUS = (1<<3),
! 69: IMV_OS_ATTR_FORWARDING_ENABLED = (1<<4),
! 70: IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED = (1<<5),
! 71: IMV_OS_ATTR_DEVICE_ID = (1<<6),
! 72: IMV_OS_ATTR_MUST = (1<<7)-1,
! 73: IMV_OS_ATTR_INSTALLED_PACKAGES = (1<<7),
! 74: IMV_OS_ATTR_SETTINGS = (1<<8)
! 75: };
! 76:
! 77: /**
! 78: * Private data of an imv_os_agent_t object.
! 79: */
! 80: struct private_imv_os_agent_t {
! 81:
! 82: /**
! 83: * Public members of imv_os_agent_t
! 84: */
! 85: imv_agent_if_t public;
! 86:
! 87: /**
! 88: * IMV agent responsible for generic functions
! 89: */
! 90: imv_agent_t *agent;
! 91:
! 92: /**
! 93: * IMV OS database
! 94: */
! 95: imv_os_database_t *db;
! 96:
! 97: };
! 98:
! 99: METHOD(imv_agent_if_t, bind_functions, TNC_Result,
! 100: private_imv_os_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
! 101: {
! 102: return this->agent->bind_functions(this->agent, bind_function);
! 103: }
! 104:
! 105: METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
! 106: private_imv_os_agent_t *this, TNC_ConnectionID id,
! 107: TNC_ConnectionState new_state)
! 108: {
! 109: TNC_IMV_Action_Recommendation rec;
! 110: imv_state_t *state;
! 111: imv_session_t *session;
! 112:
! 113: switch (new_state)
! 114: {
! 115: case TNC_CONNECTION_STATE_CREATE:
! 116: state = imv_os_state_create(id);
! 117: return this->agent->create_state(this->agent, state);
! 118: case TNC_CONNECTION_STATE_DELETE:
! 119: return this->agent->delete_state(this->agent, id);
! 120: case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
! 121: case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
! 122: case TNC_CONNECTION_STATE_ACCESS_NONE:
! 123: if (this->agent->get_state(this->agent, id, &state) && imcv_db)
! 124: {
! 125: session = state->get_session(state);
! 126:
! 127: if (session->get_policy_started(session))
! 128: {
! 129: switch (new_state)
! 130: {
! 131: case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
! 132: rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
! 133: break;
! 134: case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
! 135: rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
! 136: break;
! 137: case TNC_CONNECTION_STATE_ACCESS_NONE:
! 138: default:
! 139: rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
! 140: }
! 141: imcv_db->add_recommendation(imcv_db, session, rec);
! 142: if (!imcv_db->policy_script(imcv_db, session, FALSE))
! 143: {
! 144: DBG1(DBG_IMV, "error in policy script stop");
! 145: }
! 146: }
! 147: }
! 148: /* fall through to default state */
! 149: default:
! 150: return this->agent->change_state(this->agent, id, new_state, NULL);
! 151: }
! 152: }
! 153:
! 154: /**
! 155: * Process a received message
! 156: */
! 157: static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
! 158: imv_msg_t *in_msg)
! 159: {
! 160: imv_msg_t *out_msg;
! 161: imv_os_state_t *os_state;
! 162: imv_session_t *session;
! 163: imv_os_info_t *os_info = NULL;
! 164: enumerator_t *enumerator;
! 165: pa_tnc_attr_t *attr;
! 166: pen_type_t type;
! 167: TNC_Result result;
! 168: chunk_t os_name = chunk_empty;
! 169: chunk_t os_version = chunk_empty;
! 170: bool fatal_error = FALSE, assessment = FALSE;
! 171: uint16_t missing;
! 172:
! 173: os_state = (imv_os_state_t*)state;
! 174: session = state->get_session(state);
! 175: os_info = session->get_os_info(session);
! 176:
! 177: /* generate an outgoing PA-TNC message - we might need it */
! 178: out_msg = imv_msg_create_as_reply(in_msg);
! 179:
! 180: /* parse received PA-TNC message and handle local and remote errors */
! 181: result = in_msg->receive(in_msg,out_msg, &fatal_error);
! 182: if (result != TNC_RESULT_SUCCESS)
! 183: {
! 184: out_msg->destroy(out_msg);
! 185: return result;
! 186: }
! 187:
! 188: /* analyze PA-TNC attributes */
! 189: enumerator = in_msg->create_attribute_enumerator(in_msg);
! 190: while (enumerator->enumerate(enumerator, &attr))
! 191: {
! 192: type = attr->get_type(attr);
! 193:
! 194: if (type.vendor_id == PEN_IETF)
! 195: {
! 196: switch (type.type)
! 197: {
! 198: case IETF_ATTR_PRODUCT_INFORMATION:
! 199: {
! 200: ietf_attr_product_info_t *attr_cast;
! 201: pen_t vendor_id;
! 202:
! 203: state->set_action_flags(state,
! 204: IMV_OS_ATTR_PRODUCT_INFORMATION);
! 205: attr_cast = (ietf_attr_product_info_t*)attr;
! 206: os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
! 207: os_info->set_name(os_info, os_name);
! 208:
! 209: if (vendor_id != PEN_IETF)
! 210: {
! 211: DBG1(DBG_IMV, "operating system name is '%.*s' "
! 212: "from vendor %N", os_name.len, os_name.ptr,
! 213: pen_names, vendor_id);
! 214: }
! 215: else
! 216: {
! 217: DBG1(DBG_IMV, "operating system name is '%.*s'",
! 218: os_name.len, os_name.ptr);
! 219: }
! 220: break;
! 221: }
! 222: case IETF_ATTR_STRING_VERSION:
! 223: {
! 224: ietf_attr_string_version_t *attr_cast;
! 225:
! 226: state->set_action_flags(state,
! 227: IMV_OS_ATTR_STRING_VERSION);
! 228: attr_cast = (ietf_attr_string_version_t*)attr;
! 229: os_version = attr_cast->get_version(attr_cast, NULL, NULL);
! 230: os_info->set_version(os_info, os_version);
! 231:
! 232: if (os_version.len)
! 233: {
! 234: DBG1(DBG_IMV, "operating system version is '%.*s'",
! 235: os_version.len, os_version.ptr);
! 236: }
! 237: break;
! 238: }
! 239: case IETF_ATTR_NUMERIC_VERSION:
! 240: {
! 241: ietf_attr_numeric_version_t *attr_cast;
! 242: uint32_t major, minor;
! 243:
! 244: state->set_action_flags(state,
! 245: IMV_OS_ATTR_NUMERIC_VERSION);
! 246: attr_cast = (ietf_attr_numeric_version_t*)attr;
! 247: attr_cast->get_version(attr_cast, &major, &minor);
! 248: DBG1(DBG_IMV, "operating system numeric version is %d.%d",
! 249: major, minor);
! 250: break;
! 251: }
! 252: case IETF_ATTR_OPERATIONAL_STATUS:
! 253: {
! 254: ietf_attr_op_status_t *attr_cast;
! 255: op_status_t op_status;
! 256: op_result_t op_result;
! 257: time_t last_boot;
! 258:
! 259: state->set_action_flags(state,
! 260: IMV_OS_ATTR_OPERATIONAL_STATUS);
! 261: attr_cast = (ietf_attr_op_status_t*)attr;
! 262: op_status = attr_cast->get_status(attr_cast);
! 263: op_result = attr_cast->get_result(attr_cast);
! 264: last_boot = attr_cast->get_last_use(attr_cast);
! 265: DBG1(DBG_IMV, "operational status: %N, result: %N",
! 266: op_status_names, op_status, op_result_names, op_result);
! 267: DBG1(DBG_IMV, "last boot: %T", &last_boot, TRUE);
! 268: break;
! 269: }
! 270: case IETF_ATTR_FORWARDING_ENABLED:
! 271: {
! 272: generic_attr_bool_t *attr_cast;
! 273: os_fwd_status_t fwd_status;
! 274:
! 275: state->set_action_flags(state,
! 276: IMV_OS_ATTR_FORWARDING_ENABLED);
! 277: attr_cast = (generic_attr_bool_t*)attr;
! 278: fwd_status = attr_cast->get_status(attr_cast);
! 279: DBG1(DBG_IMV, "IPv4 forwarding is %N",
! 280: os_fwd_status_names, fwd_status);
! 281: if (fwd_status == OS_FWD_ENABLED)
! 282: {
! 283: os_state->set_os_settings(os_state,
! 284: OS_SETTINGS_FWD_ENABLED);
! 285: }
! 286: break;
! 287: }
! 288: case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
! 289: {
! 290: generic_attr_bool_t *attr_cast;
! 291: bool default_pwd_status;
! 292:
! 293: state->set_action_flags(state,
! 294: IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
! 295: attr_cast = (generic_attr_bool_t*)attr;
! 296: default_pwd_status = attr_cast->get_status(attr_cast);
! 297: DBG1(DBG_IMV, "factory default password is %sabled",
! 298: default_pwd_status ? "en":"dis");
! 299: if (default_pwd_status)
! 300: {
! 301: os_state->set_os_settings(os_state,
! 302: OS_SETTINGS_DEFAULT_PWD_ENABLED);
! 303: }
! 304: break;
! 305: }
! 306: case IETF_ATTR_INSTALLED_PACKAGES:
! 307: {
! 308: ietf_attr_installed_packages_t *attr_cast;
! 309: enumerator_t *e;
! 310: status_t status;
! 311:
! 312: state->set_action_flags(state,
! 313: IMV_OS_ATTR_INSTALLED_PACKAGES);
! 314: if (!this->db)
! 315: {
! 316: break;
! 317: }
! 318: attr_cast = (ietf_attr_installed_packages_t*)attr;
! 319:
! 320: e = attr_cast->create_enumerator(attr_cast);
! 321: status = this->db->check_packages(this->db, os_state, e);
! 322: e->destroy(e);
! 323:
! 324: if (status == FAILED)
! 325: {
! 326: state->set_recommendation(state,
! 327: TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
! 328: TNC_IMV_EVALUATION_RESULT_ERROR);
! 329: assessment = TRUE;
! 330: }
! 331: missing = attr_cast->get_count(attr_cast);
! 332: os_state->set_missing(os_state, missing);
! 333: attr_cast->clear_packages(attr_cast);
! 334: break;
! 335: }
! 336: default:
! 337: break;
! 338: }
! 339: }
! 340: else if (type.vendor_id == PEN_ITA)
! 341: {
! 342: switch (type.type)
! 343: {
! 344: case ITA_ATTR_SETTINGS:
! 345: {
! 346: ita_attr_settings_t *attr_cast;
! 347: enumerator_t *e;
! 348: char *name;
! 349: chunk_t value;
! 350:
! 351: state->set_action_flags(state, IMV_OS_ATTR_SETTINGS);
! 352:
! 353: attr_cast = (ita_attr_settings_t*)attr;
! 354: e = attr_cast->create_enumerator(attr_cast);
! 355: while (e->enumerate(e, &name, &value))
! 356: {
! 357: if (streq(name, unknown_source_str) &&
! 358: chunk_equals(value, chunk_from_chars('1')))
! 359: {
! 360: os_state->set_os_settings(os_state,
! 361: OS_SETTINGS_UNKNOWN_SOURCE);
! 362: }
! 363: DBG1(DBG_IMV, "setting '%s'\n %.*s",
! 364: name, value.len, value.ptr);
! 365: }
! 366: e->destroy(e);
! 367: break;
! 368: }
! 369: case ITA_ATTR_DEVICE_ID:
! 370: {
! 371: chunk_t value;
! 372:
! 373: state->set_action_flags(state, IMV_OS_ATTR_DEVICE_ID);
! 374:
! 375: value = attr->get_value(attr);
! 376: DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr);
! 377: session->set_device_id(session, value);
! 378: break;
! 379: }
! 380: default:
! 381: break;
! 382: }
! 383: }
! 384: }
! 385: enumerator->destroy(enumerator);
! 386:
! 387: if (fatal_error)
! 388: {
! 389: state->set_recommendation(state,
! 390: TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
! 391: TNC_IMV_EVALUATION_RESULT_ERROR);
! 392: assessment = TRUE;
! 393: }
! 394:
! 395: if (assessment)
! 396: {
! 397: os_state->set_handshake_state(os_state, IMV_OS_STATE_END);
! 398: result = out_msg->send_assessment(out_msg);
! 399: if (result == TNC_RESULT_SUCCESS)
! 400: {
! 401: result = this->agent->provide_recommendation(this->agent, state);
! 402: }
! 403: }
! 404: else
! 405: {
! 406: /* send PA-TNC message with the EXCL flag set */
! 407: result = out_msg->send(out_msg, TRUE);
! 408: }
! 409: out_msg->destroy(out_msg);
! 410:
! 411: return result;
! 412: }
! 413:
! 414: METHOD(imv_agent_if_t, receive_message, TNC_Result,
! 415: private_imv_os_agent_t *this, TNC_ConnectionID id,
! 416: TNC_MessageType msg_type, chunk_t msg)
! 417: {
! 418: imv_state_t *state;
! 419: imv_msg_t *in_msg;
! 420: TNC_Result result;
! 421:
! 422: if (!this->agent->get_state(this->agent, id, &state))
! 423: {
! 424: return TNC_RESULT_FATAL;
! 425: }
! 426: in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
! 427: result = receive_msg(this, state, in_msg);
! 428: in_msg->destroy(in_msg);
! 429:
! 430: return result;
! 431: }
! 432:
! 433: METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
! 434: private_imv_os_agent_t *this, TNC_ConnectionID id,
! 435: TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
! 436: TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
! 437: {
! 438: imv_state_t *state;
! 439: imv_msg_t *in_msg;
! 440: TNC_Result result;
! 441:
! 442: if (!this->agent->get_state(this->agent, id, &state))
! 443: {
! 444: return TNC_RESULT_FATAL;
! 445: }
! 446: in_msg = imv_msg_create_from_long_data(this->agent, state, id,
! 447: src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
! 448: result = receive_msg(this, state, in_msg);
! 449: in_msg->destroy(in_msg);
! 450:
! 451: return result;
! 452:
! 453: }
! 454:
! 455: /**
! 456: * Build an IETF Attribute Request attribute for missing attributes
! 457: */
! 458: static pa_tnc_attr_t* build_attr_request(uint32_t received)
! 459: {
! 460: pa_tnc_attr_t *attr;
! 461: ietf_attr_attr_request_t *attr_cast;
! 462:
! 463: attr = ietf_attr_attr_request_create(PEN_RESERVED, 0);
! 464: attr_cast = (ietf_attr_attr_request_t*)attr;
! 465:
! 466: if (!(received & IMV_OS_ATTR_PRODUCT_INFORMATION) ||
! 467: !(received & IMV_OS_ATTR_STRING_VERSION))
! 468: {
! 469: attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION);
! 470: attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION);
! 471: }
! 472: if (!(received & IMV_OS_ATTR_NUMERIC_VERSION))
! 473: {
! 474: attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_NUMERIC_VERSION);
! 475: }
! 476: if (!(received & IMV_OS_ATTR_OPERATIONAL_STATUS))
! 477: {
! 478: attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS);
! 479: }
! 480: if (!(received & IMV_OS_ATTR_FORWARDING_ENABLED))
! 481: {
! 482: attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED);
! 483: }
! 484: if (!(received & IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED))
! 485: {
! 486: attr_cast->add(attr_cast, PEN_IETF,
! 487: IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
! 488: }
! 489: if (!(received & IMV_OS_ATTR_DEVICE_ID))
! 490: {
! 491: attr_cast->add(attr_cast, PEN_ITA, ITA_ATTR_DEVICE_ID);
! 492: }
! 493:
! 494: return attr;
! 495: }
! 496:
! 497: METHOD(imv_agent_if_t, batch_ending, TNC_Result,
! 498: private_imv_os_agent_t *this, TNC_ConnectionID id)
! 499: {
! 500: imv_msg_t *out_msg;
! 501: imv_state_t *state;
! 502: imv_session_t *session;
! 503: imv_workitem_t *workitem;
! 504: imv_os_state_t *os_state;
! 505: imv_os_handshake_state_t handshake_state;
! 506: pa_tnc_attr_t *attr;
! 507: TNC_IMVID imv_id;
! 508: TNC_Result result = TNC_RESULT_SUCCESS;
! 509: bool no_workitems = TRUE;
! 510: enumerator_t *enumerator;
! 511: uint32_t received;
! 512:
! 513: if (!this->agent->get_state(this->agent, id, &state))
! 514: {
! 515: return TNC_RESULT_FATAL;
! 516: }
! 517: os_state = (imv_os_state_t*)state;
! 518: handshake_state = os_state->get_handshake_state(os_state);
! 519: received = state->get_action_flags(state);
! 520: session = state->get_session(state);
! 521: imv_id = this->agent->get_id(this->agent);
! 522:
! 523: if (handshake_state == IMV_OS_STATE_END)
! 524: {
! 525: return TNC_RESULT_SUCCESS;
! 526: }
! 527:
! 528: /* create an empty out message - we might need it */
! 529: out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
! 530: msg_types[0]);
! 531:
! 532: if (handshake_state == IMV_OS_STATE_INIT)
! 533: {
! 534: size_t max_attr_size = INSTALLED_PACKAGES_MAX_ATTR_SIZE;
! 535: size_t max_seg_size;
! 536: seg_contract_t *contract;
! 537: seg_contract_manager_t *contracts;
! 538: char buf[BUF_LEN];
! 539:
! 540: /* Determine maximum PA-TNC attribute segment size */
! 541: max_seg_size = state->get_max_msg_len(state)
! 542: - PA_TNC_HEADER_SIZE
! 543: - PA_TNC_ATTR_HEADER_SIZE
! 544: - TCG_SEG_ATTR_SEG_ENV_HEADER;
! 545:
! 546: /* Announce support of PA-TNC segmentation to IMC */
! 547: contract = seg_contract_create(msg_types[0], max_attr_size,
! 548: max_seg_size, TRUE, imv_id, FALSE);
! 549: contract->get_info_string(contract, buf, BUF_LEN, TRUE);
! 550: DBG2(DBG_IMV, "%s", buf);
! 551: contracts = state->get_contracts(state);
! 552: contracts->add_contract(contracts, contract);
! 553: attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE);
! 554: out_msg->add_attribute(out_msg, attr);
! 555:
! 556: if ((received & IMV_OS_ATTR_MUST) != IMV_OS_ATTR_MUST)
! 557: {
! 558: /* create attribute request for missing mandatory attributes */
! 559: out_msg->add_attribute(out_msg, build_attr_request(received));
! 560: }
! 561: }
! 562:
! 563: if (handshake_state < IMV_OS_STATE_POLICY_START)
! 564: {
! 565: if (session->get_policy_started(session))
! 566: {
! 567: /* the policy script has already been started by another IMV */
! 568: handshake_state = IMV_OS_STATE_POLICY_START;
! 569: }
! 570: else
! 571: {
! 572: if (((received & IMV_OS_ATTR_PRODUCT_INFORMATION) &&
! 573: (received & IMV_OS_ATTR_STRING_VERSION)) &&
! 574: ((received & IMV_OS_ATTR_DEVICE_ID) ||
! 575: (handshake_state == IMV_OS_STATE_ATTR_REQ)))
! 576: {
! 577: if (!session->get_device_id(session, NULL))
! 578: {
! 579: session->set_device_id(session, chunk_empty);
! 580: }
! 581: if (imcv_db)
! 582: {
! 583: /* start the policy script */
! 584: if (!imcv_db->policy_script(imcv_db, session, TRUE))
! 585: {
! 586: DBG1(DBG_IMV, "error in policy script start");
! 587: }
! 588: }
! 589: else
! 590: {
! 591: DBG2(DBG_IMV, "no workitems available - "
! 592: "no evaluation possible");
! 593: state->set_recommendation(state,
! 594: TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
! 595: TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
! 596: session->set_policy_started(session, TRUE);
! 597: }
! 598: handshake_state = IMV_OS_STATE_POLICY_START;
! 599: }
! 600: else if (handshake_state == IMV_OS_STATE_ATTR_REQ)
! 601: {
! 602: /**
! 603: * both the IETF Product Information and IETF String Version
! 604: * attribute should have been present
! 605: */
! 606: state->set_recommendation(state,
! 607: TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
! 608: TNC_IMV_EVALUATION_RESULT_ERROR);
! 609:
! 610: /* send assessment */
! 611: result = out_msg->send_assessment(out_msg);
! 612: out_msg->destroy(out_msg);
! 613:
! 614: if (result != TNC_RESULT_SUCCESS)
! 615: {
! 616: return result;
! 617: }
! 618: return this->agent->provide_recommendation(this->agent, state);
! 619: }
! 620: else
! 621: {
! 622: handshake_state = IMV_OS_STATE_ATTR_REQ;
! 623: }
! 624: }
! 625: os_state->set_handshake_state(os_state, handshake_state);
! 626: }
! 627:
! 628: if (handshake_state == IMV_OS_STATE_POLICY_START)
! 629: {
! 630: enumerator = session->create_workitem_enumerator(session);
! 631: if (enumerator)
! 632: {
! 633: while (enumerator->enumerate(enumerator, &workitem))
! 634: {
! 635: if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY)
! 636: {
! 637: continue;
! 638: }
! 639:
! 640: switch (workitem->get_type(workitem))
! 641: {
! 642: case IMV_WORKITEM_PACKAGES:
! 643: attr = ietf_attr_attr_request_create(PEN_IETF,
! 644: IETF_ATTR_INSTALLED_PACKAGES);
! 645: out_msg->add_attribute(out_msg, attr);
! 646: break;
! 647: case IMV_WORKITEM_UNKNOWN_SOURCE:
! 648: attr = ita_attr_get_settings_create(unknown_source_str);
! 649: out_msg->add_attribute(out_msg, attr);
! 650: break;
! 651: case IMV_WORKITEM_FORWARDING:
! 652: case IMV_WORKITEM_DEFAULT_PWD:
! 653: break;
! 654: default:
! 655: continue;
! 656: }
! 657: workitem->set_imv_id(workitem, imv_id);
! 658: no_workitems = FALSE;
! 659: }
! 660: enumerator->destroy(enumerator);
! 661:
! 662: if (no_workitems)
! 663: {
! 664: DBG2(DBG_IMV, "IMV %d has no workitems - "
! 665: "no evaluation requested", imv_id);
! 666: state->set_recommendation(state,
! 667: TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
! 668: TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
! 669: }
! 670: handshake_state = IMV_OS_STATE_WORKITEMS;
! 671: os_state->set_handshake_state(os_state, handshake_state);
! 672: }
! 673: }
! 674:
! 675: if (handshake_state == IMV_OS_STATE_WORKITEMS)
! 676: {
! 677: TNC_IMV_Evaluation_Result eval;
! 678: TNC_IMV_Action_Recommendation rec;
! 679: char result_str[BUF_LEN];
! 680: bool fail;
! 681:
! 682: enumerator = session->create_workitem_enumerator(session);
! 683: while (enumerator->enumerate(enumerator, &workitem))
! 684: {
! 685: if (workitem->get_imv_id(workitem) != imv_id)
! 686: {
! 687: continue;
! 688: }
! 689:
! 690: switch (workitem->get_type(workitem))
! 691: {
! 692: case IMV_WORKITEM_PACKAGES:
! 693: {
! 694: int count, count_update, count_blacklist, count_ok;
! 695:
! 696: if (!(received & IMV_OS_ATTR_INSTALLED_PACKAGES) ||
! 697: os_state->get_missing(os_state) > 0)
! 698: {
! 699: continue;
! 700: }
! 701: os_state->get_count(os_state, &count, &count_update,
! 702: &count_blacklist, &count_ok);
! 703: fail = count_update || count_blacklist;
! 704: eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR :
! 705: TNC_IMV_EVALUATION_RESULT_COMPLIANT;
! 706: snprintf(result_str, BUF_LEN, "processed %d packages: "
! 707: "%d vulnerable, %d blacklisted, %d ok, %d unknown",
! 708: count, count_update, count_blacklist, count_ok,
! 709: count - count_update - count_blacklist - count_ok);
! 710: break;
! 711: }
! 712: case IMV_WORKITEM_UNKNOWN_SOURCE:
! 713: if (!(received & IMV_OS_ATTR_SETTINGS))
! 714: {
! 715: continue;
! 716: }
! 717: fail = os_state->get_os_settings(os_state) &
! 718: OS_SETTINGS_UNKNOWN_SOURCE;
! 719: eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR :
! 720: TNC_IMV_EVALUATION_RESULT_COMPLIANT;
! 721: snprintf(result_str, BUF_LEN, "unknown sources%s enabled",
! 722: fail ? "" : " not");
! 723: break;
! 724: case IMV_WORKITEM_FORWARDING:
! 725: if (!(received & IMV_OS_ATTR_FORWARDING_ENABLED))
! 726: {
! 727: continue;
! 728: }
! 729: fail = os_state->get_os_settings(os_state) &
! 730: OS_SETTINGS_FWD_ENABLED;
! 731: eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR :
! 732: TNC_IMV_EVALUATION_RESULT_COMPLIANT;
! 733: snprintf(result_str, BUF_LEN, "forwarding%s enabled",
! 734: fail ? "" : " not");
! 735: break;
! 736: case IMV_WORKITEM_DEFAULT_PWD:
! 737: if (!(received & IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED))
! 738: {
! 739: continue;
! 740: }
! 741: fail = os_state->get_os_settings(os_state) &
! 742: OS_SETTINGS_DEFAULT_PWD_ENABLED;
! 743: eval = fail ? TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR :
! 744: TNC_IMV_EVALUATION_RESULT_COMPLIANT;
! 745: snprintf(result_str, BUF_LEN, "factory default password%s enabled",
! 746: fail ? "" : " not");
! 747: break;
! 748: default:
! 749: continue;
! 750: }
! 751: session->remove_workitem(session, enumerator);
! 752: rec = workitem->set_result(workitem, result_str, eval);
! 753: state->update_recommendation(state, rec, eval);
! 754: imcv_db->finalize_workitem(imcv_db, workitem);
! 755: workitem->destroy(workitem);
! 756: }
! 757: enumerator->destroy(enumerator);
! 758:
! 759: /* finalized all workitems ? */
! 760: if (session->get_workitem_count(session, imv_id) == 0)
! 761: {
! 762: os_state->set_handshake_state(os_state, IMV_OS_STATE_END);
! 763:
! 764: result = out_msg->send_assessment(out_msg);
! 765: out_msg->destroy(out_msg);
! 766: if (result != TNC_RESULT_SUCCESS)
! 767: {
! 768: return result;
! 769: }
! 770: return this->agent->provide_recommendation(this->agent, state);
! 771: }
! 772: }
! 773:
! 774: /* send non-empty PA-TNC message with excl flag not set */
! 775: if (out_msg->get_attribute_count(out_msg))
! 776: {
! 777: result = out_msg->send(out_msg, FALSE);
! 778: }
! 779: out_msg->destroy(out_msg);
! 780:
! 781: return result;
! 782: }
! 783:
! 784: METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
! 785: private_imv_os_agent_t *this, TNC_ConnectionID id)
! 786: {
! 787: imv_state_t *state;
! 788:
! 789: if (!this->agent->get_state(this->agent, id, &state))
! 790: {
! 791: return TNC_RESULT_FATAL;
! 792: }
! 793: return this->agent->provide_recommendation(this->agent, state);
! 794: }
! 795:
! 796: METHOD(imv_agent_if_t, destroy, void,
! 797: private_imv_os_agent_t *this)
! 798: {
! 799: DESTROY_IF(this->agent);
! 800: DESTROY_IF(this->db);
! 801: free(this);
! 802: }
! 803:
! 804: /**
! 805: * Described in header.
! 806: */
! 807: imv_agent_if_t *imv_os_agent_create(const char *name, TNC_IMVID id,
! 808: TNC_Version *actual_version)
! 809: {
! 810: private_imv_os_agent_t *this;
! 811: imv_agent_t *agent;
! 812:
! 813: agent = imv_agent_create(name, msg_types, countof(msg_types), id,
! 814: actual_version);
! 815: if (!agent)
! 816: {
! 817: return NULL;
! 818: }
! 819:
! 820: INIT(this,
! 821: .public = {
! 822: .bind_functions = _bind_functions,
! 823: .notify_connection_change = _notify_connection_change,
! 824: .receive_message = _receive_message,
! 825: .receive_message_long = _receive_message_long,
! 826: .batch_ending = _batch_ending,
! 827: .solicit_recommendation = _solicit_recommendation,
! 828: .destroy = _destroy,
! 829: },
! 830: .agent = agent,
! 831: .db = imv_os_database_create(imcv_db),
! 832: );
! 833:
! 834: return &this->public;
! 835: }
! 836:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>