implemented parsing of TNCCS 1.1 messages
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 9 Jan 2011 09:00:54 +0000 (10:00 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 9 Jan 2011 09:00:54 +0000 (10:00 +0100)
17 files changed:
src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c
src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h
src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c
src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h
src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c
src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h
src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c
src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h
src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
src/libcharon/plugins/tnccs_11/tnccs_11.c

index d44645d..fbcb133 100644 (file)
@@ -106,8 +106,6 @@ METHOD(tnccs_batch_t, process, status_t,
     xmlChar *batchid, *recipient;
        int batch_id;
 
-       status_t status;
-
        this->doc = xmlParseMemory(this->encoding.ptr, this->encoding.len);
        if (!this->doc)
        {
@@ -206,30 +204,28 @@ METHOD(tnccs_batch_t, process, status_t,
                        continue;
                }
 
-               tnccs_msg = tnccs_msg_create_from_node(cur);
-               if (!tnccs_msg)
+               tnccs_msg = tnccs_msg_create_from_node(cur, this->errors);
+
+               /* exit if a message parsing error occurred */
+               if (this->errors->get_count(this->errors) > 0)
                {
-                       continue;
+                       return FAILED;
                }
 
-               DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names,
-                                                                                          tnccs_msg->get_type(tnccs_msg));
-               status = tnccs_msg->process(tnccs_msg);
-               if (status == FAILED)
+               /* ignore unrecognized messages */
+               if (!tnccs_msg)
                {
-                       tnccs_msg->destroy(tnccs_msg);
-                       return FAILED;
+                       continue;
                }
+
                this->messages->insert_last(this->messages, tnccs_msg);
        }
        return SUCCESS;
 
 fatal:
-       DBG1(DBG_TNC, "%s", error_msg);
        msg = tnccs_error_msg_create(error_type, error_msg);
        this->errors->insert_last(this->errors, msg);
        return FAILED;
-
 }
 
 METHOD(tnccs_batch_t, create_msg_enumerator, enumerator_t*,
@@ -238,6 +234,12 @@ METHOD(tnccs_batch_t, create_msg_enumerator, enumerator_t*,
        return this->messages->create_enumerator(this->messages);
 }
 
+METHOD(tnccs_batch_t, create_error_enumerator, enumerator_t*,
+       private_tnccs_batch_t *this)
+{
+       return this->errors->create_enumerator(this->errors);
+}
+
 METHOD(tnccs_batch_t, destroy, void,
        private_tnccs_batch_t *this)
 {
@@ -267,6 +269,7 @@ tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id)
                        .build = _build,
                        .process = _process,
                        .create_msg_enumerator = _create_msg_enumerator,
+                       .create_error_enumerator = _create_error_enumerator,
                        .destroy = _destroy,
                },
                .is_server = is_server,
@@ -305,6 +308,7 @@ tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id, chunk_
                        .build = _build,
                        .process = _process,
                        .create_msg_enumerator = _create_msg_enumerator,
+                       .create_error_enumerator = _create_error_enumerator,
                        .destroy = _destroy,
                },
                .is_server = is_server,
index 6f47e56..25301f7 100644 (file)
@@ -67,6 +67,13 @@ struct tnccs_batch_t {
        enumerator_t* (*create_msg_enumerator)(tnccs_batch_t *this);
 
        /**
+        * Enumerates over all parsing errors
+        *
+        * @return                              return error enumerator
+        */
+       enumerator_t* (*create_error_enumerator)(tnccs_batch_t *this);
+
+       /**
         * Destroys a tnccs_batch_t object.
         */
        void (*destroy)(tnccs_batch_t *this);
index 2c3bc59..c99cd2e 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <tnc/tnccs/tnccs.h>
 #include <debug.h>
+#include <utils/lexparser.h>
 
 typedef struct private_imc_imv_msg_t private_imc_imv_msg_t;
 
@@ -54,26 +55,8 @@ struct private_imc_imv_msg_t {
 
 };
 
-METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
-       private_imc_imv_msg_t *this)
-{
-       return this->type;
-}
-
-METHOD(tnccs_msg_t, get_node, xmlNodePtr,
-       private_imc_imv_msg_t *this)
-{
-       return this->node;
-}
-
-METHOD(tnccs_msg_t, process, status_t,
-       private_imc_imv_msg_t *this)
-{
-       return SUCCESS;
-}
-
 /**
- * Converts message data into multiple base64-encoded lines 
+ * Encodes message data into multiple base64-encoded lines 
  */
 static chunk_t encode_base64(chunk_t data)
 {
@@ -106,6 +89,41 @@ static chunk_t encode_base64(chunk_t data)
        return encoding;
 }
 
+/**
+ * Decodes message data from multiple base64-encoded lines 
+ */
+static chunk_t decode_base64(chunk_t data)
+{
+       chunk_t decoding, data_line, b64_line;
+       u_char *pos;
+
+       /* compute and allocate maximum size of decoded message data */
+       decoding = chunk_alloc(3 * ((data.len + 3) / 4));
+       pos = decoding.ptr;
+       decoding.len = 0;
+
+       while (fetchline(&data, &b64_line))
+       {
+               data_line = chunk_from_base64(b64_line, pos);
+               pos += data_line.len;
+               decoding.len += data_line.len;
+       }
+
+       return decoding;
+}
+
+METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
+       private_imc_imv_msg_t *this)
+{
+       return this->type;
+}
+
+METHOD(tnccs_msg_t, get_node, xmlNodePtr,
+       private_imc_imv_msg_t *this)
+{
+       return this->node;
+}
+
 METHOD(tnccs_msg_t, destroy, void,
        private_imc_imv_msg_t *this)
 {
@@ -128,16 +146,19 @@ METHOD(imc_imv_msg_t, get_msg_body, chunk_t,
 /**
  * See header
  */
-tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node)
+tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
 {
        private_imc_imv_msg_t *this;
+       xmlNsPtr ns;
+       xmlNodePtr cur;
+       xmlChar *content;
+       chunk_t b64_body;
 
        INIT(this,
                .public = {
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_msg_type = _get_msg_type,
@@ -147,6 +168,26 @@ tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node)
                .node = node,
        );
 
+       ns =  node->ns;
+       cur = node->xmlChildrenNode;
+       while (cur)
+       {
+               if (streq((char*)cur->name, "Type") && cur->ns == ns)
+               {
+                       content = xmlNodeGetContent(cur);
+                   this->msg_type = strtoul((char*)content, NULL, 16);
+                   xmlFree(content);
+               }
+               else if (streq((char*)cur->name, "Base64") && cur->ns == ns)
+               {
+                       content = xmlNodeGetContent(cur);
+                       b64_body = chunk_create((char*)content, strlen((char*)content));
+                       this->msg_body = decode_base64(b64_body);
+                   xmlFree(content);
+               }
+               cur = cur->next;
+       }
+
        return &this->public.tnccs_msg_interface;
 }
 
@@ -165,7 +206,6 @@ tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body)
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_msg_type = _get_msg_type,
index ccf31d3..335b1b7 100644 (file)
@@ -56,8 +56,9 @@ struct imc_imv_msg_t {
  * Create an IMC-IMV message from XML-encoded message node
  *
  * @param msg_node                     XML-encoded message node
- */
-tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node);
+ * @param errors                       linked list of TNCCS error messages
+*/
+tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
 
 /**
  * Create an IMC-IMV message from parameters
index 8a56468..5a876e3 100644 (file)
@@ -57,6 +57,11 @@ struct private_tnccs_error_msg_t {
         * Error message
         */
        char *error_msg;
+
+       /**
+        * reference count
+        */
+       refcount_t ref;
 };
 
 METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t,
@@ -71,17 +76,21 @@ METHOD(tnccs_msg_t, get_node, xmlNodePtr,
        return this->node;
 }
 
-METHOD(tnccs_msg_t, process, status_t,
+METHOD(tnccs_msg_t, get_ref, tnccs_msg_t*,
        private_tnccs_error_msg_t *this)
 {
-       return SUCCESS;
+       ref_get(&this->ref);
+       return &this->public.tnccs_msg_interface;
 }
 
 METHOD(tnccs_msg_t, destroy, void,
        private_tnccs_error_msg_t *this)
 {
-       free(this->error_msg);
-       free(this);
+       if (ref_put(&this->ref))
+       {
+               free(this->error_msg);
+               free(this);
+       }
 }
 
 METHOD(tnccs_error_msg_t, get_message, char*,
@@ -98,21 +107,42 @@ METHOD(tnccs_error_msg_t, get_message, char*,
 tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node)
 {
        private_tnccs_error_msg_t *this;
-
+       xmlChar *error_type_name, *error_msg;
+       
        INIT(this,
                .public = {
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
+                               .get_ref = _get_ref,
                                .destroy = _destroy,
                        },
                        .get_message = _get_message,
                },
                .type = TNCCS_MSG_ERROR,
                .node = node,
+               .error_type = TNCCS_ERROR_OTHER,
        );
 
+       error_type_name = xmlGetProp(node, (const xmlChar*)"type");
+       if (error_type_name)
+       {
+               this->error_type = enum_from_name(tnccs_error_type_names,
+                                                                                 (char*)error_type_name);
+               if (this->error_type == -1)
+               {
+                       this->error_type = TNCCS_ERROR_OTHER;
+               }
+               xmlFree(error_type_name);
+       }
+
+       error_msg = xmlNodeGetContent(node);
+       if (error_msg)
+       {
+               this->error_msg = strdup((char*)error_msg);
+               xmlFree(error_msg);
+       }
+
        return &this->public.tnccs_msg_interface;
 }
 
@@ -129,7 +159,7 @@ tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg)
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
+                               .get_ref = _get_ref,
                                .destroy = _destroy,
                        },
                        .get_message = _get_message,
@@ -140,18 +170,20 @@ tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg)
                .error_msg  = strdup(msg),
        );
 
-     n = xmlNewNode(NULL, BAD_CAST "Type");
-    xmlNodeSetContent(n, BAD_CAST "00000002");
-    xmlAddChild(this->node, n);
+       DBG1(DBG_TNC, "%s", msg);
+
+       n = xmlNewNode(NULL, BAD_CAST "Type");
+       xmlNodeSetContent(n, BAD_CAST "00000002");
+       xmlAddChild(this->node, n);
 
-    n = xmlNewNode(NULL, BAD_CAST "XML");
-    xmlAddChild(this->node, n);
+       n = xmlNewNode(NULL, BAD_CAST "XML");
+       xmlAddChild(this->node, n);
 
-    n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
-    xmlNewProp(n2, BAD_CAST "type",
+       n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
+       xmlNewProp(n2, BAD_CAST "type",
                                   BAD_CAST enum_to_name(tnccs_error_type_names, type));
-    xmlNodeSetContent(n2, BAD_CAST msg);
-    xmlAddChild(n, n2);
+       xmlNodeSetContent(n2, BAD_CAST msg);
+       xmlAddChild(n, n2);
 
        return &this->public.tnccs_msg_interface;
 }
index ca16af9..61deaff 100644 (file)
@@ -56,8 +56,8 @@ struct tnccs_error_msg_t {
        /**
         * Get error message and type
         *
-        * @param type                  TNCCS error type
-        * @return                              arbitrary error message
+        * @param type          TNCCS error type
+        * @return                      arbitrary error message
         */
        char* (*get_message)(tnccs_error_msg_t *this, tnccs_error_type_t *type);
 };
@@ -65,7 +65,7 @@ struct tnccs_error_msg_t {
 /**
  * Create a TNCCS-Error message from XML-encoded message node
  *
- * @param msg_node                     XML-encoded message node
+ * @param msg_node             XML-encoded message node
  */
 tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node);
 
index cb7360f..323bbf8 100644 (file)
@@ -36,19 +36,24 @@ ENUM(tnccs_msg_type_names, IMC_IMV_MSG, TNCCS_MSG_ROOF,
 /**
  * See header
  */
-tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node)
+tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
 {
+       char *error_msg, buf[BUF_LEN];
+       tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
+       tnccs_msg_t *msg;
        tnccs_msg_type_t type = IMC_IMV_MSG;
 
        if (streq((char*)node->name, "IMC-IMV-Message"))
        {
-               return imc_imv_msg_create_from_node(node);
+               DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
+               return imc_imv_msg_create_from_node(node, errors);
        }
        else if (streq((char*)node->name, "TNCC-TNCS-Message"))
        {
                bool found = FALSE;
                xmlNsPtr ns = node->ns;
                xmlNodePtr cur = node->xmlChildrenNode;
+               xmlNodePtr xml_msg_node = NULL;
 
                while (cur)
                {
@@ -59,27 +64,66 @@ tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node)
                            type = strtol((char*)content, NULL, 16);
                        xmlFree(content);
                                found = TRUE;
-                               break;
+                       }
+                       else if (streq((char*)cur->name, "XML") && cur->ns == ns)
+                       {
+                               xml_msg_node = cur->xmlChildrenNode;
                        }
                        cur = cur->next;
                }
                if (!found)
                {
-                       DBG1(DBG_TNC, "ignoring TNCC-TNCS-Messsage without type");
-                       return NULL;
+                       error_msg = "Type is missing in TNCC-TNCS-Message";
+                       goto fatal;
+               }
+               if (!xml_msg_node)
+               {
+                       error_msg = "XML node is missing in TNCC-TNCS-Message";
+                       goto fatal;
+               }
+               cur = xml_msg_node;
+
+           /* skip empty and blank nodes */
+       while (cur && xmlIsBlankNode(cur))
+               {
+                       cur = cur->next;
+               }
+               if (!cur)
+               {
+                       error_msg = "XML node is empty";
+                       goto fatal;
                }
+
+               /* check if TNCCS message type and node name agree */ 
+               if (type >= TNCCS_MSG_RECOMMENDATION && type <= TNCCS_MSG_ROOF)
+               {
+                       DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
+                       if (cur->ns != ns)
+                       {
+                               error_msg = "node is not in the TNCCS message namespace";
+                               goto fatal;
+                       }
+                       if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name))
+                       {
+                               error_msg = buf;
+                               snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'",
+                                                tnccs_msg_type_names, type, (char*)cur->name);
+                               goto fatal;
+                       }
+               }
+
                switch (type)
                {
                        case TNCCS_MSG_RECOMMENDATION:
-                               return tnccs_recommendation_msg_create_from_node(node);
+                               return tnccs_recommendation_msg_create_from_node(cur, errors);
                        case TNCCS_MSG_ERROR:
-                               return tnccs_error_msg_create_from_node(node);
+                               return tnccs_error_msg_create_from_node(cur);
                        case TNCCS_MSG_PREFERRED_LANGUAGE:
-                               return tnccs_preferred_language_msg_create_from_node(node);
+                               return tnccs_preferred_language_msg_create_from_node(cur, errors);
                        case TNCCS_MSG_REASON_STRINGS:
-                               return tnccs_reason_strings_msg_create_from_node(node);
+                               return tnccs_reason_strings_msg_create_from_node(cur, errors);
                        case TNCCS_MSG_TNCS_CONTACT_INFO:
-                               return tnccs_tncs_contact_info_msg_create_from_node(node);
+                               return tnccs_tncs_contact_info_msg_create_from_node(cur, errors);
                        default:
                                DBG1(DBG_TNC, "ignoring TNCC-TNCS-Message with type %d", type);
                                return NULL;
@@ -87,5 +131,10 @@ tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node)
        }
        DBG1(DBG_TNC, "ignoring unknown message node '%s'", (char*)node->name);
        return NULL;
+
+fatal:
+       msg = tnccs_error_msg_create(error_type, error_msg);
+       errors->insert_last(errors, msg);
+       return NULL;
 }
 
index c4c637d..e0b5444 100644 (file)
@@ -25,6 +25,7 @@ typedef enum tnccs_msg_type_t tnccs_msg_type_t;
 typedef struct tnccs_msg_t tnccs_msg_t;
 
 #include <library.h>
+#include <utils/linked_list.h>
 #include <libxml/parser.h>
 
 /**
@@ -75,19 +76,27 @@ struct tnccs_msg_t {
        status_t (*process)(tnccs_msg_t *this);
 
        /**
+        * Get a new reference to the message.
+        *
+        * @return                      this, with an increased refcount
+        */
+       tnccs_msg_t* (*get_ref)(tnccs_msg_t *this);
+
+       /**
         * Destroys a tnccs_msg_t object.
         */
        void (*destroy)(tnccs_msg_t *this);
 };
 
 /**
- * Create an unprocessed TNCCS message
+ * Create a pre-processed TNCCS message
  *
  * Useful for the parser which wants a generic constructor for all
  * tnccs_msg_t types.
  *
  * @param node         TNCCS message node
+ * @param errors       linked list of TNCCS error messages
  */
-tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node);
+tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors);
 
 #endif /** TNCCS_MSG_H_ @}*/
index 9859222..fd85350 100644 (file)
@@ -57,12 +57,6 @@ METHOD(tnccs_msg_t, get_node, xmlNodePtr,
        return this->node;
 }
 
-METHOD(tnccs_msg_t, process, status_t,
-       private_tnccs_preferred_language_msg_t *this)
-{
-       return SUCCESS;
-}
-
 METHOD(tnccs_msg_t, destroy, void,
        private_tnccs_preferred_language_msg_t *this)
 {
@@ -79,16 +73,17 @@ METHOD(tnccs_preferred_language_msg_t, get_preferred_language, char*,
 /**
  * See header
  */
-tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node)
+tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
+                                                                                                       linked_list_t *errors)
 {
        private_tnccs_preferred_language_msg_t *this;
+       xmlChar *language;
 
        INIT(this,
                .public = {
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_preferred_language = _get_preferred_language,
@@ -97,6 +92,10 @@ tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node)
                .node = node,
        );
 
+       language = xmlNodeGetContent(node);
+       this->preferred_language = strdup((char*)language);
+       xmlFree(language);
+
        return &this->public.tnccs_msg_interface;
 }
 
@@ -113,7 +112,6 @@ tnccs_msg_t *tnccs_preferred_language_msg_create(char *language)
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_preferred_language = _get_preferred_language,
index d57cc6e..97e0ff8 100644 (file)
@@ -49,8 +49,10 @@ struct tnccs_preferred_language_msg_t {
  * Create a TNCCS-PreferredLanguage message from XML-encoded message node
  *
  * @param msg_node                     XML-encoded message node
+ * @param errors                       linked list of TNCCS error messages
  */
-tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node);
+tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node,
+                                                                                                       linked_list_t *errors);
 
 /**
  * Create a TNCCS-PreferredLanguage message from parameters
index af1621b..ad1ed36 100644 (file)
@@ -62,12 +62,6 @@ METHOD(tnccs_msg_t, get_node, xmlNodePtr,
        return this->node;
 }
 
-METHOD(tnccs_msg_t, process, status_t,
-       private_tnccs_reason_strings_msg_t *this)
-{
-       return SUCCESS;
-}
-
 METHOD(tnccs_msg_t, destroy, void,
        private_tnccs_reason_strings_msg_t *this)
 {
@@ -87,7 +81,8 @@ METHOD(tnccs_reason_strings_msg_t, get_reason, char*,
 /**
  * See header
  */
-tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node)
+tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
+                                                                                                          linked_list_t *errors)
 {
        private_tnccs_reason_strings_msg_t *this;
 
@@ -96,7 +91,6 @@ tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node)
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_reason = _get_reason,
@@ -121,7 +115,6 @@ tnccs_msg_t *tnccs_reason_strings_msg_create(char *language, char *reason)
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_reason = _get_reason,
index 0b68c2c..9057477 100644 (file)
@@ -48,8 +48,10 @@ struct tnccs_reason_strings_msg_t {
  * Create a TNCCS-ReasonStrings message from XML-encoded message node
  *
  * @param msg_node                     XML-encoded message node
+ * @param errors                       linked list of TNCCS error messages
  */
-tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node);
+tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node,
+                                                                                                          linked_list_t *errors);
 
 /**
  * Create a TNCCS-ReasonStrings message from parameters
index 62874b0..2d57c7d 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include "tnccs_recommendation_msg.h"
+#include "tnccs_error_msg.h"
 
 #include <debug.h>
 
@@ -57,12 +58,6 @@ METHOD(tnccs_msg_t, get_node, xmlNodePtr,
        return this->node;
 }
 
-METHOD(tnccs_msg_t, process, status_t,
-       private_tnccs_recommendation_msg_t *this)
-{
-       return SUCCESS;
-}
-
 METHOD(tnccs_msg_t, destroy, void,
        private_tnccs_recommendation_msg_t *this)
 {
@@ -78,16 +73,20 @@ METHOD(tnccs_recommendation_msg_t, get_recommendation, TNC_IMV_Action_Recommenda
 /**
  * See header
  */
-tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node)
+tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
+                                                                                                          linked_list_t *errors)
 {
        private_tnccs_recommendation_msg_t *this;
+       xmlChar *rec_string;
+       char *error_msg, buf[BUF_LEN];
+       tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
+       tnccs_msg_t *msg;
 
        INIT(this,
                .public = {
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_recommendation = _get_recommendation,
@@ -96,7 +95,41 @@ tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node)
                .node = node,
        );
 
+       rec_string = xmlGetProp(node, (const xmlChar*)"type");
+       if (!rec_string)
+       {
+               error_msg = "type property in TNCCS-Recommendation is missing";
+               goto fatal;
+       }               
+       else if (streq((char*)rec_string, "allow"))
+       {
+               this->rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+       }
+       else if (streq((char*)rec_string, "isolate"))
+       {
+               this->rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+       }
+       else if (streq((char*)rec_string, "none"))
+       {
+               this->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+       }
+       else
+       {
+               error_msg = buf;
+               snprintf(buf, BUF_LEN, "unsupported type property value '%s' "
+                                                          "in TNCCS-Recommendation", rec_string);
+               xmlFree(rec_string);
+               goto fatal;
+       }
+       xmlFree(rec_string);
+       
        return &this->public.tnccs_msg_interface;
+
+fatal:
+       msg = tnccs_error_msg_create(error_type, error_msg);
+       errors->insert_last(errors, msg);
+       _destroy(this);
+       return NULL;
 }
 
 /**
@@ -106,14 +139,13 @@ tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec)
 {
        private_tnccs_recommendation_msg_t *this;
        xmlNodePtr n, n2;
-       char *recommendation_string;
+       char *rec_string;
 
        INIT(this,
                .public = {
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                        .get_recommendation = _get_recommendation,
@@ -134,19 +166,19 @@ tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec)
        switch (rec)
        {
                case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
-                       recommendation_string = "allow";
+                       rec_string = "allow";
                        break;
                case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
-                       recommendation_string = "isolate";
+                       rec_string = "isolate";
                        break;
                case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
                case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
                default:
-                       recommendation_string = "none";
+                       rec_string = "none";
        }
 
        n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type));
-       xmlNodeSetContent(n2, BAD_CAST recommendation_string);
+       xmlNodeSetContent(n2, BAD_CAST rec_string);
        xmlAddChild(n, n2);
 
        return &this->public.tnccs_msg_interface;
index 923a03b..42f6e8b 100644 (file)
@@ -49,8 +49,10 @@ struct tnccs_recommendation_msg_t {
  * Create a TNCCS-Recommendation message from XML-encoded message node
  *
  * @param msg_node                     XML-encoded message node
+ * @param errors                       linked list of TNCCS error messages
  */
-tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node);
+tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node,
+                                                                                                          linked_list_t *errors);
 
 /**
  * Create a TNCCS-Recommendation message from parameters
index 394e645..a7836ea 100644 (file)
@@ -51,11 +51,6 @@ METHOD(tnccs_msg_t, get_node, xmlNodePtr,
        return this->node;
 }
 
-METHOD(tnccs_msg_t, process, status_t,
-       private_tnccs_tncs_contact_info_msg_t *this)
-{
-       return SUCCESS;
-}
 METHOD(tnccs_msg_t, destroy, void,
        private_tnccs_tncs_contact_info_msg_t *this)
 {
@@ -65,7 +60,8 @@ METHOD(tnccs_msg_t, destroy, void,
 /**
  * See header
  */
-tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node)
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
+                                                                                                       linked_list_t *errors)
 {
        private_tnccs_tncs_contact_info_msg_t *this;
 
@@ -74,7 +70,6 @@ tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node)
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                },
@@ -98,7 +93,6 @@ tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void)
                        .tnccs_msg_interface = {
                                .get_type = _get_type,
                                .get_node = _get_node,
-                               .process = _process,
                                .destroy = _destroy,
                        },
                },
index ef21cd3..7612b10 100644 (file)
@@ -40,8 +40,10 @@ struct tnccs_tncs_contact_info_msg_t {
  * Create a TNCCS-TNCSContactInfo message from XML-encoded message node
  *
  * @param msg_node                     XML-encoded message node
+ * @param errors                       linked list of TNCCS error messages
  */
-tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node);
+tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node,
+                                                                                                       linked_list_t *errors);
 
 /**
  * Create a TNCCS-TNCSContactInfo message from parameters
index ea185e7..b950bfa 100644 (file)
 #include "batch/tnccs_batch.h"
 #include "messages/tnccs_msg.h"
 #include "messages/imc_imv_msg.h"
+#include "messages/tnccs_error_msg.h"
 #include "messages/tnccs_preferred_language_msg.h"
+#include "messages/tnccs_reason_strings_msg.h"
+#include "messages/tnccs_recommendation_msg.h"
 
 #include <daemon.h>
 #include <debug.h>
@@ -64,6 +67,16 @@ struct private_tnccs_11_t {
        mutex_t *mutex;
 
        /**
+        * Flag set while processing
+        */
+       bool fatal_error;
+
+       /**
+        * Flag set by TNCCS-Recommendation message
+        */
+       bool delete_state;
+
+       /**
         * Flag set by IMC/IMV RequestHandshakeRetry() function
         */
        bool request_handshake_retry;
@@ -125,6 +138,54 @@ static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg)
                        }
                        break;
                }
+               case TNCCS_MSG_RECOMMENDATION:
+               {
+                       tnccs_recommendation_msg_t *rec_msg;
+                       TNC_IMV_Action_Recommendation rec;
+                       TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
+
+                       rec_msg = (tnccs_recommendation_msg_t*)msg;
+                       rec = rec_msg->get_recommendation(rec_msg);
+                       if (this->is_server)
+                       {
+                               DBG1(DBG_TNC, "ignoring NCCS-Recommendation message from "
+                                                         " TNC client");
+                               break;
+                       }
+                       DBG1(DBG_TNC, "TNC recommendation is '%N'",
+                                                  action_recommendation_names, rec);
+                       switch (rec)
+                       {
+                               case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+                                       state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+                                       break;
+                               case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+                                       state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+                                       break;
+                               case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+                               default:
+                                       state = TNC_CONNECTION_STATE_ACCESS_NONE;
+                       }
+                       charon->imcs->notify_connection_change(charon->imcs,
+                                                                                                  this->connection_id, state);
+                       this->delete_state = TRUE;
+                       break;
+               }
+               case TNCCS_MSG_ERROR:
+               {
+                       tnccs_error_msg_t *err_msg;
+                       tnccs_error_type_t error_type;
+                       char *error_msg;
+
+                       err_msg = (tnccs_error_msg_t*)msg;
+                       error_msg = err_msg->get_message(err_msg, &error_type);
+                       DBG1(DBG_TNC, "received TNCCS-Error '%N': %s",
+                                tnccs_error_type_names, error_type, error_msg);
+
+                       /* we assume that all errors are fatal */
+                       this->fatal_error = TRUE;
+                       break;
+               }
                case TNCCS_MSG_PREFERRED_LANGUAGE:
                {
                        tnccs_preferred_language_msg_t *lang_msg;
@@ -148,6 +209,8 @@ METHOD(tls_t, process, status_t,
 {
        chunk_t data;
        tnccs_batch_t *batch;
+       tnccs_msg_t *msg;
+       enumerator_t *enumerator;
        status_t status;
 
        if (this->is_server && !this->connection_id)
@@ -170,11 +233,28 @@ METHOD(tls_t, process, status_t,
        batch = tnccs_batch_create_from_data(this->is_server, ++this->batch_id, data);
        status = batch->process(batch);
 
-       if (status != FAILED)
+       if (status == FAILED)
        {
-               enumerator_t *enumerator;
-               tnccs_msg_t *msg;
+               this->fatal_error = TRUE;
+               this->mutex->lock(this->mutex);
+               if (this->batch)
+               {
+                       DBG1(DBG_TNC, "cancelling TNCCS batch");
+                       this->batch->destroy(this->batch);
+                }
+               this->batch = tnccs_batch_create(this->is_server, this->batch_id);
 
+               /* add error messages to outbound batch */
+               enumerator = batch->create_error_enumerator(batch);
+               while (enumerator->enumerate(enumerator, &msg))
+               {
+                       this->batch->add_msg(this->batch, msg->get_ref(msg));
+               }
+               enumerator->destroy(enumerator);
+               this->mutex->unlock(this->mutex);
+       }
+       else
+       {
                enumerator = batch->create_msg_enumerator(batch);
                while (enumerator->enumerate(enumerator, &msg))
                {
@@ -182,6 +262,22 @@ METHOD(tls_t, process, status_t,
                }
                enumerator->destroy(enumerator);
 
+               /* received any TNCCS-Error messages */
+               if (this->fatal_error)
+               {
+                       DBG1(DBG_TNC, "a fatal TNCCS-Error occurred, terminating connection");
+                       batch->destroy(batch);
+                       return FAILED;
+               }
+
+               if (this->is_server)
+               {
+                       charon->imvs->batch_ending(charon->imvs, this->connection_id);
+               }
+               else
+               {
+                       charon->imcs->batch_ending(charon->imcs, this->connection_id);
+               }
        }
        batch->destroy(batch);