refactored PA-TNC message handling by IMVs
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 17 Oct 2012 21:15:14 +0000 (23:15 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 17 Oct 2012 21:15:14 +0000 (23:15 +0200)
14 files changed:
src/libimcv/Makefile.am
src/libimcv/imc/imc_msg.c
src/libimcv/imv/imv_agent.c
src/libimcv/imv/imv_agent.h
src/libimcv/imv/imv_msg.c [new file with mode: 0644]
src/libimcv/imv/imv_msg.h [new file with mode: 0644]
src/libimcv/plugins/imv_os/imv_os.c
src/libimcv/plugins/imv_scanner/imv_scanner.c
src/libimcv/plugins/imv_test/imv_test.c
src/libpts/plugins/imv_attestation/imv_attestation.c
src/libpts/plugins/imv_attestation/imv_attestation_build.c
src/libpts/plugins/imv_attestation/imv_attestation_build.h
src/libpts/plugins/imv_attestation/imv_attestation_process.c
src/libpts/plugins/imv_attestation/imv_attestation_process.h

index 34746a8..41146c9 100644 (file)
@@ -10,6 +10,7 @@ libimcv_la_SOURCES = \
        imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \
        imc/imc_msg.h imc/imc_msg.c \
        imv/imv_agent.h imv/imv_agent.c imv/imv_state.h \
+       imv/imv_msg.h imv/imv_msg.c \
        ietf/ietf_attr.h ietf/ietf_attr.c \
        ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
        ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
index e21c985..80fc520 100644 (file)
@@ -100,7 +100,7 @@ METHOD(imc_msg_t, send_, TNC_Result,
        bool attr_added;
        chunk_t msg;
        enumerator_t *enumerator;
-       TNC_Result result;
+       TNC_Result result = TNC_RESULT_SUCCESS;
 
        while (this->attr_list->get_count(this->attr_list))
        {
index f6d13da..a21fb93 100644 (file)
@@ -96,44 +96,6 @@ struct private_imv_agent_t {
                                                                        TNC_UInt32 type_count);
 
        /**
-        * Call when an IMV-IMC message is to be sent
-        *
-        * @param imv_id                        IMV ID assigned by TNCS
-        * @param connection_id         network connection ID assigned by TNCS
-        * @param msg                           message to send
-        * @param msg_len                       message length in bytes
-        * @param msg_type                      message type
-        * @return                                      TNC result code
-        */
-       TNC_Result (*send_message)(TNC_IMVID imv_id,
-                                                          TNC_ConnectionID connection_id,
-                                                          TNC_BufferReference msg,
-                                                          TNC_UInt32 msg_len,
-                                                          TNC_MessageType msg_type);
-
-       /**
-        * Call when an IMV-IMC message is to be sent with long message types
-        *
-        * @param imv_id                        IMV ID assigned by TNCS
-        * @param connection_id         network connection ID assigned by TNCS
-        * @param msg_flags                     message flags
-        * @param msg                           message to send
-        * @param msg_len                       message length in bytes
-        * @param msg_vid                       message vendor ID
-        * @param msg_subtype           message subtype
-        * @param dst_imc_id            destination IMC ID
-        * @return                                      TNC result code
-        */
-       TNC_Result (*send_message_long)(TNC_IMVID imv_id,
-                                                                       TNC_ConnectionID connection_id,
-                                                                       TNC_UInt32 msg_flags,
-                                                                       TNC_BufferReference msg,
-                                                                       TNC_UInt32 msg_len,
-                                                                       TNC_VendorID msg_vid,
-                                                                       TNC_MessageSubtype msg_subtype,
-                                                                       TNC_UInt32 dst_imc_id);
-
-       /**
         * Deliver IMV Action Recommendation and IMV Evaluation Results to the TNCS
         *
         * @param imv_id                        IMV ID assigned by TNCS
@@ -219,14 +181,14 @@ METHOD(imv_agent_t, bind_functions, TNC_Result,
                this->public.request_handshake_retry = NULL;
        }
        if (bind_function(this->id, "TNC_TNCS_SendMessage",
-                       (void**)&this->send_message) != TNC_RESULT_SUCCESS)
+                       (void**)&this->public.send_message) != TNC_RESULT_SUCCESS)
        {
-               this->send_message = NULL;
+               this->public.send_message = NULL;
        }
        if (bind_function(this->id, "TNC_TNCS_SendMessageLong",
-                       (void**)&this->send_message_long) != TNC_RESULT_SUCCESS)
+                       (void**)&this->public.send_message_long) != TNC_RESULT_SUCCESS)
        {
-               this->send_message_long = NULL;
+               this->public.send_message_long = NULL;
        }
        if (bind_function(this->id, "TNC_TNCS_ProvideRecommendation",
                        (void**)&this->provide_recommendation) != TNC_RESULT_SUCCESS)
@@ -512,215 +474,18 @@ METHOD(imv_agent_t, get_state, bool,
        return TRUE;
 }
 
-METHOD(imv_agent_t, send_message, TNC_Result,
-       private_imv_agent_t *this, TNC_ConnectionID connection_id, bool excl,
-       TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, TNC_VendorID msg_vid,
-       TNC_MessageSubtype msg_subtype, linked_list_t *attr_list)
-{
-       TNC_MessageType type;
-       TNC_UInt32 msg_flags;
-       TNC_Result result = TNC_RESULT_FATAL;
-       imv_state_t *state;
-       pa_tnc_attr_t *attr;
-       pa_tnc_msg_t *pa_tnc_msg;
-       chunk_t msg;
-       enumerator_t *enumerator;
-       bool attr_added;
-
-       state = find_connection(this, connection_id);
-       if (!state)
-       {
-               DBG1(DBG_IMV, "IMV %u \"%s\" has no state for Connection ID %u",
-                                         this->id, this->name, connection_id);
-               return TNC_RESULT_FATAL;
-       }
-
-       while (attr_list->get_count(attr_list))
-       {
-               pa_tnc_msg = pa_tnc_msg_create(state->get_max_msg_len(state));
-               attr_added = FALSE;
-
-               enumerator = attr_list->create_enumerator(attr_list);
-               while (enumerator->enumerate(enumerator, &attr))
-               {
-                       if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
-                       {
-                               attr_added = TRUE;
-                       }
-                       else
-                       {
-                               if (attr_added)
-                               {
-                                       break;
-                               }
-                               else
-                               {
-                                       DBG1(DBG_IMV, "PA-TNC attribute too large to send, deleted");
-                                       attr->destroy(attr);
-                               }
-                       }
-                       attr_list->remove_at(attr_list, enumerator);
-               }
-               enumerator->destroy(enumerator);
-
-               /* build and send the PA-TNC message via the IF-IMV interface */
-               if (!pa_tnc_msg->build(pa_tnc_msg))
-               {
-                       pa_tnc_msg->destroy(pa_tnc_msg);
-                       return TNC_RESULT_FATAL;
-               }
-               msg = pa_tnc_msg->get_encoding(pa_tnc_msg);
-
-               if (state->has_long(state) && this->send_message_long)
-               {
-                       if (!src_imv_id)
-                       {
-                               src_imv_id = this->id;
-                       }
-                       msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
-
-                       result = this->send_message_long(src_imv_id, connection_id,
-                                                               msg_flags, msg.ptr, msg.len, msg_vid,
-                                                               msg_subtype, dst_imc_id);
-               }
-               else if (this->send_message)
-               {
-                       type = msg_vid << 8 | msg_subtype;
-
-                       result = this->send_message(this->id, connection_id, msg.ptr,
-                                                               msg.len, type);
-               }
-
-               pa_tnc_msg->destroy(pa_tnc_msg);
-
-               if (result != TNC_RESULT_SUCCESS)
-               {
-                       break;
-               }
-       }
-       return result;
-}
-
-METHOD(imv_agent_t, set_recommendation, TNC_Result,
-       private_imv_agent_t *this, TNC_ConnectionID connection_id,
-                                                          TNC_IMV_Action_Recommendation rec,
-                                                          TNC_IMV_Evaluation_Result eval)
-{
-       imv_state_t *state;
-
-       state = find_connection(this, connection_id);
-       if (!state)
-       {
-               DBG1(DBG_IMV, "IMV %u \"%s\" has no state for Connection ID %u",
-                                         this->id, this->name, connection_id);
-               return TNC_RESULT_FATAL;
-       }
-
-       state->set_recommendation(state, rec, eval);
-       return this->provide_recommendation(this->id, connection_id, rec, eval);
-}
-
-METHOD(imv_agent_t, receive_message, TNC_Result,
-       private_imv_agent_t *this, imv_state_t *state, chunk_t msg,
-       TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype,
-       TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, pa_tnc_msg_t **pa_tnc_msg)
-{
-       pa_tnc_msg_t *pa_msg;
-       pa_tnc_attr_t *error_attr;
-       linked_list_t *error_attr_list;
-       enumerator_t *enumerator;
-       TNC_UInt32 src_imv_id, dst_imc_id;
-       TNC_ConnectionID connection_id;
-       TNC_Result result;
-
-       connection_id = state->get_connection_id(state);
-
-       if (state->has_long(state))
-       {
-               if (dst_imv_id != TNC_IMVID_ANY)
-               {
-                       DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u "
-                                                 "from IMC %u to IMV %u", this->id, this->name,
-                                                  connection_id, src_imc_id, dst_imv_id);
-               }
-               else
-               {
-                       DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u "
-                                                 "from IMC %u", this->id, this->name, connection_id,
-                                                  src_imc_id);
-               }
-       }
-       else
-       {
-               DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u",
-                                          this->id, this->name, connection_id);
-       }
-
-       *pa_tnc_msg = NULL;
-       pa_msg = pa_tnc_msg_create_from_data(msg);
-
-       switch (pa_msg->process(pa_msg))
-       {
-               case SUCCESS:
-                       *pa_tnc_msg = pa_msg;
-                       break;
-               case VERIFY_ERROR:
-                       /* extract and copy by refence all error attributes */
-                       error_attr_list = linked_list_create();
-
-                       enumerator = pa_msg->create_error_enumerator(pa_msg);
-                       while (enumerator->enumerate(enumerator, &error_attr))
-                       {
-                               error_attr_list->insert_last(error_attr_list,
-                                                                                        error_attr->get_ref(error_attr));
-                       }
-                       enumerator->destroy(enumerator);
-
-                       src_imv_id = (dst_imv_id == TNC_IMVID_ANY) ? this->id : dst_imv_id;
-                       dst_imc_id = state->has_excl(state) ? src_imc_id : TNC_IMCID_ANY;
-
-                       result = send_message(this, connection_id, state->has_excl(state),
-                                                                 src_imv_id, dst_imc_id, msg_vid, msg_subtype,
-                                                                 error_attr_list);
-
-                       error_attr_list->destroy(error_attr_list);
-                       pa_msg->destroy(pa_msg);
-                       return result;
-               case FAILED:
-               default:
-                       pa_msg->destroy(pa_msg);
-                       state->set_recommendation(state,
-                                                       TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
-                                                       TNC_IMV_EVALUATION_RESULT_ERROR);
-                       return this->provide_recommendation(this->id, connection_id,
-                                                       TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
-                                                       TNC_IMV_EVALUATION_RESULT_ERROR);
-       }
-       return TNC_RESULT_SUCCESS;
-}
-
 METHOD(imv_agent_t, provide_recommendation, TNC_Result,
-       private_imv_agent_t *this, TNC_ConnectionID connection_id,
-       TNC_UInt32 dst_imc_id, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype)
+       private_imv_agent_t *this, imv_state_t *state)
 {
-       imv_state_t *state;
-       linked_list_t *attr_list;
-       pa_tnc_attr_t *attr;
-       TNC_Result result;
        TNC_IMV_Action_Recommendation rec;
        TNC_IMV_Evaluation_Result eval;
+       TNC_ConnectionID connection_id;
        TNC_UInt32 lang_len;
        char buf[BUF_LEN];
        chunk_t pref_lang = { buf, 0 }, reason_string, reason_lang;
 
-       state = find_connection(this, connection_id);
-       if (!state)
-       {
-               DBG1(DBG_IMV, "IMV %u \"%s\" has no state for Connection ID %u",
-                                         this->id, this->name, connection_id);
-               return TNC_RESULT_FATAL;
-       }
        state->get_recommendation(state, &rec, &eval);
+       connection_id = state->get_connection_id(state);
 
        /* send a reason string if action recommendation is not allow */
        if (rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
@@ -750,24 +515,21 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result,
                                                                reason_lang.len, reason_lang.ptr);
                }
        }
-
-       /* Send an IETF Assessment Result attribute if enabled */
-       if (lib->settings->get_bool(lib->settings, "libimcv.assessment_result", TRUE))
-       {
-               attr = ietf_attr_assess_result_create(eval);
-               attr_list = linked_list_create();
-               attr_list->insert_last(attr_list, attr);
-               result = send_message(this, connection_id, FALSE, this->id, dst_imc_id,
-                                                         msg_vid, msg_subtype, attr_list);
-               attr_list->destroy(attr_list);
-               if (result != TNC_RESULT_SUCCESS)
-               {
-                       return result;
-               }
-       }
        return this->provide_recommendation(this->id, connection_id, rec, eval);
 }
 
+METHOD(imv_agent_t, get_name, const char*,
+       private_imv_agent_t *this)
+{
+       return  this->name;
+}
+
+METHOD(imv_agent_t, get_id, TNC_IMVID,
+       private_imv_agent_t *this)
+{
+       return  this->id;
+}
+
 METHOD(imv_agent_t, reserve_additional_ids, TNC_Result,
        private_imv_agent_t *this, int count)
 {
@@ -849,10 +611,9 @@ imv_agent_t *imv_agent_create(const char *name,
                        .delete_state = _delete_state,
                        .change_state = _change_state,
                        .get_state = _get_state,
-                       .send_message = _send_message,
-                       .receive_message = _receive_message,
-                       .set_recommendation = _set_recommendation,
                        .provide_recommendation = _provide_recommendation,
+                       .get_name = _get_name,
+                       .get_id = _get_id,
                        .reserve_additional_ids = _reserve_additional_ids,
                        .count_additional_ids = _count_additional_ids,
                        .create_id_enumerator = _create_id_enumerator,
index 45d0cbd..4a4e718 100644 (file)
@@ -51,6 +51,44 @@ struct imv_agent_t {
                                                                                  TNC_RetryReason reason);
 
        /**
+        * Call when an IMV-IMC message is to be sent
+        *
+        * @param imv_id                        IMV ID assigned by TNCS
+        * @param connection_id         network connection ID assigned by TNCS
+        * @param msg                           message to send
+        * @param msg_len                       message length in bytes
+        * @param msg_type                      message type
+        * @return                                      TNC result code
+        */
+       TNC_Result (*send_message)(TNC_IMVID imv_id,
+                                                          TNC_ConnectionID connection_id,
+                                                          TNC_BufferReference msg,
+                                                          TNC_UInt32 msg_len,
+                                                          TNC_MessageType msg_type);
+
+       /**
+        * Call when an IMV-IMC message is to be sent with long message types
+        *
+        * @param imv_id                        IMV ID assigned by TNCS
+        * @param connection_id         network connection ID assigned by TNCS
+        * @param msg_flags                     message flags
+        * @param msg                           message to send
+        * @param msg_len                       message length in bytes
+        * @param msg_vid                       message vendor ID
+        * @param msg_subtype           message subtype
+        * @param dst_imc_id            destination IMC ID
+        * @return                                      TNC result code
+        */
+       TNC_Result (*send_message_long)(TNC_IMVID imv_id,
+                                                                       TNC_ConnectionID connection_id,
+                                                                       TNC_UInt32 msg_flags,
+                                                                       TNC_BufferReference msg,
+                                                                       TNC_UInt32 msg_len,
+                                                                       TNC_VendorID msg_vid,
+                                                                       TNC_MessageSubtype msg_subtype,
+                                                                       TNC_UInt32 dst_imc_id);
+
+       /**
         * Bind TNCS functions
         *
         * @param bind_function         function offered by the TNCS
@@ -100,71 +138,26 @@ struct imv_agent_t {
                                          TNC_ConnectionID connection_id, imv_state_t **state);
 
        /**
-        * Call when a PA-TNC message is to be sent
-        *
-        * @param connection_id         network connection ID assigned by TNCS
-        * @param excl                          exclusive flag
-        * @param src_imv_id            IMV ID to be set as source
-        * @param dst_imc_id            IMD ID to be set as destination
-        * @param msg_vid                       message vendor ID
-        * @param msg_subtype           message subtype
-        * @param attr_list                     list of PA-TNC attributes to send
-        * @return                                      TNC result code
-        */
-       TNC_Result (*send_message)(imv_agent_t *this,
-                                                          TNC_ConnectionID connection_id, bool excl,
-                                                          TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id,
-                                                          TNC_VendorID msg_vid,
-                                                          TNC_MessageSubtype msg_subtype,
-                                                          linked_list_t *attr_list);
-
-       /**
-        * Call when a PA-TNC message was received
+        * Deliver IMV Action Recommendation and IMV Evaluation Result to the TNCS
         *
-        * @param state                         state for current connection
-        * @param msg                           received unparsed message
-        * @param msg_vid                       message vendorID of the received message
-        * @param msg_subtype           message subtype of the received message
-        * @param src_imc_id            source IMC ID
-        * @param dst_imv_id            destination IMV ID
-        * @param pa_tnc_message        parsed PA-TNC message or NULL if an error occurred
+        * @param state                         state bound to a connection ID
         * @return                                      TNC result code
         */
-       TNC_Result (*receive_message)(imv_agent_t *this,
-                                                                 imv_state_t *state, chunk_t msg,
-                                                                 TNC_VendorID msg_vid,
-                                                                 TNC_MessageSubtype msg_subtype,
-                                                                 TNC_UInt32 src_imc_id,
-                                                                 TNC_UInt32 dst_imv_id,
-                                                                 pa_tnc_msg_t **pa_tnc_msg);
+       TNC_Result (*provide_recommendation)(imv_agent_t *this, imv_state_t* state);
 
        /**
-        * Set Action Recommendation and Evaluation Result in the IMV state
+        * Get IMV name
         *
-        * @param connection_id         network connection ID assigned by TNCS
-        * @param rec                           IMV action recommendation
-        * @param eval                          IMV evaluation result
-        * @return                                      TNC result code
+        * return                                       IMV name
         */
-       TNC_Result (*set_recommendation)(imv_agent_t *this,
-                                                                        TNC_ConnectionID connection_id,
-                                                                        TNC_IMV_Action_Recommendation rec,
-                                                                        TNC_IMV_Evaluation_Result eval);
+       const char* (*get_name)(imv_agent_t *this);
 
        /**
-        * Deliver IMV Action Recommendation and IMV Evaluation Result to the TNCS
+        * Get base IMV ID
         *
-        * @param connection_id         network connection ID assigned by TNCS
-        * @param dst_imc_id            IMD ID to be set as destination
-        * @param msg_vid                       message vendor ID
-        * @param msg_subtype           message subtype
-        * @return                                      TNC result code
+        * return                                       base IMV ID
         */
-       TNC_Result (*provide_recommendation)(imv_agent_t *this,
-                                                                                TNC_ConnectionID connection_id,
-                                                                                TNC_UInt32 dst_imc_id,
-                                                                                TNC_VendorID msg_vid,
-                                                                                TNC_MessageSubtype msg_subtype);
+       TNC_IMVID (*get_id)(imv_agent_t *this);
 
        /**
         * Reserve additional IMV IDs from TNCS
diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c
new file mode 100644 (file)
index 0000000..9781c28
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_msg.h"
+
+#include "ietf/ietf_attr.h"
+#include "ietf/ietf_attr_assess_result.h"
+
+#include <tncif_names.h>
+
+#include <pen/pen.h>
+#include <utils/linked_list.h>
+#include <debug.h>
+
+typedef struct private_imv_msg_t private_imv_msg_t;
+
+/**
+ * Private data of a imv_msg_t object.
+ *
+ */
+struct private_imv_msg_t {
+
+       /**
+        * Public imv_msg_t interface.
+        */
+       imv_msg_t public;
+
+       /**
+        * Connection ID 
+        */
+       TNC_ConnectionID connection_id;
+
+       /**
+        * source ID 
+        */
+       TNC_UInt32 src_id; 
+
+       /**
+        * destination ID 
+        */
+       TNC_UInt32 dst_id; 
+
+       /**
+        * PA-TNC message type 
+        */
+       pen_type_t msg_type; 
+
+       /**
+        * List of PA-TNC attributes to be sent
+        */
+       linked_list_t *attr_list;
+
+       /**
+        * PA-TNC message 
+        */
+       pa_tnc_msg_t *pa_msg;
+
+       /**
+        * Assigned IMV agent 
+        */
+       imv_agent_t *agent;
+
+       /**
+        * Assigned IMV state 
+        */
+       imv_state_t *state;
+};
+
+METHOD(imv_msg_t, get_src_id, TNC_UInt32,
+       private_imv_msg_t *this)
+{
+       return this->src_id;
+}
+
+METHOD(imv_msg_t, get_dst_id, TNC_UInt32,
+       private_imv_msg_t *this)
+{
+       return this->dst_id;
+}
+
+METHOD(imv_msg_t, set_msg_type, void,
+       private_imv_msg_t *this, pen_type_t msg_type)
+{
+       if (msg_type.vendor_id != this->msg_type.vendor_id ||
+               msg_type.type != this->msg_type.type)
+       {
+               this->msg_type = msg_type;
+               this->dst_id = TNC_IMCID_ANY;
+       }
+}
+
+METHOD(imv_msg_t, add_attribute, void,
+       private_imv_msg_t *this, pa_tnc_attr_t *attr)
+{
+       this->attr_list->insert_last(this->attr_list, attr);
+}
+
+METHOD(imv_msg_t, send_, TNC_Result,
+       private_imv_msg_t *this, bool excl)
+{
+       pa_tnc_msg_t *pa_tnc_msg;
+       pa_tnc_attr_t *attr;
+       TNC_UInt32 msg_flags;
+       TNC_MessageType msg_type;
+       bool attr_added;
+       chunk_t msg;
+       enumerator_t *enumerator;
+       TNC_Result result = TNC_RESULT_SUCCESS;
+
+       while (this->attr_list->get_count(this->attr_list))
+       {
+               pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
+               attr_added = FALSE;
+
+               enumerator = this->attr_list->create_enumerator(this->attr_list);
+               while (enumerator->enumerate(enumerator, &attr))
+               {
+                       if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
+                       {
+                               attr_added = TRUE;
+                       }
+                       else
+                       {
+                               if (attr_added)
+                               {
+                                       break;
+                               }
+                               else
+                               {
+                                       DBG1(DBG_IMV, "PA-TNC attribute too large to send, deleted");
+                                       attr->destroy(attr);
+                               }
+                       }
+                       this->attr_list->remove_at(this->attr_list, enumerator);
+               }
+               enumerator->destroy(enumerator);
+
+               /* build and send the PA-TNC message via the IF-IMV interface */
+               if (!pa_tnc_msg->build(pa_tnc_msg))
+               {
+                       pa_tnc_msg->destroy(pa_tnc_msg);
+                       return TNC_RESULT_FATAL;
+               }
+               msg = pa_tnc_msg->get_encoding(pa_tnc_msg);
+               DBG3(DBG_IMV, "created PA-TNC message: %B", &msg);
+
+               if (this->state->has_long(this->state) && this->agent->send_message_long)
+               {
+                       excl = excl && this->state->has_excl(this->state) && 
+                                                  this->dst_id != TNC_IMCID_ANY;
+                       msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
+                       result = this->agent->send_message_long(this->src_id,
+                                                       this->connection_id, msg_flags, msg.ptr, msg.len,
+                                                       this->msg_type.vendor_id, this->msg_type.type,
+                                                       this->dst_id);
+               }
+               else if (this->agent->send_message)
+               {
+                       msg_type = (this->msg_type.vendor_id << 8) |
+                                          (this->msg_type.type & 0x000000ff);
+                       result = this->agent->send_message(this->src_id, this->connection_id,
+                                                                                          msg.ptr, msg.len, msg_type);
+               }
+
+               pa_tnc_msg->destroy(pa_tnc_msg);
+
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       break;
+               }
+       }
+       return result;
+}
+
+METHOD(imv_msg_t, send_assessment, TNC_Result,
+       private_imv_msg_t *this)
+{
+       TNC_IMV_Action_Recommendation rec;
+       TNC_IMV_Evaluation_Result eval;
+       pa_tnc_attr_t *attr;
+
+       /* Send an IETF Assessment Result attribute if enabled */
+       if (lib->settings->get_bool(lib->settings, "libimcv.assessment_result",
+                                                               TRUE))
+       {
+               this->state->get_recommendation(this->state, &rec, &eval);
+               attr = ietf_attr_assess_result_create(eval);
+               add_attribute(this, attr);
+
+               /* send PA-TNC message with the excl flag set */
+               return send_(this, TRUE);
+       }
+       return TNC_RESULT_SUCCESS;
+}
+
+METHOD(imv_msg_t, receive, TNC_Result,
+       private_imv_msg_t *this, bool *fatal_error)
+{
+       enumerator_t *enumerator;
+       pa_tnc_attr_t *attr;
+       chunk_t msg;
+
+       if (this->state->has_long(this->state))
+       {
+               if (this->dst_id != TNC_IMVID_ANY)
+               {
+                       DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u "
+                                                 "from IMC %u to IMV %u",
+                                                  this->agent->get_id(this->agent),
+                                                  this->agent->get_name(this->agent),
+                                                  this->connection_id, this->src_id, this->dst_id);
+               }
+               else
+               {
+                       DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u "
+                                                 "from IMC %u", this->agent->get_id(this->agent),
+                                                  this->agent->get_name(this->agent),
+                                                  this->connection_id, this->src_id);
+               }
+       }
+       else
+       {
+               DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u",
+                                          this->agent->get_id(this->agent),
+                                          this->agent->get_name(this->agent),
+                                          this->connection_id);
+       }
+       msg = this->pa_msg->get_encoding(this->pa_msg);
+       DBG3(DBG_IMV, "%B", &msg);
+
+       switch (this->pa_msg->process(this->pa_msg))
+       {
+               case SUCCESS:
+                       break;
+               case VERIFY_ERROR:
+               {
+                       imv_msg_t *error_msg;
+                       TNC_Result result;
+
+                       error_msg = imv_msg_create_as_reply(&this->public);
+
+                       /* extract and copy by reference all error attributes */
+                       enumerator = this->pa_msg->create_error_enumerator(this->pa_msg);
+                       while (enumerator->enumerate(enumerator, &attr))
+                       {
+                               error_msg->add_attribute(error_msg, attr->get_ref(attr));
+                       }
+                       enumerator->destroy(enumerator);
+
+                       /* 
+                        * send the PA-TNC message containing all error attributes
+                        * with the excl flag set
+                        */
+                       result = error_msg->send(error_msg, TRUE);
+                       error_msg->destroy(error_msg);
+                       return result;
+               }
+               case FAILED:
+               default:
+                       return TNC_RESULT_FATAL;
+       }
+
+       /* preprocess any received IETF standard error attributes */
+       *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg);
+               
+       return TNC_RESULT_SUCCESS;
+}
+
+METHOD(imv_msg_t, delete_attributes, void,
+       private_imv_msg_t *this)
+{
+       pa_tnc_attr_t *attr;
+
+       while (this->attr_list->remove_last(this->attr_list, (void**)&attr) == SUCCESS)
+       {
+               attr->destroy(attr);
+       }
+}
+
+METHOD(imv_msg_t, create_attribute_enumerator, enumerator_t*,
+       private_imv_msg_t *this)
+{
+       return this->pa_msg->create_attribute_enumerator(this->pa_msg);
+}
+
+METHOD(imv_msg_t, destroy, void,
+       private_imv_msg_t *this)
+{
+       this->attr_list->destroy_offset(this->attr_list,
+                                                                       offsetof(pa_tnc_attr_t, destroy));
+       DESTROY_IF(this->pa_msg);
+       free(this);
+}
+
+/**
+ * See header
+ */
+imv_msg_t *imv_msg_create(imv_agent_t *agent, imv_state_t *state,
+                                                 TNC_ConnectionID connection_id,
+                                                 TNC_UInt32 src_id, TNC_UInt32 dst_id,
+                                                 pen_type_t msg_type)
+{
+       private_imv_msg_t *this;
+
+       INIT(this,
+               .public = {
+                       .get_src_id = _get_src_id,
+                       .get_dst_id = _get_dst_id,
+                       .set_msg_type = _set_msg_type,
+                       .send = _send_,
+                       .send_assessment = _send_assessment,
+                       .receive = _receive,
+                       .add_attribute = _add_attribute,
+                       .create_attribute_enumerator = _create_attribute_enumerator,
+                       .destroy = _destroy,
+               },
+               .connection_id = connection_id,
+               .src_id = src_id,
+               .dst_id = dst_id,
+               .msg_type = msg_type,
+               .attr_list = linked_list_create(),
+               .agent = agent,
+               .state = state,
+       );
+
+       return &this->public;
+}
+
+/**
+ * See header
+ */
+imv_msg_t* imv_msg_create_as_reply(imv_msg_t *msg)
+{
+       private_imv_msg_t *in;
+       TNC_UInt32 src_id;
+
+       in = (private_imv_msg_t*)msg;
+       src_id = (in->dst_id != TNC_IMVID_ANY) ? 
+                         in->dst_id : in->agent->get_id(in->agent);
+
+       return imv_msg_create(in->agent, in->state, in->connection_id, src_id,
+                                                 in->src_id, in->msg_type);
+}
+
+/**
+ * See header
+ */
+imv_msg_t *imv_msg_create_from_data(imv_agent_t *agent, imv_state_t *state,
+                                                                       TNC_ConnectionID connection_id,
+                                                                       TNC_MessageType msg_type,
+                                                                       chunk_t msg)
+{
+       TNC_VendorID msg_vid;
+       TNC_MessageSubtype msg_subtype;
+
+       msg_vid = msg_type >> 8;
+       msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+
+       return imv_msg_create_from_long_data(agent, state, connection_id,
+                                                               TNC_IMCID_ANY, agent->get_id(agent),  
+                                                               msg_vid, msg_subtype, msg);
+}
+
+/**
+ * See header
+ */
+imv_msg_t *imv_msg_create_from_long_data(imv_agent_t *agent, imv_state_t *state,
+                                                                                TNC_ConnectionID connection_id,
+                                                                                TNC_UInt32 src_id,
+                                                                                TNC_UInt32 dst_id,
+                                                                                TNC_VendorID msg_vid,
+                                                                                TNC_MessageSubtype msg_subtype,
+                                                                                chunk_t msg)
+{
+       private_imv_msg_t *this;
+
+       INIT(this,
+               .public = {
+                       .get_src_id = _get_src_id,
+                       .get_dst_id = _get_dst_id,
+                       .set_msg_type = _set_msg_type,
+                       .send = _send_,
+                       .receive = _receive,
+                       .add_attribute = _add_attribute,
+                       .delete_attributes = _delete_attributes,
+                       .create_attribute_enumerator = _create_attribute_enumerator,
+                       .destroy = _destroy,
+               },
+               .connection_id = connection_id,
+               .src_id = src_id,
+               .dst_id = dst_id,
+               .msg_type = pen_type_create(msg_vid, msg_subtype),
+               .attr_list = linked_list_create(),
+               .pa_msg = pa_tnc_msg_create_from_data(msg),
+               .agent = agent,
+               .state = state,
+       );
+
+       return &this->public;
+}
+
diff --git a/src/libimcv/imv/imv_msg.h b/src/libimcv/imv/imv_msg.h
new file mode 100644 (file)
index 0000000..43e646d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup imv_msg imv_msg
+ * @{ @ingroup libimcv
+ */
+
+#ifndef IMV_MSG_H_
+#define IMV_MSG_H_
+
+#include <imv/imv_agent.h>
+
+typedef struct imv_msg_t imv_msg_t;
+
+#include <library.h>
+
+/**
+ * Interface for a PA-TNC message handled by an IMV.
+ *
+ */
+struct imv_msg_t {
+
+       /**
+        * Get source ID of PA-TNC message
+        *
+        * @return                                      src ID
+        */
+       TNC_UInt32 (*get_src_id)(imv_msg_t *this);
+
+       /**
+        * Get destination ID of PA-TNC message
+        *
+        * @return                                      destination ID
+        */
+       TNC_UInt32 (*get_dst_id)(imv_msg_t *this);
+
+       /**
+        * Set the type of a PA-TNC message
+        *
+        * @param msg_type                      message type
+        */
+       void (*set_msg_type)(imv_msg_t *this, pen_type_t msg_type);
+
+       /**
+        * Sends one or multiple PA-TNC messages
+        *
+        * @param excl                          set the excl message flag if supported
+        * @return                                      TNC result code
+        */
+       TNC_Result (*send)(imv_msg_t *this, bool excl);
+
+       /**
+        * Send a PA-TNC message containing an IETF Assessment Result attribute
+        *
+        * @return                                      TNC result code
+        */
+       TNC_Result (*send_assessment)(imv_msg_t *this);
+
+       /**
+        * Processes a received PA-TNC message
+        *
+        * @param fatal_error           TRUE if IMC sent a fatal error message
+        * @return                                      TNC result code
+        */
+       TNC_Result (*receive)(imv_msg_t *this, bool *fatal_error);
+
+       /**
+        * Add a PA-TNC attribute to the send queue
+        *
+        * @param attr                          PA-TNC attribute to be added
+        */
+       void (*add_attribute)(imv_msg_t *this, pa_tnc_attr_t *attr);
+       
+       /**
+        * Delete all PA-TNC attributes in the send queue
+        *
+        */
+       void (*delete_attributes)(imv_msg_t *this);
+
+       /**
+        * Enumerator over PA-TNC attributes contained in the PA-TNC message
+        *
+        * @return                                      PA-TNC attribute enumerator
+        */
+       enumerator_t* (*create_attribute_enumerator)(imv_msg_t *this);
+
+       /**
+        * Destroys a imv_msg_t object.
+        */
+       void (*destroy)(imv_msg_t *this);
+};
+
+/**
+ * Create a wrapper for an outbound message
+ *
+ * @param agent                                        IMV agent responsible for the message
+ * @param state                                        IMV state for the given connection ID
+ * @param connection_id                        connection ID
+ * @param src_id                               source IMV ID
+ * @param dst_id                               destination IMC ID
+ * @param msg_type                             PA-TNC message type
+ */
+imv_msg_t* imv_msg_create(imv_agent_t *agent, imv_state_t *state,
+                                                 TNC_ConnectionID connection_id,
+                                                 TNC_UInt32 src_id, TNC_UInt32 dst_id,
+                                                 pen_type_t msg_type);
+
+/**
+ * Create a wrapper for an outbound message based on a received message
+ *
+ * @param msg                                  received message the reply is based on
+ */
+imv_msg_t* imv_msg_create_as_reply(imv_msg_t *msg);
+
+/**
+ * Create a wrapper around message data received via the legacy IF-IMV interface
+ *
+ * @param agent                                        IMV agent responsible for the message
+ * @param state                                        IMV state for the given connection ID
+ * @param connection_id                        connection ID
+ * @param msg_type                             PA-TNC message type
+ * @param msg                                  received PA-TNC message blob
+ */
+imv_msg_t* imv_msg_create_from_data(imv_agent_t *agent, imv_state_t *state,
+                                                                       TNC_ConnectionID connection_id,
+                                                                       TNC_MessageType msg_type,
+                                                                       chunk_t msg); 
+
+/**
+ * Create a wrapper around message data received via the long IF-IMV interface
+ *
+ * @param agent                                        IMV agent responsible for the message
+ * @param state                                        IMV state for the given connection ID
+ * @param connection_id                        connection ID
+ * @param src_id                               source IMC ID
+ * @param dst_id                               destination IMV ID
+ * @param msg_flags                            PA-TNC message flags
+ * @param msg_vid                              PA-TNC message vendor ID
+ * @param msg_subtype                  PA-TNC subtype
+ * @param msg                                  received PA-TNC message blob
+ */
+imv_msg_t* imv_msg_create_from_long_data(imv_agent_t *agent, imv_state_t *state,
+                                                                                TNC_ConnectionID connection_id,
+                                                                                TNC_UInt32 src_id, TNC_UInt32 dst_id,
+                                                                                TNC_VendorID msg_vid,
+                                                                                TNC_MessageSubtype msg_subtype,
+                                                                                chunk_t msg); 
+
+#endif /** IMV_MSG_H_ @}*/
index e050b6d..d7832f7 100644 (file)
@@ -16,6 +16,7 @@
 #include "imv_os_state.h"
 
 #include <imv/imv_agent.h>
+#include <imv/imv_msg.h>
 #include <pa_tnc/pa_tnc_msg.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_attr_request.h>
@@ -99,56 +100,30 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
        }
 }
 
-static TNC_Result receive_message(TNC_IMVID imv_id,
-                                                                 TNC_ConnectionID connection_id,
-                                                                 TNC_UInt32 msg_flags,
-                                                                 chunk_t msg,
-                                                                 TNC_VendorID msg_vid,
-                                                                 TNC_MessageSubtype msg_subtype,
-                                                                 TNC_UInt32 src_imc_id,
-                                                                 TNC_UInt32 dst_imv_id)
+static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
 {
-       pa_tnc_msg_t *pa_tnc_msg;
-       pa_tnc_attr_t *attr;
-       pen_type_t type;
-       linked_list_t *attr_list;
-       imv_state_t *state;
+       imv_msg_t *out_msg;
        imv_os_state_t *os_state;
        enumerator_t *enumerator;
+       pa_tnc_attr_t *attr;
+       pen_type_t type;
        TNC_Result result;
        chunk_t os_name = chunk_empty;
        chunk_t os_version = chunk_empty;
-       bool fatal_error, assessment = FALSE;
+       bool fatal_error = FALSE, assessment = FALSE;
 
-       if (!imv_os)
-       {
-               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
-               return TNC_RESULT_NOT_INITIALIZED;
-       }
 
-       /* get current IMV state */
-       if (!imv_os->get_state(imv_os, connection_id, &state))
-       {
-               return TNC_RESULT_FATAL;
-       }
-       os_state = (imv_os_state_t*)state;
-
-       /* parse received PA-TNC message and automatically handle any errors */ 
-       result = imv_os->receive_message(imv_os, state, msg, msg_vid,
-                                                       msg_subtype, src_imc_id, dst_imv_id, &pa_tnc_msg);
-
-       /* no parsed PA-TNC attributes available if an error occurred */
-       if (!pa_tnc_msg)
+       /* parse received PA-TNC message and handle local and remote errors */
+       result = in_msg->receive(in_msg, &fatal_error);
+       if (result != TNC_RESULT_SUCCESS)
        {
                return result;
        }
 
-       /* preprocess any IETF standard error attributes */
-       fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg);
+       out_msg = imv_msg_create_as_reply(in_msg);
 
        /* analyze PA-TNC attributes */
-       attr_list = linked_list_create();
-       enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
+       enumerator = in_msg->create_attribute_enumerator(in_msg);
        while (enumerator->enumerate(enumerator, &attr))
        {
                type = attr->get_type(attr);
@@ -251,6 +226,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
        {
                char *product_info;
 
+               os_state = (imv_os_state_t*)state;
                os_state->set_info(os_state, os_name, os_version);
                product_info = os_state->get_info(os_state);
 
@@ -269,10 +245,9 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
                                                   product_info);
                        attr = ietf_attr_attr_request_create(PEN_IETF,
                                                                IETF_ATTR_INSTALLED_PACKAGES);
-                       attr_list->insert_last(attr_list, attr);
+                       out_msg->add_attribute(out_msg, attr);
                }
        }
-       pa_tnc_msg->destroy(pa_tnc_msg);
 
        if (fatal_error)
        {
@@ -284,15 +259,18 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
 
        if (assessment)
        {
-               attr_list->destroy_offset(attr_list, offsetof(pa_tnc_attr_t, destroy));
-               return imv_os->provide_recommendation(imv_os, connection_id, src_imc_id,
-                                                                       PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM);
+               result = out_msg->send_assessment(out_msg);
+               out_msg->destroy(out_msg);
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       return result;
+               }  
+               return imv_os->provide_recommendation(imv_os, state);
        }
 
-       result = imv_os->send_message(imv_os, connection_id, TRUE, imv_id,
-                                       src_imc_id, PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM,
-                                       attr_list);
-       attr_list->destroy(attr_list);
+       /* send PA-TNC message with excl flag set */ 
+       result = out_msg->send(out_msg, TRUE);
+       out_msg->destroy(out_msg);
 
        return result;
  }
@@ -306,14 +284,25 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                                                  TNC_UInt32 msg_len,
                                                                  TNC_MessageType msg_type)
 {
-       TNC_VendorID msg_vid;
-       TNC_MessageSubtype msg_subtype;
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
 
-       msg_vid = msg_type >> 8;
-       msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+       if (!imv_os)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_os->get_state(imv_os, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imv_msg_create_from_data(imv_os, state, connection_id, msg_type,
+                                                                         chunk_create(msg, msg_len));
+       result = receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
 
-       return receive_message(imv_id, connection_id, 0, chunk_create(msg, msg_len),
-                                                  msg_vid,     msg_subtype, 0, TNC_IMVID_ANY);
+       return result;
 }
 
 /**
@@ -329,9 +318,26 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
                                                                          TNC_UInt32 src_imc_id,
                                                                          TNC_UInt32 dst_imv_id)
 {
-       return receive_message(imv_id, connection_id, msg_flags,
-                                                  chunk_create(msg, msg_len), msg_vid, msg_subtype,
-                                                  src_imc_id, dst_imv_id);
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
+
+       if (!imv_os)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_os->get_state(imv_os, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imv_msg_create_from_long_data(imv_os, state, connection_id,
+                                                               src_imc_id, dst_imv_id, msg_vid, msg_subtype,
+                                                               chunk_create(msg, msg_len));
+       result =receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
+
+       return result;
 }
 
 /**
@@ -340,13 +346,18 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
                                                                                 TNC_ConnectionID connection_id)
 {
+       imv_state_t *state;
+
        if (!imv_os)
        {
                DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
-       return imv_os->provide_recommendation(imv_os, connection_id, TNC_IMCID_ANY,
-                                                               PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM);
+       if (!imv_os->get_state(imv_os, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       return imv_os->provide_recommendation(imv_os, state);
 }
 
 /**
@@ -364,8 +375,6 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
                DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
-
-       /* get current IMV state */
        if (!imv_os->get_state(imv_os, connection_id, &state))
        {
                return TNC_RESULT_FATAL;
@@ -374,11 +383,12 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
 
        if (os_state->get_info(os_state) == NULL)
        {
+               imv_msg_t *out_msg;
                pa_tnc_attr_t *attr;
-               linked_list_t *attr_list;
                ietf_attr_attr_request_t *attr_cast;
 
-               attr_list = linked_list_create();
+               out_msg = imv_msg_create(imv_os, state, connection_id, imv_id,
+                                                                TNC_IMCID_ANY, msg_types[0]);
                attr = ietf_attr_attr_request_create(PEN_IETF,
                                                                                         IETF_ATTR_PRODUCT_INFORMATION);
                attr_cast = (ietf_attr_attr_request_t*)attr;
@@ -386,11 +396,11 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_OPERATIONAL_STATUS);
                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED);
                attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
-               attr_list->insert_last(attr_list, attr);
-               result = imv_os->send_message(imv_os, connection_id, FALSE, imv_id,
-                                       TNC_IMCID_ANY, PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM,
-                                       attr_list);
-               attr_list->destroy(attr_list);
+               out_msg->add_attribute(out_msg, attr);
+
+               /* send PA-TNC message with excl flag not set */
+               result = out_msg->send(out_msg, FALSE);
+               out_msg->destroy(out_msg);
        }
 
        return result;
index 5766922..4989d48 100644 (file)
@@ -16,6 +16,7 @@
 #include "imv_scanner_state.h"
 
 #include <imv/imv_agent.h>
+#include <imv/imv_msg.h>
 #include <pa_tnc/pa_tnc_msg.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_pa_tnc_error.h>
@@ -176,50 +177,24 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
        }
 }
 
-static TNC_Result receive_message(TNC_IMVID imv_id,
-                                                                 TNC_ConnectionID connection_id,
-                                                                 TNC_UInt32 msg_flags,
-                                                                 chunk_t msg,
-                                                                 TNC_VendorID msg_vid,
-                                                                 TNC_MessageSubtype msg_subtype,
-                                                                 TNC_UInt32 src_imc_id,
-                                                                 TNC_UInt32 dst_imv_id)
+static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
 {
-       pa_tnc_msg_t *pa_tnc_msg;
+       imv_msg_t *out_msg;
+       enumerator_t *enumerator;
        pa_tnc_attr_t *attr;
        pen_type_t type;
-       imv_state_t *state;
-       enumerator_t *enumerator;
        TNC_Result result;
-       bool fatal_error;
-
-       if (!imv_scanner)
-       {
-               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
-               return TNC_RESULT_NOT_INITIALIZED;
-       }
-
-       /* get current IMV state */
-       if (!imv_scanner->get_state(imv_scanner, connection_id, &state))
-       {
-               return TNC_RESULT_FATAL;
-       }
+       bool fatal_error = FALSE;
 
-       /* parse received PA-TNC message and automatically handle any errors */ 
-       result = imv_scanner->receive_message(imv_scanner, state, msg, msg_vid,
-                                                       msg_subtype, src_imc_id, dst_imv_id, &pa_tnc_msg);
-
-       /* no parsed PA-TNC attributes available if an error occurred */
-       if (!pa_tnc_msg)
+       /* parse received PA-TNC message and handle local and remote errors */
+       result = in_msg->receive(in_msg, &fatal_error);
+       if (result != TNC_RESULT_SUCCESS)
        {
                return result;
        }
 
-       /* preprocess any IETF standard error attributes */
-       fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg);
-
        /* analyze PA-TNC attributes */
-       enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
+       enumerator = in_msg->create_attribute_enumerator(in_msg);
        while (enumerator->enumerate(enumerator, &attr))
        {
                type = attr->get_type(attr);
@@ -301,16 +276,22 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
                }               
        }
        enumerator->destroy(enumerator);
-       pa_tnc_msg->destroy(pa_tnc_msg);
 
        if (fatal_error)
        {
                state->set_recommendation(state,
                                                                TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
-                                                               TNC_IMV_EVALUATION_RESULT_ERROR);                         
+                                                               TNC_IMV_EVALUATION_RESULT_ERROR);
        }
-       return imv_scanner->provide_recommendation(imv_scanner, connection_id,
-                                                               src_imc_id, PEN_ITA, PA_SUBTYPE_ITA_SCANNER);
+
+       out_msg = imv_msg_create_as_reply(in_msg);
+       result = out_msg->send_assessment(out_msg);
+       out_msg->destroy(out_msg);
+       if (result != TNC_RESULT_SUCCESS)
+       {
+               return result;
+       }  
+       return imv_scanner->provide_recommendation(imv_scanner, state);
  }
 
 /**
@@ -322,14 +303,26 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                                                  TNC_UInt32 msg_len,
                                                                  TNC_MessageType msg_type)
 {
-       TNC_VendorID msg_vid;
-       TNC_MessageSubtype msg_subtype;
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
 
-       msg_vid = msg_type >> 8;
-       msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+       if (!imv_scanner)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_scanner->get_state(imv_scanner, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+
+       in_msg = imv_msg_create_from_data(imv_scanner, state, connection_id, msg_type,
+                                                                         chunk_create(msg, msg_len));
+       result = receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
 
-       return receive_message(imv_id, connection_id, 0, chunk_create(msg, msg_len),
-                                                  msg_vid,     msg_subtype, 0, TNC_IMVID_ANY);
+       return result;
 }
 
 /**
@@ -345,9 +338,26 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
                                                                          TNC_UInt32 src_imc_id,
                                                                          TNC_UInt32 dst_imv_id)
 {
-       return receive_message(imv_id, connection_id, msg_flags,
-                                                  chunk_create(msg, msg_len), msg_vid, msg_subtype,
-                                                  src_imc_id, dst_imv_id);
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
+
+       if (!imv_scanner)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_scanner->get_state(imv_scanner, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imv_msg_create_from_long_data(imv_scanner, state, connection_id,
+                                                               src_imc_id, dst_imv_id, msg_vid, msg_subtype,
+                                                               chunk_create(msg, msg_len));
+       result =receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
+
+       return result;
 }
 
 /**
@@ -356,13 +366,18 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
                                                                                 TNC_ConnectionID connection_id)
 {
+       imv_state_t *state;
+
        if (!imv_scanner)
        {
                DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
-       return imv_scanner->provide_recommendation(imv_scanner, connection_id,
-                                                       TNC_IMCID_ANY, PEN_ITA, PA_SUBTYPE_ITA_SCANNER);
+       if (!imv_scanner->get_state(imv_scanner, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       return imv_scanner->provide_recommendation(imv_scanner, state);
 }
 
 /**
index 171cf25..3558350 100644 (file)
@@ -16,6 +16,7 @@
 #include "imv_test_state.h"
 
 #include <imv/imv_agent.h>
+#include <imv/imv_msg.h>
 #include <pa_tnc/pa_tnc_msg.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_pa_tnc_error.h>
@@ -92,59 +93,32 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
        }
 }
 
-static TNC_Result receive_message(TNC_IMVID imv_id,
-                                                                 TNC_ConnectionID connection_id,
-                                                                 TNC_UInt32 msg_flags,
-                                                                 chunk_t msg,
-                                                                 TNC_VendorID msg_vid,
-                                                                 TNC_MessageSubtype msg_subtype,
-                                                                 TNC_UInt32 src_imc_id,
-                                                                 TNC_UInt32 dst_imv_id)
+static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
 {
-       pa_tnc_msg_t *pa_tnc_msg;
-       pa_tnc_attr_t *attr;
-       pen_type_t attr_type;
-       linked_list_t *attr_list;
-       imv_state_t *state;
+       imv_msg_t *out_msg;
        imv_test_state_t *test_state;
        enumerator_t *enumerator;
+       pa_tnc_attr_t *attr;
+       pen_type_t attr_type;
        TNC_Result result;
        int rounds;
-       bool fatal_error, received_command = FALSE, retry = FALSE;
-
-       if (!imv_test)
-       {
-               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
-               return TNC_RESULT_NOT_INITIALIZED;
-       }
-
-       /* get current IMV state */
-       if (!imv_test->get_state(imv_test, connection_id, &state))
-       {
-               return TNC_RESULT_FATAL;
-       }
-       test_state = (imv_test_state_t*)state;
-
-       /* parse received PA-TNC message and automatically handle any errors */ 
-       result = imv_test->receive_message(imv_test, state, msg, msg_vid,
-                                                       msg_subtype, src_imc_id, dst_imv_id, &pa_tnc_msg);
+       bool fatal_error = FALSE, received_command = FALSE, retry = FALSE;
 
-       /* no parsed PA-TNC attributes available if an error occurred */
-       if (!pa_tnc_msg)
+       /* parse received PA-TNC message and handle local and remote errors */
+       result = in_msg->receive(in_msg, &fatal_error);
+       if (result != TNC_RESULT_SUCCESS)
        {
                return result;
        }
 
-       /* preprocess any IETF standard error attributes */
-       fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg);
-
        /* add any new IMC and set its number of rounds */
        rounds = lib->settings->get_int(lib->settings,
                                                                "libimcv.plugins.imv-test.rounds", 0);
-       test_state->add_imc(test_state, src_imc_id, rounds);
+       test_state = (imv_test_state_t*)state;
+       test_state->add_imc(test_state, in_msg->get_src_id(in_msg), rounds);
 
        /* analyze PA-TNC attributes */
-       enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
+       enumerator = in_msg->create_attribute_enumerator(in_msg);
        while (enumerator->enumerate(enumerator, &attr))
        {
                attr_type = attr->get_type(attr);
@@ -202,41 +176,60 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
                }
        }
        enumerator->destroy(enumerator);
-       pa_tnc_msg->destroy(pa_tnc_msg);
 
        if (fatal_error)
        {
                state->set_recommendation(state,
-                                                               TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
-                                                               TNC_IMV_EVALUATION_RESULT_ERROR);                         
-               return imv_test->provide_recommendation(imv_test, connection_id,
-                                                                       src_imc_id, PEN_ITA, PA_SUBTYPE_ITA_TEST);
+                                                       TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+                                                       TNC_IMV_EVALUATION_RESULT_ERROR);
+               out_msg = imv_msg_create_as_reply(in_msg);
+               result = out_msg->send_assessment(out_msg);
+               out_msg->destroy(out_msg);
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       return result;
+               }  
+               return imv_test->provide_recommendation(imv_test, state);
        }
 
        /* request a handshake retry ? */
        if (retry)
        {
                test_state->set_rounds(test_state, rounds);
-               return imv_test->request_handshake_retry(imv_id, connection_id,
-                                                               TNC_RETRY_REASON_IMV_SERIOUS_EVENT);
+               return imv_test->request_handshake_retry(imv_test->get_id(imv_test),
+                                                                                       state->get_connection_id(state),
+                                                                                       TNC_RETRY_REASON_IMV_SERIOUS_EVENT);
        }
        
        /* repeat the measurement ? */
-       if (test_state->another_round(test_state, src_imc_id))
+       if (test_state->another_round(test_state, in_msg->get_src_id(in_msg)))
        {
-               attr_list = linked_list_create();
+               out_msg = imv_msg_create_as_reply(in_msg);
                attr = ita_attr_command_create("repeat");
-               attr_list->insert_last(attr_list, attr);
-               result = imv_test->send_message(imv_test, connection_id, TRUE, imv_id,
-                                               src_imc_id, PEN_ITA, PA_SUBTYPE_ITA_TEST, attr_list);   
-               attr_list->destroy(attr_list);
+               out_msg->add_attribute(out_msg, attr);
+
+               /* send PA-TNC message with excl flag set */
+               result = out_msg->send(out_msg, TRUE);  
+               out_msg->destroy(out_msg);
 
                return result;
        }
 
-       return received_command ? imv_test->provide_recommendation(imv_test,
-                                connection_id, src_imc_id, PEN_ITA, PA_SUBTYPE_ITA_TEST) :
-                                TNC_RESULT_SUCCESS;
+       if (received_command)
+       {
+               out_msg = imv_msg_create_as_reply(in_msg);
+               result = out_msg->send_assessment(out_msg);
+               out_msg->destroy(out_msg);
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       return result;
+               }  
+               return imv_test->provide_recommendation(imv_test, state);
+       }
+       else
+       {       
+               return TNC_RESULT_SUCCESS;
+       }
 }
 
 /**
@@ -248,14 +241,25 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                                                  TNC_UInt32 msg_len,
                                                                  TNC_MessageType msg_type)
 {
-       TNC_VendorID msg_vid;
-       TNC_MessageSubtype msg_subtype;
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
 
-       msg_vid = msg_type >> 8;
-       msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+       if (!imv_test)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_test->get_state(imv_test, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imv_msg_create_from_data(imv_test, state, connection_id, msg_type,
+                                                                         chunk_create(msg, msg_len));
+       result = receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
 
-       return receive_message(imv_id, connection_id, 0, chunk_create(msg, msg_len),
-                                                  msg_vid,     msg_subtype, 0, TNC_IMVID_ANY);
+       return result;
 }
 
 /**
@@ -271,9 +275,26 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
                                                                          TNC_UInt32 src_imc_id,
                                                                          TNC_UInt32 dst_imv_id)
 {
-       return receive_message(imv_id, connection_id, msg_flags,
-                                                  chunk_create(msg, msg_len), msg_vid, msg_subtype,
-                                                  src_imc_id, dst_imv_id);
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
+
+       if (!imv_test)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_test->get_state(imv_test, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imv_msg_create_from_long_data(imv_test, state, connection_id,
+                                                               src_imc_id, dst_imv_id, msg_vid, msg_subtype,
+                                                               chunk_create(msg, msg_len));
+       result =receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
+
+       return result;
 }
 
 /**
@@ -282,13 +303,18 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
                                                                                 TNC_ConnectionID connection_id)
 {
+       imv_state_t *state;
+
        if (!imv_test)
        {
                DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
-       return imv_test->provide_recommendation(imv_test, connection_id,
-                                                       TNC_IMCID_ANY, PEN_ITA, PA_SUBTYPE_ITA_TEST);
+       if (!imv_test->get_state(imv_test, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       return imv_test->provide_recommendation(imv_test, state);
 }
 
 /**
index 23bfda4..a5175d9 100644 (file)
@@ -18,6 +18,7 @@
 #include "imv_attestation_build.h"
 
 #include <imv/imv_agent.h>
+#include <imv/imv_msg.h>
 #include <pa_tnc/pa_tnc_msg.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_pa_tnc_error.h>
@@ -169,97 +170,55 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
        }
 }
 
-static TNC_Result send_message(TNC_ConnectionID connection_id)
+static TNC_Result send_message(imv_state_t *state, imv_msg_t *out_msg)
 {
-       linked_list_t *attr_list;
-       imv_state_t *state;
        imv_attestation_state_t *attestation_state;
        TNC_Result result;
 
-       if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
-       {
-               return TNC_RESULT_FATAL;
-       }
        attestation_state = (imv_attestation_state_t*)state;
-       attr_list = linked_list_create();
 
-       if (imv_attestation_build(attr_list, attestation_state, supported_algorithms,
+       if (imv_attestation_build(out_msg, attestation_state, supported_algorithms,
                                                          supported_dh_groups, pts_db))
        {
-               if (attr_list->get_count(attr_list))
-               {
-                       result = imv_attestation->send_message(imv_attestation,
-                                                       connection_id, FALSE, 0, TNC_IMCID_ANY,
-                                                       PEN_TCG, PA_SUBTYPE_TCG_PTS, attr_list);
-               }
-               else
-               {
-                       result = TNC_RESULT_SUCCESS;
-               }
-               attr_list->destroy(attr_list);
+               result = out_msg->send(out_msg, TRUE);
        }
        else
        {
-               attr_list->destroy_offset(attr_list, offsetof(pa_tnc_attr_t, destroy));
+               out_msg->delete_attributes(out_msg);
                result = TNC_RESULT_FATAL;
        }
 
        return result;
 }
 
-static TNC_Result receive_message(TNC_IMVID imv_id,
-                                                                 TNC_ConnectionID connection_id,
-                                                                 TNC_UInt32 msg_flags,
-                                                                 chunk_t msg,
-                                                                 TNC_VendorID msg_vid,
-                                                                 TNC_MessageSubtype msg_subtype,
-                                                                 TNC_UInt32 src_imc_id,
-                                                                 TNC_UInt32 dst_imv_id)
+static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
 {
-       pa_tnc_msg_t *pa_tnc_msg;
+       imv_attestation_state_t *attestation_state;
+       imv_msg_t *out_msg;
+       enumerator_t *enumerator;
        pa_tnc_attr_t *attr;
        pen_type_t type;
-       linked_list_t *attr_list;
-       imv_state_t *state;
-       imv_attestation_state_t *attestation_state;
+       TNC_Result result;
        pts_t *pts;
        chunk_t os_name = chunk_empty;
        chunk_t os_version = chunk_empty;
-       enumerator_t *enumerator;
-       TNC_Result result;
+       bool fatal_error = FALSE;
 
-       if (!imv_attestation)
+       /* parse received PA-TNC message and handle local and remote errors */
+       result = in_msg->receive(in_msg, &fatal_error);
+       if (result != TNC_RESULT_SUCCESS)
        {
-               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
-               return TNC_RESULT_NOT_INITIALIZED;
+               return result;
        }
 
-       /* get current IMV state  */
-       if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
-       {
-               return TNC_RESULT_FATAL;
-       }
        attestation_state = (imv_attestation_state_t*)state;
        pts = attestation_state->get_pts(attestation_state);
 
-       /* parse received PA-TNC message and automatically handle any errors */
-       result = imv_attestation->receive_message(imv_attestation, state, msg,
-                                        msg_vid, msg_subtype, src_imc_id, dst_imv_id, &pa_tnc_msg);
-
-       /* no parsed PA-TNC attributes available if an error occurred */
-       if (!pa_tnc_msg)
-       {
-               return result;
-       }
-
-       /* preprocess any IETF standard error attributes */
-       result = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg) ?
-                                       TNC_RESULT_FATAL : TNC_RESULT_SUCCESS;
-
-       attr_list = linked_list_create();
+       out_msg = imv_msg_create_as_reply(in_msg);
+       out_msg->set_msg_type(out_msg, msg_types[0]);
 
        /* analyze PA-TNC attributes */
-       enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
+       enumerator = in_msg->create_attribute_enumerator(in_msg);
        while (enumerator->enumerate(enumerator, &attr))
        {
                type = attr->get_type(attr);
@@ -311,7 +270,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
                }
                else if (type.vendor_id == PEN_TCG)
                {
-                       if (!imv_attestation_process(attr, attr_list, attestation_state,
+                       if (!imv_attestation_process(attr, out_msg, attestation_state, 
                                supported_algorithms,supported_dh_groups, pts_db, pts_credmgr))
                        {
                                result = TNC_RESULT_FATAL;
@@ -325,37 +284,46 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
        {
                pts->set_platform_info(pts, os_name, os_version);
        }
-       pa_tnc_msg->destroy(pa_tnc_msg);
 
        if (result != TNC_RESULT_SUCCESS)
        {
-               attr_list->destroy_offset(attr_list, offsetof(pa_tnc_attr_t, destroy));
+               out_msg->delete_attributes(out_msg);
                state->set_recommendation(state,
                                                                TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
                                                                TNC_IMV_EVALUATION_RESULT_ERROR);
-               return imv_attestation->provide_recommendation(imv_attestation,
-                                       connection_id, src_imc_id, PEN_TCG, PA_SUBTYPE_TCG_PTS);
+               result = out_msg->send_assessment(out_msg);
+               out_msg->destroy(out_msg);
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       return result;
+               }
+               return imv_attestation->provide_recommendation(imv_attestation, state);
        }
 
-       if (attr_list->get_count(attr_list))
+       /* send PA-TNC message with excl flag set */
+       result = out_msg->send(out_msg, TRUE);
+
+       if (result != TNC_RESULT_SUCCESS)
        {
-               result = imv_attestation->send_message(imv_attestation, connection_id,
-                                               FALSE, 0, TNC_IMCID_ANY, PEN_TCG, PA_SUBTYPE_TCG_PTS,
-                                               attr_list);
-               attr_list->destroy(attr_list);
+               out_msg->destroy(out_msg);
                return result;
        }
-       attr_list->destroy(attr_list);
 
        /* check the IMV state for the next PA-TNC attributes to send */
-       result = send_message(connection_id);
+       result = send_message(state, out_msg);
+
        if (result != TNC_RESULT_SUCCESS)
        {
                state->set_recommendation(state,
                                                                TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                                                                TNC_IMV_EVALUATION_RESULT_ERROR);
-               return imv_attestation->provide_recommendation(imv_attestation,
-                                               connection_id, src_imc_id, PEN_TCG, PA_SUBTYPE_TCG_PTS);
+               out_msg->delete_attributes(out_msg);
+               result = out_msg->send_assessment(out_msg);
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       return result;
+               }
+               return imv_attestation->provide_recommendation(imv_attestation, state);
        }
 
        if (attestation_state->get_handshake_state(attestation_state) ==
@@ -379,9 +347,15 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
                                                                TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
                                                                TNC_IMV_EVALUATION_RESULT_COMPLIANT);
                }
-               return imv_attestation->provide_recommendation(imv_attestation,
-                                               connection_id, src_imc_id, PEN_TCG, PA_SUBTYPE_TCG_PTS);
+               result = out_msg->send_assessment(out_msg);
+               out_msg->destroy(out_msg);
+               if (result != TNC_RESULT_SUCCESS)
+               {
+                       return result;
+               }
+               return imv_attestation->provide_recommendation(imv_attestation, state);
        }
+       out_msg->destroy(out_msg);
 
        return result;
 }
@@ -395,14 +369,25 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                                                  TNC_UInt32 msg_len,
                                                                  TNC_MessageType msg_type)
 {
-       TNC_VendorID msg_vid;
-       TNC_MessageSubtype msg_subtype;
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
 
-       msg_vid = msg_type >> 8;
-       msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+       if (!imv_attestation)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imv_msg_create_from_data(imv_attestation, state, connection_id, 
+                                                                         msg_type, chunk_create(msg, msg_len));
+       result = receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
 
-       return receive_message(imv_id, connection_id, 0, chunk_create(msg, msg_len),
-                                                  msg_vid,     msg_subtype, 0, TNC_IMVID_ANY);
+       return result;
 }
 
 /**
@@ -418,9 +403,26 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
                                                                          TNC_UInt32 src_imc_id,
                                                                          TNC_UInt32 dst_imv_id)
 {
-       return receive_message(imv_id, connection_id, msg_flags,
-                                                  chunk_create(msg, msg_len), msg_vid, msg_subtype,
-                                                  src_imc_id, dst_imv_id);
+       imv_state_t *state;
+       imv_msg_t *in_msg;
+       TNC_Result result;
+
+       if (!imv_attestation)
+       {
+               DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+               return TNC_RESULT_NOT_INITIALIZED;
+       }
+       if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       in_msg = imv_msg_create_from_long_data(imv_attestation, state, connection_id,
+                                                               src_imc_id, dst_imv_id, msg_vid, msg_subtype,
+                                                               chunk_create(msg, msg_len));
+       result =receive_message(state, in_msg);
+       in_msg->destroy(in_msg);
+
+       return result;
 }
 
 /**
@@ -429,13 +431,18 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
                                                                                 TNC_ConnectionID connection_id)
 {
+       imv_state_t *state;
+
        if (!imv_attestation)
        {
                DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
-       return imv_attestation->provide_recommendation(imv_attestation,
-                                       connection_id, TNC_IMCID_ANY, PEN_TCG, PA_SUBTYPE_TCG_PTS);
+       if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       return imv_attestation->provide_recommendation(imv_attestation, state);
 }
 
 /**
@@ -444,27 +451,11 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
 TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
                                                           TNC_ConnectionID connection_id)
 {
-       imv_state_t *state;
-       imv_attestation_state_t *attestation_state;
-
        if (!imv_attestation)
        {
                DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
-       /* get current IMV state */
-       if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
-       {
-               return TNC_RESULT_FATAL;
-       }
-       attestation_state = (imv_attestation_state_t*)state;
-
-       /* Check if IMV has to initiate the PA-TNC exchange */
-       if (attestation_state->get_handshake_state(attestation_state) ==
-               IMV_ATTESTATION_STATE_INIT)
-       {
-               return send_message(connection_id);
-       }
        return TNC_RESULT_SUCCESS;
 }
 
index 23195d6..2f36724 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <debug.h>
 
-bool imv_attestation_build(linked_list_t *attr_list,
+bool imv_attestation_build(imv_msg_t *out_msg,
                                                   imv_attestation_state_t *attestation_state,
                                                   pts_meas_algorithms_t supported_algorithms,
                                                   pts_dh_group_t supported_dh_groups,
@@ -76,12 +76,12 @@ bool imv_attestation_build(linked_list_t *attr_list,
                        flags = pts->get_proto_caps(pts);
                        attr = tcg_pts_attr_proto_caps_create(flags, TRUE);
                        attr->set_noskip_flag(attr, TRUE);
-                       attr_list->insert_last(attr_list, attr);
+                       out_msg->add_attribute(out_msg, attr);
 
                        /* Send Measurement Algorithms attribute */
                        attr = tcg_pts_attr_meas_algo_create(supported_algorithms, FALSE);
                        attr->set_noskip_flag(attr, TRUE);
-                       attr_list->insert_last(attr_list, attr);
+                       out_msg->add_attribute(out_msg, attr);
 
                        attestation_state->set_handshake_state(attestation_state,
                                                                                IMV_ATTESTATION_STATE_NONCE_REQ);
@@ -97,7 +97,7 @@ bool imv_attestation_build(linked_list_t *attr_list,
                        attr = tcg_pts_attr_dh_nonce_params_req_create(min_nonce_len,
                                                                                                         supported_dh_groups);
                        attr->set_noskip_flag(attr, TRUE);
-                       attr_list->insert_last(attr_list, attr);
+                       out_msg->add_attribute(out_msg, attr);
 
                        attestation_state->set_handshake_state(attestation_state,
                                                                                IMV_ATTESTATION_STATE_TPM_INIT);
@@ -116,18 +116,18 @@ bool imv_attestation_build(linked_list_t *attr_list,
                                attr = tcg_pts_attr_dh_nonce_finish_create(selected_algorithm,
                                                                                        initiator_value, initiator_nonce);
                                attr->set_noskip_flag(attr, TRUE);
-                       attr_list->insert_last(attr_list, attr);
+                               out_msg->add_attribute(out_msg, attr);
                        }
 
                        /* Send Get TPM Version attribute */
                        attr = tcg_pts_attr_get_tpm_version_info_create();
                        attr->set_noskip_flag(attr, TRUE);
-                       attr_list->insert_last(attr_list, attr);
+                       out_msg->add_attribute(out_msg, attr);
 
                        /* Send Get AIK attribute */
                        attr = tcg_pts_attr_get_aik_create();
                        attr->set_noskip_flag(attr, TRUE);
-                       attr_list->insert_last(attr_list, attr);
+                       out_msg->add_attribute(out_msg, attr);
 
                        attestation_state->set_handshake_state(attestation_state,
                                                                                IMV_ATTESTATION_STATE_MEAS);
@@ -140,7 +140,7 @@ bool imv_attestation_build(linked_list_t *attr_list,
                        char *platform_info, *pathname;
                        u_int16_t request_id;
                        int id, type;
-                       bool is_dir;
+                       bool is_dir, have_request = FALSE;
 
                        attestation_state->set_handshake_state(attestation_state,
                                                                                IMV_ATTESTATION_STATE_COMP_EVID);
@@ -173,7 +173,8 @@ bool imv_attestation_build(linked_list_t *attr_list,
                                attr = tcg_pts_attr_req_file_meta_create(is_dir, delimiter,
                                                                                                                 pathname);
                                attr->set_noskip_flag(attr, TRUE);
-                               attr_list->insert_last(attr_list, attr);
+                               out_msg->add_attribute(out_msg, attr);
+                               have_request = TRUE;
                        }
                        enumerator->destroy(enumerator);
                        
@@ -194,12 +195,13 @@ bool imv_attestation_build(linked_list_t *attr_list,
                                attr = tcg_pts_attr_req_file_meas_create(is_dir, request_id,
                                                                                                         delimiter, pathname);
                                attr->set_noskip_flag(attr, TRUE);
-                               attr_list->insert_last(attr_list, attr);
+                               out_msg->add_attribute(out_msg, attr);
+                               have_request = TRUE;
                        }
                        enumerator->destroy(enumerator);
 
                        /* do we have any file metadata or measurement requests? */
-                       if (attr_list->get_count(attr_list))
+                       if (have_request)
                        {
                                break;
                        }
@@ -282,12 +284,12 @@ bool imv_attestation_build(linked_list_t *attr_list,
                        if (attr)
                        {
                                /* Send Request Functional Component Evidence attribute */
-                               attr_list->insert_last(attr_list, attr);
+                               out_msg->add_attribute(out_msg, attr);
 
                                /* Send Generate Attestation Evidence attribute */
                                attr = tcg_pts_attr_gen_attest_evid_create();
                                attr->set_noskip_flag(attr, TRUE);
-                               attr_list->insert_last(attr_list, attr);
+                               out_msg->add_attribute(out_msg, attr);
 
                                attestation_state->set_handshake_state(attestation_state,
                                                                                IMV_ATTESTATION_STATE_EVID_FINAL);
index 7f934fd..0fc10f0 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "imv_attestation_state.h"
 
-#include <pa_tnc/pa_tnc_msg.h>
+#include <imv/imv_msg.h>
 #include <library.h>
 
 #include <pts/pts_database.h>
 /**
  * Process a TCG PTS attribute
  *
- * @param attr_list                            list of PA-TNC attriubutes to be built
+ * @param out_msg                              outbound PA-TNC message to be built
  * @param attestation_state            attestation state of a given connection
  * @param supported_algorithms supported PTS measurement algorithms
  * @param supported_dh_groups  supported DH groups
  * @param pts_db                               PTS configuration database
  * @return                                             TRUE if successful
  */
-bool imv_attestation_build(linked_list_t *attr_list,
+bool imv_attestation_build(imv_msg_t *out_msg,
                                                   imv_attestation_state_t *attestation_state,
                                                   pts_meas_algorithms_t supported_algorithms,
                                                   pts_dh_group_t supported_dh_groups,
index 37e9ac7..39ba9f0 100644 (file)
@@ -34,7 +34,7 @@
 
 #include <inttypes.h>
 
-bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
+bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
                                                         imv_attestation_state_t *attestation_state,
                                                         pts_meas_algorithms_t supported_algorithms,
                                                         pts_dh_group_t supported_dh_groups,
@@ -96,7 +96,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
                                attr = pts_dh_nonce_error_create(
                                                                        max(PTS_MIN_NONCE_LEN, min_nonce_len),
                                                                                PTS_MAX_NONCE_LEN);
-                               attr_list->insert_last(attr_list, attr);
+                               out_msg->add_attribute(out_msg, attr);
                                break;
                        }
 
@@ -113,7 +113,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
                        if (selected_algorithm == PTS_MEAS_ALGO_NONE)
                        {
                                attr = pts_hash_alg_error_create(supported_algorithms);
-                               attr_list->insert_last(attr_list, attr);
+                               out_msg->add_attribute(out_msg, attr);
                                break;
                        }
                        pts->set_dh_hash_algorithm(pts, selected_algorithm);
index 4d4eeef..b809ccf 100644 (file)
@@ -29,6 +29,7 @@
 #include <credentials/credential_manager.h>
 #include <crypto/hashers/hasher.h>
 
+#include <imv/imv_msg.h>
 #include <pa_tnc/pa_tnc_attr.h>
 
 #include <pts/pts_database.h>
@@ -39,7 +40,7 @@
  * Process a TCG PTS attribute
  *
  * @param attr                                 PA-TNC attribute to be processed
- * @param attr_list                            list with PA-TNC error attributes
+ * @param out_msg                              PA-TNC message containing error messages
  * @param attestation_state            attestation state of a given connection
  * @param supported_algorithms supported PTS measurement algorithms
  * @param supported_dh_groups  supported DH groups
@@ -47,7 +48,7 @@
  * @param pts_credmgr                  PTS credential manager
  * @return                                             TRUE if successful
  */
-bool imv_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
+bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
                                                         imv_attestation_state_t *attestation_state,
                                                         pts_meas_algorithms_t supported_algorithms,
                                                         pts_dh_group_t supported_dh_groups,