]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
imv-swima: Support subscriptions
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 25 Jul 2018 06:41:05 +0000 (08:41 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 30 Jul 2018 10:06:34 +0000 (12:06 +0200)
src/libimcv/imv/imv_database.c
src/libimcv/imv/imv_session.c
src/libimcv/imv/imv_session.h
src/libimcv/imv/imv_session_manager.c
src/libimcv/plugins/imv_swima/imv_swima_agent.c
src/libimcv/plugins/imv_swima/imv_swima_state.c
src/libimcv/plugins/imv_swima/imv_swima_state.h

index b444abdbb866a22538e9e710a9d6793cb4d0b8df..03f58320414f0a5c89dd693cabd759b7f001f52a 100644 (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))
index bc6b5a8d11e94500d9e5292f6cf76705d9c014b7..830dd48d4c5ea14412006743aec1c338439e0ca0 100644 (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(),
index 107716f30aaeeb5015fbb927572ad39b8e55f63d..a2f6fc2a832bb74f1e67bfb6e8f583a41008320e 100644 (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_ @}*/
index c9760299849b5dfa499e6756763342ff80c86345..2e3cfa46684ffb0c574f6c6f9e14bdbaff7b6a39 100644 (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);
index 1d9944200e782f0b83cb42ac1bf256160e1a0365..377c89d3d832d1d2bd4a89d6f1b87c16cd7ad148 100644 (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;
-
-                               /* 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;
index 03500bc2d359d76a89d16741e5b13ee11676380b..bcacce0b3f35dc14433d3342c13a7a797be2bfe6 100644 (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,
index 4fa32daf4c92cd20331c8eb4746f86e5bcf8acdd..e2f805189308ac3f28266f566ef388369b47ea76 100644 (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);
 };
 
 /**