diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-09-09 05:13:13 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-09-09 05:13:50 +0200 |
commit | 6f93927b6c6a0094cb81b7c560baf9b15d339ba5 (patch) | |
tree | 5d30fd31f96da80556407dbfc194c6abc6075a40 | |
parent | bcf8cdd556d23844e633c09f27e05c2395364c3d (diff) | |
download | strongswan-6f93927b6c6a0094cb81b7c560baf9b15d339ba5.tar.bz2 strongswan-6f93927b6c6a0094cb81b7c560baf9b15d339ba5.tar.xz |
introduced sending of standard IETF Assessment Result PA-TNC attribute by IMVs
21 files changed, 638 insertions, 83 deletions
@@ -1,14 +1,17 @@ strongswan-5.0.1 ---------------- +- Introduced the sending of the standard IETF Assessment Result + PA-TNC attribute by all strongSwan Integrity Measurement Verifiers. + - Extended PTS Attestation IMC/IMV pair to provide full evidence of the Linux IMA measurement process. All pertinent file information - of a Linux OS can be collected an stored in an SQL database. + of a Linux OS can be collected and stored in an SQL database. - The PA-TNC and PB-TNC protocols can now process huge data payloads >64 kB by distributing PA-TNC attributes over multiple PA-TNC messages and these messages over several PB-TNC batches. As long as no - consolidated recommandation from all IMVs can be obtained the TNC + consolidated recommandation from all IMVs can be obtained, the TNC server requests more client data by sending an empty SDATA batch. - The rightgroups2 ipsec.conf option can require group membership during diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c index 64cdbcb26..856bd6c59 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2010-2012 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 @@ -280,6 +281,24 @@ METHOD(recommendations_t, have_recommendation, bool, return TRUE; } +METHOD(recommendations_t, clear_recommendation, void, + private_tnc_imv_recommendations_t *this) +{ + enumerator_t *enumerator; + recommendation_entry_t *entry; + + enumerator = this->recs->create_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &entry)) + { + entry->have_recommendation = FALSE; + entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION; + entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW; + chunk_clear(&entry->reason); + chunk_clear(&entry->reason_language); + } + enumerator->destroy(enumerator); +} + METHOD(recommendations_t, get_preferred_language, chunk_t, private_tnc_imv_recommendations_t *this) { @@ -370,21 +389,6 @@ METHOD(recommendations_t, create_reason_enumerator, enumerator_t*, (void*)reason_filter, NULL, NULL); } -METHOD(recommendations_t, clear_reasons, void, - private_tnc_imv_recommendations_t *this) -{ - enumerator_t *enumerator; - recommendation_entry_t *entry; - - enumerator = this->recs->create_enumerator(this->recs); - while (enumerator->enumerate(enumerator, &entry)) - { - chunk_clear(&entry->reason); - chunk_clear(&entry->reason_language); - } - enumerator->destroy(enumerator); -} - METHOD(recommendations_t, destroy, void, private_tnc_imv_recommendations_t *this) { @@ -415,12 +419,12 @@ recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list) .public = { .provide_recommendation = _provide_recommendation, .have_recommendation = _have_recommendation, + .clear_recommendation = _clear_recommendation, .get_preferred_language = _get_preferred_language, .set_preferred_language = _set_preferred_language, .set_reason_string = _set_reason_string, .set_reason_language = _set_reason_language, .create_reason_enumerator = _create_reason_enumerator, - .clear_reasons = _clear_reasons, .destroy = _destroy, }, .recs = linked_list_create(), diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c index eeb4c1ac9..3b563a30b 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c @@ -403,7 +403,6 @@ static void check_and_build_recommendation(private_tnccs_11_t *this) this->batch->add_msg(this->batch, msg); } enumerator->destroy(enumerator); - this->recs->clear_reasons(this->recs); /* we have reache the final state */ this->delete_state = TRUE; diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 26edcb576..f2e958cfb 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -398,6 +398,7 @@ static void build_retry_batch(private_tnccs_20_t *this) if (this->is_server) { + this->recs->clear_recommendation(this->recs); tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); } @@ -574,7 +575,6 @@ static void check_and_build_recommendation(private_tnccs_20_t *this) this->messages->insert_last(this->messages, msg); } enumerator->destroy(enumerator); - this->recs->clear_reasons(this->recs); } } @@ -639,12 +639,17 @@ METHOD(tls_t, build, status_t, this->request_handshake_retry = FALSE; } + if (this->is_server && state == PB_STATE_SERVER_WORKING && + this->recs->have_recommendation(this->recs, NULL, NULL)) + { + check_and_build_recommendation(this); + } + if (this->batch_type == PB_BATCH_NONE) { if (this->is_server && state == PB_STATE_SERVER_WORKING) { - if (this->state_machine->get_empty_cdata(this->state_machine) || - this->recs->have_recommendation(this->recs, NULL, NULL)) + if (this->state_machine->get_empty_cdata(this->state_machine)) { check_and_build_recommendation(this); } diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index 63548647d..e0e8f1017 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -14,6 +14,7 @@ libimcv_la_SOURCES = \ ietf/ietf_attr_port_filter.h ietf/ietf_attr_port_filter.c \ ietf/ietf_attr_product_info.h ietf/ietf_attr_product_info.c \ ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \ + ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \ ita/ita_attr.h ita/ita_attr.c \ ita/ita_attr_command.h ita/ita_attr_command.c \ ita/ita_attr_dummy.h ita/ita_attr_dummy.c \ diff --git a/src/libimcv/ietf/ietf_attr.c b/src/libimcv/ietf/ietf_attr.c index 144b890ba..fc89c5716 100644 --- a/src/libimcv/ietf/ietf_attr.c +++ b/src/libimcv/ietf/ietf_attr.c @@ -17,6 +17,7 @@ #include "ietf/ietf_attr_port_filter.h" #include "ietf/ietf_attr_product_info.h" #include "ietf/ietf_attr_attr_request.h" +#include "ietf/ietf_attr_assess_result.h" ENUM(ietf_attr_names, IETF_ATTR_TESTING, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED, "Testing", @@ -49,12 +50,13 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value) return ietf_attr_port_filter_create_from_data(value); case IETF_ATTR_PA_TNC_ERROR: return ietf_attr_pa_tnc_error_create_from_data(value); + case IETF_ATTR_ASSESSMENT_RESULT: + return ietf_attr_assess_result_create_from_data(value); case IETF_ATTR_TESTING: case IETF_ATTR_NUMERIC_VERSION: case IETF_ATTR_STRING_VERSION: case IETF_ATTR_OPERATIONAL_STATUS: case IETF_ATTR_INSTALLED_PACKAGES: - case IETF_ATTR_ASSESSMENT_RESULT: case IETF_ATTR_REMEDIATION_INSTRUCTIONS: case IETF_ATTR_FORWARDING_ENABLED: case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED: diff --git a/src/libimcv/ietf/ietf_attr_assess_result.c b/src/libimcv/ietf/ietf_attr_assess_result.c new file mode 100644 index 000000000..6893730bf --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_assess_result.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2012 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 "ietf_attr_assess_result.h" + +#include <pa_tnc/pa_tnc_msg.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <debug.h> + +typedef struct private_ietf_attr_assess_result_t private_ietf_attr_assess_result_t; + +/** + * PA-TNC Product Information type (see section 4.2.2 of RFC 5792) + * + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Assessment Result | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define ASSESS_RESULT_SIZE 4 + +/** + * Private data of an ietf_attr_assess_result_t object. + */ +struct private_ietf_attr_assess_result_t { + + /** + * Public members of ietf_attr_assess_result_t + */ + ietf_attr_assess_result_t public; + + /** + * Vendor-specific attribute type + */ + pen_type_t type; + + /** + * Attribute value + */ + chunk_t value; + + /** + * Noskip flag + */ + bool noskip_flag; + + /** + * Assessment Result + */ + u_int32_t result; + + /** + * Reference count + */ + refcount_t ref; +}; + +METHOD(pa_tnc_attr_t, get_type, pen_type_t, + private_ietf_attr_assess_result_t *this) +{ + return this->type; +} + +METHOD(pa_tnc_attr_t, get_value, chunk_t, + private_ietf_attr_assess_result_t *this) +{ + return this->value; +} + +METHOD(pa_tnc_attr_t, get_noskip_flag, bool, + private_ietf_attr_assess_result_t *this) +{ + return this->noskip_flag; +} + +METHOD(pa_tnc_attr_t, set_noskip_flag,void, + private_ietf_attr_assess_result_t *this, bool noskip) +{ + this->noskip_flag = noskip; +} + +METHOD(pa_tnc_attr_t, build, void, + private_ietf_attr_assess_result_t *this) +{ + bio_writer_t *writer; + + if (this->value.ptr) + { + return; + } + + writer = bio_writer_create(ASSESS_RESULT_SIZE); + writer->write_uint32(writer, this->result); + this->value = chunk_clone(writer->get_buf(writer)); + writer->destroy(writer); +} + +METHOD(pa_tnc_attr_t, process, status_t, + private_ietf_attr_assess_result_t *this, u_int32_t *offset) +{ + bio_reader_t *reader; + + if (this->value.len < ASSESS_RESULT_SIZE) + { + DBG1(DBG_TNC, "insufficient data for IETF assessment result"); + *offset = 0; + return FAILED; + } + reader = bio_reader_create(this->value); + reader->read_uint32(reader, &this->result); + reader->destroy(reader); + + return SUCCESS; +} + +METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*, + private_ietf_attr_assess_result_t *this) +{ + ref_get(&this->ref); + return &this->public.pa_tnc_attribute; +} + +METHOD(pa_tnc_attr_t, destroy, void, + private_ietf_attr_assess_result_t *this) +{ + if (ref_put(&this->ref)) + { + free(this->value.ptr); + free(this); + } +} + +METHOD(ietf_attr_assess_result_t, get_result, u_int32_t, + private_ietf_attr_assess_result_t *this) +{ + return this->result; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_assess_result_create(u_int32_t result) +{ + private_ietf_attr_assess_result_t *this; + + INIT(this, + .public = { + .pa_tnc_attribute = { + .get_type = _get_type, + .get_value = _get_value, + .get_noskip_flag = _get_noskip_flag, + .set_noskip_flag = _set_noskip_flag, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_result = _get_result, + }, + .type = { PEN_IETF, IETF_ATTR_ASSESSMENT_RESULT }, + .result = result, + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_assess_result_create_from_data(chunk_t data) +{ + private_ietf_attr_assess_result_t *this; + + INIT(this, + .public = { + .pa_tnc_attribute = { + .get_type = _get_type, + .get_value = _get_value, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_result = _get_result, + }, + .type = { PEN_IETF, IETF_ATTR_ASSESSMENT_RESULT }, + .value = chunk_clone(data), + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + diff --git a/src/libimcv/ietf/ietf_attr_assess_result.h b/src/libimcv/ietf/ietf_attr_assess_result.h new file mode 100644 index 000000000..fab8bc3f0 --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_assess_result.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012 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 ietf_attr_assess_resultt ietf_attr_assess_result + * @{ @ingroup ietf + */ + +#ifndef IETF_ATTR_ASSESS_RESULT_H_ +#define IETF_ATTR_ASSESS_RESULT_H_ + +typedef struct ietf_attr_assess_result_t ietf_attr_assess_result_t; + +#include "ietf_attr.h" +#include "pa_tnc/pa_tnc_attr.h" + + +/** + * Class implementing the IETF PA-TNC Assessment Result attribute. + * + */ +struct ietf_attr_assess_result_t { + + /** + * Public PA-TNC attribute interface + */ + pa_tnc_attr_t pa_tnc_attribute; + + /** + * Get the assessment result + * + * @return Assessment Result + */ + u_int32_t (*get_result)(ietf_attr_assess_result_t *this); + +}; + +/** + * Creates an ietf_attr_assess_result_t object + * + */ +pa_tnc_attr_t* ietf_attr_assess_result_create(u_int32_t result); + +/** + * Creates an ietf_attr_assess_result_t object from received data + * + * @param value unparsed attribute value + */ +pa_tnc_attr_t* ietf_attr_assess_result_create_from_data(chunk_t value); + +#endif /** IETF_ATTR_ASSESS_RESULT_H_ @}*/ diff --git a/src/libimcv/imc/imc_state.h b/src/libimcv/imc/imc_state.h index 37f6a7405..c34441f0f 100644 --- a/src/libimcv/imc/imc_state.h +++ b/src/libimcv/imc/imc_state.h @@ -23,6 +23,8 @@ #define IMC_STATE_H_ #include <tncif.h> +#include <tncifimv.h> +#include <tncifimc.h> #include <library.h> @@ -34,8 +36,7 @@ typedef struct imc_state_t imc_state_t; struct imc_state_t { /** - * Get the TNCS connection I -D attached to the state + * Get the TNCS connection ID attached to the state * * @return TNCS connection ID of the state */ @@ -86,6 +87,25 @@ D attached to the state void (*change_state)(imc_state_t *this, TNC_ConnectionState new_state); /** + * Set the Assessment/Evaluation Result + * + * @param id IMC ID + * @param result Assessment/Evaluation Result + */ + void (*set_result)(imc_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result result); + + /** + * Get the Assessment/Evaluation Result + * + * @param id IMC ID + * @param result Assessment/Evaluation Result + * @return TRUE if result is known + */ + bool (*get_result)(imc_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result *result); + + /** * Destroys an imc_state_t object */ void (*destroy)(imc_state_t *this); diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c index 0935caad9..1ec5ba002 100644 --- a/src/libimcv/imv/imv_agent.c +++ b/src/libimcv/imv/imv_agent.c @@ -15,6 +15,7 @@ #include "imcv.h" #include "imv_agent.h" +#include "ietf/ietf_attr_assess_result.h" #include <tncif_names.h> @@ -682,9 +683,13 @@ METHOD(imv_agent_t, receive_message, TNC_Result, } METHOD(imv_agent_t, provide_recommendation, TNC_Result, - private_imv_agent_t *this, TNC_ConnectionID connection_id) + private_imv_agent_t *this, TNC_ConnectionID connection_id, + TNC_UInt32 dst_imc_id) { imv_state_t *state; + linked_list_t *attr_list; + pa_tnc_attr_t *attr; + TNC_Result result; TNC_IMV_Action_Recommendation rec; TNC_IMV_Evaluation_Result eval; TNC_UInt32 lang_len; @@ -700,7 +705,6 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result, } state->get_recommendation(state, &rec, &eval); - /* send a reason string if action recommendation is not allow */ if (rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW) { @@ -729,7 +733,19 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result, reason_lang.len, reason_lang.ptr); } } - + + /* Send and IETF Assessment Result attribute */ + attr = ietf_attr_assess_result_create(eval); + attr_list = linked_list_create(); + attr_list->insert_last(attr_list, attr); + result = send_message(this, connection_id, FALSE, this->id, dst_imc_id, + attr_list); + attr_list->destroy(attr_list); + if (result != TNC_RESULT_SUCCESS) + { + return result; + } + return this->provide_recommendation(this->id, connection_id, rec, eval); } diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h index fd1a91fd0..34ac3c109 100644 --- a/src/libimcv/imv/imv_agent.h +++ b/src/libimcv/imv/imv_agent.h @@ -151,10 +151,12 @@ struct imv_agent_t { * Deliver IMV Action Recommendation and IMV Evaluation Result to the TNCS * * @param connection_id network connection ID assigned by TNCS + * @param dst_imc_id IMD ID to be set as destination * @return TNC result code */ TNC_Result (*provide_recommendation)(imv_agent_t *this, - TNC_ConnectionID connection_id); + TNC_ConnectionID connection_id, + TNC_UInt32 dst_imc_id); /** * Reserve additional IMV IDs from TNCS diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner.c b/src/libimcv/plugins/imc_scanner/imc_scanner.c index 803a031de..7f8b04799 100644 --- a/src/libimcv/plugins/imc_scanner/imc_scanner.c +++ b/src/libimcv/plugins/imc_scanner/imc_scanner.c @@ -20,8 +20,8 @@ #include <ietf/ietf_attr.h> #include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_port_filter.h> +#include <ietf/ietf_attr_assess_result.h> -#include <tncif_names.h> #include <tncif_pa_subtypes.h> #include <pen/pen.h> @@ -85,6 +85,15 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, case TNC_CONNECTION_STATE_CREATE: state = imc_scanner_state_create(connection_id); return imc_scanner->create_state(imc_scanner, state); + case TNC_CONNECTION_STATE_HANDSHAKE: + if (imc_scanner->change_state(imc_scanner, connection_id, new_state, + &state) != TNC_RESULT_SUCCESS) + { + return TNC_RESULT_FATAL; + } + state->set_result(state, imc_id, + TNC_IMV_EVALUATION_RESULT_DONT_KNOW); + return TNC_RESULT_SUCCESS; case TNC_CONNECTION_STATE_DELETE: return imc_scanner->delete_state(imc_scanner, connection_id); default: @@ -268,7 +277,10 @@ static TNC_Result receive_message(TNC_IMCID imc_id, TNC_UInt32 dst_imc_id) { pa_tnc_msg_t *pa_tnc_msg; + pa_tnc_attr_t *attr; + pen_type_t attr_type; imc_state_t *state; + enumerator_t *enumerator; TNC_Result result; bool fatal_error; @@ -296,14 +308,39 @@ static TNC_Result receive_message(TNC_IMCID imc_id, /* preprocess any IETF standard error attributes */ fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg); + + /* analyze PA-TNC attributes */ + enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg); + while (enumerator->enumerate(enumerator, &attr)) + { + attr_type = attr->get_type(attr); + + if (attr_type.vendor_id == PEN_IETF && + attr_type.type == IETF_ATTR_ASSESSMENT_RESULT) + { + ietf_attr_assess_result_t *ietf_attr; + + ietf_attr = (ietf_attr_assess_result_t*)attr; + state->set_result(state, dst_imc_id, + ietf_attr->get_result(ietf_attr)); + } + } + enumerator->destroy(enumerator); pa_tnc_msg->destroy(pa_tnc_msg); - /* if no error occurred then always return the same response */ - return fatal_error ? TNC_RESULT_FATAL : send_message(connection_id); + if (fatal_error) + { + return TNC_RESULT_FATAL; + } + + /* if no assessment result is known then repeat the measurement */ + return state->get_result(state, dst_imc_id, NULL) ? + TNC_RESULT_SUCCESS : send_message(connection_id); } /** * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3 + */ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, TNC_ConnectionID connection_id, diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner_state.c b/src/libimcv/plugins/imc_scanner/imc_scanner_state.c index adee8e92c..991b24a73 100644 --- a/src/libimcv/plugins/imc_scanner/imc_scanner_state.c +++ b/src/libimcv/plugins/imc_scanner/imc_scanner_state.c @@ -15,6 +15,8 @@ #include "imc_scanner_state.h" +#include <tncif_names.h> + #include <debug.h> typedef struct private_imc_scanner_state_t private_imc_scanner_state_t; @@ -40,6 +42,11 @@ struct private_imc_scanner_state_t { TNC_ConnectionState state; /** + * Assessment/Evaluation Result + */ + TNC_IMV_Evaluation_Result result; + + /** * Does the TNCCS connection support long message types? */ bool has_long; @@ -98,6 +105,26 @@ METHOD(imc_state_t, change_state, void, this->state = new_state; } +METHOD(imc_state_t, set_result, void, + private_imc_scanner_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result result) +{ + DBG1(DBG_IMC, "set assessment result for IMC %u to '%N'", + id, TNC_IMV_Evaluation_Result_names, result); + this->result = result; +} + +METHOD(imc_state_t, get_result, bool, + private_imc_scanner_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result *result) +{ + if (result) + { + *result = this->result; + } + return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW; +} + METHOD(imc_state_t, destroy, void, private_imc_scanner_state_t *this) { @@ -121,10 +148,13 @@ imc_state_t *imc_scanner_state_create(TNC_ConnectionID connection_id) .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, .change_state = _change_state, + .set_result = _set_result, + .get_result = _get_result, .destroy = _destroy, }, }, .state = TNC_CONNECTION_STATE_CREATE, + .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, .connection_id = connection_id, ); diff --git a/src/libimcv/plugins/imc_test/imc_test.c b/src/libimcv/plugins/imc_test/imc_test.c index bc2a233f6..6283309c4 100644 --- a/src/libimcv/plugins/imc_test/imc_test.c +++ b/src/libimcv/plugins/imc_test/imc_test.c @@ -19,11 +19,11 @@ #include <pa_tnc/pa_tnc_msg.h> #include <ietf/ietf_attr.h> #include <ietf/ietf_attr_pa_tnc_error.h> +#include <ietf/ietf_attr_assess_result.h> #include <ita/ita_attr.h> #include <ita/ita_attr_command.h> #include <ita/ita_attr_dummy.h> -#include <tncif_names.h> #include <tncif_pa_subtypes.h> #include <pen/pen.h> @@ -75,8 +75,11 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, imc_state_t *state; imc_test_state_t *test_state; TNC_Result result; + TNC_UInt32 additional_id; char *command; bool retry; + void *pointer; + enumerator_t *enumerator; int dummy_size, additional_ids; if (!imc_test) @@ -129,6 +132,26 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, test_state->get_command(test_state)); test_state->set_command(test_state, command); } + + state->set_result(state, imc_id, TNC_IMV_EVALUATION_RESULT_DONT_KNOW); + + /* Exit if there are no additional IMC IDs */ + if (!imc_test->count_additional_ids(imc_test)) + { + return result; + } + + enumerator = imc_test->create_id_enumerator(imc_test); + while (enumerator->enumerate(enumerator, &pointer)) + { + /* interpret pointer as scalar value */ + additional_id = (TNC_UInt32)pointer; + + state->set_result(state, additional_id, + TNC_IMV_EVALUATION_RESULT_DONT_KNOW); + } + enumerator->destroy(enumerator); + return TNC_RESULT_SUCCESS; case TNC_CONNECTION_STATE_DELETE: @@ -294,33 +317,45 @@ static TNC_Result receive_message(TNC_IMCID imc_id, { attr_type = attr->get_type(attr); - if (attr_type.vendor_id != PEN_ITA) - { - continue; - } - if (attr_type.type == ITA_ATTR_COMMAND) + if (attr_type.vendor_id == PEN_IETF) { - ita_attr_command_t *ita_attr; + ietf_attr_assess_result_t *ietf_attr; - ita_attr = (ita_attr_command_t*)attr; - DBG1(DBG_IMC, "received command '%s'", - ita_attr->get_command(ita_attr)); + ietf_attr = (ietf_attr_assess_result_t*)attr; + state->set_result(state, dst_imc_id, + ietf_attr->get_result(ietf_attr)); } - else if (attr_type.type == ITA_ATTR_DUMMY) + else if (attr_type.vendor_id == PEN_ITA) { - ita_attr_dummy_t *ita_attr; + if (attr_type.type == ITA_ATTR_COMMAND) + { + ita_attr_command_t *ita_attr; + + ita_attr = (ita_attr_command_t*)attr; + DBG1(DBG_IMC, "received command '%s'", + ita_attr->get_command(ita_attr)); + } + else if (attr_type.type == ITA_ATTR_DUMMY) + { + ita_attr_dummy_t *ita_attr; - ita_attr = (ita_attr_dummy_t*)attr; - DBG1(DBG_IMC, "received dummy attribute value (%d bytes)", - ita_attr->get_size(ita_attr)); + ita_attr = (ita_attr_dummy_t*)attr; + DBG1(DBG_IMC, "received dummy attribute value (%d bytes)", + ita_attr->get_size(ita_attr)); + } } } enumerator->destroy(enumerator); pa_tnc_msg->destroy(pa_tnc_msg); - /* if no error occurred then always return the same response */ - return fatal_error ? TNC_RESULT_FATAL : - send_message(state, dst_imc_id, src_imv_id); + if (fatal_error) + { + return TNC_RESULT_FATAL; + } + + /* if no assessment result is known then repeat the measurement */ + return state->get_result(state, dst_imc_id, NULL) ? + TNC_RESULT_SUCCESS : send_message(state, dst_imc_id, src_imv_id); } /** diff --git a/src/libimcv/plugins/imc_test/imc_test_state.c b/src/libimcv/plugins/imc_test/imc_test_state.c index 5877d1efd..e70eb1492 100644 --- a/src/libimcv/plugins/imc_test/imc_test_state.c +++ b/src/libimcv/plugins/imc_test/imc_test_state.c @@ -15,10 +15,13 @@ #include "imc_test_state.h" +#include <tncif_names.h> + #include <debug.h> #include <utils/linked_list.h> typedef struct private_imc_test_state_t private_imc_test_state_t; +typedef struct entry_t entry_t; /** * Private data of an imc_test_state_t object. @@ -41,6 +44,11 @@ struct private_imc_test_state_t { TNC_ConnectionState state; /** + * Assessment/Evaluation Results for all IMC IDs + */ + linked_list_t *results; + + /** * Does the TNCCS connection support long message types? */ bool has_long; @@ -77,6 +85,14 @@ struct private_imc_test_state_t { }; +/** + * Stores the Assessment/Evaluation Result for a given IMC ID + */ +struct entry_t { + TNC_IMCID id; + TNC_IMV_Evaluation_Result result; +}; + METHOD(imc_state_t, get_connection_id, TNC_ConnectionID, private_imc_test_state_t *this) { @@ -120,9 +136,68 @@ METHOD(imc_state_t, change_state, void, this->state = new_state; } +METHOD(imc_state_t, set_result, void, + private_imc_test_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result result) +{ + enumerator_t *enumerator; + entry_t *entry; + bool found = FALSE; + + DBG1(DBG_IMC, "set assessment result for IMC %u to '%N'", + id, TNC_IMV_Evaluation_Result_names, result); + + enumerator = this->results->create_enumerator(this->results); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->id == id) + { + entry->result = result; + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + if (!found) + { + entry = malloc_thing(entry_t); + entry->id = id; + entry->result = result; + this->results->insert_last(this->results, entry); + } +} + +METHOD(imc_state_t, get_result, bool, + private_imc_test_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result *result) +{ + enumerator_t *enumerator; + entry_t *entry; + TNC_IMV_Evaluation_Result eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW; + + enumerator = this->results->create_enumerator(this->results); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->id == id) + { + eval = entry->result; + break; + } + } + enumerator->destroy(enumerator); + + if (result) + { + *result = eval; + } + return eval != TNC_IMV_EVALUATION_RESULT_DONT_KNOW; +} + METHOD(imc_state_t, destroy, void, private_imc_test_state_t *this) { + this->results->destroy_function(this->results, free); free(this->command); free(this); } @@ -190,6 +265,8 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id, .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, .change_state = _change_state, + .set_result = _set_result, + .get_result = _get_result, .destroy = _destroy, }, .get_command = _get_command, @@ -199,6 +276,7 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id, .do_handshake_retry = _do_handshake_retry, }, .state = TNC_CONNECTION_STATE_CREATE, + .results = linked_list_create(), .connection_id = connection_id, .command = strdup(command), .dummy_size = dummy_size, diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner.c b/src/libimcv/plugins/imv_scanner/imv_scanner.c index 1c5d18e75..1352397c6 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner.c @@ -308,10 +308,9 @@ static TNC_Result receive_message(TNC_IMVID imv_id, state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); - return imv_scanner->provide_recommendation(imv_scanner, connection_id); } - - return imv_scanner->provide_recommendation(imv_scanner, connection_id); + return imv_scanner->provide_recommendation(imv_scanner, connection_id, + src_imc_id); } /** @@ -362,7 +361,8 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id, DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name); return TNC_RESULT_NOT_INITIALIZED; } - return imv_scanner->provide_recommendation(imv_scanner, connection_id); + return imv_scanner->provide_recommendation(imv_scanner, connection_id, + TNC_IMCID_ANY); } /** diff --git a/src/libimcv/plugins/imv_test/imv_test.c b/src/libimcv/plugins/imv_test/imv_test.c index 10a206b1c..5ea82e97c 100644 --- a/src/libimcv/plugins/imv_test/imv_test.c +++ b/src/libimcv/plugins/imv_test/imv_test.c @@ -209,7 +209,8 @@ static TNC_Result receive_message(TNC_IMVID imv_id, state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); - return imv_test->provide_recommendation(imv_test, connection_id); + return imv_test->provide_recommendation(imv_test, connection_id, + src_imc_id); } /* request a handshake retry ? */ @@ -233,9 +234,8 @@ static TNC_Result receive_message(TNC_IMVID imv_id, return result; } - return received_command ? - imv_test->provide_recommendation(imv_test, connection_id) : - TNC_RESULT_SUCCESS; + return received_command ? imv_test->provide_recommendation(imv_test, + connection_id, src_imc_id) : TNC_RESULT_SUCCESS; } /** @@ -286,7 +286,8 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id, DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name); return TNC_RESULT_NOT_INITIALIZED; } - return imv_test->provide_recommendation(imv_test, connection_id); + return imv_test->provide_recommendation(imv_test, connection_id, + TNC_IMCID_ANY); } /** diff --git a/src/libpts/plugins/imc_attestation/imc_attestation.c b/src/libpts/plugins/imc_attestation/imc_attestation.c index 19b2745d0..c3df27866 100644 --- a/src/libpts/plugins/imc_attestation/imc_attestation.c +++ b/src/libpts/plugins/imc_attestation/imc_attestation.c @@ -21,6 +21,7 @@ #include <ietf/ietf_attr.h> #include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_product_info.h> +#include <ietf/ietf_attr_assess_result.h> #include <libpts.h> @@ -108,9 +109,17 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, case TNC_CONNECTION_STATE_CREATE: state = imc_attestation_state_create(connection_id); return imc_attestation->create_state(imc_attestation, state); + case TNC_CONNECTION_STATE_HANDSHAKE: + if (imc_attestation->change_state(imc_attestation, connection_id, + new_state, &state) != TNC_RESULT_SUCCESS) + { + return TNC_RESULT_FATAL; + } + state->set_result(state, imc_id, + TNC_IMV_EVALUATION_RESULT_DONT_KNOW); + return TNC_RESULT_SUCCESS; case TNC_CONNECTION_STATE_DELETE: return imc_attestation->delete_state(imc_attestation, connection_id); - case TNC_CONNECTION_STATE_HANDSHAKE: case TNC_CONNECTION_STATE_ACCESS_ISOLATED: case TNC_CONNECTION_STATE_ACCESS_NONE: default: @@ -216,24 +225,35 @@ static TNC_Result receive_message(TNC_IMCID imc_id, { type = attr->get_type(attr); - if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR) + if (type.vendor_id == PEN_IETF) { - ietf_attr_pa_tnc_error_t *error_attr; - pen_type_t error_code; - chunk_t msg_info; + if (type.type == IETF_ATTR_PA_TNC_ERROR) + { + ietf_attr_pa_tnc_error_t *error_attr; + pen_type_t error_code; + chunk_t msg_info; - error_attr = (ietf_attr_pa_tnc_error_t*)attr; - error_code = error_attr->get_error_code(error_attr); + error_attr = (ietf_attr_pa_tnc_error_t*)attr; + error_code = error_attr->get_error_code(error_attr); - if (error_code.vendor_id == PEN_TCG) - { - msg_info = error_attr->get_msg_info(error_attr); + if (error_code.vendor_id == PEN_TCG) + { + msg_info = error_attr->get_msg_info(error_attr); - DBG1(DBG_IMC, "received TCG-PTS error '%N'", - pts_error_code_names, error_code.type); - DBG1(DBG_IMC, "error information: %B", &msg_info); + DBG1(DBG_IMC, "received TCG-PTS error '%N'", + pts_error_code_names, error_code.type); + DBG1(DBG_IMC, "error information: %B", &msg_info); - result = TNC_RESULT_FATAL; + result = TNC_RESULT_FATAL; + } + } + else if (type.type == IETF_ATTR_ASSESSMENT_RESULT) + { + ietf_attr_assess_result_t *ietf_attr; + + ietf_attr = (ietf_attr_assess_result_t*)attr; + state->set_result(state, dst_imc_id, + ietf_attr->get_result(ietf_attr)); } } else if (type.vendor_id == PEN_TCG) diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_state.c b/src/libpts/plugins/imc_attestation/imc_attestation_state.c index 65662db2a..8ebabafa2 100644 --- a/src/libpts/plugins/imc_attestation/imc_attestation_state.c +++ b/src/libpts/plugins/imc_attestation/imc_attestation_state.c @@ -17,6 +17,8 @@ #include <libpts.h> +#include <tncif_names.h> + #include <utils/linked_list.h> #include <debug.h> @@ -44,6 +46,11 @@ struct private_imc_attestation_state_t { TNC_ConnectionState state; /** + * Assessment/Evaluation Result + */ + TNC_IMV_Evaluation_Result result; + + /** * Does the TNCCS connection support long message types? */ bool has_long; @@ -118,6 +125,26 @@ METHOD(imc_state_t, change_state, void, this->state = new_state; } +METHOD(imc_state_t, set_result, void, + private_imc_attestation_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result result) +{ + DBG1(DBG_IMC, "set assessment result for IMC %u to '%N'", + id, TNC_IMV_Evaluation_Result_names, result); + this->result = result; +} + +METHOD(imc_state_t, get_result, bool, + private_imc_attestation_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result *result) +{ + if (result) + { + *result = this->result; + } + return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW; +} + METHOD(imc_state_t, destroy, void, private_imc_attestation_state_t *this) { @@ -197,6 +224,8 @@ imc_state_t *imc_attestation_state_create(TNC_ConnectionID connection_id) .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, .change_state = _change_state, + .set_result = _set_result, + .get_result = _get_result, .destroy = _destroy, }, .get_pts = _get_pts, @@ -206,6 +235,7 @@ imc_state_t *imc_attestation_state_create(TNC_ConnectionID connection_id) }, .connection_id = connection_id, .state = TNC_CONNECTION_STATE_CREATE, + .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, .pts = pts_create(TRUE), .components = linked_list_create(), .list = linked_list_create(), diff --git a/src/libpts/plugins/imv_attestation/imv_attestation.c b/src/libpts/plugins/imv_attestation/imv_attestation.c index 8e8e70e83..201496e8a 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation.c @@ -310,7 +310,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id, TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, TNC_IMV_EVALUATION_RESULT_ERROR); return imv_attestation->provide_recommendation(imv_attestation, - connection_id); + connection_id, src_imc_id); } if (attr_list->get_count(attr_list)) @@ -330,7 +330,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); return imv_attestation->provide_recommendation(imv_attestation, - connection_id); + connection_id, src_imc_id); } if (attestation_state->get_handshake_state(attestation_state) == @@ -355,7 +355,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id, TNC_IMV_EVALUATION_RESULT_COMPLIANT); } return imv_attestation->provide_recommendation(imv_attestation, - connection_id); + connection_id, src_imc_id); } return result; @@ -410,7 +410,7 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id, return TNC_RESULT_NOT_INITIALIZED; } return imv_attestation->provide_recommendation(imv_attestation, - connection_id); + connection_id, TNC_IMCID_ANY); } /** diff --git a/src/libtnccs/tnc/imv/imv_recommendations.h b/src/libtnccs/tnc/imv/imv_recommendations.h index d694e16ae..e7fe355f7 100644 --- a/src/libtnccs/tnc/imv/imv_recommendations.h +++ b/src/libtnccs/tnc/imv/imv_recommendations.h @@ -68,6 +68,11 @@ struct recommendations_t { TNC_IMV_Evaluation_Result *eval); /** + * Clear all recommendation information + */ + void (*clear_recommendation)(recommendations_t *this); + + /** * Get the preferred language for remediation messages * * @return preferred language @@ -110,11 +115,6 @@ struct recommendations_t { enumerator_t* (*create_reason_enumerator)(recommendations_t *this); /** - * Clears all reason entries - */ - void (*clear_reasons)(recommendations_t *this); - - /** * Destroys an imv_t object. */ void (*destroy)(recommendations_t *this); |