diff options
Diffstat (limited to 'src/libimcv')
39 files changed, 1852 insertions, 435 deletions
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index fae9fd662..e0e8f1017 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -13,8 +13,11 @@ libimcv_la_SOURCES = \ ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \ 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 \ pa_tnc/pa_tnc_attr.h \ pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \ pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c diff --git a/src/libimcv/Makefile.in b/src/libimcv/Makefile.in index 7e90a7aca..d1a1373af 100644 --- a/src/libimcv/Makefile.in +++ b/src/libimcv/Makefile.in @@ -53,6 +53,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -81,10 +82,11 @@ LTLIBRARIES = $(ipseclib_LTLIBRARIES) libimcv_la_DEPENDENCIES = $(top_builddir)/src/libtncif/libtncif.la am_libimcv_la_OBJECTS = imcv.lo imc_agent.lo imv_agent.lo ietf_attr.lo \ ietf_attr_pa_tnc_error.lo ietf_attr_port_filter.lo \ - ietf_attr_product_info.lo ita_attr.lo ita_attr_command.lo \ - pa_tnc_msg.lo pa_tnc_attr_manager.lo + ietf_attr_product_info.lo ietf_attr_attr_request.lo \ + ietf_attr_assess_result.lo ita_attr.lo ita_attr_command.lo \ + ita_attr_dummy.lo pa_tnc_msg.lo pa_tnc_attr_manager.lo libimcv_la_OBJECTS = $(am_libimcv_la_OBJECTS) -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f @@ -149,6 +151,7 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ @@ -243,11 +246,14 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -264,11 +270,12 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ @@ -284,6 +291,7 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ @@ -293,7 +301,6 @@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ @@ -332,8 +339,11 @@ libimcv_la_SOURCES = \ ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \ 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 \ pa_tnc/pa_tnc_attr.h \ pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \ pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c @@ -415,6 +425,8 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_assess_result.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_attr_request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_pa_tnc_error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_port_filter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attr_product_info.Plo@am__quote@ @@ -423,6 +435,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_agent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ita_attr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ita_attr_command.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ita_attr_dummy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pa_tnc_attr_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pa_tnc_msg.Plo@am__quote@ @@ -489,6 +502,20 @@ ietf_attr_product_info.lo: ietf/ietf_attr_product_info.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ietf_attr_product_info.lo `test -f 'ietf/ietf_attr_product_info.c' || echo '$(srcdir)/'`ietf/ietf_attr_product_info.c +ietf_attr_attr_request.lo: ietf/ietf_attr_attr_request.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ietf_attr_attr_request.lo -MD -MP -MF $(DEPDIR)/ietf_attr_attr_request.Tpo -c -o ietf_attr_attr_request.lo `test -f 'ietf/ietf_attr_attr_request.c' || echo '$(srcdir)/'`ietf/ietf_attr_attr_request.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ietf_attr_attr_request.Tpo $(DEPDIR)/ietf_attr_attr_request.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ietf/ietf_attr_attr_request.c' object='ietf_attr_attr_request.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ietf_attr_attr_request.lo `test -f 'ietf/ietf_attr_attr_request.c' || echo '$(srcdir)/'`ietf/ietf_attr_attr_request.c + +ietf_attr_assess_result.lo: ietf/ietf_attr_assess_result.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ietf_attr_assess_result.lo -MD -MP -MF $(DEPDIR)/ietf_attr_assess_result.Tpo -c -o ietf_attr_assess_result.lo `test -f 'ietf/ietf_attr_assess_result.c' || echo '$(srcdir)/'`ietf/ietf_attr_assess_result.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ietf_attr_assess_result.Tpo $(DEPDIR)/ietf_attr_assess_result.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ietf/ietf_attr_assess_result.c' object='ietf_attr_assess_result.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ietf_attr_assess_result.lo `test -f 'ietf/ietf_attr_assess_result.c' || echo '$(srcdir)/'`ietf/ietf_attr_assess_result.c + ita_attr.lo: ita/ita_attr.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ita_attr.lo -MD -MP -MF $(DEPDIR)/ita_attr.Tpo -c -o ita_attr.lo `test -f 'ita/ita_attr.c' || echo '$(srcdir)/'`ita/ita_attr.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ita_attr.Tpo $(DEPDIR)/ita_attr.Plo @@ -503,6 +530,13 @@ ita_attr_command.lo: ita/ita_attr_command.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ita_attr_command.lo `test -f 'ita/ita_attr_command.c' || echo '$(srcdir)/'`ita/ita_attr_command.c +ita_attr_dummy.lo: ita/ita_attr_dummy.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ita_attr_dummy.lo -MD -MP -MF $(DEPDIR)/ita_attr_dummy.Tpo -c -o ita_attr_dummy.lo `test -f 'ita/ita_attr_dummy.c' || echo '$(srcdir)/'`ita/ita_attr_dummy.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ita_attr_dummy.Tpo $(DEPDIR)/ita_attr_dummy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ita/ita_attr_dummy.c' object='ita_attr_dummy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ita_attr_dummy.lo `test -f 'ita/ita_attr_dummy.c' || echo '$(srcdir)/'`ita/ita_attr_dummy.c + pa_tnc_msg.lo: pa_tnc/pa_tnc_msg.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pa_tnc_msg.lo -MD -MP -MF $(DEPDIR)/pa_tnc_msg.Tpo -c -o pa_tnc_msg.lo `test -f 'pa_tnc/pa_tnc_msg.c' || echo '$(srcdir)/'`pa_tnc/pa_tnc_msg.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pa_tnc_msg.Tpo $(DEPDIR)/pa_tnc_msg.Plo diff --git a/src/libimcv/ietf/ietf_attr.c b/src/libimcv/ietf/ietf_attr.c index 89c6fc8db..fc89c5716 100644 --- a/src/libimcv/ietf/ietf_attr.c +++ b/src/libimcv/ietf/ietf_attr.c @@ -16,6 +16,8 @@ #include "ietf/ietf_attr_pa_tnc_error.h" #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", @@ -40,19 +42,21 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, chunk_t value) { switch (type) { + case IETF_ATTR_ATTRIBUTE_REQUEST: + return ietf_attr_attr_request_create_from_data(value); + case IETF_ATTR_PRODUCT_INFORMATION: + return ietf_attr_product_info_create_from_data(value); case IETF_ATTR_PORT_FILTER: 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_PRODUCT_INFORMATION: - return ietf_attr_product_info_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_ATTRIBUTE_REQUEST: 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/ietf/ietf_attr_attr_request.c b/src/libimcv/ietf/ietf_attr_attr_request.c new file mode 100644 index 000000000..c0dcd0983 --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_attr_request.c @@ -0,0 +1,270 @@ +/* + * 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 "imcv.h" +#include "ietf_attr_attr_request.h" + +#include <pa_tnc/pa_tnc_msg.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <utils/linked_list.h> + +#include <debug.h> + +typedef struct private_ietf_attr_attr_request_t private_ietf_attr_attr_request_t; + +/** + * PA-TNC Attribute Request type (see section 4.2.1 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | PA-TNC Attribute Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA-TNC Attribute Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | PA-TNC Attribute Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA-TNC Attribute Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define ATTR_REQUEST_ENTRY_SIZE 8 + +/** + * Private data of an ietf_attr_attr_request_t object. + */ +struct private_ietf_attr_attr_request_t { + + /** + * Public members of ietf_attr_attr_request_t + */ + ietf_attr_attr_request_t public; + + /** + * Vendor-specific attribute type + */ + pen_type_t type; + + /** + * Attribute value + */ + chunk_t value; + + /** + * Noskip flag + */ + bool noskip_flag; + + /** + * List of requested attribute types + */ + linked_list_t *list; + + /** + * Reference count + */ + refcount_t ref; +}; + +METHOD(pa_tnc_attr_t, get_type, pen_type_t, + private_ietf_attr_attr_request_t *this) +{ + return this->type; +} + +METHOD(pa_tnc_attr_t, get_value, chunk_t, + private_ietf_attr_attr_request_t *this) +{ + return this->value; +} + +METHOD(pa_tnc_attr_t, get_noskip_flag, bool, + private_ietf_attr_attr_request_t *this) +{ + return this->noskip_flag; +} + +METHOD(pa_tnc_attr_t, set_noskip_flag,void, + private_ietf_attr_attr_request_t *this, bool noskip) +{ + this->noskip_flag = noskip; +} + +METHOD(pa_tnc_attr_t, build, void, + private_ietf_attr_attr_request_t *this) +{ + bio_writer_t *writer; + enumerator_t *enumerator; + pen_type_t *entry; + + if (this->value.ptr) + { + return; + } + writer = bio_writer_create(ATTR_REQUEST_ENTRY_SIZE * + this->list->get_count(this->list)); + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + writer->write_uint32(writer, entry->vendor_id); + writer->write_uint32(writer, entry->type); + } + enumerator->destroy(enumerator); + + this->value = chunk_clone(writer->get_buf(writer)); + writer->destroy(writer); +} + +METHOD(ietf_attr_attr_request_t, add, void, + private_ietf_attr_attr_request_t *this, pen_t vendor_id, u_int32_t type) +{ + pen_type_t *entry; + + entry = malloc_thing(pen_type_t); + entry->vendor_id = vendor_id; + entry->type = type; + this->list->insert_last(this->list, entry); +} + +METHOD(pa_tnc_attr_t, process, status_t, + private_ietf_attr_attr_request_t *this, u_int32_t *offset) +{ + bio_reader_t *reader; + enum_name_t *pa_attr_names; + pen_t vendor_id; + u_int32_t type; + u_int8_t reserved; + int count; + + count = this->value.len / ATTR_REQUEST_ENTRY_SIZE; + if (this->value.len != ATTR_REQUEST_ENTRY_SIZE * count) + { + DBG1(DBG_TNC, "incorrect attribute length for IETF attribute request"); + *offset = 0; + return FAILED; + } + + reader = bio_reader_create(this->value); + while (count--) + { + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + + pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes, + vendor_id); + if (pa_attr_names) + { + DBG2(DBG_TNC, " 0x%06x/0x%08x '%N/%N'", vendor_id, type, + pen_names, vendor_id, pa_attr_names, type); + } + else + { + DBG2(DBG_TNC, " 0x%06x/0x%08x '%N'", vendor_id, type, + pen_names, vendor_id); + } + add(this, vendor_id, type); + } + reader->destroy(reader); + + return SUCCESS; +} + +METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*, + private_ietf_attr_attr_request_t *this) +{ + ref_get(&this->ref); + return &this->public.pa_tnc_attribute; +} + +METHOD(pa_tnc_attr_t, destroy, void, + private_ietf_attr_attr_request_t *this) +{ + if (ref_put(&this->ref)) + { + this->list->destroy_function(this->list, free); + free(this->value.ptr); + free(this); + } +} + +METHOD(ietf_attr_attr_request_t, create_enumerator, enumerator_t*, + private_ietf_attr_attr_request_t *this) +{ + return this->list->create_enumerator(this->list); +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type) +{ + private_ietf_attr_attr_request_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, + }, + .add = _add, + .create_enumerator = _create_enumerator, + }, + .type = { PEN_IETF, IETF_ATTR_ATTRIBUTE_REQUEST }, + .list = linked_list_create(), + .ref = 1, + ); + add(this, vendor_id, type); + + return &this->public.pa_tnc_attribute; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data) +{ + private_ietf_attr_attr_request_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, + }, + .add = _add, + .create_enumerator = _create_enumerator, + }, + .type = { PEN_IETF,IETF_ATTR_ATTRIBUTE_REQUEST }, + .value = chunk_clone(data), + .list = linked_list_create(), + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + diff --git a/src/libimcv/ietf/ietf_attr_attr_request.h b/src/libimcv/ietf/ietf_attr_attr_request.h new file mode 100644 index 000000000..22c5be0a0 --- /dev/null +++ b/src/libimcv/ietf/ietf_attr_attr_request.h @@ -0,0 +1,71 @@ +/* + * 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_attr_requestt ietf_attr_attr_request + * @{ @ingroup ietf + */ + +#ifndef IETF_ATTR_ATTR_REQUEST_H_ +#define IETF_ATTR_ATTR_REQUEST_H_ + +typedef struct ietf_attr_attr_request_t ietf_attr_attr_request_t; + +#include "ietf_attr.h" +#include "pa_tnc/pa_tnc_attr.h" + + +/** + * Class implementing the IETF PA-TNC Attribute Request attribute. + * + */ +struct ietf_attr_attr_request_t { + + /** + * Public PA-TNC attribute interface + */ + pa_tnc_attr_t pa_tnc_attribute; + + /** + * Adds another attribute type to the attribute request + * + * @param vendor_id Attribute Vendor ID + * @param type Attribute Type + */ + void (*add)(ietf_attr_attr_request_t *this, pen_t vendor_id, u_int32_t type); + + /** + * Creates an enumerator over all attribute types contained + * in the attribute request + * + * @return Attribute Type enumerator returns (vendor ID, type) + */ + enumerator_t* (*create_enumerator)(ietf_attr_attr_request_t *this); +}; + +/** + * Creates an ietf_attr_attr_request_t object + * + */ +pa_tnc_attr_t* ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type); + +/** + * Creates an ietf_attr_attr_request_t object from received data + * + * @param value unparsed attribute value + */ +pa_tnc_attr_t* ietf_attr_attr_request_create_from_data(chunk_t value); + +#endif /** IETF_ATTR_ATTR_REQUEST_H_ @}*/ diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c index 6daee1a77..46f5d6716 100644 --- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c +++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -107,14 +108,9 @@ struct private_ietf_attr_pa_tnc_error_t { ietf_attr_pa_tnc_error_t public; /** - * Attribute vendor ID + * Vendor-specific attribute type */ - pen_t vendor_id; - - /** - * Attribute type - */ - u_int32_t type; + pen_type_t type; /** * Attribute value @@ -127,14 +123,9 @@ struct private_ietf_attr_pa_tnc_error_t { bool noskip_flag; /** - * Error code vendor ID - */ - pen_t error_vendor_id; - - /** - * Error code + * Vendor-specific error code */ - u_int32_t error_code; + pen_type_t error_code; /** * First 8 bytes of erroneous PA-TNC message @@ -157,13 +148,7 @@ struct private_ietf_attr_pa_tnc_error_t { refcount_t ref; }; -METHOD(pa_tnc_attr_t, get_vendor_id, pen_t, - private_ietf_attr_pa_tnc_error_t *this) -{ - return this->vendor_id; -} - -METHOD(pa_tnc_attr_t, get_type, u_int32_t, +METHOD(pa_tnc_attr_t, get_type, pen_type_t, private_ietf_attr_pa_tnc_error_t *this) { return this->type; @@ -192,15 +177,19 @@ METHOD(pa_tnc_attr_t, build, void, { bio_writer_t *writer; + if (this->value.ptr) + { + return; + } writer = bio_writer_create(PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE); writer->write_uint8 (writer, PA_ERROR_RESERVED); - writer->write_uint24(writer, this->error_vendor_id); - writer->write_uint32(writer, this->error_code); + writer->write_uint24(writer, this->error_code.vendor_id); + writer->write_uint32(writer, this->error_code.type); writer->write_data (writer, this->msg_info); - if (this->error_vendor_id == PEN_IETF) + if (this->error_code.vendor_id == PEN_IETF) { - switch (this->error_code) + switch (this->error_code.type) { case PA_ERROR_INVALID_PARAMETER: writer->write_uint32(writer, this->error_offset); @@ -235,10 +224,10 @@ METHOD(pa_tnc_attr_t, process, status_t, } reader = bio_reader_create(this->value); reader->read_uint8 (reader, &reserved); - reader->read_uint24(reader, &this->error_vendor_id); - reader->read_uint32(reader, &this->error_code); + reader->read_uint24(reader, &this->error_code.vendor_id); + reader->read_uint32(reader, &this->error_code.type); - if (this->error_vendor_id == PEN_IETF) + if (this->error_code.vendor_id == PEN_IETF) { if (!reader->read_data(reader, PA_ERROR_MSG_INFO_SIZE, &this->msg_info)) { @@ -249,7 +238,7 @@ METHOD(pa_tnc_attr_t, process, status_t, } this->msg_info = chunk_clone(this->msg_info); - switch (this->error_code) + switch (this->error_code.type) { case PA_ERROR_INVALID_PARAMETER: if (!reader->read_uint32(reader, &this->error_offset)) @@ -305,13 +294,7 @@ METHOD(pa_tnc_attr_t, destroy, void, } } -METHOD(ietf_attr_pa_tnc_error_t, get_error_vendor_id, pen_t, - private_ietf_attr_pa_tnc_error_t *this) -{ - return this->error_vendor_id; -} - -METHOD(ietf_attr_pa_tnc_error_t, get_error_code, u_int32_t, +METHOD(ietf_attr_pa_tnc_error_t, get_error_code, pen_type_t, private_ietf_attr_pa_tnc_error_t *this) { return this->error_code; @@ -344,13 +327,12 @@ METHOD(ietf_attr_pa_tnc_error_t, get_offset, u_int32_t, /** * Described in header. */ -pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id, - u_int32_t error_code, +pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code, chunk_t msg_info) { private_ietf_attr_pa_tnc_error_t *this; - if (vendor_id == PEN_IETF) + if (error_code.vendor_id == PEN_IETF) { msg_info.len = PA_ERROR_MSG_INFO_SIZE; } @@ -362,7 +344,6 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id, INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .get_noskip_flag = _get_noskip_flag, @@ -372,16 +353,13 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id, .get_ref = _get_ref, .destroy = _destroy, }, - .get_vendor_id = _get_error_vendor_id, .get_error_code = _get_error_code, .get_msg_info = _get_msg_info, .get_attr_info = _get_attr_info, .set_attr_info = _set_attr_info, .get_offset = _get_offset, }, - .vendor_id = PEN_IETF, - .type = IETF_ATTR_PA_TNC_ERROR, - .error_vendor_id = vendor_id, + .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR }, .error_code = error_code, .msg_info = chunk_clone(msg_info), .ref = 1, @@ -393,8 +371,7 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_t vendor_id, /** * Described in header. */ -pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id, - u_int32_t error_code, +pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code, chunk_t msg_info, u_int32_t error_offset) { @@ -406,7 +383,6 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id, INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .get_noskip_flag = _get_noskip_flag, @@ -416,16 +392,13 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id, .get_ref = _get_ref, .destroy = _destroy, }, - .get_vendor_id = _get_error_vendor_id, .get_error_code = _get_error_code, .get_msg_info = _get_msg_info, .get_attr_info = _get_attr_info, .set_attr_info = _set_attr_info, .get_offset = _get_offset, }, - .vendor_id = PEN_IETF, - .type = IETF_ATTR_PA_TNC_ERROR, - .error_vendor_id = vendor_id, + .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR }, .error_code = error_code, .msg_info = chunk_clone(msg_info), .error_offset = error_offset, @@ -445,7 +418,6 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data) INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .build = _build, @@ -453,15 +425,13 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data) .get_ref = _get_ref, .destroy = _destroy, }, - .get_vendor_id = _get_error_vendor_id, .get_error_code = _get_error_code, .get_msg_info = _get_msg_info, .get_attr_info = _get_attr_info, .set_attr_info = _set_attr_info, .get_offset = _get_offset, }, - .vendor_id = PEN_IETF, - .type = IETF_ATTR_PA_TNC_ERROR, + .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR }, .value = chunk_clone(data), .ref = 1, ); diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h index 945e06c62..d28c524aa 100644 --- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h +++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2012 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -62,11 +62,11 @@ struct ietf_attr_pa_tnc_error_t { pen_t (*get_vendor_id)(ietf_attr_pa_tnc_error_t *this); /** - * Get PA-TNC error code + * Get Vendor-specific PA-TNC error code * * @return error code */ - pa_tnc_error_code_t (*get_error_code)(ietf_attr_pa_tnc_error_t *this); + pen_type_t (*get_error_code)(ietf_attr_pa_tnc_error_t *this); /** * Get first 8 bytes of erroneous PA-TNC message @@ -101,26 +101,22 @@ struct ietf_attr_pa_tnc_error_t { /** * Creates an ietf_attr_pa_tnc_error_t object from an error code * - * @param vendor_id PA-TNC error code vendor ID - * @param error_code PA-TNC error code + * @param error_code Vendor-specific PA-TNC error code * @param header PA-TNC message header (first 8 bytes) * */ -pa_tnc_attr_t* ietf_attr_pa_tnc_error_create(pen_t vendor_id, - u_int32_t error_code, +pa_tnc_attr_t* ietf_attr_pa_tnc_error_create(pen_type_t error_code, chunk_t header); /** * Creates an ietf_attr_pa_tnc_error_t object from an error code with offset * - * @param vendor_id PA-TNC error code vendor ID - * @param error_code PA-TNC error code + * @param error_code Vendor-specifica PA-TNC error code * @param header PA-TNC message header (first 8 bytes) * @param error_offset PA-TNC error offset in bytes * */ -pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_with_offset(pen_t vendor_id, - u_int32_t error_code, +pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code, chunk_t header, u_int32_t error_offset); diff --git a/src/libimcv/ietf/ietf_attr_port_filter.c b/src/libimcv/ietf/ietf_attr_port_filter.c index b53019657..5ea52256b 100644 --- a/src/libimcv/ietf/ietf_attr_port_filter.c +++ b/src/libimcv/ietf/ietf_attr_port_filter.c @@ -58,14 +58,9 @@ struct private_ietf_attr_port_filter_t { ietf_attr_port_filter_t public; /** - * Attribute vendor ID + * Vendor-specific attribute type */ - pen_t vendor_id; - - /** - * Attribute type - */ - u_int32_t type; + pen_type_t type; /** * Attribute value @@ -88,13 +83,7 @@ struct private_ietf_attr_port_filter_t { refcount_t ref; }; -METHOD(pa_tnc_attr_t, get_vendor_id, pen_t, - private_ietf_attr_port_filter_t *this) -{ - return this->vendor_id; -} - -METHOD(pa_tnc_attr_t, get_type, u_int32_t, +METHOD(pa_tnc_attr_t, get_type, pen_type_t, private_ietf_attr_port_filter_t *this) { return this->type; @@ -125,6 +114,10 @@ METHOD(pa_tnc_attr_t, build, void, enumerator_t *enumerator; port_entry_t *entry; + if (this->value.ptr) + { + return; + } writer = bio_writer_create(this->ports->get_count(this->ports) * PORT_FILTER_ENTRY_SIZE); @@ -232,7 +225,6 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void) INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .get_noskip_flag = _get_noskip_flag, @@ -245,8 +237,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void) .add_port = _add_port, .create_port_enumerator = _create_port_enumerator, }, - .vendor_id = PEN_IETF, - .type = IETF_ATTR_PORT_FILTER, + .type = { PEN_IETF, IETF_ATTR_PORT_FILTER }, .ports = linked_list_create(), .ref = 1, ); @@ -264,7 +255,6 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data) INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .build = _build, @@ -275,8 +265,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(chunk_t data) .add_port = _add_port, .create_port_enumerator = _create_port_enumerator, }, - .vendor_id = PEN_IETF, - .type = IETF_ATTR_PORT_FILTER, + .type = {PEN_IETF, IETF_ATTR_PORT_FILTER }, .value = chunk_clone(data), .ports = linked_list_create(), .ref = 1, diff --git a/src/libimcv/ietf/ietf_attr_product_info.c b/src/libimcv/ietf/ietf_attr_product_info.c index 548793547..dcc0e0294 100644 --- a/src/libimcv/ietf/ietf_attr_product_info.c +++ b/src/libimcv/ietf/ietf_attr_product_info.c @@ -46,14 +46,9 @@ struct private_ietf_attr_product_info_t { ietf_attr_product_info_t public; /** - * Attribute vendor ID + * Vendor-specific attribute type */ - pen_t vendor_id; - - /** - * Attribute type - */ - u_int32_t type; + pen_type_t type; /** * Attribute value @@ -86,13 +81,7 @@ struct private_ietf_attr_product_info_t { refcount_t ref; }; -METHOD(pa_tnc_attr_t, get_vendor_id, pen_t, - private_ietf_attr_product_info_t *this) -{ - return this->vendor_id; -} - -METHOD(pa_tnc_attr_t, get_type, u_int32_t, +METHOD(pa_tnc_attr_t, get_type, pen_type_t, private_ietf_attr_product_info_t *this) { return this->type; @@ -122,6 +111,10 @@ METHOD(pa_tnc_attr_t, build, void, bio_writer_t *writer; chunk_t product_name; + if (this->value.ptr) + { + return; + } product_name = chunk_create(this->product_name, strlen(this->product_name)); writer = bio_writer_create(PRODUCT_INFO_MIN_SIZE); @@ -201,7 +194,6 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id, INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .get_noskip_flag = _get_noskip_flag, @@ -213,8 +205,7 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id, }, .get_info = _get_info, }, - .vendor_id = PEN_IETF, - .type = IETF_ATTR_PRODUCT_INFORMATION, + .type = { PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION }, .product_vendor_id = vendor_id, .product_id = id, .product_name = strdup(name), @@ -234,7 +225,6 @@ pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data) INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .build = _build, @@ -244,8 +234,7 @@ pa_tnc_attr_t *ietf_attr_product_info_create_from_data(chunk_t data) }, .get_info = _get_info, }, - .vendor_id = PEN_IETF, - .type = IETF_ATTR_PRODUCT_INFORMATION, + .type = { PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION }, .value = chunk_clone(data), .ref = 1, ); diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c index de2f959a4..8d1e70716 100644 --- a/src/libimcv/imc/imc_agent.c +++ b/src/libimcv/imc/imc_agent.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -18,7 +19,6 @@ #include <tncif_names.h> #include <debug.h> -#include <utils/linked_list.h> #include <threading/rwlock.h> typedef struct private_imc_agent_t private_imc_agent_t; @@ -333,12 +333,31 @@ static char* get_str_attribute(private_imc_agent_t *this, TNC_ConnectionID id, return NULL; } +/** + * Read an UInt32 attribute + */ +static u_int32_t get_uint_attribute(private_imc_agent_t *this, TNC_ConnectionID id, + TNC_AttributeID attribute_id) +{ + TNC_UInt32 len; + char buf[4]; + + if (this->get_attribute && + this->get_attribute(this->id, id, attribute_id, 4, buf, &len) == + TNC_RESULT_SUCCESS && len == 4) + { + return untoh32(buf); + } + return 0; + } + METHOD(imc_agent_t, create_state, TNC_Result, private_imc_agent_t *this, imc_state_t *state) { TNC_ConnectionID conn_id; char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL; bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE; + u_int32_t max_msg_len; conn_id = state->get_connection_id(state); if (find_connection(this, conn_id)) @@ -357,14 +376,18 @@ METHOD(imc_agent_t, create_state, TNC_Result, tnccs_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_VERSION); t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL); t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION); + max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE); state->set_flags(state, has_long, has_excl); + state->set_max_msg_len(state, max_msg_len); + + DBG2(DBG_IMC, "IMC %u \"%s\" created a state for %s %s Connection ID %u: " + "%slong %sexcl %ssoh", this->id, this->name, + tnccs_p ? tnccs_p:"?", tnccs_v ? tnccs_v:"?", conn_id, + has_long ? "+":"-", has_excl ? "+":"-", has_soh ? "+":"-"); + DBG2(DBG_IMC, " over %s %s with maximum PA-TNC message size of %u bytes", + t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len); - DBG2(DBG_IMC, "IMC %u \"%s\" created a state for Connection ID %u: " - "%s %s with %slong %sexcl %ssoh over %s %s", - this->id, this->name, conn_id, tnccs_p ? tnccs_p:"?", - tnccs_v ? tnccs_v:"?", has_long ? "+":"-", has_excl ? "+":"-", - has_soh ? "+":"-", t_p ? t_p:"?", t_v ? t_v :"?"); free(tnccs_p); free(tnccs_v); free(t_p); @@ -453,11 +476,17 @@ METHOD(imc_agent_t, get_state, bool, METHOD(imc_agent_t, send_message, TNC_Result, private_imc_agent_t *this, TNC_ConnectionID connection_id, bool excl, - TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, chunk_t msg) + TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, linked_list_t *attr_list) { TNC_MessageType type; TNC_UInt32 msg_flags; + TNC_Result result = TNC_RESULT_FATAL; imc_state_t *state; + pa_tnc_attr_t *attr; + pa_tnc_msg_t *pa_tnc_msg; + chunk_t msg; + enumerator_t *enumerator; + bool attr_added; state = find_connection(this, connection_id); if (!state) @@ -467,26 +496,70 @@ METHOD(imc_agent_t, send_message, TNC_Result, return TNC_RESULT_FATAL; } - if (state->has_long(state) && this->send_message_long) + while (attr_list->get_count(attr_list)) { - if (!src_imc_id) + pa_tnc_msg = pa_tnc_msg_create(state->get_max_msg_len(state)); + attr_added = FALSE; + + enumerator = attr_list->create_enumerator(attr_list); + while (enumerator->enumerate(enumerator, &attr)) { - src_imc_id = this->id; + if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr)) + { + attr_added = TRUE; + } + else + { + if (attr_added) + { + break; + } + else + { + DBG1(DBG_IMC, "PA-TNC attribute too large to send, deleted"); + attr->destroy(attr); + } + } + attr_list->remove_at(attr_list, enumerator); } - msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; + enumerator->destroy(enumerator); - return this->send_message_long(src_imc_id, connection_id, msg_flags, - msg.ptr, msg.len, this->vendor_id, - this->subtype, dst_imv_id); - } - if (this->send_message) - { - type = (this->vendor_id << 8) | this->subtype; + /* build and send the PA-TNC message via the IF-IMC interface */ + if (!pa_tnc_msg->build(pa_tnc_msg)) + { + pa_tnc_msg->destroy(pa_tnc_msg); + return TNC_RESULT_FATAL; + } + msg = pa_tnc_msg->get_encoding(pa_tnc_msg); + + if (state->has_long(state) && this->send_message_long) + { + if (!src_imc_id) + { + src_imc_id = this->id; + } + msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; + + result = this->send_message_long(src_imc_id, connection_id, + msg_flags, msg.ptr, msg.len, this->vendor_id, + this->subtype, dst_imv_id); + } + else if (this->send_message) + { + type = (this->vendor_id << 8) | this->subtype; - return this->send_message(this->id, connection_id, msg.ptr, msg.len, - type); + result = this->send_message(this->id, connection_id, msg.ptr, + msg.len, type); + } + + pa_tnc_msg->destroy(pa_tnc_msg); + + if (result != TNC_RESULT_SUCCESS) + { + break; + } } - return TNC_RESULT_FATAL; + return result; } METHOD(imc_agent_t, receive_message, TNC_Result, @@ -494,11 +567,11 @@ METHOD(imc_agent_t, receive_message, TNC_Result, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, pa_tnc_msg_t **pa_tnc_msg) { - pa_tnc_msg_t *pa_msg, *error_msg; + pa_tnc_msg_t *pa_msg; pa_tnc_attr_t *error_attr; + linked_list_t *error_attr_list; enumerator_t *enumerator; - TNC_MessageType msg_type; - TNC_UInt32 msg_flags, src_imc_id, dst_imv_id; + TNC_UInt32 src_imc_id, dst_imv_id; TNC_ConnectionID connection_id; TNC_Result result; @@ -534,51 +607,24 @@ METHOD(imc_agent_t, receive_message, TNC_Result, *pa_tnc_msg = pa_msg; break; case VERIFY_ERROR: - /* build error message */ - error_msg = pa_tnc_msg_create(); + /* extract and copy by refence all error attributes */ + error_attr_list = linked_list_create(); + enumerator = pa_msg->create_error_enumerator(pa_msg); while (enumerator->enumerate(enumerator, &error_attr)) { - error_msg->add_attribute(error_msg, - error_attr->get_ref(error_attr)); + error_attr_list->insert_last(error_attr_list, + error_attr->get_ref(error_attr)); } enumerator->destroy(enumerator); - error_msg->build(error_msg); - - /* send error message */ - if (state->has_long(state) && this->send_message_long) - { - if (state->has_excl(state)) - { - msg_flags = TNC_MESSAGE_FLAGS_EXCLUSIVE; - dst_imv_id = src_imv_id; - } - else - { - msg_flags = 0; - dst_imv_id = TNC_IMVID_ANY; - } - src_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? this->id - : dst_imc_id; - result = this->send_message_long(src_imc_id, connection_id, - msg_flags, msg.ptr, msg.len, msg_vid, - msg_subtype, dst_imv_id); - } - else if (this->send_message) - { - msg_type = (msg_vid << 8) | msg_subtype; + src_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? this->id : dst_imc_id; + dst_imv_id = state->has_excl(state) ? src_imv_id : TNC_IMVID_ANY; - result = this->send_message(this->id, connection_id, - msg.ptr, msg.len, msg_type); - } - else - { - result = TNC_RESULT_FATAL; - } + result = send_message(this, connection_id, state->has_excl(state), + src_imc_id, dst_imv_id, error_attr_list); - /* clean up */ - error_msg->destroy(error_msg); + error_attr_list->destroy(error_attr_list); pa_msg->destroy(pa_msg); return result; case FAILED: diff --git a/src/libimcv/imc/imc_agent.h b/src/libimcv/imc/imc_agent.h index d1fef4d8d..e87450aa6 100644 --- a/src/libimcv/imc/imc_agent.h +++ b/src/libimcv/imc/imc_agent.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -26,6 +27,7 @@ #include <tncifimc.h> #include <pen/pen.h> +#include <utils/linked_list.h> #include <library.h> @@ -104,13 +106,13 @@ struct imc_agent_t { * @param excl exclusive flag * @param src_imc_id IMC ID to be set as source * @param dst_imv_id IMV ID to be set as destination - * @param msg message to send + * @param attr_list list of PA-TNC attributes to send * @return TNC result code */ TNC_Result (*send_message)(imc_agent_t *this, TNC_ConnectionID connection_id, bool excl, TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, - chunk_t msg); + linked_list_t *attr_list); /** * Call when a PA-TNC message was received diff --git a/src/libimcv/imc/imc_state.h b/src/libimcv/imc/imc_state.h index f1b0358c9..c34441f0f 100644 --- a/src/libimcv/imc/imc_state.h +++ b/src/libimcv/imc/imc_state.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -22,6 +23,8 @@ #define IMC_STATE_H_ #include <tncif.h> +#include <tncifimv.h> +#include <tncifimc.h> #include <library.h> @@ -33,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 */ @@ -64,6 +66,20 @@ D attached to the state void (*set_flags)(imc_state_t *this, bool has_long, bool has_excl); /** + * Set the maximum size of a PA-TNC message for this TNCCS connection + * + * @max_msg_len maximum size of a PA-TNC message + */ + void (*set_max_msg_len)(imc_state_t *this, u_int32_t max_msg_len); + + /** + * Get the maximum size of a PA-TNC message for this TNCCS connection + * + * @return maximum size of a PA-TNC message + */ + u_int32_t (*get_max_msg_len)(imc_state_t *this); + + /** * Change the connection state * * @param new_state new connection state @@ -71,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/imcv.c b/src/libimcv/imcv.c index a8c0af47b..b84548f9b 100644 --- a/src/libimcv/imcv.c +++ b/src/libimcv/imcv.c @@ -108,7 +108,7 @@ bool libimcv_init(void) } if (!lib->plugins->load(lib->plugins, NULL, - "sha1 sha2 random gmp pubkey x509")) + "sha1 sha2 random nonce gmp pubkey x509")) { library_deinit(); return FALSE; diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c index 56131c547..fa04e0237 100644 --- a/src/libimcv/imv/imv_agent.c +++ b/src/libimcv/imv/imv_agent.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -14,11 +15,11 @@ #include "imcv.h" #include "imv_agent.h" +#include "ietf/ietf_attr_assess_result.h" #include <tncif_names.h> #include <debug.h> -#include <utils/linked_list.h> #include <threading/rwlock.h> typedef struct private_imv_agent_t private_imv_agent_t; @@ -49,6 +50,11 @@ struct private_imv_agent_t { TNC_MessageSubtype subtype; /** + * Maximum PA-TNC Message size + */ + size_t max_msg_len; + + /** * ID of IMV as assigned by TNCS */ TNC_IMVID id; @@ -351,12 +357,31 @@ static char* get_str_attribute(private_imv_agent_t *this, TNC_ConnectionID id, return NULL; } +/** + * Read an UInt32 attribute + */ +static u_int32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID id, + TNC_AttributeID attribute_id) +{ + TNC_UInt32 len; + char buf[4]; + + if (this->get_attribute && + this->get_attribute(this->id, id, attribute_id, 4, buf, &len) == + TNC_RESULT_SUCCESS && len == 4) + { + return untoh32(buf); + } + return 0; + } + METHOD(imv_agent_t, create_state, TNC_Result, private_imv_agent_t *this, imv_state_t *state) { TNC_ConnectionID conn_id; char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL; bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE; + u_int32_t max_msg_len; conn_id = state->get_connection_id(state); if (find_connection(this, conn_id)) @@ -371,18 +396,22 @@ METHOD(imv_agent_t, create_state, TNC_Result, has_long = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_LONG_TYPES); has_excl = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_EXCLUSIVE); has_soh = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_SOH); - tnccs_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL); + tnccs_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL); tnccs_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_VERSION); t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL); t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION); + max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE); state->set_flags(state, has_long, has_excl); + state->set_max_msg_len(state, max_msg_len); + + DBG2(DBG_IMV, "IMV %u \"%s\" created a state for %s %s Connection ID %u: " + "%slong %sexcl %ssoh", this->id, this->name, + tnccs_p ? tnccs_p:"?", tnccs_v ? tnccs_v:"?", conn_id, + has_long ? "+":"-", has_excl ? "+":"-", has_soh ? "+":"-"); + DBG2(DBG_IMV, " over %s %s with maximum PA-TNC message size of %u bytes", + t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len); - DBG2(DBG_IMV, "IMV %u \"%s\" created a state for Connection ID %u: " - "%s %s with %slong %sexcl %ssoh over %s %s", - this->id, this->name, conn_id, tnccs_p ? tnccs_p:"?", - tnccs_v ? tnccs_v:"?", has_long ? "+":"-", has_excl ? "+":"-", - has_soh ? "+":"-", t_p ? t_p:"?", t_v ? t_v :"?"); free(tnccs_p); free(tnccs_v); free(t_p); @@ -449,7 +478,7 @@ METHOD(imv_agent_t, change_state, TNC_Result, DBG1(DBG_IMV, "IMV %u \"%s\" was notified of unknown state %u " "for Connection ID %u", this->id, this->name, new_state, connection_id); - return TNC_RESULT_INVALID_PARAMETER; + return TNC_RESULT_INVALID_PARAMETER; } return TNC_RESULT_SUCCESS; } @@ -470,11 +499,17 @@ METHOD(imv_agent_t, get_state, bool, METHOD(imv_agent_t, send_message, TNC_Result, private_imv_agent_t *this, TNC_ConnectionID connection_id, bool excl, - TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, chunk_t msg) + TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, linked_list_t *attr_list) { TNC_MessageType type; TNC_UInt32 msg_flags; + TNC_Result result = TNC_RESULT_FATAL; imv_state_t *state; + pa_tnc_attr_t *attr; + pa_tnc_msg_t *pa_tnc_msg; + chunk_t msg; + enumerator_t *enumerator; + bool attr_added; state = find_connection(this, connection_id); if (!state) @@ -484,26 +519,70 @@ METHOD(imv_agent_t, send_message, TNC_Result, return TNC_RESULT_FATAL; } - if (state->has_long(state) && this->send_message_long) + while (attr_list->get_count(attr_list)) { - if (!src_imv_id) + pa_tnc_msg = pa_tnc_msg_create(this->max_msg_len); + attr_added = FALSE; + + enumerator = attr_list->create_enumerator(attr_list); + while (enumerator->enumerate(enumerator, &attr)) + { + if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr)) + { + attr_added = TRUE; + } + else + { + if (attr_added) + { + break; + } + else + { + DBG1(DBG_IMV, "PA-TNC attribute too large to send, deleted"); + attr->destroy(attr); + } + } + attr_list->remove_at(attr_list, enumerator); + } + enumerator->destroy(enumerator); + + /* build and send the PA-TNC message via the IF-IMV interface */ + if (!pa_tnc_msg->build(pa_tnc_msg)) { - src_imv_id = this->id; + pa_tnc_msg->destroy(pa_tnc_msg); + return TNC_RESULT_FATAL; } - msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; + msg = pa_tnc_msg->get_encoding(pa_tnc_msg); - return this->send_message_long(src_imv_id, connection_id, msg_flags, - msg.ptr, msg.len, this->vendor_id, - this->subtype, dst_imc_id); - } - if (this->send_message) - { - type = (this->vendor_id << 8) | this->subtype; + if (state->has_long(state) && this->send_message_long) + { + if (!src_imv_id) + { + src_imv_id = this->id; + } + msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; - return this->send_message(this->id, connection_id, msg.ptr, msg.len, - type); + result = this->send_message_long(src_imv_id, connection_id, + msg_flags, msg.ptr, msg.len, this->vendor_id, + this->subtype, dst_imc_id); + } + else if (this->send_message) + { + type = (this->vendor_id << 8) | this->subtype; + + result = this->send_message(this->id, connection_id, msg.ptr, + msg.len, type); + } + + pa_tnc_msg->destroy(pa_tnc_msg); + + if (result != TNC_RESULT_SUCCESS) + { + break; + } } - return TNC_RESULT_FATAL; + return result; } METHOD(imv_agent_t, set_recommendation, TNC_Result, @@ -530,11 +609,11 @@ METHOD(imv_agent_t, receive_message, TNC_Result, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, pa_tnc_msg_t **pa_tnc_msg) { - pa_tnc_msg_t *pa_msg, *error_msg; + pa_tnc_msg_t *pa_msg; pa_tnc_attr_t *error_attr; + linked_list_t *error_attr_list; enumerator_t *enumerator; - TNC_MessageType msg_type; - TNC_UInt32 msg_flags, src_imv_id, dst_imc_id; + TNC_UInt32 src_imv_id, dst_imc_id; TNC_ConnectionID connection_id; TNC_Result result; @@ -570,53 +649,24 @@ METHOD(imv_agent_t, receive_message, TNC_Result, *pa_tnc_msg = pa_msg; break; case VERIFY_ERROR: - /* build error message */ - error_msg = pa_tnc_msg_create(); + /* extract and copy by refence all error attributes */ + error_attr_list = linked_list_create(); + enumerator = pa_msg->create_error_enumerator(pa_msg); while (enumerator->enumerate(enumerator, &error_attr)) { - error_msg->add_attribute(error_msg, - error_attr->get_ref(error_attr)); + error_attr_list->insert_last(error_attr_list, + error_attr->get_ref(error_attr)); } enumerator->destroy(enumerator); - error_msg->build(error_msg); - /* send error message */ - msg = error_msg->get_encoding(error_msg); + src_imv_id = (dst_imv_id == TNC_IMVID_ANY) ? this->id : dst_imv_id; + dst_imc_id = state->has_excl(state) ? src_imc_id : TNC_IMCID_ANY; - if (state->has_long(state) && this->send_message_long) - { - if (state->has_excl(state)) - { - msg_flags = TNC_MESSAGE_FLAGS_EXCLUSIVE; - dst_imc_id = src_imc_id; - } - else - { - msg_flags = 0; - dst_imc_id = TNC_IMCID_ANY; - } - src_imv_id = (dst_imv_id == TNC_IMVID_ANY) ? this->id - : dst_imv_id; - - result = this->send_message_long(src_imv_id, connection_id, - msg_flags, msg.ptr, msg.len, msg_vid, - msg_subtype, dst_imc_id); - } - else if (this->send_message) - { - msg_type = (msg_vid << 8) | msg_subtype; + result = send_message(this, connection_id, state->has_excl(state), + src_imv_id, dst_imc_id, error_attr_list); - result = this->send_message(this->id, connection_id, - msg.ptr, msg.len, msg_type); - } - else - { - result = TNC_RESULT_FATAL; - } - - /* clean up */ - error_msg->destroy(error_msg); + error_attr_list->destroy(error_attr_list); pa_msg->destroy(pa_msg); return result; case FAILED: @@ -633,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; @@ -651,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) { @@ -663,8 +716,8 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result, lang_len <= BUF_LEN) { pref_lang.len = lang_len; - DBG2(DBG_IMV, "preferred language is '%.*s'", - pref_lang.len, pref_lang.ptr); + DBG2(DBG_IMV, "preferred language is '%.*s'", (int)pref_lang.len, + pref_lang.ptr); } /* find a reason string for the preferred or default language and set it */ @@ -680,7 +733,21 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result, reason_lang.len, reason_lang.ptr); } } - + + /* Send an IETF Assessment Result attribute if enabled */ + if (lib->settings->get_bool(lib->settings, "libimcv.assessment_result", TRUE)) + { + 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); } @@ -777,6 +844,7 @@ imv_agent_t *imv_agent_create(const char *name, .name = name, .vendor_id = vendor_id, .subtype = subtype, + .max_msg_len = 65490, .id = id, .additional_ids = linked_list_create(), .connections = linked_list_create(), diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h index de70f3bc1..34ac3c109 100644 --- a/src/libimcv/imv/imv_agent.h +++ b/src/libimcv/imv/imv_agent.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -26,6 +27,7 @@ #include <tncifimv.h> #include <pen/pen.h> +#include <utils/linked_list.h> #include <library.h> @@ -104,13 +106,13 @@ struct imv_agent_t { * @param excl exclusive flag * @param src_imv_id IMV ID to be set as source * @param dst_imc_id IMD ID to be set as destination - * @param msg message to send + * @param attr_list list of PA-TNC attributes to send * @return TNC result code */ TNC_Result (*send_message)(imv_agent_t *this, TNC_ConnectionID connection_id, bool excl, TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, - chunk_t msg); + linked_list_t *attr_list); /** * Call when a PA-TNC message was received @@ -149,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/imv/imv_state.h b/src/libimcv/imv/imv_state.h index 9e7a29a9f..1b0845b84 100644 --- a/src/libimcv/imv/imv_state.h +++ b/src/libimcv/imv/imv_state.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -63,6 +64,20 @@ struct imv_state_t { void (*set_flags)(imv_state_t *this, bool has_long, bool has_excl); /** + * Set the maximum size of a PA-TNC message for this TNCCS connection + * + * @max_msg_len maximum size of a PA-TNC message + */ + void (*set_max_msg_len)(imv_state_t *this, u_int32_t max_msg_len); + + /** + * Get the maximum size of a PA-TNC message for this TNCCS connection + * + * @return maximum size of a PA-TNC message + */ + u_int32_t (*get_max_msg_len)(imv_state_t *this); + + /** * Change the connection state * * @param new_state new connection state diff --git a/src/libimcv/ita/ita_attr.c b/src/libimcv/ita/ita_attr.c index ec23c11ea..0ea799c3a 100644 --- a/src/libimcv/ita/ita_attr.c +++ b/src/libimcv/ita/ita_attr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2012 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -15,9 +15,11 @@ #include "ita_attr.h" #include "ita/ita_attr_command.h" +#include "ita/ita_attr_dummy.h" -ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_COMMAND, +ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DUMMY, "Command", + "Dummy", ); /** @@ -29,6 +31,8 @@ pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, chunk_t value) { case ITA_ATTR_COMMAND: return ita_attr_command_create_from_data(value); + case ITA_ATTR_DUMMY: + return ita_attr_dummy_create_from_data(value); default: return NULL; } diff --git a/src/libimcv/ita/ita_attr.h b/src/libimcv/ita/ita_attr.h index 82debdd1e..3baf0e3b8 100644 --- a/src/libimcv/ita/ita_attr.h +++ b/src/libimcv/ita/ita_attr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2012 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ typedef enum ita_attr_t ita_attr_t; */ enum ita_attr_t { ITA_ATTR_COMMAND = 1, + ITA_ATTR_DUMMY = 2, }; /** diff --git a/src/libimcv/ita/ita_attr_command.c b/src/libimcv/ita/ita_attr_command.c index 5c1577a7c..d43e4777b 100644 --- a/src/libimcv/ita/ita_attr_command.c +++ b/src/libimcv/ita/ita_attr_command.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -32,14 +33,9 @@ struct private_ita_attr_command_t { ita_attr_command_t public; /** - * Attribute vendor ID + * Vendor-specific attribute type */ - pen_t vendor_id; - - /** - * Attribute type - */ - u_int32_t type; + pen_type_t type; /** * Attribute value @@ -62,13 +58,7 @@ struct private_ita_attr_command_t { refcount_t ref; }; -METHOD(pa_tnc_attr_t, get_vendor_id, pen_t, - private_ita_attr_command_t *this) -{ - return this->vendor_id; -} - -METHOD(pa_tnc_attr_t, get_type, u_int32_t, +METHOD(pa_tnc_attr_t, get_type, pen_type_t, private_ita_attr_command_t *this) { return this->type; @@ -95,6 +85,10 @@ METHOD(pa_tnc_attr_t, set_noskip_flag,void, METHOD(pa_tnc_attr_t, build, void, private_ita_attr_command_t *this) { + if (this->value.ptr) + { + return; + } this->value = chunk_create(this->command, strlen(this->command)); this->value = chunk_clone(this->value); } @@ -143,7 +137,6 @@ pa_tnc_attr_t *ita_attr_command_create(char *command) INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .get_noskip_flag = _get_noskip_flag, @@ -155,8 +148,7 @@ pa_tnc_attr_t *ita_attr_command_create(char *command) }, .get_command = _get_command, }, - .vendor_id = PEN_ITA, - .type = ITA_ATTR_COMMAND, + .type = { PEN_ITA, ITA_ATTR_COMMAND }, .command = strdup(command), .ref = 1, ); @@ -174,7 +166,6 @@ pa_tnc_attr_t *ita_attr_command_create_from_data(chunk_t data) INIT(this, .public = { .pa_tnc_attribute = { - .get_vendor_id = _get_vendor_id, .get_type = _get_type, .get_value = _get_value, .build = _build, @@ -184,8 +175,7 @@ pa_tnc_attr_t *ita_attr_command_create_from_data(chunk_t data) }, .get_command = _get_command, }, - .vendor_id = PEN_ITA, - .type = ITA_ATTR_COMMAND, + .type = {PEN_ITA, ITA_ATTR_COMMAND }, .value = chunk_clone(data), .ref = 1, ); diff --git a/src/libimcv/ita/ita_attr_dummy.c b/src/libimcv/ita/ita_attr_dummy.c new file mode 100644 index 000000000..f122256a1 --- /dev/null +++ b/src/libimcv/ita/ita_attr_dummy.c @@ -0,0 +1,183 @@ +/* + * 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 "ita_attr.h" +#include "ita_attr_dummy.h" + +#include <pen/pen.h> + +#include <debug.h> + +typedef struct private_ita_attr_dummy_t private_ita_attr_dummy_t; + +/** + * Private data of an ita_attr_dummy_t object. + */ +struct private_ita_attr_dummy_t { + + /** + * Public members of ita_attr_dummy_t + */ + ita_attr_dummy_t public; + + /** + * Vendor-specific attribute type + */ + pen_type_t type; + + /** + * Attribute value + */ + chunk_t value; + + /** + * Noskip flag + */ + bool noskip_flag; + + /** + * Size of the attribute value + */ + int size; + + /** + * Reference count + */ + refcount_t ref; +}; + +METHOD(pa_tnc_attr_t, get_type, pen_type_t, + private_ita_attr_dummy_t *this) +{ + return this->type; +} + +METHOD(pa_tnc_attr_t, get_value, chunk_t, + private_ita_attr_dummy_t *this) +{ + return this->value; +} + +METHOD(pa_tnc_attr_t, get_noskip_flag, bool, + private_ita_attr_dummy_t *this) +{ + return this->noskip_flag; +} + +METHOD(pa_tnc_attr_t, set_noskip_flag,void, + private_ita_attr_dummy_t *this, bool noskip) +{ + this->noskip_flag = noskip; +} + +METHOD(pa_tnc_attr_t, build, void, + private_ita_attr_dummy_t *this) +{ + if (this->value.ptr) + { + return; + } + this->value = chunk_alloc(this->size); + memset(this->value.ptr, 0xdd, this->value.len); +} + +METHOD(pa_tnc_attr_t, process, status_t, + private_ita_attr_dummy_t *this, u_int32_t *offset) +{ + this->size = this->value.len; + + return SUCCESS; +} + +METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*, + private_ita_attr_dummy_t *this) +{ + ref_get(&this->ref); + return &this->public.pa_tnc_attribute; +} + +METHOD(pa_tnc_attr_t, destroy, void, + private_ita_attr_dummy_t *this) +{ + if (ref_put(&this->ref)) + { + free(this->value.ptr); + free(this); + } +} + +METHOD(ita_attr_dummy_t, get_size, int, + private_ita_attr_dummy_t *this) +{ + return this->size; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ita_attr_dummy_create(int size) +{ + private_ita_attr_dummy_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_size = _get_size, + }, + .type = { PEN_ITA, ITA_ATTR_DUMMY }, + .size = size, + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ita_attr_dummy_create_from_data(chunk_t data) +{ + private_ita_attr_dummy_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_size = _get_size, + }, + .type = { PEN_ITA, ITA_ATTR_DUMMY }, + .value = chunk_clone(data), + .ref = 1, + ); + + return &this->public.pa_tnc_attribute; +} + + diff --git a/src/libimcv/ita/ita_attr_dummy.h b/src/libimcv/ita/ita_attr_dummy.h new file mode 100644 index 000000000..afd543b52 --- /dev/null +++ b/src/libimcv/ita/ita_attr_dummy.h @@ -0,0 +1,61 @@ +/* + * 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 ita_attr_dummyt ita_attr_dummy + * @{ @ingroup ita_attr_dummy + */ + +#ifndef ITA_ATTR_DUMMY_H_ +#define ITA_ATTR_DUMMY_H_ + +typedef struct ita_attr_dummy_t ita_attr_dummy_t; + +#include "pa_tnc/pa_tnc_attr.h" + +/** + * Class implementing the ITA Dummy PA-TNC attribute. + * + */ +struct ita_attr_dummy_t { + + /** + * Public PA-TNC attribute interface + */ + pa_tnc_attr_t pa_tnc_attribute; + + /** + * Get the size the ITA Dummy attribute value + * + * @return size of dummy attribute value + */ + int (*get_size)(ita_attr_dummy_t *this); +}; + +/** + * Creates an ita_attr_dummy_t object with a given size + * + * @param size size of dummy attribute value + */ +pa_tnc_attr_t* ita_attr_dummy_create(int size); + +/** + * Creates an ita_attr_dummy_t object from received data + * + * @param command ITA command string + */ +pa_tnc_attr_t* ita_attr_dummy_create_from_data(chunk_t value); + +#endif /** ITA_ATTR_DUMMY_H_ @}*/ diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.h b/src/libimcv/pa_tnc/pa_tnc_attr.h index b6057a70b..9abdba78c 100644 --- a/src/libimcv/pa_tnc/pa_tnc_attr.h +++ b/src/libimcv/pa_tnc/pa_tnc_attr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2012 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -33,18 +33,11 @@ typedef struct pa_tnc_attr_t pa_tnc_attr_t; struct pa_tnc_attr_t { /** - * Get the vendor ID of an PA-TNC attribute + * Get the vendor ID/type of an PA-TNC attribute * - * @return attribute vendor ID + * @return vendor-specific attribute type */ - u_int32_t (*get_vendor_id)(pa_tnc_attr_t *this); - - /** - * Get the type of an PA-TNC attribute - * - * @return attribute type - */ - u_int32_t (*get_type)(pa_tnc_attr_t *this); + pen_type_t (*get_type)(pa_tnc_attr_t *this); /** * Get the value of an PA-TNC attribute diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c index b5df0a5b5..b1476fc7f 100644 --- a/src/libimcv/pa_tnc/pa_tnc_msg.c +++ b/src/libimcv/pa_tnc/pa_tnc_msg.c @@ -1,6 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen - * + * Copyright (C) 2011-2012 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -90,6 +89,16 @@ struct private_pa_tnc_msg_t { u_int32_t identifier; /** + * Current PA-TNC Message size + */ + size_t msg_len; + + /** + * Maximum PA-TNC Message size + */ + size_t max_msg_len; + + /** * Encoded message */ chunk_t encoding; @@ -101,67 +110,84 @@ METHOD(pa_tnc_msg_t, get_encoding, chunk_t, return this->encoding; } -METHOD(pa_tnc_msg_t, add_attribute, void, +METHOD(pa_tnc_msg_t, add_attribute, bool, private_pa_tnc_msg_t *this, pa_tnc_attr_t *attr) { + chunk_t attr_value; + size_t attr_len; + + attr->build(attr); + attr_value = attr->get_value(attr); + attr_len = PA_TNC_ATTR_HEADER_SIZE + attr_value.len; + + if (this->max_msg_len && this->msg_len + attr_len > this->max_msg_len) + { + /* attribute just does not fit into this message */ + return FALSE; + } + this->msg_len += attr_len; + this->attributes->insert_last(this->attributes, attr); + return TRUE; } -METHOD(pa_tnc_msg_t, build, void, +METHOD(pa_tnc_msg_t, build, bool, private_pa_tnc_msg_t *this) { bio_writer_t *writer; enumerator_t *enumerator; pa_tnc_attr_t *attr; enum_name_t *pa_attr_names; - pen_t vendor_id; - u_int32_t type; + pen_type_t type; u_int8_t flags; chunk_t value; - rng_t *rng; + nonce_gen_t *ng; - /* create a random message identifier */ - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - rng->get_bytes(rng, sizeof(this->identifier), (u_int8_t*)&this->identifier); - rng->destroy(rng); - DBG2(DBG_TNC, "creating PA-TNC message with ID 0x%08x", this->identifier); + /* generate a nonce as a message identifier */ + ng = lib->crypto->create_nonce_gen(lib->crypto); + if (!ng || !ng->get_nonce(ng, 4, (u_int8_t*)&this->identifier)) + { + DBG1(DBG_TNC, "failed to generate random PA-TNC message identifier"); + DESTROY_IF(ng); + return FALSE; + } + ng->destroy(ng); + DBG1(DBG_TNC, "creating PA-TNC message with ID 0x%08x", this->identifier); /* build message header */ - writer = bio_writer_create(PA_TNC_HEADER_SIZE); + writer = bio_writer_create(this->msg_len); writer->write_uint8 (writer, PA_TNC_VERSION); writer->write_uint24(writer, PA_TNC_RESERVED); writer->write_uint32(writer, this->identifier); - /* build and append encoding of PA-TNC attributes */ + /* append encoded value of PA-TNC attributes */ enumerator = this->attributes->create_enumerator(this->attributes); while (enumerator->enumerate(enumerator, &attr)) { - attr->build(attr); - vendor_id = attr->get_vendor_id(attr); - type = attr->get_type(attr); + type = attr->get_type(attr); value = attr->get_value(attr); flags = attr->get_noskip_flag(attr) ? PA_TNC_ATTR_FLAG_NOSKIP : PA_TNC_ATTR_FLAG_NONE; pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes, - vendor_id); + type.vendor_id); if (pa_attr_names) { DBG2(DBG_TNC, "creating PA-TNC attribute type '%N/%N' " - "0x%06x/0x%08x", pen_names, vendor_id, - pa_attr_names, type, vendor_id, type); + "0x%06x/0x%08x", pen_names, type.vendor_id, + pa_attr_names, type.type, type.vendor_id, type.type); } else { DBG2(DBG_TNC, "creating PA-TNC attribute type '%N' " - "0x%06x/0x%08x", pen_names, vendor_id, - vendor_id, type); + "0x%06x/0x%08x", pen_names, type.vendor_id, + type.vendor_id, type.type); } DBG3(DBG_TNC, "%B", &value); writer->write_uint8 (writer, flags); - writer->write_uint24(writer, vendor_id); - writer->write_uint32(writer, type); + writer->write_uint24(writer, type.vendor_id); + writer->write_uint32(writer, type.type); writer->write_uint32(writer, PA_TNC_ATTR_HEADER_SIZE + value.len); writer->write_data (writer, value); } @@ -170,6 +196,8 @@ METHOD(pa_tnc_msg_t, build, void, free(this->encoding.ptr); this->encoding = chunk_clone(writer->get_buf(writer)); writer->destroy(writer); + + return TRUE; } METHOD(pa_tnc_msg_t, process, status_t, @@ -179,6 +207,7 @@ METHOD(pa_tnc_msg_t, process, status_t, pa_tnc_attr_t *error; u_int8_t version; u_int32_t reserved, offset, attr_offset; + pen_type_t error_code; /* process message header */ if (this->encoding.len < PA_TNC_HEADER_SIZE) @@ -191,13 +220,14 @@ METHOD(pa_tnc_msg_t, process, status_t, reader->read_uint8 (reader, &version); reader->read_uint24(reader, &reserved); reader->read_uint32(reader, &this->identifier); - DBG2(DBG_TNC, "processing PA-TNC message with ID 0x%08x", this->identifier); + DBG1(DBG_TNC, "processing PA-TNC message with ID 0x%08x", this->identifier); if (version != PA_TNC_VERSION) { + pen_type_t error_code = { PEN_IETF, PA_ERROR_VERSION_NOT_SUPPORTED }; + DBG1(DBG_TNC, "PA-TNC version %u not supported", version); - error = ietf_attr_pa_tnc_error_create(PEN_IETF, - PA_ERROR_VERSION_NOT_SUPPORTED, this->encoding); + error = ietf_attr_pa_tnc_error_create(error_code, this->encoding); goto err; } @@ -214,6 +244,7 @@ METHOD(pa_tnc_msg_t, process, status_t, pa_tnc_attr_t *attr; enum_name_t *pa_attr_names; ietf_attr_pa_tnc_error_t *error_attr; + pen_type_t error_code; attr_info = reader->peek(reader); attr_info.len = PA_TNC_ATTR_INFO_SIZE; @@ -241,18 +272,18 @@ METHOD(pa_tnc_msg_t, process, status_t, { DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length", length); - error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, - PA_ERROR_INVALID_PARAMETER, this->encoding, - offset + PA_TNC_ATTR_INFO_SIZE); + error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER); + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset + PA_TNC_ATTR_INFO_SIZE); goto err; } if (!reader->read_data(reader, length - PA_TNC_ATTR_HEADER_SIZE, &value)) { DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value"); - error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, - PA_ERROR_INVALID_PARAMETER, this->encoding, - offset + PA_TNC_ATTR_INFO_SIZE); + error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER); + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset + PA_TNC_ATTR_INFO_SIZE); goto err; } DBG3(DBG_TNC, "%B", &value); @@ -264,8 +295,10 @@ METHOD(pa_tnc_msg_t, process, status_t, if (flags & PA_TNC_ATTR_FLAG_NOSKIP) { DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag"); - error = ietf_attr_pa_tnc_error_create(PEN_IETF, - PA_ERROR_ATTR_TYPE_NOT_SUPPORTED, this->encoding); + error_code = pen_type_create(PEN_IETF, + PA_ERROR_ATTR_TYPE_NOT_SUPPORTED); + error = ietf_attr_pa_tnc_error_create(error_code, + this->encoding); error_attr = (ietf_attr_pa_tnc_error_t*)error; error_attr->set_attr_info(error_attr, attr_info); goto err; @@ -281,18 +314,21 @@ METHOD(pa_tnc_msg_t, process, status_t, if (attr->process(attr, &attr_offset) != SUCCESS) { attr->destroy(attr); - if (vendor_id == PEN_IETF && type == IETF_ATTR_PA_TNC_ERROR) + if (error_code.vendor_id == PEN_IETF && + error_code.type == IETF_ATTR_PA_TNC_ERROR) { /* error while processing a PA-TNC error attribute - abort */ reader->destroy(reader); return FAILED; } - error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, - PA_ERROR_INVALID_PARAMETER, this->encoding, + error_code = pen_type_create(PEN_IETF, + PA_ERROR_ATTR_TYPE_NOT_SUPPORTED); + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset + PA_TNC_ATTR_HEADER_SIZE + attr_offset); goto err; } - add_attribute(this, attr); + this->attributes->insert_last(this->attributes, attr); offset += length; } @@ -302,8 +338,9 @@ METHOD(pa_tnc_msg_t, process, status_t, return SUCCESS; } DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header"); - error = ietf_attr_pa_tnc_error_create_with_offset(PEN_IETF, - PA_ERROR_INVALID_PARAMETER, this->encoding, offset); + error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER); + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset); err: reader->destroy(reader); @@ -316,35 +353,35 @@ METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool, { enumerator_t *enumerator; pa_tnc_attr_t *attr; + pen_type_t type; bool fatal_error = FALSE; enumerator = this->attributes->create_enumerator(this->attributes); while (enumerator->enumerate(enumerator, &attr)) { - if (attr->get_vendor_id(attr) == PEN_IETF && - attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR) + type = attr->get_type(attr); + + if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR) { ietf_attr_pa_tnc_error_t *error_attr; - pen_t error_vendor_id; - pa_tnc_error_code_t error_code; + pen_type_t error_code; chunk_t msg_info, attr_info; u_int32_t offset; error_attr = (ietf_attr_pa_tnc_error_t*)attr; - error_vendor_id = error_attr->get_vendor_id(error_attr); error_code = error_attr->get_error_code(error_attr); msg_info = error_attr->get_msg_info(error_attr); /* skip errors from non-IETF namespaces */ - if (error_vendor_id != PEN_IETF) + if (error_code.vendor_id != PEN_IETF) { continue; } DBG1(DBG_IMC, "received PA-TNC error '%N' concerning message " - "0x%08x/0x%08x", pa_tnc_error_code_names, error_code, + "0x%08x/0x%08x", pa_tnc_error_code_names, error_code.type, untoh32(msg_info.ptr), untoh32(msg_info.ptr + 4)); - switch (error_code) + switch (error_code.type) { case PA_ERROR_INVALID_PARAMETER: offset = error_attr->get_offset(error_attr); @@ -358,8 +395,9 @@ METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool, break; } - /* remove the processed IETF standard error attribute */ + /* remove and delete the processed IETF standard error attribute */ this->attributes->remove_at(this->attributes, enumerator); + attr->destroy(attr); fatal_error = TRUE; } } @@ -394,7 +432,7 @@ METHOD(pa_tnc_msg_t, destroy, void, /** * See header */ -pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data) +pa_tnc_msg_t *pa_tnc_msg_create(size_t max_msg_len) { private_pa_tnc_msg_t *this; @@ -409,9 +447,10 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data) .create_error_enumerator = _create_error_enumerator, .destroy = _destroy, }, - .encoding = chunk_clone(data), .attributes = linked_list_create(), .errors = linked_list_create(), + .msg_len = PA_TNC_HEADER_SIZE, + .max_msg_len = max_msg_len, ); return &this->public; @@ -420,8 +459,26 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data) /** * See header */ -pa_tnc_msg_t *pa_tnc_msg_create(void) +pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data) { - return pa_tnc_msg_create_from_data(chunk_empty); + private_pa_tnc_msg_t *this; + + INIT(this, + .public = { + .get_encoding = _get_encoding, + .add_attribute = _add_attribute, + .build = _build, + .process = _process, + .process_ietf_std_errors = _process_ietf_std_errors, + .create_attribute_enumerator = _create_attribute_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .encoding = chunk_clone(data), + .attributes = linked_list_create(), + .errors = linked_list_create(), + ); + + return &this->public; } diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h index c3ce829d5..80016fecd 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 Andreas Steffen + * Copyright (C) 2011-2012 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -46,13 +46,16 @@ struct pa_tnc_msg_t { * Add a PA-TNC attribute * * @param attr PA-TNC attribute to be addedd + * @return TRUE if attribute fit into message and was added */ - void (*add_attribute)(pa_tnc_msg_t *this, pa_tnc_attr_t* attr); + bool (*add_attribute)(pa_tnc_msg_t *this, pa_tnc_attr_t* attr); /** * Build the PA-TNC message + * + * @return TRUE if PA-TNC message was built successfully */ - void (*build)(pa_tnc_msg_t *this); + bool (*build)(pa_tnc_msg_t *this); /** * Process the PA-TNC message @@ -91,7 +94,7 @@ struct pa_tnc_msg_t { /** * Create an empty PA-TNC message */ -pa_tnc_msg_t* pa_tnc_msg_create(void); +pa_tnc_msg_t* pa_tnc_msg_create(size_t max_msg_len); /** * Create an unprocessed PA-TNC message from received data diff --git a/src/libimcv/plugins/imc_scanner/Makefile.in b/src/libimcv/plugins/imc_scanner/Makefile.in index 497d317d5..d06798170 100644 --- a/src/libimcv/plugins/imc_scanner/Makefile.in +++ b/src/libimcv/plugins/imc_scanner/Makefile.in @@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -81,7 +82,7 @@ imc_scanner_la_OBJECTS = $(am_imc_scanner_la_OBJECTS) imc_scanner_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imc_scanner_la_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f @@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ @@ -201,11 +203,14 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -222,11 +227,12 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ @@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ @@ -251,7 +258,6 @@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner.c b/src/libimcv/plugins/imc_scanner/imc_scanner.c index b24c39c3a..34c9359fe 100644 --- a/src/libimcv/plugins/imc_scanner/imc_scanner.c +++ b/src/libimcv/plugins/imc_scanner/imc_scanner.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -19,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> @@ -37,7 +38,7 @@ static const char imc_name[] = "Scanner"; #define IMC_SUBTYPE PA_SUBTYPE_ITA_SCANNER static imc_agent_t *imc_scanner; - + /** * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 */ @@ -84,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: @@ -123,7 +133,7 @@ static bool do_netstat(ietf_attr_port_filter_t *attr) enumerator_t *enumerator; bool allowed, found = FALSE; - DBG2(DBG_IMC, "%.*s", strlen(buf)-1, buf); + DBG2(DBG_IMC, "%.*s", (int)(strlen(buf)-1), buf); if (n++ < 2) { @@ -199,7 +209,7 @@ static bool do_netstat(ietf_attr_port_filter_t *attr) } } enumerator->destroy(enumerator); - + /* Skip the duplicate port entry */ if (found) { @@ -221,7 +231,7 @@ end: static TNC_Result send_message(TNC_ConnectionID connection_id) { - pa_tnc_msg_t *msg; + linked_list_t *attr_list; pa_tnc_attr_t *attr; ietf_attr_port_filter_t *attr_port_filter; TNC_Result result; @@ -234,12 +244,11 @@ static TNC_Result send_message(TNC_ConnectionID connection_id) attr->destroy(attr); return TNC_RESULT_FATAL; } - msg = pa_tnc_msg_create(); - msg->add_attribute(msg, attr); - msg->build(msg); + attr_list = linked_list_create(); + attr_list->insert_last(attr_list, attr); result = imc_scanner->send_message(imc_scanner, connection_id, FALSE, 0, - TNC_IMVID_ANY, msg->get_encoding(msg)); - msg->destroy(msg); + TNC_IMVID_ANY, attr_list); + attr_list->destroy(attr_list); return result; } @@ -268,8 +277,12 @@ 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; + TNC_UInt32 target_imc_id; bool fatal_error; if (!imc_scanner) @@ -284,7 +297,7 @@ static TNC_Result receive_message(TNC_IMCID imc_id, return TNC_RESULT_FATAL; } - /* parse received PA-TNC message and automatically handle any errors */ + /* parse received PA-TNC message and automatically handle any errors */ result = imc_scanner->receive_message(imc_scanner, state, msg, msg_vid, msg_subtype, src_imv_id, dst_imc_id, &pa_tnc_msg); @@ -293,17 +306,43 @@ static TNC_Result receive_message(TNC_IMCID imc_id, { return result; } + target_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? imc_id : dst_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, target_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, target_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 563105548..991b24a73 100644 --- a/src/libimcv/plugins/imc_scanner/imc_scanner_state.c +++ b/src/libimcv/plugins/imc_scanner/imc_scanner_state.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -14,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 +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; @@ -48,6 +56,10 @@ struct private_imc_scanner_state_t { */ bool has_excl; + /** + * Maximum PA-TNC message size for this TNCCS connection + */ + u_int32_t max_msg_len; }; METHOD(imc_state_t, get_connection_id, TNC_ConnectionID, @@ -75,12 +87,44 @@ METHOD(imc_state_t, set_flags, void, this->has_excl = has_excl; } +METHOD(imc_state_t, set_max_msg_len, void, + private_imc_scanner_state_t *this, u_int32_t max_msg_len) +{ + this->max_msg_len = max_msg_len; +} + +METHOD(imc_state_t, get_max_msg_len, u_int32_t, + private_imc_scanner_state_t *this) +{ + return this->max_msg_len; +} + METHOD(imc_state_t, change_state, void, private_imc_scanner_state_t *this, TNC_ConnectionState new_state) { 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) { @@ -101,11 +145,16 @@ imc_state_t *imc_scanner_state_create(TNC_ConnectionID connection_id) .has_long = _has_long, .has_excl = _has_excl, .set_flags = _set_flags, + .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/Makefile.in b/src/libimcv/plugins/imc_test/Makefile.in index b4e3f8ae0..8e37e7e9e 100644 --- a/src/libimcv/plugins/imc_test/Makefile.in +++ b/src/libimcv/plugins/imc_test/Makefile.in @@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -81,7 +82,7 @@ imc_test_la_OBJECTS = $(am_imc_test_la_OBJECTS) imc_test_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imc_test_la_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f @@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ @@ -201,11 +203,14 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -222,11 +227,12 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ @@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ @@ -251,7 +258,6 @@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/src/libimcv/plugins/imc_test/imc_test.c b/src/libimcv/plugins/imc_test/imc_test.c index fe005ed4a..ee8e5b206 100644 --- a/src/libimcv/plugins/imc_test/imc_test.c +++ b/src/libimcv/plugins/imc_test/imc_test.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -18,10 +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> @@ -73,9 +75,12 @@ 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; - int additional_ids; + void *pointer; + enumerator_t *enumerator; + int dummy_size, additional_ids; if (!imc_test) { @@ -88,9 +93,12 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, case TNC_CONNECTION_STATE_CREATE: command = lib->settings->get_str(lib->settings, "libimcv.plugins.imc-test.command", "none"); + dummy_size = lib->settings->get_int(lib->settings, + "libimcv.plugins.imc-test.dummy_size", 0); retry = lib->settings->get_bool(lib->settings, "libimcv.plugins.imc-test.retry", FALSE); - state = imc_test_state_create(connection_id, command, retry); + state = imc_test_state_create(connection_id, command, dummy_size, + retry); result = imc_test->create_state(imc_test, state); if (result != TNC_RESULT_SUCCESS) @@ -124,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: @@ -158,23 +186,30 @@ static TNC_Result send_message(imc_state_t *state, TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id) { imc_test_state_t *test_state; - pa_tnc_msg_t *msg; + linked_list_t *attr_list; pa_tnc_attr_t *attr; bool excl; TNC_ConnectionID connection_id; TNC_Result result; + attr_list = linked_list_create(); connection_id = state->get_connection_id(state); test_state = (imc_test_state_t*)state; + + if (test_state->get_dummy_size(test_state)) + { + attr = ita_attr_dummy_create(test_state->get_dummy_size(test_state)); + attr->set_noskip_flag(attr, TRUE); + attr_list->insert_last(attr_list, attr); + } attr = ita_attr_command_create(test_state->get_command(test_state)); attr->set_noskip_flag(attr, TRUE); - msg = pa_tnc_msg_create(); - msg->add_attribute(msg, attr); - msg->build(msg); + attr_list->insert_last(attr_list, attr); + excl = dst_imv_id != TNC_IMVID_ANY; result = imc_test->send_message(imc_test, connection_id, excl, src_imc_id, - dst_imv_id, msg->get_encoding(msg)); - msg->destroy(msg); + dst_imv_id, attr_list); + attr_list->destroy(attr_list); return result; } @@ -245,9 +280,11 @@ static TNC_Result receive_message(TNC_IMCID 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; + TNC_UInt32 target_imc_id; bool fatal_error = FALSE; if (!imc_test) @@ -271,6 +308,7 @@ static TNC_Result receive_message(TNC_IMCID imc_id, { return result; } + target_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? imc_id : dst_imc_id; /* preprocess any IETF standard error attributes */ fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg); @@ -279,22 +317,47 @@ static TNC_Result receive_message(TNC_IMCID imc_id, enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg); while (enumerator->enumerate(enumerator, &attr)) { - if (attr->get_vendor_id(attr) == PEN_ITA && - attr->get_type(attr) == ITA_ATTR_COMMAND) + attr_type = attr->get_type(attr); + + if (attr_type.vendor_id == PEN_IETF) { - ita_attr_command_t *ita_attr; - char *command; - - ita_attr = (ita_attr_command_t*)attr; - command = ita_attr->get_command(ita_attr); + ietf_attr_assess_result_t *ietf_attr; + + ietf_attr = (ietf_attr_assess_result_t*)attr; + state->set_result(state, target_imc_id, + ietf_attr->get_result(ietf_attr)); + } + else if (attr_type.vendor_id == PEN_ITA) + { + 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)); + } } } 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, target_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 2adfd7d64..e70eb1492 100644 --- a/src/libimcv/plugins/imc_test/imc_test_state.c +++ b/src/libimcv/plugins/imc_test/imc_test_state.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -14,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 +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; @@ -50,11 +59,21 @@ struct private_imc_test_state_t { bool has_excl; /** + * Maximum PA-TNC message size for this TNCCS connection + */ + u_int32_t max_msg_len; + + /** * Command to transmit to IMV */ char *command; /** + * Size of the dummy attribute value to transmit to IMV + */ + int dummy_size; + + /** * Is it the first handshake? */ bool first_handshake; @@ -66,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) { @@ -91,15 +118,86 @@ METHOD(imc_state_t, set_flags, void, this->has_excl = has_excl; } +METHOD(imc_state_t, set_max_msg_len, void, + private_imc_test_state_t *this, u_int32_t max_msg_len) +{ + this->max_msg_len = max_msg_len; +} + +METHOD(imc_state_t, get_max_msg_len, u_int32_t, + private_imc_test_state_t *this) +{ + return this->max_msg_len; +} + METHOD(imc_state_t, change_state, void, private_imc_test_state_t *this, TNC_ConnectionState new_state) { 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); } @@ -120,6 +218,13 @@ METHOD(imc_test_state_t, set_command, void, free(old_command); } +METHOD(imc_test_state_t, get_dummy_size, int, + private_imc_test_state_t *this) +{ + return this->dummy_size; +} + + METHOD(imc_test_state_t, is_first_handshake, bool, private_imc_test_state_t *this) { @@ -146,7 +251,7 @@ METHOD(imc_test_state_t, do_handshake_retry, bool, * Described in header. */ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id, - char *command, bool retry) + char *command, int dummy_size, bool retry) { private_imc_test_state_t *this; @@ -157,17 +262,24 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id, .has_long = _has_long, .has_excl = _has_excl, .set_flags = _set_flags, + .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, .set_command = _set_command, + .get_dummy_size = _get_dummy_size, .is_first_handshake = _is_first_handshake, .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, .first_handshake = TRUE, .handshake_retry = retry, ); @@ -175,4 +287,3 @@ imc_state_t *imc_test_state_create(TNC_ConnectionID connection_id, return &this->public.interface; } - diff --git a/src/libimcv/plugins/imc_test/imc_test_state.h b/src/libimcv/plugins/imc_test/imc_test_state.h index d9160df94..402fd14b3 100644 --- a/src/libimcv/plugins/imc_test/imc_test_state.h +++ b/src/libimcv/plugins/imc_test/imc_test_state.h @@ -52,6 +52,13 @@ struct imc_test_state_t { void (*set_command)(imc_test_state_t *this, char *command); /** + * get the value size of a dummy attribute to send to IMV + * + * @return size of the dummy attribute value to send to IMV + */ + int (*get_dummy_size)(imc_test_state_t *this); + + /** * Test and reset the first handshake flag * * @return TRUE if first handshake @@ -70,11 +77,12 @@ struct imc_test_state_t { /** * Create an imc_test_state_t instance * - * @param id connection ID - * @param command command to send to IMV - * @param retry TRUE if a handshake retry should be done + * @param id connection ID + * @param command command to send to IMV + * @param dummy_size size of the dummy attribute to send (only if > 0) + * @param retry TRUE if a handshake retry should be done */ imc_state_t* imc_test_state_create(TNC_ConnectionID id, char* command, - bool retry); + int dummy_size, bool retry); #endif /** IMC_TEST_STATE_H_ @}*/ diff --git a/src/libimcv/plugins/imv_scanner/Makefile.in b/src/libimcv/plugins/imv_scanner/Makefile.in index 63602c707..126a42c93 100644 --- a/src/libimcv/plugins/imv_scanner/Makefile.in +++ b/src/libimcv/plugins/imv_scanner/Makefile.in @@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -81,7 +82,7 @@ imv_scanner_la_OBJECTS = $(am_imv_scanner_la_OBJECTS) imv_scanner_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imv_scanner_la_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f @@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ @@ -201,11 +203,14 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -222,11 +227,12 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ @@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ @@ -251,7 +258,6 @@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner.c b/src/libimcv/plugins/imv_scanner/imv_scanner.c index dba3fd632..1352397c6 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -186,6 +187,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id, { pa_tnc_msg_t *pa_tnc_msg; pa_tnc_attr_t *attr; + pen_type_t type; imv_state_t *state; enumerator_t *enumerator; TNC_Result result; @@ -220,8 +222,9 @@ static TNC_Result receive_message(TNC_IMVID imv_id, enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg); while (enumerator->enumerate(enumerator, &attr)) { - if (attr->get_vendor_id(attr) == PEN_IETF && - attr->get_type(attr) == IETF_ATTR_PORT_FILTER) + type = attr->get_type(attr); + + if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PORT_FILTER) { ietf_attr_port_filter_t *attr_port_filter; enumerator_t *enumerator; @@ -305,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); } /** @@ -359,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_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c index 422cb980d..fecc84e70 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -50,6 +51,11 @@ struct private_imv_scanner_state_t { bool has_excl; /** + * Maximum PA-TNC message size for this TNCCS connection + */ + u_int32_t max_msg_len; + + /** * IMV action recommendation */ TNC_IMV_Action_Recommendation rec; @@ -115,6 +121,18 @@ METHOD(imv_state_t, set_flags, void, this->has_excl = has_excl; } +METHOD(imv_state_t, set_max_msg_len, void, + private_imv_scanner_state_t *this, u_int32_t max_msg_len) +{ + this->max_msg_len = max_msg_len; +} + +METHOD(imv_state_t, get_max_msg_len, u_int32_t, + private_imv_scanner_state_t *this) +{ + return this->max_msg_len; +} + METHOD(imv_state_t, change_state, void, private_imv_scanner_state_t *this, TNC_ConnectionState new_state) { @@ -223,6 +241,8 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID connection_id) .has_long = _has_long, .has_excl = _has_excl, .set_flags = _set_flags, + .set_max_msg_len = _set_max_msg_len, + .get_max_msg_len = _get_max_msg_len, .change_state = _change_state, .get_recommendation = _get_recommendation, .set_recommendation = _set_recommendation, diff --git a/src/libimcv/plugins/imv_test/Makefile.in b/src/libimcv/plugins/imv_test/Makefile.in index e51ad9afd..e395f8187 100644 --- a/src/libimcv/plugins/imv_test/Makefile.in +++ b/src/libimcv/plugins/imv_test/Makefile.in @@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -81,7 +82,7 @@ imv_test_la_OBJECTS = $(am_imv_test_la_OBJECTS) imv_test_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imv_test_la_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f @@ -107,6 +108,7 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ @@ -201,11 +203,14 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -222,11 +227,12 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ @@ -242,6 +248,7 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ @@ -251,7 +258,6 @@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/src/libimcv/plugins/imv_test/imv_test.c b/src/libimcv/plugins/imv_test/imv_test.c index 0afd81aec..5ea82e97c 100644 --- a/src/libimcv/plugins/imv_test/imv_test.c +++ b/src/libimcv/plugins/imv_test/imv_test.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -20,6 +21,7 @@ #include <ietf/ietf_attr_pa_tnc_error.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> @@ -101,12 +103,14 @@ static TNC_Result receive_message(TNC_IMVID imv_id, { pa_tnc_msg_t *pa_tnc_msg; pa_tnc_attr_t *attr; + pen_type_t attr_type; + linked_list_t *attr_list; imv_state_t *state; imv_test_state_t *test_state; enumerator_t *enumerator; TNC_Result result; int rounds; - bool fatal_error, retry = FALSE; + bool fatal_error, received_command = FALSE, retry = FALSE; if (!imv_test) { @@ -143,12 +147,18 @@ static TNC_Result receive_message(TNC_IMVID imv_id, enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg); while (enumerator->enumerate(enumerator, &attr)) { - if (attr->get_vendor_id(attr) == PEN_ITA && - attr->get_type(attr) == ITA_ATTR_COMMAND) + attr_type = attr->get_type(attr); + + if (attr_type.vendor_id != PEN_ITA) + { + continue; + } + if (attr_type.type == ITA_ATTR_COMMAND) { ita_attr_command_t *ita_attr; char *command; + received_command = TRUE; ita_attr = (ita_attr_command_t*)attr; command = ita_attr->get_command(ita_attr); @@ -181,7 +191,15 @@ static TNC_Result receive_message(TNC_IMVID imv_id, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); } - } + } + else if (attr_type.type == ITA_ATTR_DUMMY) + { + ita_attr_dummy_t *ita_attr; + + ita_attr = (ita_attr_dummy_t*)attr; + DBG1(DBG_IMV, "received dummy attribute value (%d bytes)", + ita_attr->get_size(ita_attr)); + } } enumerator->destroy(enumerator); pa_tnc_msg->destroy(pa_tnc_msg); @@ -191,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 ? */ @@ -205,18 +224,18 @@ static TNC_Result receive_message(TNC_IMVID imv_id, /* repeat the measurement ? */ if (test_state->another_round(test_state, src_imc_id)) { + attr_list = linked_list_create(); attr = ita_attr_command_create("repeat"); - pa_tnc_msg = pa_tnc_msg_create(); - pa_tnc_msg->add_attribute(pa_tnc_msg, attr); - pa_tnc_msg->build(pa_tnc_msg); + attr_list->insert_last(attr_list, attr); result = imv_test->send_message(imv_test, connection_id, TRUE, imv_id, - src_imc_id, pa_tnc_msg->get_encoding(pa_tnc_msg)); - pa_tnc_msg->destroy(pa_tnc_msg); + src_imc_id, attr_list); + attr_list->destroy(attr_list); return result; } - return imv_test->provide_recommendation(imv_test, connection_id); + return received_command ? imv_test->provide_recommendation(imv_test, + connection_id, src_imc_id) : TNC_RESULT_SUCCESS; } /** @@ -267,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/libimcv/plugins/imv_test/imv_test_state.c b/src/libimcv/plugins/imv_test/imv_test_state.c index 530090af7..67f22c062 100644 --- a/src/libimcv/plugins/imv_test/imv_test_state.c +++ b/src/libimcv/plugins/imv_test/imv_test_state.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-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 @@ -51,6 +52,11 @@ struct private_imv_test_state_t { bool has_excl; /** + * Maximum PA-TNC message size for this TNCCS connection + */ + u_int32_t max_msg_len; + + /** * IMV action recommendation */ TNC_IMV_Action_Recommendation rec; @@ -122,6 +128,18 @@ METHOD(imv_state_t, set_flags, void, this->has_excl = has_excl; } +METHOD(imv_state_t, set_max_msg_len, void, + private_imv_test_state_t *this, u_int32_t max_msg_len) +{ + this->max_msg_len = max_msg_len; +} + +METHOD(imv_state_t, get_max_msg_len, u_int32_t, + private_imv_test_state_t *this) +{ + return this->max_msg_len; +} + METHOD(imv_state_t, change_state, void, private_imv_test_state_t *this, TNC_ConnectionState new_state) { @@ -274,6 +292,8 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id) .has_long = _has_long, .has_excl = _has_excl, .set_flags = _set_flags, + .set_max_msg_len = _set_max_msg_len, + .get_max_msg_len = _get_max_msg_len, .change_state = _change_state, .get_recommendation = _get_recommendation, .set_recommendation = _set_recommendation, |