diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2015-08-18 20:25:26 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2015-08-18 21:24:26 +0200 |
commit | 10f25a3dd9390ff25a995ed422be697b76873625 (patch) | |
tree | 64c59b1e6b83da541ae6363544a7c6a7ddca0100 /src/libimcv | |
parent | 6bd1216e7a8a41eb6c103c27a05f50871e1aef99 (diff) | |
download | strongswan-10f25a3dd9390ff25a995ed422be697b76873625.tar.bz2 strongswan-10f25a3dd9390ff25a995ed422be697b76873625.tar.xz |
Fixed the implemention of the IF-M segmentation protocol
The first segment only fit if the segmentation envelope attribute
was preceded by a Max Attribute Size Response attribute. The
improved implementation fills up the first PA-TNC message with
the first segment up to the maximum message size.
Diffstat (limited to 'src/libimcv')
-rw-r--r-- | src/libimcv/imc/imc_msg.c | 30 | ||||
-rw-r--r-- | src/libimcv/imv/imv_msg.c | 28 | ||||
-rw-r--r-- | src/libimcv/pa_tnc/pa_tnc_msg.c | 10 | ||||
-rw-r--r-- | src/libimcv/pa_tnc/pa_tnc_msg.h | 9 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_swid/imc_swid.c | 6 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_attestation/imv_attestation_agent.c | 6 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_agent.c | 6 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_swid/imv_swid_agent.c | 6 | ||||
-rw-r--r-- | src/libimcv/seg/seg_contract.c | 6 | ||||
-rw-r--r-- | src/libimcv/seg/seg_contract.h | 6 | ||||
-rw-r--r-- | src/libimcv/seg/seg_env.c | 15 | ||||
-rw-r--r-- | src/libimcv/seg/seg_env.h | 5 | ||||
-rw-r--r-- | src/libimcv/suites/test_imcv_seg.c | 15 |
13 files changed, 97 insertions, 51 deletions
diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c index 83337cf7b..9e12e29f1 100644 --- a/src/libimcv/imc/imc_msg.c +++ b/src/libimcv/imc/imc_msg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 Andreas Steffen + * Copyright (C) 2012-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -108,6 +108,7 @@ METHOD(imc_msg_t, send_, TNC_Result, pa_tnc_attr_t *attr; TNC_UInt32 msg_flags; TNC_MessageType msg_type; + size_t max_msg_len, min_seg_attr_len, space_left; bool attr_added, oversize; chunk_t msg; seg_contract_t *contract; @@ -120,23 +121,37 @@ METHOD(imc_msg_t, send_, TNC_Result, contract = contracts->get_contract(contracts, this->msg_type, FALSE, this->dst_id); + /* Retrieve maximum allowed PA-TNC message size if set */ + max_msg_len = this->state->get_max_msg_len(this->state); + + /* Minimum size needed for Segmentation Envelope Attribute */ + min_seg_attr_len = PA_TNC_ATTR_HEADER_SIZE + TCG_SEG_ATTR_SEG_ENV_HEADER + + PA_TNC_ATTR_HEADER_SIZE; + while (this->attr_list->get_count(this->attr_list)) { - pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state)); + pa_tnc_msg = pa_tnc_msg_create(max_msg_len); attr_added = FALSE; enumerator = this->attr_list->create_enumerator(this->attr_list); while (enumerator->enumerate(enumerator, &attr)) { + space_left = pa_tnc_msg->get_space(pa_tnc_msg); + if (contract && contract->check_size(contract, attr, &oversize)) { if (oversize) { - /* TODO generate SWID error msg */ + /* TODO handle oversized attributes */ + } + else if (max_msg_len == 0 || space_left >= min_seg_attr_len) + { + attr = contract->first_segment(contract, attr, space_left); } else { - attr = contract->first_segment(contract, attr); + /* segment attribute in next iteration */ + break; } } if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr)) @@ -147,11 +162,12 @@ METHOD(imc_msg_t, send_, TNC_Result, { if (attr_added) { + /* there might be space for attribute in next iteration */ break; } else { - DBG1(DBG_IMC, "PA-TNC attribute too large to send, deleted"); + DBG1(DBG_IMV, "PA-TNC attribute too large to send, deleted"); attr->destroy(attr); } } @@ -341,9 +357,7 @@ METHOD(imc_msg_t, receive, TNC_Result, my_max_seg_size = this->state->get_max_msg_len(this->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; + - TCG_SEG_ATTR_SEG_ENV_HEADER; /* If segmentation is possible select lower segment size */ if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION && diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c index fdf63325d..039124c2a 100644 --- a/src/libimcv/imv/imv_msg.c +++ b/src/libimcv/imv/imv_msg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 Andreas Steffen + * Copyright (C) 2012-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -125,6 +125,7 @@ METHOD(imv_msg_t, send_, TNC_Result, pa_tnc_attr_t *attr; TNC_UInt32 msg_flags; TNC_MessageType msg_type; + size_t max_msg_len, min_seg_attr_len, space_left; bool attr_added, oversize; chunk_t msg; seg_contract_t *contract; @@ -137,23 +138,37 @@ METHOD(imv_msg_t, send_, TNC_Result, contract = contracts->get_contract(contracts, this->msg_type, FALSE, this->dst_id); + /* Retrieve maximum allowed PA-TNC message size if set */ + max_msg_len = this->state->get_max_msg_len(this->state); + + /* Minimum size needed for Segmentation Envelope Attribute */ + min_seg_attr_len = PA_TNC_ATTR_HEADER_SIZE + TCG_SEG_ATTR_SEG_ENV_HEADER + + PA_TNC_ATTR_HEADER_SIZE; + while (this->attr_list->get_count(this->attr_list)) { - pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state)); + pa_tnc_msg = pa_tnc_msg_create(max_msg_len); attr_added = FALSE; enumerator = this->attr_list->create_enumerator(this->attr_list); while (enumerator->enumerate(enumerator, &attr)) { + space_left = pa_tnc_msg->get_space(pa_tnc_msg); + if (contract && contract->check_size(contract, attr, &oversize)) { if (oversize) { - /* TODO generate SWID error msg */ + /* TODO handle oversized attributes */ + } + else if (max_msg_len == 0 || space_left >= min_seg_attr_len) + { + attr = contract->first_segment(contract, attr, space_left); } else { - attr = contract->first_segment(contract, attr); + /* segment attribute in next iteration */ + break; } } if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr)) @@ -164,6 +179,7 @@ METHOD(imv_msg_t, send_, TNC_Result, { if (attr_added) { + /* there might be space for attribute in next iteration */ break; } else @@ -377,9 +393,7 @@ METHOD(imv_msg_t, receive, TNC_Result, my_max_seg_size = this->state->get_max_msg_len(this->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; + - TCG_SEG_ATTR_SEG_ENV_HEADER; /* If segmentation is possible select lower segment size */ if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION && diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c index ea4dee950..17c649dfd 100644 --- a/src/libimcv/pa_tnc/pa_tnc_msg.c +++ b/src/libimcv/pa_tnc/pa_tnc_msg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2014 Andreas Steffen + * Copyright (C) 2011-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -92,6 +92,12 @@ METHOD(pa_tnc_msg_t, get_encoding, chunk_t, return this->encoding; } +METHOD(pa_tnc_msg_t, get_space, size_t, + private_pa_tnc_msg_t *this) +{ + return this->max_msg_len ? this->max_msg_len - this->msg_len : 0; +} + METHOD(pa_tnc_msg_t, add_attribute, bool, private_pa_tnc_msg_t *this, pa_tnc_attr_t *attr) { @@ -389,6 +395,7 @@ pa_tnc_msg_t *pa_tnc_msg_create(size_t max_msg_len) INIT(this, .public = { .get_encoding = _get_encoding, + .get_space = _get_space, .add_attribute = _add_attribute, .build = _build, .process = _process, @@ -416,6 +423,7 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data) INIT(this, .public = { .get_encoding = _get_encoding, + .get_space = _get_space, .add_attribute = _add_attribute, .build = _build, .process = _process, diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h index 57ff1a04c..3be302032 100644 --- a/src/libimcv/pa_tnc/pa_tnc_msg.h +++ b/src/libimcv/pa_tnc/pa_tnc_msg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2014 Andreas Steffen + * Copyright (C) 2011-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -44,6 +44,13 @@ struct pa_tnc_msg_t { chunk_t (*get_encoding)(pa_tnc_msg_t *this); /** + * Get the remaining space in octets left in the PA-TNC message + * + * @return remaining space or 0 if max_msg_len is not set + */ + size_t (*get_space)(pa_tnc_msg_t *this); + + /** * Add a PA-TNC attribute * * @param attr PA-TNC attribute to be addedd diff --git a/src/libimcv/plugins/imc_swid/imc_swid.c b/src/libimcv/plugins/imc_swid/imc_swid.c index 40f352ad9..0dcb9afb6 100644 --- a/src/libimcv/plugins/imc_swid/imc_swid.c +++ b/src/libimcv/plugins/imc_swid/imc_swid.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Andreas Steffen + * Copyright (C) 2013-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -134,9 +134,7 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, /* 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; + - TCG_SEG_ATTR_SEG_ENV_HEADER; /* Announce support of PA-TNC segmentation to IMV */ contract = seg_contract_create(msg_types[0], max_attr_size, max_seg_size, diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c index 8e3736857..9656306ca 100644 --- a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c +++ b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2011-2012 Sansar Choinyambuu - * Copyright (C) 2011-2014 Andreas Steffen + * Copyright (C) 2011-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -484,9 +484,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, 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; + - TCG_SEG_ATTR_SEG_ENV_HEADER; /* Announce support of PA-TNC segmentation to IMC */ contract = seg_contract_create(msg_types[0], max_attr_size, diff --git a/src/libimcv/plugins/imv_os/imv_os_agent.c b/src/libimcv/plugins/imv_os/imv_os_agent.c index f0b1936ab..5eefb51ad 100644 --- a/src/libimcv/plugins/imv_os/imv_os_agent.c +++ b/src/libimcv/plugins/imv_os/imv_os_agent.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Andreas Steffen + * Copyright (C) 2013-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -542,9 +542,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, 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; + - TCG_SEG_ATTR_SEG_ENV_HEADER; /* Announce support of PA-TNC segmentation to IMC */ contract = seg_contract_create(msg_types[0], max_attr_size, diff --git a/src/libimcv/plugins/imv_swid/imv_swid_agent.c b/src/libimcv/plugins/imv_swid/imv_swid_agent.c index 5bebf32c0..6d327830f 100644 --- a/src/libimcv/plugins/imv_swid/imv_swid_agent.c +++ b/src/libimcv/plugins/imv_swid/imv_swid_agent.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Andreas Steffen + * Copyright (C) 2013-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -446,9 +446,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, 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; + - TCG_SEG_ATTR_SEG_ENV_HEADER; /* Announce support of PA-TNC segmentation to IMC */ contract = seg_contract_create(msg_types[0], max_attr_size, diff --git a/src/libimcv/seg/seg_contract.c b/src/libimcv/seg/seg_contract.c index 7db702a08..41aed583a 100644 --- a/src/libimcv/seg/seg_contract.c +++ b/src/libimcv/seg/seg_contract.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Andreas Steffen + * Copyright (C) 2014-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -148,7 +148,7 @@ METHOD(seg_contract_t, check_size, bool, } METHOD(seg_contract_t, first_segment, pa_tnc_attr_t*, - private_seg_contract_t *this, pa_tnc_attr_t *attr) + private_seg_contract_t *this, pa_tnc_attr_t *attr, size_t max_attr_len) { seg_env_t *seg_env; @@ -160,7 +160,7 @@ METHOD(seg_contract_t, first_segment, pa_tnc_attr_t*, } this->seg_envs->insert_last(this->seg_envs, seg_env); - return seg_env->first_segment(seg_env); + return seg_env->first_segment(seg_env, max_attr_len); } METHOD(seg_contract_t, next_segment, pa_tnc_attr_t*, diff --git a/src/libimcv/seg/seg_contract.h b/src/libimcv/seg/seg_contract.h index 23676a9f4..afbf30934 100644 --- a/src/libimcv/seg/seg_contract.h +++ b/src/libimcv/seg/seg_contract.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Andreas Steffen + * Copyright (C) 2014-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -78,9 +78,11 @@ struct seg_contract_t { * Generate first segment of a PA-TNC attribute according to the contract * * @param attr PA-TNC attribute to be segmented + * @param max_attr_len Maximum size of first segment envelope attribute * @return First segment envelope attribute */ - pa_tnc_attr_t* (*first_segment)(seg_contract_t *this, pa_tnc_attr_t *attr); + pa_tnc_attr_t* (*first_segment)(seg_contract_t *this, pa_tnc_attr_t *attr, + size_t max_attr_len); /** * Generate next segment of a PA-TNC attribute according to the contract diff --git a/src/libimcv/seg/seg_env.c b/src/libimcv/seg/seg_env.c index f38419248..8d0f76007 100644 --- a/src/libimcv/seg/seg_env.c +++ b/src/libimcv/seg/seg_env.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Andreas Steffen + * Copyright (C) 2014-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -89,14 +89,21 @@ METHOD(seg_env_t, get_base_attr_info, chunk_t, } METHOD(seg_env_t, first_segment, pa_tnc_attr_t*, - private_seg_env_t *this) + private_seg_env_t *this, size_t max_attr_len) { pa_tnc_attr_t *seg_env_attr; bio_writer_t *writer; pen_type_t type; chunk_t segment_data, value; + size_t seg_size; uint8_t flags, seg_env_flags; + /* compute size of first segment */ + seg_size = max_attr_len ? min(this->max_seg_size, + max_attr_len - PA_TNC_ATTR_HEADER_SIZE + - TCG_SEG_ATTR_SEG_ENV_HEADER) + : this->max_seg_size; + /* get components of base attribute header and data */ flags = this->base_attr->get_noskip_flag(this->base_attr) ? PA_TNC_ATTR_FLAG_NOSKIP : PA_TNC_ATTR_FLAG_NONE; @@ -104,7 +111,7 @@ METHOD(seg_env_t, first_segment, pa_tnc_attr_t*, /* attribute data going into the first segment */ segment_data = this->data; - segment_data.len = this->max_seg_size - PA_TNC_ATTR_HEADER_SIZE; + segment_data.len = seg_size - PA_TNC_ATTR_HEADER_SIZE; /* build encoding of the base attribute header and first segment data */ writer = bio_writer_create(this->max_seg_size); @@ -118,7 +125,7 @@ METHOD(seg_env_t, first_segment, pa_tnc_attr_t*, this->data = chunk_skip(this->data, segment_data.len); DBG2(DBG_TNC, "creating first segment for base attribute ID %d (%d bytes)", - this->base_attr_id, this->max_seg_size); + this->base_attr_id, seg_size); seg_env_flags = SEG_ENV_FLAG_START | SEG_ENV_FLAG_MORE; seg_env_attr = tcg_seg_attr_seg_env_create(value, seg_env_flags, diff --git a/src/libimcv/seg/seg_env.h b/src/libimcv/seg/seg_env.h index 611f9a98a..5f21236f0 100644 --- a/src/libimcv/seg/seg_env.h +++ b/src/libimcv/seg/seg_env.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Andreas Steffen + * Copyright (C) 2014-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -66,9 +66,10 @@ struct seg_env_t { /** * Generate the first segment envelope of the base attribute * + * @param max_attr_len Maximum size of first attribute segment envelope * @return First attribute segment envelope */ - pa_tnc_attr_t* (*first_segment)(seg_env_t *this); + pa_tnc_attr_t* (*first_segment)(seg_env_t *this, size_t max_attr_len); /** * Generate the next segment envelope of the base attribute diff --git a/src/libimcv/suites/test_imcv_seg.c b/src/libimcv/suites/test_imcv_seg.c index 8b51eda05..5245be9fa 100644 --- a/src/libimcv/suites/test_imcv_seg.c +++ b/src/libimcv/suites/test_imcv_seg.c @@ -42,7 +42,7 @@ static struct { { 24, 1, 24 }, { 25, 1, 23 }, { 47, 1, 1 }, - { 48, 0, 0 }, + { 48, 0, 0 }, }; static char command[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -87,7 +87,7 @@ START_TEST(test_imcv_seg_env) if (n == 0) { /* create first segment */ - attr = seg_env->first_segment(seg_env); + attr = seg_env->first_segment(seg_env, 0); seg_env_attr = (tcg_seg_attr_seg_env_t*)attr; segment = seg_env_attr->get_segment(seg_env_attr, &flags); @@ -168,8 +168,9 @@ START_TEST(test_imcv_seg_env_special) pen_type_t type; seg_env_t *seg_env; chunk_t segment, value; + uint32_t max_attr_len = 60; uint32_t max_seg_size = 47; - uint32_t last_seg_size = 1; + uint32_t last_seg_size = 4; uint32_t offset = 12; base_attr = ita_attr_command_create(command); @@ -179,7 +180,7 @@ START_TEST(test_imcv_seg_env_special) base_attr->set_noskip_flag(base_attr, TRUE); seg_env = seg_env_create(id, base_attr, max_seg_size); - attr = seg_env->first_segment(seg_env); + attr = seg_env->first_segment(seg_env, max_attr_len); attr->destroy(attr); /* don't return last segment indicator */ @@ -306,7 +307,7 @@ START_TEST(test_imcv_seg_contract) contract_r = seg_contract_create(msg_type, max_attr_size, max_seg_size, FALSE, issuer_id, TRUE); attr = contract_r->first_segment(contract_r, - base_attr_r->get_ref(base_attr_r)); + base_attr_r->get_ref(base_attr_r), 0); if (seg_env_tests[_i].next_segs == 0) { @@ -422,8 +423,8 @@ START_TEST(test_imcv_seg_contract_special) ck_assert(!oversize); /* get first segment of each base attribute */ - attr1_f = contract_r->first_segment(contract_r, base_attr1_r->get_ref(base_attr1_r)); - attr2_f = contract_r->first_segment(contract_r, base_attr2_r->get_ref(base_attr2_r)); + attr1_f = contract_r->first_segment(contract_r, base_attr1_r->get_ref(base_attr1_r), 0); + attr2_f = contract_r->first_segment(contract_r, base_attr2_r->get_ref(base_attr2_r), 0); ck_assert(attr1_f); ck_assert(attr2_f); seg_env_attr1 = (tcg_seg_attr_seg_env_t*)attr1_f; |