introduced sending of standard IETF Assessment Result PA-TNC attribute by IMVs

This commit is contained in:
Andreas Steffen 2012-09-09 05:13:13 +02:00
parent bcf8cdd556
commit 6f93927b6c
21 changed files with 639 additions and 84 deletions

7
NEWS
View File

@ -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

View File

@ -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(),

View File

@ -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;

View File

@ -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);
}

View File

@ -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 \

View File

@ -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:

View File

@ -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;
}

View File

@ -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_ @}*/

View File

@ -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
*/
@ -85,6 +86,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
*/

View File

@ -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);
}

View File

@ -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

View File

@ -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,

View File

@ -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;
@ -39,6 +41,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?
*/
@ -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,
);

View File

@ -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)
if (attr_type.vendor_id == PEN_IETF)
{
continue;
}
if (attr_type.type == ITA_ATTR_COMMAND)
{
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_dummy_t*)attr;
DBG1(DBG_IMC, "received dummy attribute value (%d bytes)",
ita_attr->get_size(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));
}
}
}
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);
}
/**

View File

@ -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.
@ -40,6 +43,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?
*/
@ -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,

View File

@ -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);
}
/**

View File

@ -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);
}
/**

View File

@ -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;
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)
if (type.type == IETF_ATTR_PA_TNC_ERROR)
{
msg_info = error_attr->get_msg_info(error_attr);
ietf_attr_pa_tnc_error_t *error_attr;
pen_type_t error_code;
chunk_t 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);
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
error_code = error_attr->get_error_code(error_attr);
result = TNC_RESULT_FATAL;
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);
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)

View File

@ -17,6 +17,8 @@
#include <libpts.h>
#include <tncif_names.h>
#include <utils/linked_list.h>
#include <debug.h>
@ -43,6 +45,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?
*/
@ -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(),

View File

@ -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);
}
/**

View File

@ -67,6 +67,11 @@ struct recommendations_t {
TNC_IMV_Action_Recommendation *rec,
TNC_IMV_Evaluation_Result *eval);
/**
* Clear all recommendation information
*/
void (*clear_recommendation)(recommendations_t *this);
/**
* Get the preferred language for remediation messages
*
@ -109,11 +114,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.
*/