diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2014-10-05 18:40:24 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2014-10-05 18:43:55 +0200 |
commit | a5dfe7a29a2967d671e6f39cd696dc5a56567f2f (patch) | |
tree | 8a1c8f201a95f638c4692d28cc770f41e8ca1a1d /src | |
parent | fc47211740b2ef5eebd010e7469f612c018ccf52 (diff) | |
download | strongswan-a5dfe7a29a2967d671e6f39cd696dc5a56567f2f.tar.bz2 strongswan-a5dfe7a29a2967d671e6f39cd696dc5a56567f2f.tar.xz |
OS IMV proposes IF-M segmentation contract
The OS IMV sends a TCG IF-M Segmentation contract request.
All IETF standard attributes support segmentation. Additionally
the IETF Installed Packages standard attributes supports
incremental processing while segments are received.
Diffstat (limited to 'src')
-rw-r--r-- | src/libimcv/ietf/ietf_attr_installed_packages.c | 116 | ||||
-rw-r--r-- | src/libimcv/ietf/ietf_attr_installed_packages.h | 12 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_os/imc_os.c | 62 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_agent.c | 41 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_state.c | 18 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_state.h | 12 |
6 files changed, 153 insertions, 108 deletions
diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.c b/src/libimcv/ietf/ietf_attr_installed_packages.c index 2c61d7254..155a7826c 100644 --- a/src/libimcv/ietf/ietf_attr_installed_packages.c +++ b/src/libimcv/ietf/ietf_attr_installed_packages.c @@ -62,16 +62,31 @@ struct private_ietf_attr_installed_packages_t { size_t length; /** - * Attribute value or segment + * Offset up to which attribute value has been processed + */ + size_t offset; + + /** + * Current position of attribute value pointer */ chunk_t value; /** + * Contains complete attribute or current segment + */ + chunk_t segment; + + /** * Noskip flag */ bool noskip_flag; /** + * Number of Installed Packages in attribute + */ + uint16_t count; + + /** * List of Installed Package entries */ linked_list_t *packages; @@ -148,6 +163,7 @@ METHOD(pa_tnc_attr_t, build, void, enumerator->destroy(enumerator); this->value = writer->extract_buf(writer); + this->segment = this->value; this->length = this->value.len; writer->destroy(writer); } @@ -157,70 +173,82 @@ METHOD(pa_tnc_attr_t, process, status_t, { bio_reader_t *reader; package_entry_t *entry; - status_t status = FAILED; + status_t status = NEED_MORE; chunk_t name, version; - u_int16_t reserved, count; + u_int16_t reserved; u_char *pos; - *offset = 0; - - if (this->value.len < this->length) - { - return NEED_MORE; - } - if (this->value.len < IETF_INSTALLED_PACKAGES_MIN_SIZE) - { - DBG1(DBG_TNC, "insufficient data for IETF installed packages"); - return FAILED; + if (this->offset == 0) + { + if (this->length < IETF_INSTALLED_PACKAGES_MIN_SIZE) + { + DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_IETF, + ietf_attr_names, this->type.type); + *offset = this->offset; + return FAILED; + } + if (this->value.len < IETF_INSTALLED_PACKAGES_MIN_SIZE) + { + return NEED_MORE; + } + reader = bio_reader_create(this->value); + reader->read_uint16(reader, &reserved); + reader->read_uint16(reader, &this->count); + this->offset = IETF_INSTALLED_PACKAGES_MIN_SIZE; + this->value = reader->peek(reader); + reader->destroy(reader); } + reader = bio_reader_create(this->value); - reader->read_uint16(reader, &reserved); - reader->read_uint16(reader, &count); - *offset = IETF_INSTALLED_PACKAGES_MIN_SIZE; - while (reader->remaining(reader)) + while (this->count) { if (!reader->read_data8(reader, &name)) { - DBG1(DBG_TNC, "insufficient data for IETF installed package name"); goto end; } pos = memchr(name.ptr, '\0', name.len); if (pos) { DBG1(DBG_TNC, "nul termination in IETF installed package name"); - *offset += 1 + (pos - name.ptr); + *offset = this->offset + 1 + (pos - name.ptr); + status = FAILED; goto end; } - *offset += 1 + name.len; + this->offset += 1 + name.len; if (!reader->read_data8(reader, &version)) { - DBG1(DBG_TNC, "insufficient data for IETF installed package version"); goto end; } pos = memchr(version.ptr, '\0', version.len); if (pos) { DBG1(DBG_TNC, "nul termination in IETF installed package version"); - *offset += 1 + (pos - version.ptr); + *offset = this->offset + 1 + (pos - version.ptr); + status = FAILED; goto end; } - *offset += 1 + version.len; + this->offset += 1 + version.len; + this->value = reader->peek(reader); entry = malloc_thing(package_entry_t); entry->name = chunk_clone(name); entry->version = chunk_clone(version); this->packages->insert_last(this->packages, entry); + + /* at least one tag ID was processed */ + status = SUCCESS; + this->count--; } - if (count != this->packages->get_count(this->packages)) + if (this->length != this->offset) { - DBG1(DBG_TNC, "IETF installed package count unequal to " - "number of included packages"); - goto end; + DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_IETF, + ietf_attr_names, this->type.type); + *offset = this->offset; + status = FAILED; } - status = SUCCESS; end: reader->destroy(reader); @@ -230,7 +258,9 @@ end: METHOD(pa_tnc_attr_t, add_segment, void, private_ietf_attr_installed_packages_t *this, chunk_t segment) { - this->value = chunk_cat("mc", this->value, segment); + this->value = chunk_cat("cc", this->value, segment); + chunk_free(&this->segment); + this->segment = this->value; } METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*, @@ -246,7 +276,7 @@ METHOD(pa_tnc_attr_t, destroy, void, if (ref_put(&this->ref)) { this->packages->destroy_function(this->packages, (void*)free_package_entry); - free(this->value.ptr); + free(this->segment.ptr); free(this); } } @@ -285,6 +315,23 @@ METHOD(ietf_attr_installed_packages_t, create_enumerator, enumerator_t*, (void*)package_filter, NULL, NULL); } +METHOD(ietf_attr_installed_packages_t, get_count, uint16_t, + private_ietf_attr_installed_packages_t *this) +{ + return this->count; +} + +METHOD(ietf_attr_installed_packages_t, clear_packages, void, + private_ietf_attr_installed_packages_t *this) +{ + package_entry_t *entry; + + while (this->packages->remove_first(this->packages,(void**)&entry)) + { + free_package_entry(entry); + } +} + /** * Described in header. */ @@ -307,6 +354,8 @@ pa_tnc_attr_t *ietf_attr_installed_packages_create(void) }, .add = _add, .create_enumerator = _create_enumerator, + .get_count = _get_count, + .clear_packages = _clear_packages, }, .type = { PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES }, .packages = linked_list_create(), @@ -340,14 +389,19 @@ pa_tnc_attr_t *ietf_attr_installed_packages_create_from_data(size_t length, }, .add = _add, .create_enumerator = _create_enumerator, + .get_count = _get_count, + .clear_packages = _clear_packages, }, .type = {PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES }, .length = length, - .value = chunk_clone(data), + .segment = chunk_clone(data), .packages = linked_list_create(), .ref = 1, ); + /* received either complete attribute value or first segment */ + this->value = this->segment; + return &this->public.pa_tnc_attribute; } diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.h b/src/libimcv/ietf/ietf_attr_installed_packages.h index 28fba3868..9f7b7cbcf 100644 --- a/src/libimcv/ietf/ietf_attr_installed_packages.h +++ b/src/libimcv/ietf/ietf_attr_installed_packages.h @@ -56,6 +56,18 @@ struct ietf_attr_installed_packages_t { */ enumerator_t* (*create_enumerator)(ietf_attr_installed_packages_t *this); + /** + * Number of Installed Packages still missing + * + * @return Number of missing installed packages + */ + uint16_t (*get_count)(ietf_attr_installed_packages_t *this); + + /** + * Remove all Installed Packages from list + */ + void (*clear_packages)(ietf_attr_installed_packages_t *this); + }; /** diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c index 785280c28..86d2e09ca 100644 --- a/src/libimcv/plugins/imc_os/imc_os.c +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -30,7 +30,6 @@ #include <ita/ita_attr.h> #include <ita/ita_attr_get_settings.h> #include <ita/ita_attr_settings.h> -#include <ita/ita_attr_angel.h> #include <ita/ita_attr_device_id.h> #include <tncif_pa_subtypes.h> @@ -341,69 +340,24 @@ static void add_device_id(imc_msg_t *msg) */ static void add_installed_packages(imc_state_t *state, imc_msg_t *msg) { - pa_tnc_attr_t *attr = NULL, *attr_angel; + pa_tnc_attr_t *attr; ietf_attr_installed_packages_t *attr_cast; enumerator_t *enumerator; chunk_t name, version; - size_t max_attr_size, attr_size, entry_size; - bool first = TRUE; - /** - * Compute the maximum IETF Installed Packages attribute size - * leaving space for an additional ITA Angel attribute - */ - max_attr_size = state->get_max_msg_len(state) - - PA_TNC_HEADER_SIZE - PA_TNC_ATTR_HEADER_SIZE; - - /* At least one IETF Installed Packages attribute is sent */ attr = ietf_attr_installed_packages_create(); - attr_size = PA_TNC_ATTR_HEADER_SIZE + IETF_INSTALLED_PACKAGES_MIN_SIZE; enumerator = os->create_package_enumerator(os); - if (enumerator) + while (enumerator->enumerate(enumerator, &name, &version)) { - while (enumerator->enumerate(enumerator, &name, &version)) - { - DBG2(DBG_IMC, "package '%.*s' (%.*s)", - name.len, name.ptr, version.len, version.ptr); - - entry_size = 2 + name.len + version.len; - if (attr_size + entry_size > max_attr_size) - { - if (first) - { - /** - * Send an ITA Start Angel attribute to the IMV signalling - * that multiple ITA Installed Package attributes follow. - */ - attr_angel = ita_attr_angel_create(TRUE); - msg->add_attribute(msg, attr_angel); - first = FALSE; - } - msg->add_attribute(msg, attr); - - /* create the next IETF Installed Packages attribute */ - attr = ietf_attr_installed_packages_create(); - attr_size = PA_TNC_ATTR_HEADER_SIZE + - IETF_INSTALLED_PACKAGES_MIN_SIZE; - } - attr_cast = (ietf_attr_installed_packages_t*)attr; - attr_cast->add(attr_cast, name, version); - attr_size += entry_size; - } - enumerator->destroy(enumerator); + DBG2(DBG_IMC, "package '%.*s' (%.*s)", + name.len, name.ptr, version.len, version.ptr); + attr_cast = (ietf_attr_installed_packages_t*)attr; + attr_cast->add(attr_cast, name, version); } - msg->add_attribute(msg, attr); + enumerator->destroy(enumerator); - if (!first) - { - /** - * If we sent an ITA Start Angel attribute in the first place, - * terminate by appending a matching ITA Stop Angel attribute. - */ - attr_angel = ita_attr_angel_create(FALSE); - msg->add_attribute(msg, attr_angel); - } + msg->add_attribute(msg, attr); } /** diff --git a/src/libimcv/plugins/imv_os/imv_os_agent.c b/src/libimcv/plugins/imv_os/imv_os_agent.c index 8f92531ed..f0b1936ab 100644 --- a/src/libimcv/plugins/imv_os/imv_os_agent.c +++ b/src/libimcv/plugins/imv_os/imv_os_agent.c @@ -37,8 +37,9 @@ #include <ita/ita_attr.h> #include <ita/ita_attr_get_settings.h> #include <ita/ita_attr_settings.h> -#include <ita/ita_attr_angel.h> #include <ita/ita_attr_device_id.h> +#include "tcg/seg/tcg_seg_attr_max_size.h" +#include "tcg/seg/tcg_seg_attr_seg_env.h" #include <tncif_names.h> #include <tncif_pa_subtypes.h> @@ -46,6 +47,8 @@ #include <pen/pen.h> #include <utils/debug.h> +#define INSTALLED_PACKAGES_MAX_ATTR_SIZE 100000000 + typedef struct private_imv_os_agent_t private_imv_os_agent_t; typedef enum imv_os_attr_t imv_os_attr_t; @@ -166,6 +169,7 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, chunk_t os_name = chunk_empty; chunk_t os_version = chunk_empty; bool fatal_error = FALSE, assessment = FALSE; + uint16_t missing; os_state = (imv_os_state_t*)state; session = state->get_session(state); @@ -325,6 +329,9 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, TNC_IMV_EVALUATION_RESULT_ERROR); assessment = TRUE; } + missing = attr_cast->get_count(attr_cast); + os_state->set_missing(os_state, missing); + attr_cast->clear_packages(attr_cast); break; } default: @@ -371,12 +378,6 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, session->set_device_id(session, value); break; } - case ITA_ATTR_START_ANGEL: - os_state->set_angel_count(os_state, TRUE); - break; - case ITA_ATTR_STOP_ANGEL: - os_state->set_angel_count(os_state, FALSE); - break; default: break; } @@ -531,6 +532,30 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, if (handshake_state == IMV_OS_STATE_INIT) { + size_t max_attr_size = INSTALLED_PACKAGES_MAX_ATTR_SIZE; + size_t max_seg_size; + seg_contract_t *contract; + seg_contract_manager_t *contracts; + char buf[BUF_LEN]; + + /* Determine maximum PA-TNC attribute segment size */ + max_seg_size = state->get_max_msg_len(state) + - PA_TNC_HEADER_SIZE + - PA_TNC_ATTR_HEADER_SIZE + - TCG_SEG_ATTR_SEG_ENV_HEADER + - PA_TNC_ATTR_HEADER_SIZE + - TCG_SEG_ATTR_MAX_SIZE_SIZE; + + /* Announce support of PA-TNC segmentation to IMC */ + contract = seg_contract_create(msg_types[0], max_attr_size, + max_seg_size, TRUE, imv_id, FALSE); + contract->get_info_string(contract, buf, BUF_LEN, TRUE); + DBG2(DBG_IMV, "%s", buf); + contracts = state->get_contracts(state); + contracts->add_contract(contracts, contract); + attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size, TRUE); + out_msg->add_attribute(out_msg, attr); + if ((received & IMV_OS_ATTR_MUST) != IMV_OS_ATTR_MUST) { /* create attribute request for missing mandatory attributes */ @@ -673,7 +698,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, int count, count_update, count_blacklist, count_ok; if (!(received & IMV_OS_ATTR_INSTALLED_PACKAGES) || - os_state->get_angel_count(os_state) > 0) + os_state->get_missing(os_state) > 0) { continue; } diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c index 24f803d47..ac826a77c 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.c +++ b/src/libimcv/plugins/imv_os/imv_os_state.c @@ -141,9 +141,9 @@ struct private_imv_os_state_t { u_int os_settings; /** - * Angel count + * Number of installed packages still missing */ - int angel_count; + uint16_t missing; }; @@ -535,16 +535,16 @@ METHOD(imv_os_state_t, get_os_settings, u_int, return this->os_settings; } -METHOD(imv_os_state_t, set_angel_count, void, - private_imv_os_state_t *this, bool start) +METHOD(imv_os_state_t, set_missing, void, + private_imv_os_state_t *this, uint16_t missing) { - this->angel_count += start ? 1 : -1; + this->missing = missing; } -METHOD(imv_os_state_t, get_angel_count, int, +METHOD(imv_os_state_t, get_missing, uint16_t, private_imv_os_state_t *this) { - return this->angel_count; + return this->missing; } METHOD(imv_os_state_t, add_bad_package, void, @@ -598,8 +598,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id) .get_count = _get_count, .set_os_settings = _set_os_settings, .get_os_settings = _get_os_settings, - .set_angel_count = _set_angel_count, - .get_angel_count = _get_angel_count, + .set_missing = _set_missing, + .get_missing = _get_missing, .add_bad_package = _add_bad_package, }, .state = TNC_CONNECTION_STATE_CREATE, diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h index 82ebb6cc9..aa9b64076 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.h +++ b/src/libimcv/plugins/imv_os/imv_os_state.h @@ -114,18 +114,18 @@ struct imv_os_state_t { u_int (*get_os_settings)(imv_os_state_t *this); /** - * Increase/Decrease the ITA Angel count + * Set number of installed packages still missing * - * @param start TRUE increases and FALSE decreases count by one + * @param missing Number of missing installed packages */ - void (*set_angel_count)(imv_os_state_t *this, bool start); + void (*set_missing)(imv_os_state_t *this, uint16_t missing); /** - * Get the ITA Angel count + * Get number of installed packages still missing * - * @return ITA Angel count + * @return Number of missing installed packages */ - int (*get_angel_count)(imv_os_state_t *this); + uint16_t (*get_missing)(imv_os_state_t *this); /** * Store a bad package that has to be updated or removed |