diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
commit | b34738ed08c2227300d554b139e2495ca5da97d6 (patch) | |
tree | 62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libimcv/pa_tnc | |
parent | 0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff) | |
download | vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip |
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libimcv/pa_tnc')
-rw-r--r-- | src/libimcv/pa_tnc/pa_tnc_attr.h | 96 | ||||
-rw-r--r-- | src/libimcv/pa_tnc/pa_tnc_attr_manager.c | 155 | ||||
-rw-r--r-- | src/libimcv/pa_tnc/pa_tnc_attr_manager.h | 85 | ||||
-rw-r--r-- | src/libimcv/pa_tnc/pa_tnc_msg.c | 427 | ||||
-rw-r--r-- | src/libimcv/pa_tnc/pa_tnc_msg.h | 103 |
5 files changed, 866 insertions, 0 deletions
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.h b/src/libimcv/pa_tnc/pa_tnc_attr.h new file mode 100644 index 000000000..b6057a70b --- /dev/null +++ b/src/libimcv/pa_tnc/pa_tnc_attr.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pa_tnc_attr pa_tnc_attr + * @{ @ingroup libimcv + */ + +#ifndef PA_TNC_ATTR_H_ +#define PA_TNC_ATTR_H_ + +typedef struct pa_tnc_attr_t pa_tnc_attr_t; + +#include <library.h> +#include <pen/pen.h> + +/** + * Interface for an RFC 5792 PA-TNC Posture Attribute. + * + */ +struct pa_tnc_attr_t { + + /** + * Get the vendor ID of an PA-TNC attribute + * + * @return attribute vendor ID + */ + u_int32_t (*get_vendor_id)(pa_tnc_attr_t *this); + + /** + * Get the type of an PA-TNC attribute + * + * @return attribute type + */ + u_int32_t (*get_type)(pa_tnc_attr_t *this); + + /** + * Get the value of an PA-TNC attribute + * + * @return attribute value + */ + chunk_t (*get_value)(pa_tnc_attr_t *this); + + /** + * Get the noskip flag + * + * @return TRUE if the noskip flag is set + */ + bool (*get_noskip_flag)(pa_tnc_attr_t *this); + + /** + * Set the noskip flag + * + * @param noskip_flag TRUE if the noskip flag is to be set + */ + void (*set_noskip_flag)(pa_tnc_attr_t *this, bool noskip); + + /** + * Build value of an PA-TNC attribute from its parameters + */ + void (*build)(pa_tnc_attr_t *this); + + /** + * Process the value of an PA-TNC attribute to extract its parameters + * + * @param relative error offset within attribute body + * @return result status + */ + status_t (*process)(pa_tnc_attr_t *this, u_int32_t *offset); + + /** + * Get a new reference to the PA-TNC attribute + * + * @return this, with an increased refcount + */ + pa_tnc_attr_t* (*get_ref)(pa_tnc_attr_t *this); + + /** + * Destroys a pa_tnc_attr_t object. + */ + void (*destroy)(pa_tnc_attr_t *this); +}; + +#endif /** PA_TNC_ATTR_H_ @}*/ diff --git a/src/libimcv/pa_tnc/pa_tnc_attr_manager.c b/src/libimcv/pa_tnc/pa_tnc_attr_manager.c new file mode 100644 index 000000000..1de89d87d --- /dev/null +++ b/src/libimcv/pa_tnc/pa_tnc_attr_manager.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pa_tnc_attr_manager.h" + +#include <utils/linked_list.h> +#include <debug.h> + +typedef struct private_pa_tnc_attr_manager_t private_pa_tnc_attr_manager_t; +typedef struct entry_t entry_t; + +struct entry_t { + pen_t vendor_id; + enum_name_t *attr_names; + pa_tnc_attr_create_t attr_create; +}; + +/** + * Private data of a pa_tnc_attr_manager_t object. + * + */ +struct private_pa_tnc_attr_manager_t { + + /** + * Public pa_tnc_attr_manager_t interface. + */ + pa_tnc_attr_manager_t public; + + /** + * List of PA-TNC vendor attributes + */ + linked_list_t *list; +}; + +METHOD(pa_tnc_attr_manager_t, add_vendor, void, + private_pa_tnc_attr_manager_t *this, pen_t vendor_id, + pa_tnc_attr_create_t attr_create, enum_name_t *attr_names) +{ + entry_t *entry; + + entry = malloc_thing(entry_t); + entry->vendor_id = vendor_id; + entry->attr_create = attr_create; + entry->attr_names = attr_names; + + this->list->insert_last(this->list, entry); + DBG2(DBG_TNC, "added %N attributes", pen_names, vendor_id); +} + +METHOD(pa_tnc_attr_manager_t, remove_vendor, void, + private_pa_tnc_attr_manager_t *this, pen_t vendor_id) +{ + enumerator_t *enumerator; + entry_t *entry; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->vendor_id == vendor_id) + { + this->list->remove_at(this->list, enumerator); + free(entry); + DBG2(DBG_TNC, "removed %N attributes", pen_names, vendor_id); + } + } + enumerator->destroy(enumerator); +} + +METHOD(pa_tnc_attr_manager_t, get_names, enum_name_t*, + private_pa_tnc_attr_manager_t *this, pen_t vendor_id) +{ + enumerator_t *enumerator; + entry_t *entry; + enum_name_t *attr_names = NULL; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->vendor_id == vendor_id) + { + attr_names = entry->attr_names; + break; + } + } + enumerator->destroy(enumerator); + + return attr_names; +} + +METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*, + private_pa_tnc_attr_manager_t *this, pen_t vendor_id, u_int32_t type, + chunk_t value) +{ + enumerator_t *enumerator; + entry_t *entry; + pa_tnc_attr_t *attr = NULL; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->vendor_id == vendor_id) + { + if (entry->attr_create) + { + attr = entry->attr_create(type, value); + } + break; + } + } + enumerator->destroy(enumerator); + + return attr; +} + +METHOD(pa_tnc_attr_manager_t, destroy, void, + private_pa_tnc_attr_manager_t *this) +{ + this->list->destroy_function(this->list, free); + free(this); +} + +/** + * See header + */ +pa_tnc_attr_manager_t *pa_tnc_attr_manager_create(void) +{ + private_pa_tnc_attr_manager_t *this; + + INIT(this, + .public = { + .add_vendor = _add_vendor, + .remove_vendor = _remove_vendor, + .get_names = _get_names, + .create = _create, + .destroy = _destroy, + }, + .list = linked_list_create(), + ); + + return &this->public; +} + diff --git a/src/libimcv/pa_tnc/pa_tnc_attr_manager.h b/src/libimcv/pa_tnc/pa_tnc_attr_manager.h new file mode 100644 index 000000000..40c3ab335 --- /dev/null +++ b/src/libimcv/pa_tnc/pa_tnc_attr_manager.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pa_tnc_attr_manager pa_tnc_attr_manager + * @{ @ingroup libimcv + */ + +#ifndef PA_TNC_ATTR_MANAGER_H_ +#define PA_TNC_ATTR_MANAGER_H_ + +typedef struct pa_tnc_attr_manager_t pa_tnc_attr_manager_t; + +#include "pa_tnc_attr.h" + +#include <library.h> + +typedef pa_tnc_attr_t* (*pa_tnc_attr_create_t)(u_int32_t type, chunk_t value); + +/** + * Manages PA-TNC attributes for arbitrary PENs + */ +struct pa_tnc_attr_manager_t { + + /** + * Add vendor-specific attribute names and creation method + * + * @param vendor_id Private Enterprise Number (PEN) + * @param attr_create Vendor-specific attribute create method + * @param attr_names Vendor-specific attribute names + */ + void (*add_vendor)(pa_tnc_attr_manager_t *this, pen_t vendor_id, + pa_tnc_attr_create_t attr_create, + enum_name_t *attr_names); + + /** + * Remove vendor-specific attribute names and creation method + * + * @param vendor_id Private Enterprise Number (PEN) + */ + void (*remove_vendor)(pa_tnc_attr_manager_t *this, pen_t vendor_id); + + /* + * Return the PA-TNC attribute names for a given vendor ID + * + * @param vendor_id Private Enterprise Number (PEN) + * @return PA-TNC attribute names if found, NULL else + */ + enum_name_t* (*get_names)(pa_tnc_attr_manager_t *this, pen_t vendor_id); + + /** + * Create a PA-TNC attribute object from data for a given vendor ID and type + * + * @param vendor_id Private Enterprise Number (PEN) + * @param type PA-TNC attribute type + * @param value PA-TNC attribute value as encoded data + * @return PA-TNC attribute object if supported, NULL else + */ + pa_tnc_attr_t* (*create)(pa_tnc_attr_manager_t *this, pen_t vendor_id, + u_int32_t type, chunk_t value); + + /** + * Destroys a pa_tnc_attr_manager_t object. + */ + void (*destroy)(pa_tnc_attr_manager_t *this); +}; + +/** + * Create a PA-TNC attribute manager + */ +pa_tnc_attr_manager_t* pa_tnc_attr_manager_create(void); + +#endif /** PA_TNC_ATTR_MANAGER_H_ @}*/ diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c new file mode 100644 index 000000000..b5df0a5b5 --- /dev/null +++ b/src/libimcv/pa_tnc/pa_tnc_msg.c @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "imcv.h" +#include "pa_tnc_msg.h" +#include "ietf/ietf_attr_pa_tnc_error.h" + +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <utils/linked_list.h> +#include <pen/pen.h> +#include <debug.h> + + +typedef struct private_pa_tnc_msg_t private_pa_tnc_msg_t; + +/** + * PA-TNC message header + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Version | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Message Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PA_TNC_HEADER_SIZE 8 +#define PA_TNC_RESERVED 0x000000 + +/** + * PA-TNC attribute + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | PA-TNC Attribute Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA-TNC Attribute Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA-TNC Attribute Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Attribute Value (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PA_TNC_ATTR_FLAG_NONE 0x00 +#define PA_TNC_ATTR_FLAG_NOSKIP (1<<7) +#define PA_TNC_ATTR_HEADER_SIZE 12 +#define PA_TNC_ATTR_INFO_SIZE 8 + +/** + * Private data of a pa_tnc_msg_t object. + * + */ +struct private_pa_tnc_msg_t { + + /** + * Public pa_tnc_msg_t interface. + */ + pa_tnc_msg_t public; + + /** + * List of PA-TNC attributes + */ + linked_list_t *attributes; + + /** + * linked list of PA-TNC error messages + */ + linked_list_t *errors; + + /** + * Message identifier + */ + u_int32_t identifier; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pa_tnc_msg_t, get_encoding, chunk_t, + private_pa_tnc_msg_t *this) +{ + return this->encoding; +} + +METHOD(pa_tnc_msg_t, add_attribute, void, + private_pa_tnc_msg_t *this, pa_tnc_attr_t *attr) +{ + this->attributes->insert_last(this->attributes, attr); +} + +METHOD(pa_tnc_msg_t, build, void, + private_pa_tnc_msg_t *this) +{ + bio_writer_t *writer; + enumerator_t *enumerator; + pa_tnc_attr_t *attr; + enum_name_t *pa_attr_names; + pen_t vendor_id; + u_int32_t type; + u_int8_t flags; + chunk_t value; + rng_t *rng; + + /* create a random message identifier */ + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + rng->get_bytes(rng, sizeof(this->identifier), (u_int8_t*)&this->identifier); + rng->destroy(rng); + DBG2(DBG_TNC, "creating PA-TNC message with ID 0x%08x", this->identifier); + + /* build message header */ + writer = bio_writer_create(PA_TNC_HEADER_SIZE); + writer->write_uint8 (writer, PA_TNC_VERSION); + writer->write_uint24(writer, PA_TNC_RESERVED); + writer->write_uint32(writer, this->identifier); + + /* build and append encoding of PA-TNC attributes */ + enumerator = this->attributes->create_enumerator(this->attributes); + while (enumerator->enumerate(enumerator, &attr)) + { + attr->build(attr); + vendor_id = attr->get_vendor_id(attr); + type = attr->get_type(attr); + value = attr->get_value(attr); + flags = attr->get_noskip_flag(attr) ? PA_TNC_ATTR_FLAG_NOSKIP : + PA_TNC_ATTR_FLAG_NONE; + + pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes, + vendor_id); + if (pa_attr_names) + { + DBG2(DBG_TNC, "creating PA-TNC attribute type '%N/%N' " + "0x%06x/0x%08x", pen_names, vendor_id, + pa_attr_names, type, vendor_id, type); + } + else + { + DBG2(DBG_TNC, "creating PA-TNC attribute type '%N' " + "0x%06x/0x%08x", pen_names, vendor_id, + vendor_id, type); + } + DBG3(DBG_TNC, "%B", &value); + + writer->write_uint8 (writer, flags); + writer->write_uint24(writer, vendor_id); + writer->write_uint32(writer, type); + writer->write_uint32(writer, PA_TNC_ATTR_HEADER_SIZE + value.len); + writer->write_data (writer, value); + } + enumerator->destroy(enumerator); + + free(this->encoding.ptr); + this->encoding = chunk_clone(writer->get_buf(writer)); + writer->destroy(writer); +} + +METHOD(pa_tnc_msg_t, process, status_t, + private_pa_tnc_msg_t *this) +{ + bio_reader_t *reader; + pa_tnc_attr_t *error; + u_int8_t version; + u_int32_t reserved, offset, attr_offset; + + /* process message header */ + if (this->encoding.len < PA_TNC_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes insufficient to parse PA-TNC message header", + this->encoding.len); + return FAILED; + } + reader = bio_reader_create(this->encoding); + reader->read_uint8 (reader, &version); + reader->read_uint24(reader, &reserved); + reader->read_uint32(reader, &this->identifier); + DBG2(DBG_TNC, "processing PA-TNC message with ID 0x%08x", this->identifier); + + if (version != PA_TNC_VERSION) + { + DBG1(DBG_TNC, "PA-TNC version %u not supported", version); + error = ietf_attr_pa_tnc_error_create(PEN_IETF, + PA_ERROR_VERSION_NOT_SUPPORTED, this->encoding); + goto err; + } + + /* offset of the first PA-TNC attribute in the PA-TNC message */ + offset = PA_TNC_HEADER_SIZE; + + /* pre-process PA-TNC attributes */ + while (reader->remaining(reader) >= PA_TNC_ATTR_HEADER_SIZE) + { + pen_t vendor_id; + u_int8_t flags; + u_int32_t type, length; + chunk_t value, attr_info; + pa_tnc_attr_t *attr; + enum_name_t *pa_attr_names; + ietf_attr_pa_tnc_error_t *error_attr; + + attr_info = reader->peek(reader); + attr_info.len = PA_TNC_ATTR_INFO_SIZE; + reader->read_uint8 (reader, &flags); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + reader->read_uint32(reader, &length); + + pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes, + vendor_id); + if (pa_attr_names) + { + DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' " + "0x%06x/0x%08x", pen_names, vendor_id, + pa_attr_names, type, vendor_id, type); + } + else + { + DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' " + "0x%06x/0x%08x", pen_names, vendor_id, + vendor_id, type); + } + + if (length < PA_TNC_ATTR_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length", + length); + error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, + PA_ERROR_INVALID_PARAMETER, this->encoding, + offset + PA_TNC_ATTR_INFO_SIZE); + goto err; + } + + if (!reader->read_data(reader, length - PA_TNC_ATTR_HEADER_SIZE, &value)) + { + DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value"); + error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, + PA_ERROR_INVALID_PARAMETER, this->encoding, + offset + PA_TNC_ATTR_INFO_SIZE); + goto err; + } + DBG3(DBG_TNC, "%B", &value); + + attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes, + vendor_id, type, value); + if (!attr) + { + if (flags & PA_TNC_ATTR_FLAG_NOSKIP) + { + DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag"); + error = ietf_attr_pa_tnc_error_create(PEN_IETF, + PA_ERROR_ATTR_TYPE_NOT_SUPPORTED, this->encoding); + error_attr = (ietf_attr_pa_tnc_error_t*)error; + error_attr->set_attr_info(error_attr, attr_info); + goto err; + } + else + { + DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute"); + offset += length; + continue; + } + } + + if (attr->process(attr, &attr_offset) != SUCCESS) + { + attr->destroy(attr); + if (vendor_id == PEN_IETF && type == IETF_ATTR_PA_TNC_ERROR) + { + /* error while processing a PA-TNC error attribute - abort */ + reader->destroy(reader); + return FAILED; + } + error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, + PA_ERROR_INVALID_PARAMETER, this->encoding, + offset + PA_TNC_ATTR_HEADER_SIZE + attr_offset); + goto err; + } + add_attribute(this, attr); + offset += length; + } + + if (reader->remaining(reader) == 0) + { + reader->destroy(reader); + return SUCCESS; + } + DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header"); + error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, + PA_ERROR_INVALID_PARAMETER, this->encoding, offset); + +err: + reader->destroy(reader); + this->errors->insert_last(this->errors, error); + return VERIFY_ERROR; +} + +METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool, + private_pa_tnc_msg_t *this) +{ + enumerator_t *enumerator; + pa_tnc_attr_t *attr; + bool fatal_error = FALSE; + + enumerator = this->attributes->create_enumerator(this->attributes); + while (enumerator->enumerate(enumerator, &attr)) + { + if (attr->get_vendor_id(attr) == PEN_IETF && + attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR) + { + ietf_attr_pa_tnc_error_t *error_attr; + pen_t error_vendor_id; + pa_tnc_error_code_t error_code; + chunk_t msg_info, attr_info; + u_int32_t offset; + + error_attr = (ietf_attr_pa_tnc_error_t*)attr; + error_vendor_id = error_attr->get_vendor_id(error_attr); + error_code = error_attr->get_error_code(error_attr); + msg_info = error_attr->get_msg_info(error_attr); + + /* skip errors from non-IETF namespaces */ + if (error_vendor_id != PEN_IETF) + { + continue; + } + DBG1(DBG_IMC, "received PA-TNC error '%N' concerning message " + "0x%08x/0x%08x", pa_tnc_error_code_names, error_code, + untoh32(msg_info.ptr), untoh32(msg_info.ptr + 4)); + + switch (error_code) + { + case PA_ERROR_INVALID_PARAMETER: + offset = error_attr->get_offset(error_attr); + DBG1(DBG_IMC, " occurred at offset of %u bytes", offset); + break; + case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED: + attr_info = error_attr->get_attr_info(error_attr); + DBG1(DBG_IMC, " unsupported attribute %#B", &attr_info); + break; + default: + break; + } + + /* remove the processed IETF standard error attribute */ + this->attributes->remove_at(this->attributes, enumerator); + fatal_error = TRUE; + } + } + enumerator->destroy(enumerator); + + return fatal_error; +} + +METHOD(pa_tnc_msg_t, create_attribute_enumerator, enumerator_t*, + private_pa_tnc_msg_t *this) +{ + return this->attributes->create_enumerator(this->attributes); +} + +METHOD(pa_tnc_msg_t, create_error_enumerator, enumerator_t*, + private_pa_tnc_msg_t *this) +{ + return this->errors->create_enumerator(this->errors); +} + +METHOD(pa_tnc_msg_t, destroy, void, + private_pa_tnc_msg_t *this) +{ + this->attributes->destroy_offset(this->attributes, + offsetof(pa_tnc_attr_t, destroy)); + this->errors->destroy_offset(this->errors, + offsetof(pa_tnc_attr_t, destroy)); + free(this->encoding.ptr); + free(this); +} + +/** + * See header + */ +pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data) +{ + private_pa_tnc_msg_t *this; + + INIT(this, + .public = { + .get_encoding = _get_encoding, + .add_attribute = _add_attribute, + .build = _build, + .process = _process, + .process_ietf_std_errors = _process_ietf_std_errors, + .create_attribute_enumerator = _create_attribute_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .encoding = chunk_clone(data), + .attributes = linked_list_create(), + .errors = linked_list_create(), + ); + + return &this->public; +} + +/** + * See header + */ +pa_tnc_msg_t *pa_tnc_msg_create(void) +{ + return pa_tnc_msg_create_from_data(chunk_empty); +} + diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h new file mode 100644 index 000000000..c3ce829d5 --- /dev/null +++ b/src/libimcv/pa_tnc/pa_tnc_msg.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup pa_tnc_msg pa_tnc_msg + * @{ @ingroup libimcv + */ + +#ifndef PA_TNC_MSG_H_ +#define PA_TNC_MSG_H_ + +typedef struct pa_tnc_msg_t pa_tnc_msg_t; + +#define PA_TNC_VERSION 0x01 + +#include "pa_tnc_attr.h" + +#include <library.h> + +/** + * Interface for the RFC 5792 PA-TNC Posture Attribute protocol. + * + */ +struct pa_tnc_msg_t { + + /** + * Get the encoding of the PA-TNC message + * + * @return encoded PA-TNC message + */ + chunk_t (*get_encoding)(pa_tnc_msg_t *this); + + /** + * Add a PA-TNC attribute + * + * @param attr PA-TNC attribute to be addedd + */ + void (*add_attribute)(pa_tnc_msg_t *this, pa_tnc_attr_t* attr); + + /** + * Build the PA-TNC message + */ + void (*build)(pa_tnc_msg_t *this); + + /** + * Process the PA-TNC message + * + * @return return processing status + */ + status_t (*process)(pa_tnc_msg_t *this); + + /** + * Process and remove all IETF standard error PA-TNC attributes + * + * @return TRUE if at least one error attribute processed + */ + bool (*process_ietf_std_errors)(pa_tnc_msg_t *this); + + /** + * Enumerates over all PA-TNC attributes + * + * @return return attribute enumerator + */ + enumerator_t* (*create_attribute_enumerator)(pa_tnc_msg_t *this); + + /** + * Enumerates over all parsing errors + * + * @return return error enumerator + */ + enumerator_t* (*create_error_enumerator)(pa_tnc_msg_t *this); + + /** + * Destroys a pa_tnc_msg_t object. + */ + void (*destroy)(pa_tnc_msg_t *this); +}; + +/** + * Create an empty PA-TNC message + */ +pa_tnc_msg_t* pa_tnc_msg_create(void); + +/** + * Create an unprocessed PA-TNC message from received data + * + * @param data PA-TNC message data + */ +pa_tnc_msg_t* pa_tnc_msg_create_from_data(chunk_t data); + +#endif /** PA_TNC_MSG_H_ @}*/ |