From: Andreas Steffen Date: Wed, 25 Jul 2018 06:41:05 +0000 (+0200) Subject: imv-swima: Support subscriptions X-Git-Tag: 5.7.0dr8~1^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37c12f98b0a8ba5f4af2f32dc94af64a4504fc78;p=thirdparty%2Fstrongswan.git imv-swima: Support subscriptions --- diff --git a/src/libimcv/imv/imv_database.c b/src/libimcv/imv/imv_database.c index b444abdbb8..03f5832041 100644 --- a/src/libimcv/imv/imv_database.c +++ b/src/libimcv/imv/imv_database.c @@ -143,7 +143,7 @@ static bool create_session(private_imv_database_t *this, imv_session_t *session) } /* create a new session entry */ - created = session->get_creation_time(session); + created = time(NULL); conn_id = session->get_connection_id(session); this->db->execute(this->db, &session_id, "INSERT INTO sessions (time, connection, product, device) " @@ -161,6 +161,7 @@ static bool create_session(private_imv_database_t *this, imv_session_t *session) return FALSE; } session->set_session_id(session, session_id, pid, did); + session->set_creation_time(session, created); enumerator = session->create_ar_identities_enumerator(session); while (enumerator->enumerate(enumerator, &tnc_id)) diff --git a/src/libimcv/imv/imv_session.c b/src/libimcv/imv/imv_session.c index bc6b5a8d11..830dd48d4c 100644 --- a/src/libimcv/imv/imv_session.c +++ b/src/libimcv/imv/imv_session.c @@ -121,6 +121,12 @@ METHOD(imv_session_t, get_connection_id, TNC_ConnectionID, return this->conn_id; } +METHOD(imv_session_t, set_creation_time, void, + private_imv_session_t *this, time_t created) +{ + this->created = created; +} + METHOD(imv_session_t, get_creation_time, time_t, private_imv_session_t *this) { @@ -259,7 +265,7 @@ METHOD(imv_session_t, destroy, void, /** * See header */ -imv_session_t *imv_session_create(TNC_ConnectionID conn_id, time_t created, +imv_session_t *imv_session_create(TNC_ConnectionID conn_id, linked_list_t *ar_identities) { private_imv_session_t *this; @@ -269,6 +275,7 @@ imv_session_t *imv_session_create(TNC_ConnectionID conn_id, time_t created, .set_session_id = _set_session_id, .get_session_id = _get_session_id, .get_connection_id = _get_connection_id, + .set_creation_time = _set_creation_time, .get_creation_time = _get_creation_time, .create_ar_identities_enumerator = _create_ar_identities_enumerator, .get_os_info = _get_os_info, @@ -286,7 +293,6 @@ imv_session_t *imv_session_create(TNC_ConnectionID conn_id, time_t created, .destroy = _destroy, }, .conn_id = conn_id, - .created = created, .ar_identities = ar_identities, .os_info = imv_os_info_create(), .workitems = linked_list_create(), diff --git a/src/libimcv/imv/imv_session.h b/src/libimcv/imv/imv_session.h index 107716f30a..a2f6fc2a83 100644 --- a/src/libimcv/imv/imv_session.h +++ b/src/libimcv/imv/imv_session.h @@ -62,6 +62,13 @@ struct imv_session_t { */ TNC_ConnectionID (*get_connection_id)(imv_session_t *this); + /** + * Set session creation time + * + * @param created Session creation time + */ + void (*set_creation_time)(imv_session_t *this, time_t created); + /** * Get session creation time * @@ -170,10 +177,9 @@ struct imv_session_t { * Create an imv_session_t instance * * @param id Associated Connection ID - * @param created Session creation time * @param ar_identities List of Access Requestor identities */ -imv_session_t* imv_session_create(TNC_ConnectionID id, time_t created, - linked_list_t *ar_identities); +imv_session_t* imv_session_create(TNC_ConnectionID id, + linked_list_t *ar_identities); #endif /** IMV_SESSION_H_ @}*/ diff --git a/src/libimcv/imv/imv_session_manager.c b/src/libimcv/imv/imv_session_manager.c index c976029984..2e3cfa4668 100644 --- a/src/libimcv/imv/imv_session_manager.c +++ b/src/libimcv/imv/imv_session_manager.c @@ -51,7 +51,6 @@ METHOD(imv_session_manager_t, add_session, imv_session_t*, enumerator_t *enumerator; tncif_identity_t *tnc_id; imv_session_t *current, *session = NULL; - time_t created; this->mutex->lock(this->mutex); @@ -105,8 +104,7 @@ METHOD(imv_session_manager_t, add_session, imv_session_t*, enumerator->destroy(enumerator); /* create a new session entry */ - created = time(NULL); - session = imv_session_create(conn_id, created, ar_identities); + session = imv_session_create(conn_id, ar_identities); this->sessions->insert_last(this->sessions, session); this->mutex->unlock(this->mutex); diff --git a/src/libimcv/plugins/imv_swima/imv_swima_agent.c b/src/libimcv/plugins/imv_swima/imv_swima_agent.c index 1d9944200e..377c89d3d8 100644 --- a/src/libimcv/plugins/imv_swima/imv_swima_agent.c +++ b/src/libimcv/plugins/imv_swima/imv_swima_agent.c @@ -90,12 +90,19 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result, TNC_ConnectionState new_state) { imv_state_t *state; + imv_swima_state_t *swima_state; switch (new_state) { case TNC_CONNECTION_STATE_CREATE: state = imv_swima_state_create(id); return this->agent->create_state(this->agent, state); + case TNC_CONNECTION_STATE_HANDSHAKE: + this->agent->change_state(this->agent, id, new_state, &state); + state->set_action_flags(state, 0); + swima_state = (imv_swima_state_t*)state; + swima_state->set_handshake_state(swima_state, IMV_SWIMA_STATE_INIT); + return TNC_RESULT_SUCCESS; case TNC_CONNECTION_STATE_DELETE: return this->agent->delete_state(this->agent, id); default: @@ -187,11 +194,17 @@ static TNC_Result receive_msg(private_imv_swima_agent_t *this, } description = reader->peek(reader); if (description.len) - { + { DBG1(DBG_IMV, " description: %.*s", description.len, description.ptr); } reader->destroy(reader); + if (error_code.type == PA_ERROR_SWIMA_SUBSCRIPTION_DENIED) + { + swima_state->set_subscription(swima_state, FALSE); + DBG1(DBG_IMV, "SWIMA subscription %u cleared", + swima_state->get_request_id(swima_state)); + } break; } case IETF_ATTR_SW_ID_INVENTORY: @@ -474,7 +487,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, seg_contract_t *contract; seg_contract_manager_t *contracts; swima_inventory_t *targets; - uint32_t earliest_eid = 0; + uint32_t old_request_id = 0, earliest_eid = 0; char buf[BUF_LEN]; enumerator = session->create_workitem_enumerator(session); @@ -487,7 +500,13 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, { continue; } - + + earliest_eid = workitem->get_arg_int(workitem); + request_id = workitem->get_id(workitem); + workitem->set_imv_id(workitem, imv_id); + no_workitems = FALSE; + old_request_id = swima_state->get_request_id(swima_state); + flags = IETF_SWIMA_ATTR_REQ_FLAG_NONE; if (strchr(workitem->get_arg_str(workitem), 'R')) { @@ -496,47 +515,57 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, if (strchr(workitem->get_arg_str(workitem), 'S')) { flags |= IETF_SWIMA_ATTR_REQ_FLAG_S; + swima_state->set_subscription(swima_state, TRUE); + if (!old_request_id) + { + DBG1(DBG_IMV, "SWIMA subscription %u requested", + request_id); + } } if (strchr(workitem->get_arg_str(workitem), 'C')) { flags |= IETF_SWIMA_ATTR_REQ_FLAG_C; + swima_state->set_subscription(swima_state, FALSE); } - earliest_eid = workitem->get_arg_int(workitem); - - /* Determine maximum PA-TNC attribute segment size */ - max_seg_size = state->get_max_msg_len(state) - - PA_TNC_HEADER_SIZE - - PA_TNC_ATTR_HEADER_SIZE - - TCG_SEG_ATTR_SEG_ENV_HEADER; - - /* Announce support of PA-TNC segmentation to IMC */ - contract = seg_contract_create(msg_types[0], max_attr_size, - max_seg_size, TRUE, imv_id, FALSE); - contract->get_info_string(contract, buf, BUF_LEN, TRUE); - DBG2(DBG_IMV, "%s", buf); - contracts = state->get_contracts(state); - contracts->add_contract(contracts, contract); - attr = tcg_seg_attr_max_size_create(max_attr_size, - max_seg_size, TRUE); - out_msg->add_attribute(out_msg, attr); - /* Issue a SWID request */ - request_id = workitem->get_id(workitem); - swima_state->set_request_id(swima_state, request_id); - attr = ietf_swima_attr_req_create(flags, request_id); - - /* Request software identifier events */ - targets = swima_inventory_create(); - targets->set_eid(targets, earliest_eid, 0); - cast_attr = (ietf_swima_attr_req_t*)attr; - cast_attr->set_targets(cast_attr, targets); - targets->destroy(targets); + if (!old_request_id) + { + /* Determine maximum PA-TNC attribute segment size */ + max_seg_size = state->get_max_msg_len(state) + - PA_TNC_HEADER_SIZE + - PA_TNC_ATTR_HEADER_SIZE + - TCG_SEG_ATTR_SEG_ENV_HEADER; + + /* Announce support of PA-TNC segmentation to IMC */ + contract = seg_contract_create(msg_types[0], max_attr_size, + max_seg_size, TRUE, imv_id, FALSE); + contract->get_info_string(contract, buf, BUF_LEN, TRUE); + DBG2(DBG_IMV, "%s", buf); + contracts = state->get_contracts(state); + contracts->add_contract(contracts, contract); + attr = tcg_seg_attr_max_size_create(max_attr_size, + max_seg_size, TRUE); + out_msg->add_attribute(out_msg, attr); + } - out_msg->add_attribute(out_msg, attr); - workitem->set_imv_id(workitem, imv_id); - no_workitems = FALSE; - DBG2(DBG_IMV, "IMV %d issues sw request %d with earliest eid %d", - imv_id, request_id, earliest_eid); + if (!old_request_id || + !swima_state->get_subscription(swima_state)) + { + /* Issue a SWID request */ + swima_state->set_request_id(swima_state, request_id); + attr = ietf_swima_attr_req_create(flags, request_id); + + /* Request software identifier events */ + targets = swima_inventory_create(); + targets->set_eid(targets, earliest_eid, 0); + cast_attr = (ietf_swima_attr_req_t*)attr; + cast_attr->set_targets(cast_attr, targets); + targets->destroy(targets); + + out_msg->add_attribute(out_msg, attr); + DBG2(DBG_IMV, "IMV %d issues sw request %d with earliest " + "eid %d", imv_id, request_id, earliest_eid); + } break; } enumerator->destroy(enumerator); @@ -565,7 +594,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, TNC_IMV_Action_Recommendation rec; char result_str[BUF_LEN], *format = NULL, *cmd = NULL, *command; char *target_str, *error_str = ""; - int sw_id_count, tag_count, i, res; + int sw_id_count, tag_count, i, res, written; json_object *jrequest, *jresponse, *jvalue; ietf_swima_attr_req_t *cast_attr; swima_inventory_t *targets; @@ -617,16 +646,24 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, &tag_count); if (format) { - snprintf(result_str, BUF_LEN, format, + written = snprintf(result_str, BUF_LEN, format, sw_id_count, (sw_id_count == 1) ? "" : "s", tag_count, (tag_count == 1) ? "" : "s"); } else { - snprintf(result_str, BUF_LEN, "received %d SWID tag" - "%s", tag_count, (tag_count == 1) ? "" : "s"); + written = snprintf(result_str, BUF_LEN, + "received %d SWID tag%s", + tag_count, (tag_count == 1) ? "" : "s"); } + if (swima_state->get_subscription(swima_state) && + written > 0 && written < BUF_LEN) + { + snprintf(result_str + written, BUF_LEN - written, + " from subscription %u", + swima_state->get_request_id(swima_state)); + } session->remove_workitem(session, enumerator); eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT; diff --git a/src/libimcv/plugins/imv_swima/imv_swima_state.c b/src/libimcv/plugins/imv_swima/imv_swima_state.c index 03500bc2d3..bcacce0b3f 100644 --- a/src/libimcv/plugins/imv_swima/imv_swima_state.c +++ b/src/libimcv/plugins/imv_swima/imv_swima_state.c @@ -100,6 +100,11 @@ struct private_imv_swima_state_t { */ imv_remediation_string_t *remediation_string; + /** + * Has a subscription been established? + */ + bool has_subscription; + /** * SWID Tag Request ID */ @@ -177,7 +182,16 @@ METHOD(imv_state_t, get_max_msg_len, uint32_t, METHOD(imv_state_t, set_action_flags, void, private_imv_swima_state_t *this, uint32_t flags) { - this->action_flags |= flags; + if (flags == 0) + { + /* reset action flags */ + this->action_flags = 0; + } + else + { + /* add flags */ + this->action_flags |= flags; + } } METHOD(imv_state_t, get_action_flags, uint32_t, @@ -426,6 +440,18 @@ METHOD(imv_swima_state_t, get_imc_id, TNC_UInt32, return this->imc_id; } +METHOD(imv_swima_state_t, set_subscription, void, + private_imv_swima_state_t *this, bool set) +{ + this->has_subscription = set; +} + +METHOD(imv_swima_state_t, get_subscription, bool, + private_imv_swima_state_t *this) +{ + return this->has_subscription; +} + /** * Described in header. */ @@ -467,6 +493,8 @@ imv_state_t *imv_swima_state_create(TNC_ConnectionID connection_id) .set_count = _set_count, .get_count = _get_count, .get_imc_id = _get_imc_id, + .set_subscription = _set_subscription, + .get_subscription = _get_subscription, }, .state = TNC_CONNECTION_STATE_CREATE, .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, diff --git a/src/libimcv/plugins/imv_swima/imv_swima_state.h b/src/libimcv/plugins/imv_swima/imv_swima_state.h index 4fa32daf4c..e2f8051893 100644 --- a/src/libimcv/plugins/imv_swima/imv_swima_state.h +++ b/src/libimcv/plugins/imv_swima/imv_swima_state.h @@ -141,6 +141,20 @@ struct imv_swima_state_t { * @return SWID IMC ID */ TNC_UInt32 (*get_imc_id)(imv_swima_state_t *this); + + /** + * Set or clear a subscription + * + * @param set TRUE sets and FALSE clears a subscripton + */ + void (*set_subscription)(imv_swima_state_t *this, bool set); + + /** + * Get the subscription status + * + * @return TRUE if subscription is set + */ + bool (*get_subscription)(imv_swima_state_t *this); }; /**