diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2011-01-09 10:00:54 +0100 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2011-01-09 10:00:54 +0100 |
commit | 5fee822a93ce175ad6ef9d61b7adb0cfd7878356 (patch) | |
tree | 3cd06d6b88444ca298b7756bb263268294f421aa | |
parent | 33749b879c5db7ef28a611fc99e9b7bb5b2d0691 (diff) | |
download | strongswan-5fee822a93ce175ad6ef9d61b7adb0cfd7878356.tar.bz2 strongswan-5fee822a93ce175ad6ef9d61b7adb0cfd7878356.tar.xz |
implemented parsing of TNCCS 1.1 messages
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); |