aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c30
-rw-r--r--src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h7
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c84
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h5
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c64
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h6
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c69
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h13
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c16
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h4
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c11
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h4
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c60
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h4
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c10
-rw-r--r--src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h4
-rw-r--r--src/libcharon/plugins/tnccs_11/tnccs_11.c102
17 files changed, 378 insertions, 115 deletions
diff --git a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c
index d44645d70..fbcb1337b 100644
--- a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c
+++ b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c
@@ -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,
diff --git a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h
index 6f47e5660..25301f763 100644
--- a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h
+++ b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h
@@ -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);
diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c
index 2c3bc59be..c99cd2ef3 100644
--- a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c
+++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c
@@ -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,
diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h
index ccf31d346..335b1b759 100644
--- a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h
+++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h
@@ -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
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c
index 8a5646815..5a876e381 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c
@@ -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;
}
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h
index ca16af9ed..61deaffda 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h
@@ -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);
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c
index cb7360f41..323bbf87a 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c
@@ -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;
}
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h
index c4c637d8f..e0b54449a 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h
@@ -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_ @}*/
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
index 985922221..fd85350b5 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c
@@ -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,
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
index d57cc6e4d..97e0ff831 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h
@@ -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
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
index af1621b4b..ad1ed3650 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c
@@ -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,
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
index 0b68c2c13..9057477a8 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h
@@ -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
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
index 62874b0ba..2d57c7d55 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c
@@ -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;
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
index 923a03bc2..42f6e8b74 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h
@@ -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
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
index 394e64590..a7836ea96 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c
@@ -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,
},
},
diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
index ef21cd3fa..7612b102f 100644
--- a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
+++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h
@@ -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
diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c
index ea185e782..b950bfa07 100644
--- a/src/libcharon/plugins/tnccs_11/tnccs_11.c
+++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c
@@ -17,7 +17,10 @@
#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);