imv-swima: Support subscriptions

This commit is contained in:
Andreas Steffen 2018-07-25 08:41:05 +02:00
parent f649a13cc6
commit 37c12f98b0
7 changed files with 138 additions and 48 deletions

View File

@ -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))

View File

@ -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(),

View File

@ -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_ @}*/

View File

@ -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);

View File

@ -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;
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);
/* 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);
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);
/* 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);
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);
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;

View File

@ -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,

View File

@ -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);
};
/**