diff options
author | René Mayrhofer <rene@mayrhofer.eu.org> | 2011-03-05 09:20:09 +0100 |
---|---|---|
committer | René Mayrhofer <rene@mayrhofer.eu.org> | 2011-03-05 09:20:09 +0100 |
commit | 568905f488e63e28778f87ac0e38d845f45bae79 (patch) | |
tree | d9969a147e36413583ff4bc75542d34c955f8823 /src/libcharon/plugins/tnccs_20 | |
parent | f73fba54dc8b30c6482e1e8abf15bbf455592fcd (diff) | |
download | vyos-strongswan-568905f488e63e28778f87ac0e38d845f45bae79.tar.gz vyos-strongswan-568905f488e63e28778f87ac0e38d845f45bae79.zip |
Imported Upstream version 4.5.1
Diffstat (limited to 'src/libcharon/plugins/tnccs_20')
25 files changed, 4351 insertions, 20 deletions
diff --git a/src/libcharon/plugins/tnccs_20/Makefile.am b/src/libcharon/plugins/tnccs_20/Makefile.am index 3018121e3..d72fd3e34 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.am +++ b/src/libcharon/plugins/tnccs_20/Makefile.am @@ -1,21 +1,28 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ - `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic -libstrongswan_tnccs_20_la_LIBADD = -ltnc - if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnccs-20.la else plugin_LTLIBRARIES = libstrongswan-tnccs-20.la -libstrongswan_tnccs_20_la_LIBADD += $(top_builddir)/src/libtls/libtls.la +libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la endif libstrongswan_tnccs_20_la_SOURCES = \ - tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c + tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \ + batch/pb_tnc_batch.h batch/pb_tnc_batch.c \ + messages/pb_tnc_msg.h messages/pb_tnc_msg.c \ + messages/pb_experimental_msg.h messages/pb_experimental_msg.c \ + messages/pb_pa_msg.h messages/pb_pa_msg.c \ + messages/pb_assessment_result_msg.h messages/pb_assessment_result_msg.c \ + messages/pb_access_recommendation_msg.h messages/pb_access_recommendation_msg.c \ + messages/pb_error_msg.h messages/pb_error_msg.c \ + messages/pb_language_preference_msg.h messages/pb_language_preference_msg.c \ + messages/pb_reason_string_msg.h messages/pb_reason_string_msg.c \ + messages/pb_remediation_parameters_msg.h messages/pb_remediation_parameters_msg.c \ + state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version - diff --git a/src/libcharon/plugins/tnccs_20/Makefile.in b/src/libcharon/plugins/tnccs_20/Makefile.in index 6101f91df..9853be338 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.in +++ b/src/libcharon/plugins/tnccs_20/Makefile.in @@ -34,7 +34,6 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@MONOLITHIC_FALSE@am__append_1 = $(top_builddir)/src/libtls/libtls.la subdir = src/libcharon/plugins/tnccs_20 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -75,8 +74,14 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_tnccs_20_la_DEPENDENCIES = $(am__append_1) -am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo +@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la +am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo \ + pb_tnc_batch.lo pb_tnc_msg.lo pb_experimental_msg.lo \ + pb_pa_msg.lo pb_assessment_result_msg.lo \ + pb_access_recommendation_msg.lo pb_error_msg.lo \ + pb_language_preference_msg.lo pb_reason_string_msg.lo \ + pb_remediation_parameters_msg.lo pb_tnc_state_machine.lo libstrongswan_tnccs_20_la_OBJECTS = \ $(am_libstrongswan_tnccs_20_la_OBJECTS) libstrongswan_tnccs_20_la_LINK = $(LIBTOOL) --tag=CC \ @@ -223,9 +228,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +267,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -275,15 +280,25 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ - `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic -libstrongswan_tnccs_20_la_LIBADD = -ltnc $(am__append_1) @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-20.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-20.la +@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la libstrongswan_tnccs_20_la_SOURCES = \ - tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c + tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \ + batch/pb_tnc_batch.h batch/pb_tnc_batch.c \ + messages/pb_tnc_msg.h messages/pb_tnc_msg.c \ + messages/pb_experimental_msg.h messages/pb_experimental_msg.c \ + messages/pb_pa_msg.h messages/pb_pa_msg.c \ + messages/pb_assessment_result_msg.h messages/pb_assessment_result_msg.c \ + messages/pb_access_recommendation_msg.h messages/pb_access_recommendation_msg.c \ + messages/pb_error_msg.h messages/pb_error_msg.c \ + messages/pb_language_preference_msg.h messages/pb_language_preference_msg.c \ + messages/pb_reason_string_msg.h messages/pb_reason_string_msg.c \ + messages/pb_remediation_parameters_msg.h messages/pb_remediation_parameters_msg.c \ + state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version all: all-am @@ -369,6 +384,17 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_access_recommendation_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_assessment_result_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_error_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_experimental_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_language_preference_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_pa_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_reason_string_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_remediation_parameters_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_batch.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_state_machine.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20_plugin.Plo@am__quote@ @@ -393,6 +419,83 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +pb_tnc_batch.lo: batch/pb_tnc_batch.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_batch.lo -MD -MP -MF $(DEPDIR)/pb_tnc_batch.Tpo -c -o pb_tnc_batch.lo `test -f 'batch/pb_tnc_batch.c' || echo '$(srcdir)/'`batch/pb_tnc_batch.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_batch.Tpo $(DEPDIR)/pb_tnc_batch.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='batch/pb_tnc_batch.c' object='pb_tnc_batch.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 pb_tnc_batch.lo `test -f 'batch/pb_tnc_batch.c' || echo '$(srcdir)/'`batch/pb_tnc_batch.c + +pb_tnc_msg.lo: messages/pb_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 pb_tnc_msg.lo -MD -MP -MF $(DEPDIR)/pb_tnc_msg.Tpo -c -o pb_tnc_msg.lo `test -f 'messages/pb_tnc_msg.c' || echo '$(srcdir)/'`messages/pb_tnc_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_msg.Tpo $(DEPDIR)/pb_tnc_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_tnc_msg.c' object='pb_tnc_msg.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 pb_tnc_msg.lo `test -f 'messages/pb_tnc_msg.c' || echo '$(srcdir)/'`messages/pb_tnc_msg.c + +pb_experimental_msg.lo: messages/pb_experimental_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 pb_experimental_msg.lo -MD -MP -MF $(DEPDIR)/pb_experimental_msg.Tpo -c -o pb_experimental_msg.lo `test -f 'messages/pb_experimental_msg.c' || echo '$(srcdir)/'`messages/pb_experimental_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_experimental_msg.Tpo $(DEPDIR)/pb_experimental_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_experimental_msg.c' object='pb_experimental_msg.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 pb_experimental_msg.lo `test -f 'messages/pb_experimental_msg.c' || echo '$(srcdir)/'`messages/pb_experimental_msg.c + +pb_pa_msg.lo: messages/pb_pa_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 pb_pa_msg.lo -MD -MP -MF $(DEPDIR)/pb_pa_msg.Tpo -c -o pb_pa_msg.lo `test -f 'messages/pb_pa_msg.c' || echo '$(srcdir)/'`messages/pb_pa_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_pa_msg.Tpo $(DEPDIR)/pb_pa_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_pa_msg.c' object='pb_pa_msg.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 pb_pa_msg.lo `test -f 'messages/pb_pa_msg.c' || echo '$(srcdir)/'`messages/pb_pa_msg.c + +pb_assessment_result_msg.lo: messages/pb_assessment_result_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 pb_assessment_result_msg.lo -MD -MP -MF $(DEPDIR)/pb_assessment_result_msg.Tpo -c -o pb_assessment_result_msg.lo `test -f 'messages/pb_assessment_result_msg.c' || echo '$(srcdir)/'`messages/pb_assessment_result_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_assessment_result_msg.Tpo $(DEPDIR)/pb_assessment_result_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_assessment_result_msg.c' object='pb_assessment_result_msg.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 pb_assessment_result_msg.lo `test -f 'messages/pb_assessment_result_msg.c' || echo '$(srcdir)/'`messages/pb_assessment_result_msg.c + +pb_access_recommendation_msg.lo: messages/pb_access_recommendation_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 pb_access_recommendation_msg.lo -MD -MP -MF $(DEPDIR)/pb_access_recommendation_msg.Tpo -c -o pb_access_recommendation_msg.lo `test -f 'messages/pb_access_recommendation_msg.c' || echo '$(srcdir)/'`messages/pb_access_recommendation_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_access_recommendation_msg.Tpo $(DEPDIR)/pb_access_recommendation_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_access_recommendation_msg.c' object='pb_access_recommendation_msg.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 pb_access_recommendation_msg.lo `test -f 'messages/pb_access_recommendation_msg.c' || echo '$(srcdir)/'`messages/pb_access_recommendation_msg.c + +pb_error_msg.lo: messages/pb_error_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 pb_error_msg.lo -MD -MP -MF $(DEPDIR)/pb_error_msg.Tpo -c -o pb_error_msg.lo `test -f 'messages/pb_error_msg.c' || echo '$(srcdir)/'`messages/pb_error_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_error_msg.Tpo $(DEPDIR)/pb_error_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_error_msg.c' object='pb_error_msg.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 pb_error_msg.lo `test -f 'messages/pb_error_msg.c' || echo '$(srcdir)/'`messages/pb_error_msg.c + +pb_language_preference_msg.lo: messages/pb_language_preference_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 pb_language_preference_msg.lo -MD -MP -MF $(DEPDIR)/pb_language_preference_msg.Tpo -c -o pb_language_preference_msg.lo `test -f 'messages/pb_language_preference_msg.c' || echo '$(srcdir)/'`messages/pb_language_preference_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_language_preference_msg.Tpo $(DEPDIR)/pb_language_preference_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_language_preference_msg.c' object='pb_language_preference_msg.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 pb_language_preference_msg.lo `test -f 'messages/pb_language_preference_msg.c' || echo '$(srcdir)/'`messages/pb_language_preference_msg.c + +pb_reason_string_msg.lo: messages/pb_reason_string_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 pb_reason_string_msg.lo -MD -MP -MF $(DEPDIR)/pb_reason_string_msg.Tpo -c -o pb_reason_string_msg.lo `test -f 'messages/pb_reason_string_msg.c' || echo '$(srcdir)/'`messages/pb_reason_string_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_reason_string_msg.Tpo $(DEPDIR)/pb_reason_string_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_reason_string_msg.c' object='pb_reason_string_msg.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 pb_reason_string_msg.lo `test -f 'messages/pb_reason_string_msg.c' || echo '$(srcdir)/'`messages/pb_reason_string_msg.c + +pb_remediation_parameters_msg.lo: messages/pb_remediation_parameters_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 pb_remediation_parameters_msg.lo -MD -MP -MF $(DEPDIR)/pb_remediation_parameters_msg.Tpo -c -o pb_remediation_parameters_msg.lo `test -f 'messages/pb_remediation_parameters_msg.c' || echo '$(srcdir)/'`messages/pb_remediation_parameters_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_remediation_parameters_msg.Tpo $(DEPDIR)/pb_remediation_parameters_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_remediation_parameters_msg.c' object='pb_remediation_parameters_msg.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 pb_remediation_parameters_msg.lo `test -f 'messages/pb_remediation_parameters_msg.c' || echo '$(srcdir)/'`messages/pb_remediation_parameters_msg.c + +pb_tnc_state_machine.lo: state_machine/pb_tnc_state_machine.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_state_machine.lo -MD -MP -MF $(DEPDIR)/pb_tnc_state_machine.Tpo -c -o pb_tnc_state_machine.lo `test -f 'state_machine/pb_tnc_state_machine.c' || echo '$(srcdir)/'`state_machine/pb_tnc_state_machine.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_state_machine.Tpo $(DEPDIR)/pb_tnc_state_machine.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='state_machine/pb_tnc_state_machine.c' object='pb_tnc_state_machine.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 pb_tnc_state_machine.lo `test -f 'state_machine/pb_tnc_state_machine.c' || echo '$(srcdir)/'`state_machine/pb_tnc_state_machine.c + mostlyclean-libtool: -rm -f *.lo diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c new file mode 100644 index 000000000..3f38543ed --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2010 Sansar Choinyanbuu + * Copyright (C) 2010 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 "pb_tnc_batch.h" +#include "messages/pb_error_msg.h" +#include "state_machine/pb_tnc_state_machine.h" + +#include <debug.h> +#include <utils/linked_list.h> +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tnccs/tnccs.h> + +ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE, + "CDATA", + "SDATA", + "RESULT", + "CRETRY", + "SRETRY", + "CLOSE" +); + +typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t; + +/** + * PB-Batch Header (see section 4.1 of RFC 5793) + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Version |D| Reserved | B-Type| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Batch Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PB_TNC_BATCH_FLAG_NONE 0x00 +#define PB_TNC_BATCH_FLAG_D (1<<7) +#define PB_TNC_BATCH_HEADER_SIZE 8 + +/** + * PB-TNC Message (see section 4.2 of RFC 5793) + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | PB-TNC Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PB-TNC Message Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PB-TNC Message Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PB-TNC Message Value (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PB_TNC_FLAG_NONE 0x00 +#define PB_TNC_FLAG_NOSKIP (1<<7) +#define PB_TNC_HEADER_SIZE 12 + +#define PB_TNC_RESERVED_MSG_TYPE 0xffffffff + +/** + * Private data of a pb_tnc_batch_t object. + * + */ +struct private_pb_tnc_batch_t { + /** + * Public pb_pa_msg_t interface. + */ + pb_tnc_batch_t public; + + /** + * TNCC if TRUE, TNCS if FALSE + */ + bool is_server; + + /** + * PB-TNC Batch type + */ + pb_tnc_batch_type_t type; + + /** + * linked list of PB-TNC messages + */ + linked_list_t *messages; + + /** + * linked list of PB-TNC error messages + */ + linked_list_t *errors; + + /** + * Encoded message + */ + chunk_t encoding; + + /** + * Offset into encoding (used for error reporting) + */ + u_int32_t offset; +}; + +METHOD(pb_tnc_batch_t, get_type, pb_tnc_batch_type_t, + private_pb_tnc_batch_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_batch_t, get_encoding, chunk_t, + private_pb_tnc_batch_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_batch_t, add_msg, void, + private_pb_tnc_batch_t *this, pb_tnc_msg_t* msg) +{ + DBG2(DBG_TNC, "adding %N message", pb_tnc_msg_type_names, + msg->get_type(msg)); + this->messages->insert_last(this->messages, msg); +} + +METHOD(pb_tnc_batch_t, build, void, + private_pb_tnc_batch_t *this) +{ + u_int32_t batch_len, msg_len; + chunk_t msg_value; + enumerator_t *enumerator; + pb_tnc_msg_type_t msg_type; + pb_tnc_msg_t *msg; + tls_writer_t *writer; + + /* compute total PB-TNC batch size by summing over all messages */ + batch_len = PB_TNC_BATCH_HEADER_SIZE; + enumerator = this->messages->create_enumerator(this->messages); + while (enumerator->enumerate(enumerator, &msg)) + { + msg->build(msg); + msg_value = msg->get_encoding(msg); + batch_len += PB_TNC_HEADER_SIZE + msg_value.len; + } + enumerator->destroy(enumerator); + + /* build PB-TNC batch header */ + writer = tls_writer_create(batch_len); + writer->write_uint8 (writer, PB_TNC_VERSION); + writer->write_uint8 (writer, this->is_server ? + PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE); + writer->write_uint16(writer, this->type); + writer->write_uint32(writer, batch_len); + + /* build PB-TNC messages */ + enumerator = this->messages->create_enumerator(this->messages); + while (enumerator->enumerate(enumerator, &msg)) + { + u_int8_t flags = PB_TNC_FLAG_NONE; + + /* build PB-TNC message */ + msg_value = msg->get_encoding(msg); + msg_len = PB_TNC_HEADER_SIZE + msg_value.len; + msg_type = msg->get_type(msg); + if (pb_tnc_msg_infos[msg_type].has_noskip_flag) + { + flags |= PB_TNC_FLAG_NOSKIP; + } + writer->write_uint8 (writer, flags); + writer->write_uint24(writer, IETF_VENDOR_ID); + writer->write_uint32(writer, msg_type); + writer->write_uint32(writer, msg_len); + writer->write_data (writer, msg_value); + } + enumerator->destroy(enumerator); + + this->encoding = chunk_clone(writer->get_buf(writer)); + writer->destroy(writer); +} + +static status_t process_batch_header(private_pb_tnc_batch_t *this, + pb_tnc_state_machine_t *state_machine) +{ + tls_reader_t *reader; + pb_tnc_msg_t *msg; + pb_error_msg_t *err_msg; + u_int8_t version, flags, reserved, type; + u_int32_t batch_len; + bool directionality; + + if (this->encoding.len < PB_TNC_BATCH_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC batch header", + this->encoding.len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 0); + goto fatal; + } + + reader = tls_reader_create(this->encoding); + reader->read_uint8 (reader, &version); + reader->read_uint8 (reader, &flags); + reader->read_uint8 (reader, &reserved); + reader->read_uint8 (reader, &type); + reader->read_uint32(reader, &batch_len); + reader->destroy(reader); + + /* Version */ + if (version != PB_TNC_VERSION) + { + DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%01x", version); + msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID, + PB_ERROR_VERSION_NOT_SUPPORTED); + err_msg = (pb_error_msg_t*)msg; + err_msg->set_bad_version(err_msg, version); + goto fatal; + } + + /* Directionality */ + directionality = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE; + if (directionality == this->is_server) + { + DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s", + directionality ? "server" : "client"); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 1); + goto fatal; + } + + /* Batch Type */ + this->type = type & 0x0F; + if (this->type > PB_BATCH_ROOF) + { + DBG1(DBG_TNC, "unknown PB-TNC batch type: %d", this->type); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 3); + goto fatal; + } + + if (!state_machine->receive_batch(state_machine, this->type)) + { + DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N", + pb_tnc_batch_type_names, this->type); + msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID, + PB_ERROR_UNEXPECTED_BATCH_TYPE); + goto fatal; + } + + /* Batch Length */ + if (this->encoding.len != batch_len) + { + DBG1(DBG_TNC, "%u bytes of data is not equal to batch length of %u bytes", + this->encoding.len, batch_len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 4); + goto fatal; + } + + this->offset = PB_TNC_BATCH_HEADER_SIZE; + return SUCCESS; + +fatal: + this->errors->insert_last(this->errors, msg); + return FAILED; +} + +static status_t process_tnc_msg(private_pb_tnc_batch_t *this) +{ + tls_reader_t *reader; + pb_tnc_msg_t *pb_tnc_msg, *msg; + u_int8_t flags; + u_int32_t vendor_id, msg_type, msg_len, offset; + chunk_t data, msg_value; + bool noskip_flag; + status_t status; + + data = chunk_skip(this->encoding, this->offset); + + if (data.len < PB_TNC_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header", + data.len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + + reader = tls_reader_create(data); + reader->read_uint8 (reader, &flags); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &msg_type); + reader->read_uint32(reader, &msg_len); + reader->destroy(reader); + + noskip_flag = (flags & PB_TNC_FLAG_NOSKIP) != PB_TNC_FLAG_NONE; + + if (msg_len > data.len) + { + DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message", data.len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 8); + goto fatal; + } + + if (vendor_id == RESERVED_VENDOR_ID) + { + DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 1); + goto fatal; + + } + + if (msg_type == PB_TNC_RESERVED_MSG_TYPE) + { + DBG1(DBG_TNC, "PB-TNC message Type 0x%08x is reserved", + PB_TNC_RESERVED_MSG_TYPE); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 4); + goto fatal; + } + + + if (vendor_id != IETF_VENDOR_ID || msg_type > PB_MSG_ROOF) + { + if (msg_len < PB_TNC_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length", + msg_len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 8); + goto fatal; + } + + if (noskip_flag) + { + DBG1(DBG_TNC, "reject PB-TNC message (Vendor ID 0x%06x / " + "Type 0x%08x)", vendor_id, msg_type); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset); + goto fatal; + } + else + { + DBG1(DBG_TNC, "ignore PB-TNC message (Vendor ID 0x%06x / " + "Type 0x%08x)", vendor_id, msg_type); + this->offset += msg_len; + return SUCCESS; + } + } + else + { + if (pb_tnc_msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE && + pb_tnc_msg_infos[msg_type].has_noskip_flag != noskip_flag) + { + DBG1(DBG_TNC, "%N message must%s have NOSKIP flag set", + pb_tnc_msg_type_names, msg_type, + pb_tnc_msg_infos[msg_type].has_noskip_flag ? "" : " not"); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + + if (msg_len < pb_tnc_msg_infos[msg_type].min_size || + (pb_tnc_msg_infos[msg_type].exact_size && + msg_len != pb_tnc_msg_infos[msg_type].min_size)) + { + DBG1(DBG_TNC, "%N message length must be %s %u bytes but is %u bytes", + pb_tnc_msg_type_names, msg_type, + pb_tnc_msg_infos[msg_type].exact_size ? "exactly" : "at least", + pb_tnc_msg_infos[msg_type].min_size, msg_len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + } + + if (pb_tnc_msg_infos[msg_type].in_result_batch && + this->type != PB_BATCH_RESULT) + { + if (this->is_server) + { + DBG1(DBG_TNC,"reject %N message received from a PB-TNC client", + pb_tnc_msg_type_names, msg_type); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + else + { + DBG1(DBG_TNC,"ignore %N message not received within RESULT batch", + pb_tnc_msg_type_names, msg_type); + this->offset += msg_len; + return SUCCESS; + } + } + + DBG2(DBG_TNC, "processing %N message (%u bytes)", pb_tnc_msg_type_names, + msg_type, msg_len); + data.len = msg_len; + msg_value = chunk_skip(data, PB_TNC_HEADER_SIZE); + pb_tnc_msg = pb_tnc_msg_create_from_data(msg_type, msg_value); + + status = pb_tnc_msg->process(pb_tnc_msg, &offset); + if (status == FAILED || status == VERIFY_ERROR) + { + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + this->errors->insert_last(this->errors, msg); + } + if (status == FAILED) + { + pb_tnc_msg->destroy(pb_tnc_msg); + return FAILED; + } + this->messages->insert_last(this->messages, pb_tnc_msg); + this->offset += msg_len; + return status; + +fatal: + this->errors->insert_last(this->errors, msg); + return FAILED; +} + +METHOD(pb_tnc_batch_t, process, status_t, + private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine) +{ + status_t status; + + status = process_batch_header(this, state_machine); + if (status != SUCCESS) + { + return FAILED; + } + DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names, + this->type); + while (this->offset < this->encoding.len) + { + switch (process_tnc_msg(this)) + { + case FAILED: + return FAILED; + case VERIFY_ERROR: + status = VERIFY_ERROR; + break; + case SUCCESS: + default: + break; + } + } + return status; +} + +METHOD(pb_tnc_batch_t, create_msg_enumerator, enumerator_t*, + private_pb_tnc_batch_t *this) +{ + return this->messages->create_enumerator(this->messages); +} + +METHOD(pb_tnc_batch_t, create_error_enumerator, enumerator_t*, + private_pb_tnc_batch_t *this) +{ + return this->errors->create_enumerator(this->errors); +} + +METHOD(pb_tnc_batch_t, destroy, void, + private_pb_tnc_batch_t *this) +{ + this->messages->destroy_offset(this->messages, + offsetof(pb_tnc_msg_t, destroy)); + this->errors->destroy_offset(this->errors, + offsetof(pb_tnc_msg_t, destroy)); + free(this->encoding.ptr); + free(this); +} + +/** + * See header + */ +pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type) +{ + private_pb_tnc_batch_t *this; + + INIT(this, + .public = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .add_msg = _add_msg, + .build = _build, + .process = _process, + .create_msg_enumerator = _create_msg_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .is_server = is_server, + .type = type, + .messages = linked_list_create(), + .errors = linked_list_create(), + ); + + DBG2(DBG_TNC, "creating PB-TNC %N batch", pb_tnc_batch_type_names, type); + + return &this->public; +} + +/** + * See header + */ +pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data) +{ + private_pb_tnc_batch_t *this; + + INIT(this, + .public = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .add_msg = _add_msg, + .build = _build, + .process = _process, + .create_msg_enumerator = _create_msg_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .is_server = is_server, + .messages = linked_list_create(), + .errors = linked_list_create(), + .encoding = chunk_clone(data), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h new file mode 100644 index 000000000..17e5fff4c --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2010 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 pb_tnc_batch pb_tnc_batch + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_TNC_BATCH_H_ +#define PB_TNC_BATCH_H_ + +typedef enum pb_tnc_batch_type_t pb_tnc_batch_type_t; +typedef struct pb_tnc_batch_t pb_tnc_batch_t; + +#include "messages/pb_tnc_msg.h" +#include "state_machine/pb_tnc_state_machine.h" + +#include <library.h> + +/** + * PB-TNC Batch Types as defined in section 4.1 of RFC 5793 + */ +enum pb_tnc_batch_type_t { + PB_BATCH_CDATA = 1, + PB_BATCH_SDATA = 2, + PB_BATCH_RESULT = 3, + PB_BATCH_CRETRY = 4, + PB_BATCH_SRETRY = 5, + PB_BATCH_CLOSE = 6, + PB_BATCH_ROOF = 6 +}; + +/** + * enum name for pb_tnc_batch_type_t. + */ +extern enum_name_t *pb_tnc_batch_type_names; + +/** + * Interface for all PB-TNC Batch Types. + */ +struct pb_tnc_batch_t { + + /** + * Get the PB-TNC Message Type + * + * @return PB-TNC batch type + */ + pb_tnc_batch_type_t (*get_type)(pb_tnc_batch_t *this); + + /** + * Get the encoding of the PB-TNC Batch + * + * @return encoded PB-TNC batch + */ + chunk_t (*get_encoding)(pb_tnc_batch_t *this); + + /** + * Add a PB-TNC Message + * + * @param msg PB-TNC message to be addedd + */ + void (*add_msg)(pb_tnc_batch_t *this, pb_tnc_msg_t* msg); + + /** + * Build the PB-TNC Batch + */ + void (*build)(pb_tnc_batch_t *this); + + /** + * Process the PB-TNC Batch + * + * @param PB-TNC state machine + * @return return processing status + */ + status_t (*process)(pb_tnc_batch_t *this, + pb_tnc_state_machine_t *state_machine); + + /** + * Enumerates over all PB-TNC Messages + * + * @return return message enumerator + */ + enumerator_t* (*create_msg_enumerator)(pb_tnc_batch_t *this); + + /** + * Enumerates over all parsing errors + * + * @return return error enumerator + */ + enumerator_t* (*create_error_enumerator)(pb_tnc_batch_t *this); + + /** + * Destroys a pb_tnc_batch_t object. + */ + void (*destroy)(pb_tnc_batch_t *this); +}; + +/** + * Create an empty PB-TNC Batch of a given type + * + * @param is_server TRUE if server, FALSE if client + * @param type PB-TNC batch type + */ +pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type); + +/** + * Create an unprocessed PB-TNC Batch from data + * + * @param is_server TRUE if server, FALSE if client + * @param data encoded PB-TNC batch + */ +pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data); + +#endif /** PB_TNC_BATCH_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c new file mode 100644 index 000000000..41b9e31f6 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_access_recommendation_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +ENUM(pb_access_recommendation_code_names, PB_REC_ACCESS_ALLOWED, PB_REC_QUARANTINED, + "Access Allowed", + "Access Denied", + "Quarantined" +); + +typedef struct private_pb_access_recommendation_msg_t private_pb_access_recommendation_msg_t; + +/** + * PB-Access-Recommendation message (see section 4.7 of RFC 5793) + * + * 0 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 | Access Recommendation Code | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define ACCESS_RECOMMENDATION_RESERVED 0x0000 +#define ACCESS_RECOMMENDATION_MSG_SIZE 4 +/** + * Private data of a pb_access_recommendation_msg_t object. + * + */ +struct private_pb_access_recommendation_msg_t { + /** + * Public pb_access_recommendation_msg_t interface. + */ + pb_access_recommendation_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Access recommendation code + */ + u_int16_t recommendation; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_access_recommendation_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_access_recommendation_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_access_recommendation_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(ACCESS_RECOMMENDATION_MSG_SIZE); + writer->write_uint16(writer, ACCESS_RECOMMENDATION_RESERVED); + writer->write_uint16(writer, this->recommendation); + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_access_recommendation_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + u_int16_t reserved; + + /* process message */ + reader = tls_reader_create(this->encoding); + reader->read_uint16(reader, &reserved); + reader->read_uint16(reader, &this->recommendation); + reader->destroy(reader); + + if (this->recommendation < PB_REC_ACCESS_ALLOWED || + this->recommendation > PB_REC_QUARANTINED) + { + DBG1(DBG_TNC, "invalid access recommendation code (%u)", + this->recommendation); + *offset = 2; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_access_recommendation_msg_t *this) +{ + free(this->encoding.ptr); + free(this); +} + +METHOD(pb_access_recommendation_msg_t, get_access_recommendation, u_int16_t, + private_pb_access_recommendation_msg_t *this) +{ + return this->recommendation; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_access_recommendation_msg_create_from_data(chunk_t data) +{ + private_pb_access_recommendation_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_access_recommendation = _get_access_recommendation, + }, + .type = PB_MSG_ACCESS_RECOMMENDATION, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_access_recommendation_msg_create(u_int16_t recommendation) +{ + private_pb_access_recommendation_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_access_recommendation = _get_access_recommendation, + }, + .type = PB_MSG_ACCESS_RECOMMENDATION, + .recommendation = recommendation, + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h new file mode 100644 index 000000000..01b83cfd7 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 pb_access_recommendation_msg pb_access_recommendation_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_ACCESS_RECOMMENDATION_MSG_H_ +#define PB_ACCESS_RECOMMENDATION_MSG_H_ + +typedef enum pb_access_recommendation_code_t pb_access_recommendation_code_t; +typedef struct pb_access_recommendation_msg_t pb_access_recommendation_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PB Access Recommendation Codes as defined in section 4.7 of RFC 5793 + */ +enum pb_access_recommendation_code_t { + PB_REC_ACCESS_ALLOWED = 1, + PB_REC_ACCESS_DENIED = 2, + PB_REC_QUARANTINED = 3, +}; + +/** + * enum name for pb_access_recommendation_code_t. + */ +extern enum_name_t *pb_access_recommendation_code_names; + + +/** + * Class representing the PB-Access-Recommendation message type. + */ +struct pb_access_recommendation_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PB Access Recommendation + * + * @return PB Access Recommendation + */ + u_int16_t (*get_access_recommendation)(pb_access_recommendation_msg_t *this); +}; + +/** + * Create a PB-Access-Recommendation message from parameters + * + * @param recommendation Access Recommendation code + */ +pb_tnc_msg_t* pb_access_recommendation_msg_create(u_int16_t recommendation); + +/** + * Create an unprocessed PB-Access-Recommendation message from raw data + * + * @param data PB-Access-Recommendation message data + */ +pb_tnc_msg_t* pb_access_recommendation_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c new file mode 100644 index 000000000..c91e54176 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_assessment_result_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tncifimv.h> +#include <debug.h> + +typedef struct private_pb_assessment_result_msg_t private_pb_assessment_result_msg_t; + +/** + * PB-Assessment-Result message (see section 4.6 of RFC 5793) + * + * 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 ASSESSMENT_RESULT_MSG_SIZE 4 + +/** + * Private data of a pb_assessment_result_msg_t object. + * + */ +struct private_pb_assessment_result_msg_t { + /** + * Public pb_assessment_result_msg_t interface. + */ + pb_assessment_result_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Assessment result code + */ + u_int32_t assessment_result; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_assessment_result_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_assessment_result_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_assessment_result_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(ASSESSMENT_RESULT_MSG_SIZE); + writer->write_uint32(writer, this->assessment_result); + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_assessment_result_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + + /* process message */ + reader = tls_reader_create(this->encoding); + reader->read_uint32(reader, &this->assessment_result); + reader->destroy(reader); + + if (this->assessment_result < TNC_IMV_EVALUATION_RESULT_COMPLIANT || + this->assessment_result > TNC_IMV_EVALUATION_RESULT_DONT_KNOW) + { + DBG1(DBG_TNC, "invalid assessment result (%u)", + this->assessment_result); + *offset = 0; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_assessment_result_msg_t *this) +{ + free(this->encoding.ptr); + free(this); +} + +METHOD(pb_assessment_result_msg_t, get_assessment_result, u_int32_t, + private_pb_assessment_result_msg_t *this) +{ + return this->assessment_result; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_assessment_result_msg_create_from_data(chunk_t data) +{ + private_pb_assessment_result_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_assessment_result = _get_assessment_result, + }, + .type = PB_MSG_ASSESSMENT_RESULT, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_assessment_result_msg_create(u_int32_t assessment_result) +{ + private_pb_assessment_result_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_assessment_result = _get_assessment_result, + }, + .type = PB_MSG_ASSESSMENT_RESULT, + .assessment_result = assessment_result, + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h new file mode 100644 index 000000000..d2b005114 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 pb_assessment_result_msg pb_assessment_result_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_ASSESSMENT_RESULT_MSG_H_ +#define PB_ASSESSMENT_RESULT_MSG_H_ + +typedef struct pb_assessment_result_msg_t pb_assessment_result_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Assessment-Result message type. + */ +struct pb_assessment_result_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PB Assessment result + * + * @return PB Assessment result + */ + u_int32_t (*get_assessment_result)(pb_assessment_result_msg_t *this); +}; + +/** + * Create a PB-Assessment-Result message from parameters + * + * @param assessment_result Assessment result code + */ +pb_tnc_msg_t* pb_assessment_result_msg_create(u_int32_t assessment_result); + +/** + * Create an unprocessed PB-Assessment-Result message from raw data + * + * @param data PB-Assessment-Result message data + */ +pb_tnc_msg_t* pb_assessment_result_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c new file mode 100644 index 000000000..e1755c512 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_error_msg.h" + +#include <debug.h> +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tnccs/tnccs.h> + +ENUM(pb_tnc_error_code_names, PB_ERROR_UNEXPECTED_BATCH_TYPE, + PB_ERROR_VERSION_NOT_SUPPORTED, + "Unexpected Batch Type", + "Invalid Parameter", + "Local Error", + "Unsupported Mandatory Message", + "Version Not Supported" +); + +typedef struct private_pb_error_msg_t private_pb_error_msg_t; + +/** + * PB-Error message (see section 4.9 of RFC 5793) + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | Error Code Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Error Code | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Error Parameters (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define ERROR_FLAG_NONE 0x00 +#define ERROR_FLAG_FATAL (1<<7) +#define ERROR_RESERVED 0x0000 +#define ERROR_HEADER_SIZE 8 + +/** + * Private data of a pb_error_msg_t object. + * + */ +struct private_pb_error_msg_t { + /** + * Public pb_error_msg_t interface. + */ + pb_error_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Fatal flag + */ + bool fatal; + + /** + * PB Error Code Vendor ID + */ + u_int32_t vendor_id; + + /** + * PB Error Code + */ + u_int16_t error_code; + + /** + * PB Error Offset + */ + u_int32_t error_offset; + + /** + * Bad PB-TNC version received + */ + u_int8_t bad_version; + + /** + * Encoded message + */ + chunk_t encoding; + + /** + * reference count + */ + refcount_t ref; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_error_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_error_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_error_msg_t *this) +{ + tls_writer_t *writer; + + /* build message header */ + writer = tls_writer_create(ERROR_HEADER_SIZE); + writer->write_uint8 (writer, this->fatal ? + ERROR_FLAG_FATAL : ERROR_FLAG_NONE); + writer->write_uint24(writer, this->vendor_id); + writer->write_uint16(writer, this->error_code); + writer->write_uint16(writer, ERROR_RESERVED); + + /* build message body */ + if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED) + { + /* Bad version */ + writer->write_uint8(writer, this->bad_version); + writer->write_uint8(writer, PB_TNC_VERSION); /* Max version */ + writer->write_uint8(writer, PB_TNC_VERSION); /* Min version */ + writer->write_uint8(writer, 0x00); /* Reserved */ + } + else + { + /* Error Offset */ + writer->write_uint32(writer, this->error_offset); + } + + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_error_msg_t *this, u_int32_t *offset) +{ + u_int8_t flags, max_version, min_version; + u_int16_t reserved; + tls_reader_t *reader; + + if (this->encoding.len < ERROR_HEADER_SIZE) + { + DBG1(DBG_TNC,"%N message is shorter than header size of %u bytes", + pb_tnc_msg_type_names, PB_MSG_ERROR, ERROR_HEADER_SIZE); + return FAILED; + } + + /* process message header */ + reader = tls_reader_create(this->encoding); + reader->read_uint8 (reader, &flags); + reader->read_uint24(reader, &this->vendor_id); + reader->read_uint16(reader, &this->error_code); + reader->read_uint16(reader, &reserved); + this->fatal = (flags & ERROR_FLAG_FATAL) != ERROR_FLAG_NONE; + + if (this->vendor_id == IETF_VENDOR_ID && reader->remaining(reader) == 4) + { + if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED) + { + reader->read_uint8(reader, &this->bad_version); + reader->read_uint8(reader, &max_version); + reader->read_uint8(reader, &min_version); + } + else + { + reader->read_uint32(reader, &this->error_offset); + } + } + reader->destroy(reader); + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, get_ref, pb_tnc_msg_t*, + private_pb_error_msg_t *this) +{ + ref_get(&this->ref); + return &this->public.pb_interface; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_error_msg_t *this) +{ + if (ref_put(&this->ref)) + { + free(this->encoding.ptr); + free(this); + } +} + +METHOD(pb_error_msg_t, get_fatal_flag, bool, + private_pb_error_msg_t *this) +{ + return this->fatal; +} + +METHOD(pb_error_msg_t, get_vendor_id, u_int32_t, + private_pb_error_msg_t *this) +{ + return this->vendor_id; +} + +METHOD(pb_error_msg_t, get_error_code, u_int16_t, + private_pb_error_msg_t *this) +{ + return this->error_code; +} + +METHOD(pb_error_msg_t, get_offset, u_int32_t, + private_pb_error_msg_t *this) +{ + return this->error_offset; +} + +METHOD(pb_error_msg_t, get_bad_version, u_int8_t, + private_pb_error_msg_t *this) +{ + return this->bad_version; +} + +METHOD(pb_error_msg_t, set_bad_version, void, + private_pb_error_msg_t *this, u_int8_t version) +{ + this->bad_version = version; +} + +/** + * See header + */ +pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code) +{ + private_pb_error_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_fatal_flag = _get_fatal_flag, + .get_vendor_id = _get_vendor_id, + .get_error_code = _get_error_code, + .get_offset = _get_offset, + .get_bad_version = _get_bad_version, + .set_bad_version = _set_bad_version, + }, + .type = PB_MSG_ERROR, + .ref = 1, + .fatal = fatal, + .vendor_id = vendor_id, + .error_code = error_code, + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code, + u_int32_t error_offset) +{ + private_pb_error_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_fatal_flag = _get_fatal_flag, + .get_vendor_id = _get_vendor_id, + .get_error_code = _get_error_code, + .get_offset = _get_offset, + .get_bad_version = _get_bad_version, + .set_bad_version = _set_bad_version, + }, + .type = PB_MSG_ERROR, + .ref = 1, + .fatal = fatal, + .vendor_id = vendor_id, + .error_code = error_code, + .error_offset = error_offset, + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_error_msg_create_from_data(chunk_t data) +{ + private_pb_error_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_fatal_flag = _get_fatal_flag, + .get_vendor_id = _get_vendor_id, + .get_error_code = _get_error_code, + .get_offset = _get_offset, + .get_bad_version = _get_bad_version, + .set_bad_version = _set_bad_version, + }, + .type = PB_MSG_ERROR, + .ref = 1, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h new file mode 100644 index 000000000..8b92742b5 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 pb_error_msg pb_error_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_ERROR_MSG_H_ +#define PB_ERROR_MSG_H_ + +typedef enum pb_tnc_error_code_t pb_tnc_error_code_t; +typedef struct pb_error_msg_t pb_error_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PB-TNC Error Codes as defined in section 4.9.1 of RFC 5793 + */ +enum pb_tnc_error_code_t { + PB_ERROR_UNEXPECTED_BATCH_TYPE = 0, + PB_ERROR_INVALID_PARAMETER = 1, + PB_ERROR_LOCAL_ERROR = 2, + PB_ERROR_UNSUPPORTED_MANDATORY_MSG = 3, + PB_ERROR_VERSION_NOT_SUPPORTED = 4 +}; + +/** + * enum name for pb_tnc_error_code_t. + */ +extern enum_name_t *pb_tnc_error_code_names; + +/** + * Class representing the PB-Error message type. + */ +struct pb_error_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get the fatal flag + * + * @return fatal flag + */ + bool (*get_fatal_flag)(pb_error_msg_t *this); + + /** + * Get PB Error code Vendor ID + * + * @return PB Error Code Vendor ID + */ + u_int32_t (*get_vendor_id)(pb_error_msg_t *this); + + /** + * Get PB Error Code + * + * @return PB Error Code + */ + u_int16_t (*get_error_code)(pb_error_msg_t *this); + + /** + * Get the PB Error Offset + * + * @return PB Error Offset + */ + u_int32_t (*get_offset)(pb_error_msg_t *this); + + /** + * Get the PB Bad Version + * + * @return PB Bad Version + */ + u_int8_t (*get_bad_version)(pb_error_msg_t *this); + + /** + * Set the PB Bad Version + * + * @param version PB Bad Version + */ + void (*set_bad_version)(pb_error_msg_t *this, u_int8_t version); +}; + +/** + * Create a PB-Error message from parameters + * + * @param fatal fatal flag + * @param vendor_id Error Code Vendor ID + * @param error_code Error Code + */ +pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code); + +/** + * Create a PB-Error message from parameters with offset field + * + * @param fatal fatal flag + * @param vendor_id Error Code Vendor ID + * @param error_code Error Code + * @param error_offset Error Offset + */ +pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code, + u_int32_t error_offset); + +/** + * Create an unprocessed PB-Error message from raw data + * + * @param data PB-Error message data + */ +pb_tnc_msg_t* pb_error_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c new file mode 100644 index 000000000..7dfba136f --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2010 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 "pb_experimental_msg.h" + +typedef struct private_pb_experimental_msg_t private_pb_experimental_msg_t; + +/** + * Private data of a pb_experimental_msg_t object. + * + */ +struct private_pb_experimental_msg_t { + /** + * Public pb_experimental_msg_t interface. + */ + pb_experimental_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_experimental_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_experimental_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_experimental_msg_t *this) +{ + /* nothing to do since message contents equal encoding */ +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_experimental_msg_t *this, u_int32_t *offset) +{ + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_experimental_msg_t *this) +{ + free(this->encoding.ptr); + free(this); +} + +/** + * See header + */ +pb_tnc_msg_t *pb_experimental_msg_create_from_data(chunk_t data) +{ + private_pb_experimental_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + }, + .type = PB_MSG_EXPERIMENTAL, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_experimental_msg_create(chunk_t body) +{ + return pb_experimental_msg_create_from_data(body); +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h new file mode 100644 index 000000000..b1cc4f46e --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 pb_experimental_msg pb_experimental_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_EXPERIMENTAL_MSG_H_ +#define PB_EXPERIMENTAL_MSG_H_ + +typedef struct pb_experimental_msg_t pb_experimental_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Experimental message type. + */ +struct pb_experimental_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; +}; + +/** + * Create a PB-Experimental message from parameters + * + * @param body message body + */ +pb_tnc_msg_t* pb_experimental_msg_create(chunk_t body); + +/** + * Create an unprocessed PB-Experimental message from raw data + * + * @param data PB-Experimental message data + */ +pb_tnc_msg_t* pb_experimental_msg_create_from_data(chunk_t data); + +#endif /** PB_EXPERIMENTAL_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c new file mode 100644 index 000000000..9a94edf30 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_language_preference_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +typedef struct private_pb_language_preference_msg_t private_pb_language_preference_msg_t; + +/** + * PB-Language-Preference message (see section 4.10 of RFC 5793) + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Language Preference (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PB_LANG_PREFIX "Accept-Language: " +#define PB_LANG_PREFIX_LEN strlen(PB_LANG_PREFIX) + +/** + * Private data of a pb_language_preference_msg_t object. + * + */ +struct private_pb_language_preference_msg_t { + /** + * Public pb_access_recommendation_msg_t interface. + */ + pb_language_preference_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Language preference + */ + chunk_t language_preference; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_language_preference_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_language_preference_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_language_preference_msg_t *this) +{ + this->encoding = chunk_cat("cc", + chunk_create(PB_LANG_PREFIX, PB_LANG_PREFIX_LEN), + this->language_preference); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_language_preference_msg_t *this, u_int32_t *offset) +{ + chunk_t lang; + + if (this->encoding.len >= PB_LANG_PREFIX_LEN && + memeq(this->encoding.ptr, PB_LANG_PREFIX, PB_LANG_PREFIX_LEN)) + { + lang = chunk_skip(this->encoding, PB_LANG_PREFIX_LEN); + this->language_preference = lang.len ? chunk_clone(lang) : chunk_empty; + } + else + { + DBG1(DBG_TNC, "language preference must be preceded by '%s'", + PB_LANG_PREFIX); + *offset = 0; + return FAILED; + } + + if (this->language_preference.len && + this->language_preference.ptr[this->language_preference.len-1] == '\0') + { + DBG1(DBG_TNC, "language preference must not be null terminated"); + *offset = PB_LANG_PREFIX_LEN + this->language_preference.len - 1; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_language_preference_msg_t *this) +{ + free(this->encoding.ptr); + free(this->language_preference.ptr); + free(this); +} + +METHOD(pb_language_preference_msg_t, get_language_preference, chunk_t, + private_pb_language_preference_msg_t *this) +{ + return this->language_preference; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_language_preference_msg_create_from_data(chunk_t data) +{ + private_pb_language_preference_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_language_preference = _get_language_preference, + }, + .type = PB_MSG_LANGUAGE_PREFERENCE, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_language_preference_msg_create(chunk_t language_preference) +{ + private_pb_language_preference_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_language_preference = _get_language_preference, + }, + .type = PB_MSG_LANGUAGE_PREFERENCE, + .language_preference = chunk_clone(language_preference), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h new file mode 100644 index 000000000..17106f6fa --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 pb_language_preference_msg pb_language_preference_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_LANGUAGE_PREFERENCE_MSG_H_ +#define PB_LANGUAGE_PREFERENCE_MSG_H_ + +typedef struct pb_language_preference_msg_t pb_language_preference_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Language-Preference message type. + */ +struct pb_language_preference_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PB Language Preference + * + * @return Language preference + */ + chunk_t (*get_language_preference)(pb_language_preference_msg_t *this); +}; + +/** + * Create a PB-Language-Preference message from parameters + * + * @param language_preference Preferred language(s) + */ +pb_tnc_msg_t* pb_language_preference_msg_create(chunk_t language_preference); + +/** + * Create an unprocessed PB-Language-Preference message from raw data + * + * @param data PB-Language-Preference message data + */ +pb_tnc_msg_t* pb_language_preference_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c new file mode 100644 index 000000000..8315bfb76 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2010 Sansar Choinyanbuu + * Copyright (C) 2010 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 "pb_pa_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tnccs/tnccs.h> +#include <debug.h> + +ENUM(pa_tnc_subtype_names, PA_SUBTYPE_TESTING, PA_SUBTYPE_NEA_CLIENT, + "Testing", + "Operating System", + "Anti-Virus", + "Anti-Spyware", + "Anti-Malware", + "Firewall", + "IDPS", + "VPN", + "NEA Client" +); + +typedef struct private_pb_pa_msg_t private_pb_pa_msg_t; + +/** + * PB-PA message + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | PA Message Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA Subtype | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Posture Collector Identifier | Posture Validator Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA Message Body (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PA_FLAG_NONE 0x00 +#define PA_FLAG_EXCL (1<<7) +#define PA_RESERVED_SUBTYPE 0xffffffff + + +/** + * Private data of a pb_pa_msg_t object. + * + */ +struct private_pb_pa_msg_t { + /** + * Public pb_pa_msg_t interface. + */ + pb_pa_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Exclusive flag + */ + bool excl; + + /** + * PA Message Vendor ID + */ + u_int32_t vendor_id; + + /** + * PA Subtype + */ + u_int32_t subtype; + + /** + * Posture Validator Identifier + */ + u_int16_t collector_id; + + /** + * Posture Validator Identifier + */ + u_int16_t validator_id; + + /** + * PA Message Body + */ + chunk_t msg_body; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_pa_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_pa_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_pa_msg_t *this) +{ + chunk_t msg_header; + tls_writer_t *writer; + + /* build message header */ + writer = tls_writer_create(64); + writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE); + writer->write_uint24(writer, this->vendor_id); + writer->write_uint32(writer, this->subtype); + writer->write_uint16(writer, this->collector_id); + writer->write_uint16(writer, this->validator_id); + msg_header = writer->get_buf(writer); + + /* create encoding by concatenating message header and message body */ + free(this->encoding.ptr); + this->encoding = chunk_cat("cc", msg_header, this->msg_body); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_pa_msg_t *this, u_int32_t *offset) +{ + u_int8_t flags; + size_t msg_body_len; + tls_reader_t *reader; + + /* process message header */ + reader = tls_reader_create(this->encoding); + reader->read_uint8 (reader, &flags); + reader->read_uint24(reader, &this->vendor_id); + reader->read_uint32(reader, &this->subtype); + reader->read_uint16(reader, &this->collector_id); + reader->read_uint16(reader, &this->validator_id); + this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE); + + /* process message body */ + msg_body_len = reader->remaining(reader); + if (msg_body_len) + { + reader->read_data(reader, msg_body_len, &this->msg_body); + this->msg_body = chunk_clone(this->msg_body); + } + reader->destroy(reader); + + if (this->vendor_id == RESERVED_VENDOR_ID) + { + DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID); + *offset = 1; + return FAILED; + } + + if (this->subtype == PA_RESERVED_SUBTYPE) + { + DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE); + *offset = 4; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_pa_msg_t *this) +{ + free(this->encoding.ptr); + free(this->msg_body.ptr); + free(this); +} + +METHOD(pb_pa_msg_t, get_vendor_id, u_int32_t, + private_pb_pa_msg_t *this, u_int32_t *subtype) +{ + *subtype = this->subtype; + return this->vendor_id; +} + +METHOD(pb_pa_msg_t, get_collector_id, u_int16_t, + private_pb_pa_msg_t *this) +{ + return this->collector_id; +} + +METHOD(pb_pa_msg_t, get_validator_id, u_int16_t, + private_pb_pa_msg_t *this) +{ + return this->validator_id; +} + +METHOD(pb_pa_msg_t, get_body, chunk_t, + private_pb_pa_msg_t *this) +{ + return this->msg_body; +} + +METHOD(pb_pa_msg_t, get_exclusive_flag, bool, + private_pb_pa_msg_t *this) +{ + return this->excl; +} + +METHOD(pb_pa_msg_t, set_exclusive_flag, void, + private_pb_pa_msg_t *this, bool excl) +{ + this->excl = excl; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data) +{ + private_pb_pa_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_collector_id = _get_collector_id, + .get_validator_id = _get_validator_id, + .get_body = _get_body, + .get_exclusive_flag = _get_exclusive_flag, + .set_exclusive_flag = _set_exclusive_flag, + }, + .type = PB_MSG_PA, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype, + u_int16_t collector_id, u_int16_t validator_id, + chunk_t msg_body) +{ + private_pb_pa_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_collector_id = _get_collector_id, + .get_validator_id = _get_validator_id, + .get_body = _get_body, + .get_exclusive_flag = _get_exclusive_flag, + .set_exclusive_flag = _set_exclusive_flag, + }, + .type = PB_MSG_PA, + .vendor_id = vendor_id, + .subtype = subtype, + .collector_id = collector_id, + .validator_id = validator_id, + .msg_body = chunk_clone(msg_body), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h new file mode 100644 index 000000000..366d790f6 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010 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 pb_pa_msg pb_pa_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_PA_MSG_H_ +#define PB_PA_MSG_H_ + +typedef enum pa_tnc_subtype_t pa_tnc_subtype_t; +typedef struct pb_pa_msg_t pb_pa_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PA-TNC Subtypes as defined in section 3.5 of RFC 5792 + */ + enum pa_tnc_subtype_t { + PA_SUBTYPE_TESTING = 0, + PA_SUBTYPE_OPERATING_SYSTEM = 1, + PA_SUBTYPE_ANTI_VIRUS = 2, + PA_SUBTYPE_ANTI_SPYWARE = 3, + PA_SUBTYPE_ANTI_MALWARE = 4, + PA_SUBTYPE_FIREWALL = 5, + PA_SUBTYPE_IDPS = 6, + PA_SUBTYPE_VPN = 7, + PA_SUBTYPE_NEA_CLIENT = 8 +}; + +/** + * enum name for pa_tnc_subtype_t. + */ +extern enum_name_t *pa_tnc_subtype_names; + +/** + * Class representing the PB-PA message type. + */ +struct pb_pa_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PA Message Vendor ID and Subtype + * + * @param subtype PA Subtype + * @return PA Message Vendor ID + */ + u_int32_t (*get_vendor_id)(pb_pa_msg_t *this, u_int32_t *subtype); + + /** + * Get Posture Collector ID + * + * @return Posture Collector ID + */ + u_int16_t (*get_collector_id)(pb_pa_msg_t *this); + + /** + * Get Posture Validator ID + * + * @return Posture Validator ID + */ + u_int16_t (*get_validator_id)(pb_pa_msg_t *this); + + /** + * Get the PA Message Body + * + * @return PA Message Body + */ + chunk_t (*get_body)(pb_pa_msg_t *this); + + /** + * Get the exclusive flag + * + * @return exclusive flag + */ + bool (*get_exclusive_flag)(pb_pa_msg_t *this); + + /** + * Set the exclusive flag + * + * @param excl vexclusive flag + */ + void (*set_exclusive_flag)(pb_pa_msg_t *this, bool excl); +}; + +/** + * Create a PB-PA message from parameters + * + * @param vendor_id PA Message Vendor ID + * @param subtype PA Subtype + * @param collector_id Posture Collector ID + * @param validator_id Posture Validator ID + * @param msg_body PA Message Body + */ +pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype, + u_int16_t collector_id, u_int16_t validator_id, + chunk_t msg_body); + +/** + * Create an unprocessed PB-PA message from raw data + * + * @param data PB-PA message data + */ +pb_tnc_msg_t* pb_pa_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c new file mode 100644 index 000000000..e361cf2b2 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_reason_string_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +typedef struct private_pb_reason_string_msg_t private_pb_reason_string_msg_t; + +/** + * PB-Language-Preference message (see section 4.11 of RFC 5793) + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reason String Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reason String (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Lang Code Len | Reason String Language Code (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/** + * Private data of a pb_reason_string_msg_t object. + * + */ +struct private_pb_reason_string_msg_t { + /** + * Public pb_reason_string_msg_t interface. + */ + pb_reason_string_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Reason string + */ + chunk_t reason_string; + + /** + * Language code + */ + chunk_t language_code; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_reason_string_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_reason_string_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_reason_string_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(64); + writer->write_data32(writer, this->reason_string); + writer->write_data8 (writer, this->language_code); + + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_reason_string_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + + /* process message */ + reader = tls_reader_create(this->encoding); + if (!reader->read_data32(reader, &this->reason_string)) + { + DBG1(DBG_TNC, "could not parse reason string"); + reader->destroy(reader); + *offset = 0; + return FAILED; + }; + this->reason_string = chunk_clone(this->reason_string); + + if (this->reason_string.len && + this->reason_string.ptr[this->reason_string.len-1] == '\0') + { + DBG1(DBG_TNC, "reason string must not be null terminated"); + reader->destroy(reader); + *offset = 3 + this->reason_string.len; + return FAILED; + } + + if (!reader->read_data8(reader, &this->language_code)) + { + DBG1(DBG_TNC, "could not parse language code"); + reader->destroy(reader); + *offset = 4 + this->reason_string.len; + return FAILED; + }; + this->language_code = chunk_clone(this->language_code); + reader->destroy(reader); + + if (this->language_code.len && + this->language_code.ptr[this->language_code.len-1] == '\0') + { + DBG1(DBG_TNC, "language code must not be null terminated"); + *offset = 4 + this->reason_string.len + this->language_code.len; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_reason_string_msg_t *this) +{ + free(this->encoding.ptr); + free(this->reason_string.ptr); + free(this->language_code.ptr); + free(this); +} + +METHOD(pb_reason_string_msg_t, get_reason_string, chunk_t, + private_pb_reason_string_msg_t *this) +{ + return this->reason_string; +} + +METHOD(pb_reason_string_msg_t, get_language_code, chunk_t, + private_pb_reason_string_msg_t *this) +{ + return this->language_code; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_reason_string_msg_create_from_data(chunk_t data) +{ + private_pb_reason_string_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_reason_string = _get_reason_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_reason_string_msg_create(chunk_t reason_string, + chunk_t language_code) +{ + private_pb_reason_string_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_reason_string = _get_reason_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .reason_string = chunk_clone(reason_string), + .language_code = chunk_clone(language_code), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h new file mode 100644 index 000000000..bb296a90c --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 pb_reason_string_msg pb_reason_string_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_REASON_STRING_MSG_H_ +#define PB_REASON_STRING_MSG_H_ + +typedef struct pb_reason_string_msg_t pb_reason_string_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Reason-String message type. + */ +struct pb_reason_string_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get Reason String + * + * @return Reason string + */ + chunk_t (*get_reason_string)(pb_reason_string_msg_t *this); + + /** + * Get Reason String Language Code + * + * @return Language code + */ + chunk_t (*get_language_code)(pb_reason_string_msg_t *this); +}; + +/** + * Create a PB-Reason-String message from parameters + * + * @param reason_string Reason string + * @param language_code Language code + */ +pb_tnc_msg_t* pb_reason_string_msg_create(chunk_t reason_string, + chunk_t language_code); + +/** + * Create an unprocessed PB-Reason-String message from raw data + * + * @param data PB-Reason-String message data + */ +pb_tnc_msg_t* pb_reason_string_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c new file mode 100644 index 000000000..79381a7b1 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2010 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 "pb_remediation_parameters_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +ENUM(pb_tnc_remed_param_type_names, PB_REMEDIATION_URI, PB_REMEDIATION_STRING, + "Remediation-URI", + "Remediation-String" +); + +typedef struct private_pb_remediation_parameters_msg_t private_pb_remediation_parameters_msg_t; + +/** + * PB-Remediation-Parameters message (see section 4.8 of RFC 5793) + * + * 0 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 | Remediation Parameters Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation Parameters Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation Parameters (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation String Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation String (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Lang Code Len | Remediation String Lang Code (Variable Len) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/** + * Private data of a pb_remediation_parameters_msg_t object. + * + */ +struct private_pb_remediation_parameters_msg_t { + /** + * Public pb_remediation_parameters_msg_t interface. + */ + pb_remediation_parameters_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Remediation Parameters Vendor ID + */ + u_int32_t vendor_id; + + /** + * Remediation Parameters Type + */ + u_int32_t parameters_type; + + /** + * Remediation Parameters string + */ + chunk_t remediation_string; + + /** + * Language code + */ + chunk_t language_code; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_remediation_parameters_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(64); + writer->write_uint32(writer, this->vendor_id); + writer->write_uint32(writer, this->parameters_type); + writer->write_data32(writer, this->remediation_string); + writer->write_data8 (writer, this->language_code); + + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_remediation_parameters_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + + /* process message */ + reader = tls_reader_create(this->encoding); + reader->read_uint32(reader, &this->vendor_id); + reader->read_uint32(reader, &this->parameters_type); + + if (!reader->read_data32(reader, &this->remediation_string)) + { + DBG1(DBG_TNC, "could not parse remediation string"); + reader->destroy(reader); + *offset = 8; + return FAILED; + }; + this->remediation_string = chunk_clone(this->remediation_string); + + if (this->remediation_string.len && + this->remediation_string.ptr[this->remediation_string.len-1] == '\0') + { + DBG1(DBG_TNC, "remediation string must not be null terminated"); + reader->destroy(reader); + *offset = 11 + this->remediation_string.len; + return FAILED; + } + + if (!reader->read_data8(reader, &this->language_code)) + { + DBG1(DBG_TNC, "could not parse language code"); + reader->destroy(reader); + *offset = 12 + this->remediation_string.len; + return FAILED; + }; + this->language_code = chunk_clone(this->language_code); + reader->destroy(reader); + + if (this->language_code.len && + this->language_code.ptr[this->language_code.len-1] == '\0') + { + DBG1(DBG_TNC, "language code must not be null terminated"); + *offset = 12 + this->remediation_string.len + this->language_code.len; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_remediation_parameters_msg_t *this) +{ + free(this->encoding.ptr); + free(this->remediation_string.ptr); + free(this->language_code.ptr); + free(this); +} + +METHOD(pb_remediation_parameters_msg_t, get_vendor_id, u_int32_t, + private_pb_remediation_parameters_msg_t *this, u_int32_t *type) +{ + *type = this->parameters_type; + return this->vendor_id; +} + +METHOD(pb_remediation_parameters_msg_t, get_remediation_string, chunk_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->remediation_string; +} + +METHOD(pb_remediation_parameters_msg_t, get_language_code, chunk_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->language_code; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data) +{ + private_pb_remediation_parameters_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_remediation_string = _get_remediation_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id, + u_int32_t type, + chunk_t remediation_string, + chunk_t language_code) +{ + private_pb_remediation_parameters_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_remediation_string = _get_remediation_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .vendor_id = vendor_id, + .parameters_type = type, + .remediation_string = chunk_clone(remediation_string), + .language_code = chunk_clone(language_code), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h new file mode 100644 index 000000000..258d495ec --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 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 pb_remediation_parameters_msg pb_remediation_parameters_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_REMEDIATION_PARAMETERS_MSG_H_ +#define PB_REMEDIATION_PARAMETERS_MSG_H_ + +typedef enum pb_tnc_remed_param_type_t pb_tnc_remed_param_type_t; +typedef struct pb_remediation_parameters_msg_t pb_remediation_parameters_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PB-TNC Remediation Parameter Types as defined in section 4.8.1 of RFC 5793 + */ +enum pb_tnc_remed_param_type_t { + PB_REMEDIATION_URI = 1, + PB_REMEDIATION_STRING = 2, +}; + +/** + * enum name for pb_tnc_remed_param_type_t. + */ +extern enum_name_t *pb_tnc_remed_param_type_names; + +/** + * Class representing the PB-Remediation-Parameters message type. + */ +struct pb_remediation_parameters_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get Remediation Parameters Vendor ID and Type + * + * @param type Remediation Parameters Type + * @return Remediation Parameters Vendor ID + */ + u_int32_t (*get_vendor_id)(pb_remediation_parameters_msg_t *this, + u_int32_t *type); + + /** + * Get Remediation String + * + * @return Remediation String + */ + chunk_t (*get_remediation_string)(pb_remediation_parameters_msg_t *this); + + /** + * Get Reason String Language Code + * + * @return Language Code + */ + chunk_t (*get_language_code)(pb_remediation_parameters_msg_t *this); +}; + +/** + * Create a PB-Remediation-Parameters message from parameters + * + * @param vendor_id Remediation Parameters Vendor ID + * @param type Remediation Parameters Type + * @param remediation_string Remediation String + * @param language_code Language Code + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id, + u_int32_t type, + chunk_t remediation_string, + chunk_t language_code); + +/** + * Create an unprocessed PB-Remediation-Parameters message from raw data + * + * @param data PB-Remediation-Parameters message data + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c new file mode 100644 index 000000000..3565c2d84 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 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 "pb_tnc_msg.h" +#include "pb_experimental_msg.h" +#include "pb_pa_msg.h" +#include "pb_error_msg.h" +#include "pb_language_preference_msg.h" +#include "pb_assessment_result_msg.h" +#include "pb_access_recommendation_msg.h" +#include "pb_remediation_parameters_msg.h" +#include "pb_reason_string_msg.h" + +#include <library.h> + +ENUM(pb_tnc_msg_type_names, PB_MSG_EXPERIMENTAL, PB_MSG_REASON_STRING, + "PB-Experimental", + "PB-PA", + "PB-Assessment-Result", + "PB-Access-Recommendation", + "PB-Remediation-Parameters", + "PB-Error", + "PB-Language-Preference", + "PB-Reason-String" +); + +pb_tnc_msg_info_t pb_tnc_msg_infos[] = { + { 12, FALSE, FALSE, TRUE_OR_FALSE }, + { 24, FALSE, FALSE, TRUE }, + { 16, TRUE, TRUE, TRUE }, + { 16, TRUE, TRUE, FALSE }, + { 20, FALSE, TRUE, FALSE }, + { 20, FALSE, FALSE, TRUE }, + { 12, FALSE, FALSE, FALSE }, + { 17, FALSE, TRUE, FALSE }, +}; + +/** + * See header + */ +pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value) +{ + switch (type) + { + case PB_MSG_PA: + return pb_pa_msg_create_from_data(value); + case PB_MSG_ERROR: + return pb_error_msg_create_from_data(value); + case PB_MSG_EXPERIMENTAL: + return pb_experimental_msg_create_from_data(value); + case PB_MSG_LANGUAGE_PREFERENCE: + return pb_language_preference_msg_create_from_data(value); + case PB_MSG_ASSESSMENT_RESULT: + return pb_assessment_result_msg_create_from_data(value); + case PB_MSG_ACCESS_RECOMMENDATION: + return pb_access_recommendation_msg_create_from_data(value); + case PB_MSG_REMEDIATION_PARAMETERS: + return pb_remediation_parameters_msg_create_from_data(value); + case PB_MSG_REASON_STRING: + return pb_reason_string_msg_create_from_data(value); + } + return NULL; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h new file mode 100644 index 000000000..e20c8d8ff --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010 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 pb_tnc_msg pb_tnc_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_TNC_MSG_H_ +#define PB_TNC_MSG_H_ + +typedef enum pb_tnc_msg_type_t pb_tnc_msg_type_t; +typedef struct pb_tnc_msg_info_t pb_tnc_msg_info_t; +typedef struct pb_tnc_msg_t pb_tnc_msg_t; + +#include <library.h> + +#define PB_TNC_VERSION 2 + +/** + * PB-TNC Message Types as defined in section 4.3 of RFC 5793 + */ +enum pb_tnc_msg_type_t { + PB_MSG_EXPERIMENTAL = 0, + PB_MSG_PA = 1, + PB_MSG_ASSESSMENT_RESULT = 2, + PB_MSG_ACCESS_RECOMMENDATION = 3, + PB_MSG_REMEDIATION_PARAMETERS = 4, + PB_MSG_ERROR = 5, + PB_MSG_LANGUAGE_PREFERENCE = 6, + PB_MSG_REASON_STRING = 7, + PB_MSG_ROOF = 7 +}; + +/** + * enum name for pb_tnc_msg_type_t. + */ +extern enum_name_t *pb_tnc_msg_type_names; + +/** + * Information entry describing a PB-TNC Message Type + */ +struct pb_tnc_msg_info_t { + u_int32_t min_size; + bool exact_size; + bool in_result_batch; + bool has_noskip_flag; +}; + +#define TRUE_OR_FALSE 2 + +/** + * Information on PB-TNC Message Types + */ +extern pb_tnc_msg_info_t pb_tnc_msg_infos[]; + +/** + * Generic interface for all PB-TNC message types. + * + * To handle all messages in a generic way, this interface + * must be implemented by each message type. + */ +struct pb_tnc_msg_t { + + /** + * Get the PB-TNC Message Type + * + * @return PB-TNC Message Type + */ + pb_tnc_msg_type_t (*get_type)(pb_tnc_msg_t *this); + + /** + * Get the encoding of the PB-TNC Message Value + * + * @return encoded PB-TNC Message Value + */ + chunk_t (*get_encoding)(pb_tnc_msg_t *this); + + /** + * Build the PB-TNC Message Value + */ + void (*build)(pb_tnc_msg_t *this); + + /** + * Process the PB-TNC Message Value + * + * @param relative offset where an error occurred + * @return return processing status + */ + status_t (*process)(pb_tnc_msg_t *this, u_int32_t *offset); + + /** + * Get a new reference to the message. + * + * @return this, with an increased refcount + */ + pb_tnc_msg_t* (*get_ref)(pb_tnc_msg_t *this); + + /** + * Destroys a pb_tnc_msg_t object. + */ + void (*destroy)(pb_tnc_msg_t *this); +}; + +/** + * Create an unprocessed PB-TNC message + * + * Useful for the parser which wants a generic constructor for all + * pb_tnc_message_t types. + * + * @param type PB-TNC message type + * @param value PB-TNC message value + */ +pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value); + +#endif /** PB_TNC_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c new file mode 100644 index 000000000..a46dc0ab9 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2010 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 "pb_tnc_state_machine.h" + +#include <debug.h> + +ENUM(pb_tnc_state_names, PB_STATE_INIT, PB_STATE_END, + "Init", + "Server Working", + "Client Working", + "Decided", + "End" +); + +/** + * PB-TNC State Machine (see section 3.2 of RFC 5793) + * + * Receive CRETRY SRETRY + * or SRETRY +----------------+ + * +--+ | | + * v | v | + * +---------+ CRETRY +---------+ + * CDATA | Server |<---------| Decided | CLOSE + * +----------->| Working |--------->| |-------+ + * | +---------+ RESULT +---------+ | + * | ^ | | v + * | | | +---------------------->======= + * ======== | | CLOSE " End " + * " Init " CDATA| |SDATA ======= + * ======== | | ^ ^ + * | | | v | | + * | | SDATA +---------+ CLOSE | | + * | +-------->| Client |----------------------+ | + * | | Working | | + * | +---------+ | + * | | ^ | + * | +--+ | + * | Receive CRETRY | + * | CLOSE | + * +--------------------------------------------------+ + */ + +typedef struct private_pb_tnc_state_machine_t private_pb_tnc_state_machine_t; + +/** + * Private data of a pb_tnc_state_machine_t object. + * + */ +struct private_pb_tnc_state_machine_t { + /** + * Public pb_pa_message_t interface. + */ + pb_tnc_state_machine_t public; + + /** + * PB-TNC Server if TRUE, PB-TNC Client if FALSE + */ + bool is_server; + + /** + * Current PB-TNC state + */ + pb_tnc_state_t state; +}; + +METHOD(pb_tnc_state_machine_t, get_state, pb_tnc_state_t, + private_pb_tnc_state_machine_t *this) +{ + return this->state; +} + +METHOD(pb_tnc_state_machine_t, receive_batch, bool, + private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type) +{ + pb_tnc_state_t old_state = this->state; + + switch (this->state) + { + case PB_STATE_INIT: + if (this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (!this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_SERVER_WORKING: + if (!this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (!this->is_server && type == PB_BATCH_RESULT) + { + this->state = PB_STATE_DECIDED; + break; + } + if ((this->is_server && type == PB_BATCH_CRETRY) || + (!this->is_server && type == PB_BATCH_SRETRY)) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_CLIENT_WORKING: + if (this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_CRETRY) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_DECIDED: + if ((this->is_server && type == PB_BATCH_CRETRY) || + (!this->is_server && type == PB_BATCH_SRETRY)) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_END: + if (type == PB_BATCH_CLOSE) + { + break; + } + return FALSE; + } + + if (this->state != old_state) + { + DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", + pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); + } + return TRUE; +} + +METHOD(pb_tnc_state_machine_t, send_batch, bool, + private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type) +{ + pb_tnc_state_t old_state = this->state; + + switch (this->state) + { + case PB_STATE_INIT: + if (!this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_SERVER_WORKING: + if (this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_RESULT) + { + this->state = PB_STATE_DECIDED; + break; + } + if (this->is_server && type == PB_BATCH_SRETRY) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_CLIENT_WORKING: + if (!this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_DECIDED: + if ((this->is_server && type == PB_BATCH_SRETRY) || + (!this->is_server && type == PB_BATCH_CRETRY)) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_END: + if (type == PB_BATCH_CLOSE) + { + break; + } + return FALSE; + } + + if (this->state != old_state) + { + DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", + pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); + } + return TRUE; +} + +METHOD(pb_tnc_state_machine_t, destroy, void, + private_pb_tnc_state_machine_t *this) +{ + free(this); +} + +/** + * See header + */ +pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server) +{ + private_pb_tnc_state_machine_t *this; + + INIT(this, + .public = { + .get_state = _get_state, + .receive_batch = _receive_batch, + .send_batch = _send_batch, + .destroy = _destroy, + }, + .is_server = is_server, + .state = PB_STATE_INIT, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h new file mode 100644 index 000000000..8076b6ded --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 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 pb_tnc_state_machine pb_tnc_state_machine + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_TNC_STATE_MACHINE_H_ +#define PB_TNC_STATE_MACHINE_H_ + +typedef struct pb_tnc_state_machine_t pb_tnc_state_machine_t; +typedef enum pb_tnc_state_t pb_tnc_state_t; + +#include "batch/pb_tnc_batch.h" + +#include <library.h> + +/** + * PB-TNC States (state machine) as defined in section 3.2 of RFC 5793 + */ +enum pb_tnc_state_t { + PB_STATE_INIT, + PB_STATE_SERVER_WORKING, + PB_STATE_CLIENT_WORKING, + PB_STATE_DECIDED, + PB_STATE_END, +}; + +/** + * enum name for pb_tnc_state_t. + */ +extern enum_name_t *pb_tnc_state_names; + +/** + * Interface for the PB-TNC state machine. + */ +struct pb_tnc_state_machine_t { + + /** + * Get the current PB-TNC STATE + * + * @return current state + */ + pb_tnc_state_t (*get_state)(pb_tnc_state_machine_t *this); + + /** + * Compute state transition due to received PB-TNC Batch + * + * @param type type of received batch + * @result TRUE if a valid transition was found, FALSE otherwise + */ + bool (*receive_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type); + + /** + * Compute state transition due to sent PB-TNC Batch + * + * @param type type of sent batch + * @result TRUE if a valid transition was found, FALSE otherwise + */ + bool (*send_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type); + + /** + * Destroys a pb_tnc_state_machine_t object. + */ + void (*destroy)(pb_tnc_state_machine_t *this); +}; + +/** + * Create and initialize a PB-TNC state machine + * + * @param is_server TRUE if PB-TNC server, FALSE if PB-TNC client + */ +pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server); + +#endif /** PB_TNC_STATE_MACHINE_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 2bd1bc476..d53fd8eb7 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Sansar Choinyanbuu * Copyright (C) 2010 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * @@ -14,10 +15,23 @@ */ #include "tnccs_20.h" +#include "batch/pb_tnc_batch.h" +#include "messages/pb_tnc_msg.h" +#include "messages/pb_pa_msg.h" +#include "messages/pb_error_msg.h" +#include "messages/pb_assessment_result_msg.h" +#include "messages/pb_access_recommendation_msg.h" +#include "messages/pb_remediation_parameters_msg.h" +#include "messages/pb_reason_string_msg.h" +#include "messages/pb_language_preference_msg.h" +#include "state_machine/pb_tnc_state_machine.h" #include <debug.h> - -static chunk_t tncc_output; +#include <daemon.h> +#include <threading/mutex.h> +#include <tnc/tncif.h> +#include <tnc/tncifimv.h> +#include <tnc/tnccs/tnccs.h> typedef struct private_tnccs_20_t private_tnccs_20_t; @@ -35,18 +49,541 @@ struct private_tnccs_20_t { * TNCC if TRUE, TNCS if FALSE */ bool is_server; + + /** + * PB-TNC State Machine + */ + pb_tnc_state_machine_t *state_machine; + + /** + * Connection ID assigned to this TNCCS connection + */ + TNC_ConnectionID connection_id; + + /** + * PB-TNC batch being constructed + */ + pb_tnc_batch_t *batch; + + /** + * Mutex locking the batch in construction + */ + mutex_t *mutex; + + /** + * Flag set while processing + */ + bool fatal_error; + + /** + * Flag set by IMC/IMV RequestHandshakeRetry() function + */ + bool request_handshake_retry; + + /** + * Set of IMV recommendations (TNC Server only) + */ + recommendations_t *recs; }; +METHOD(tnccs_t, send_msg, void, + private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) +{ + TNC_MessageSubtype msg_sub_type; + TNC_VendorID msg_vendor_id; + pb_tnc_msg_t *pb_tnc_msg; + pb_tnc_batch_type_t batch_type; + + msg_sub_type = msg_type & TNC_SUBTYPE_ANY; + msg_vendor_id = (msg_type >> 8) & TNC_VENDORID_ANY; + + pb_tnc_msg = pb_pa_msg_create(msg_vendor_id, msg_sub_type, imc_id, imv_id, + chunk_create(msg, msg_len)); + + /* adding PA message to SDATA or CDATA batch only */ + batch_type = this->is_server ? PB_BATCH_SDATA : PB_BATCH_CDATA; + this->mutex->lock(this->mutex); + if (!this->batch) + { + this->batch = pb_tnc_batch_create(this->is_server, batch_type); + } + if (this->batch->get_type(this->batch) == batch_type) + { + this->batch->add_msg(this->batch, pb_tnc_msg); + } + else + { + pb_tnc_msg->destroy(pb_tnc_msg); + } + this->mutex->unlock(this->mutex); +} + +/** + * Handle a single PB-TNC message according to its type + */ +static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) +{ + switch (msg->get_type(msg)) + { + case PB_MSG_EXPERIMENTAL: + /* nothing to do */ + break; + case PB_MSG_PA: + { + pb_pa_msg_t *pa_msg; + TNC_MessageType msg_type; + u_int32_t vendor_id, subtype; + chunk_t msg_body; + + pa_msg = (pb_pa_msg_t*)msg; + vendor_id = pa_msg->get_vendor_id(pa_msg, &subtype); + msg_type = (vendor_id << 8) | (subtype & 0xff); + msg_body = pa_msg->get_body(pa_msg); + + DBG2(DBG_TNC, "handling PB-PA message type 0x%08x", msg_type); + + if (this->is_server) + { + charon->imvs->receive_message(charon->imvs, + this->connection_id, msg_body.ptr, msg_body.len, msg_type); + } + else + { + charon->imcs->receive_message(charon->imcs, + this->connection_id, msg_body.ptr, msg_body.len,msg_type); + } + break; + } + case PB_MSG_ASSESSMENT_RESULT: + { + pb_assessment_result_msg_t *assess_msg; + u_int32_t result; + + assess_msg = (pb_assessment_result_msg_t*)msg; + result = assess_msg->get_assessment_result(assess_msg); + DBG1(DBG_TNC, "PB-TNC assessment result is '%N'", + TNC_IMV_Evaluation_Result_names, result); + break; + } + case PB_MSG_ACCESS_RECOMMENDATION: + { + pb_access_recommendation_msg_t *rec_msg; + pb_access_recommendation_code_t rec; + TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE; + + rec_msg = (pb_access_recommendation_msg_t*)msg; + rec = rec_msg->get_access_recommendation(rec_msg); + DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'", + pb_access_recommendation_code_names, rec); + switch (rec) + { + case PB_REC_ACCESS_ALLOWED: + state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; + break; + case PB_REC_ACCESS_DENIED: + state = TNC_CONNECTION_STATE_ACCESS_NONE; + break; + case PB_REC_QUARANTINED: + state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; + } + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, state); + break; + } + case PB_MSG_REMEDIATION_PARAMETERS: + { + /* TODO : Remediation parameters message processing */ + break; + } + case PB_MSG_ERROR: + { + pb_error_msg_t *err_msg; + bool fatal; + u_int32_t vendor_id; + u_int16_t error_code; + + err_msg = (pb_error_msg_t*)msg; + fatal = err_msg->get_fatal_flag(err_msg); + vendor_id = err_msg->get_vendor_id(err_msg); + error_code = err_msg->get_error_code(err_msg); + + if (fatal) + { + this->fatal_error = TRUE; + } + + if (vendor_id == IETF_VENDOR_ID) + { + switch (error_code) + { + case PB_ERROR_INVALID_PARAMETER: + case PB_ERROR_UNSUPPORTED_MANDATORY_MSG: + DBG1(DBG_TNC, "received %s PB-TNC error '%N' " + "(offset %u bytes)", + fatal ? "fatal" : "non-fatal", + pb_tnc_error_code_names, error_code, + err_msg->get_offset(err_msg)); + break; + case PB_ERROR_VERSION_NOT_SUPPORTED: + DBG1(DBG_TNC, "received %s PB-TNC error '%N' " + "caused by bad version 0x%02x", + fatal ? "fatal" : "non-fatal", + pb_tnc_error_code_names, error_code, + err_msg->get_bad_version(err_msg)); + break; + case PB_ERROR_UNEXPECTED_BATCH_TYPE: + case PB_ERROR_LOCAL_ERROR: + default: + DBG1(DBG_TNC, "received %s PB-TNC error '%N'", + fatal ? "fatal" : "non-fatal", + pb_tnc_error_code_names, error_code); + break; + } + } + else + { + DBG1(DBG_TNC, "received %s PB-TNC error (%u) " + "with Vendor ID 0x%06x", + fatal ? "fatal" : "non-fatal", + error_code, vendor_id); + } + break; + } + case PB_MSG_LANGUAGE_PREFERENCE: + { + pb_language_preference_msg_t *lang_msg; + chunk_t lang; + + lang_msg = (pb_language_preference_msg_t*)msg; + lang = lang_msg->get_language_preference(lang_msg); + + DBG2(DBG_TNC, "setting language preference to '%.*s'", + lang.len, lang.ptr); + this->recs->set_preferred_language(this->recs, lang); + break; + } + case PB_MSG_REASON_STRING: + { + pb_reason_string_msg_t *reason_msg; + chunk_t reason_string, language_code; + + reason_msg = (pb_reason_string_msg_t*)msg; + reason_string = reason_msg->get_reason_string(reason_msg); + language_code = reason_msg->get_language_code(reason_msg); + DBG2(DBG_TNC, "reason string is '%.*s", reason_string.len, + reason_string.ptr); + DBG2(DBG_TNC, "language code is '%.*s", language_code.len, + language_code.ptr); + break; + } + default: + break; + } +} + +/** + * Build a CRETRY or SRETRY batch + */ +static void build_retry_batch(private_tnccs_20_t *this) +{ + if (this->batch) + { + DBG1(DBG_TNC, "cancelling PB-TNC %N batch", + pb_tnc_batch_type_names, this->batch->get_type(this->batch)); + this->batch->destroy(this->batch); + } + this->batch = pb_tnc_batch_create(this->is_server, + this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY); +} + METHOD(tls_t, process, status_t, private_tnccs_20_t *this, void *buf, size_t buflen) { + chunk_t data; + pb_tnc_batch_t *batch; + pb_tnc_msg_t *msg; + enumerator_t *enumerator; + status_t status; + + if (this->is_server && !this->connection_id) + { + this->connection_id = charon->tnccs->create_connection(charon->tnccs, + (tnccs_t*)this, _send_msg, + &this->request_handshake_retry, &this->recs); + if (!this->connection_id) + { + return FAILED; + } + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_CREATE); + } + + data = chunk_create(buf, buflen); + DBG1(DBG_TNC, "received TNCCS batch (%u bytes) for Connection ID %u", + data.len, this->connection_id); + DBG3(DBG_TNC, "%B", &data); + batch = pb_tnc_batch_create_from_data(this->is_server, data); + status = batch->process(batch, this->state_machine); + + if (status != FAILED) + { + enumerator_t *enumerator; + pb_tnc_msg_t *msg; + pb_tnc_batch_type_t batch_type; + bool empty = TRUE; + + batch_type = batch->get_type(batch); + + if (batch_type == PB_BATCH_CRETRY) + { + /* Send an SRETRY batch in response */ + this->mutex->lock(this->mutex); + build_retry_batch(this); + this->mutex->unlock(this->mutex); + } + else if (batch_type == PB_BATCH_SRETRY) + { + /* Restart the measurements */ + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + charon->imcs->begin_handshake(charon->imcs, this->connection_id); + } + + enumerator = batch->create_msg_enumerator(batch); + while (enumerator->enumerate(enumerator, &msg)) + { + handle_message(this, msg); + empty = FALSE; + } + enumerator->destroy(enumerator); + + /* received an empty CLOSE batch from PB-TNC client */ + if (this->is_server && batch_type == PB_BATCH_CLOSE && empty) + { + batch->destroy(batch); + if (this->fatal_error) + { + DBG1(DBG_TNC, "a fatal PB-TNC error occurred, " + "terminating connection"); + return FAILED; + } + else + { + return SUCCESS; + } + } + + if (this->is_server) + { + charon->imvs->batch_ending(charon->imvs, this->connection_id); + } + else + { + charon->imcs->batch_ending(charon->imcs, this->connection_id); + } + } + + switch (status) + { + case FAILED: + this->fatal_error = TRUE; + this->mutex->lock(this->mutex); + if (this->batch) + { + DBG1(DBG_TNC, "cancelling PB-TNC %N batch", + pb_tnc_batch_type_names, this->batch->get_type(this->batch)); + this->batch->destroy(this->batch); + } + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CLOSE); + this->mutex->unlock(this->mutex); + /* fall through to add error messages to outbound batch */ + case VERIFY_ERROR: + enumerator = batch->create_error_enumerator(batch); + while (enumerator->enumerate(enumerator, &msg)) + { + this->mutex->lock(this->mutex); + this->batch->add_msg(this->batch, msg->get_ref(msg)); + this->mutex->unlock(this->mutex); + } + enumerator->destroy(enumerator); + break; + case SUCCESS: + default: + break; + } + batch->destroy(batch); + return NEED_MORE; } +/** + * Build a RESULT batch if a final recommendation is available + */ +static void check_and_build_recommendation(private_tnccs_20_t *this) +{ + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; + TNC_IMVID id; + chunk_t reason, language; + enumerator_t *enumerator; + pb_tnc_msg_t *msg; + + if (!this->recs->have_recommendation(this->recs, &rec, &eval)) + { + charon->imvs->solicit_recommendation(charon->imvs, this->connection_id); + } + if (this->recs->have_recommendation(this->recs, &rec, &eval)) + { + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_RESULT); + + msg = pb_assessment_result_msg_create(eval); + this->batch->add_msg(this->batch, msg); + + /** + * IMV Action Recommendation and PB Access Recommendation codes + * are shifted by one. + */ + msg = pb_access_recommendation_msg_create(rec + 1); + this->batch->add_msg(this->batch, msg); + + enumerator = this->recs->create_reason_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &id, &reason, &language)) + { + msg = pb_reason_string_msg_create(reason, language); + this->batch->add_msg(this->batch, msg); + } + enumerator->destroy(enumerator); + } +} + METHOD(tls_t, build, status_t, private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen) { - return ALREADY_DONE; + status_t status; + + /* Initialize the connection */ + if (!this->is_server && !this->connection_id) + { + pb_tnc_msg_t *msg; + char *pref_lang; + + this->connection_id = charon->tnccs->create_connection(charon->tnccs, + (tnccs_t*)this, _send_msg, + &this->request_handshake_retry, NULL); + if (!this->connection_id) + { + return FAILED; + } + + /* Create PB-TNC Language Preference message */ + pref_lang = charon->imcs->get_preferred_language(charon->imcs); + msg = pb_language_preference_msg_create(chunk_create(pref_lang, + strlen(pref_lang))); + this->mutex->lock(this->mutex); + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CDATA); + this->batch->add_msg(this->batch, msg); + this->mutex->unlock(this->mutex); + + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_CREATE); + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + charon->imcs->begin_handshake(charon->imcs, this->connection_id); + } + + if (this->is_server && this->fatal_error && + this->state_machine->get_state(this->state_machine) == PB_STATE_END) + { + DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection"); + return FAILED; + } + + /* Do not allow any asynchronous IMCs or IMVs to add additional messages */ + this->mutex->lock(this->mutex); + + if (this->request_handshake_retry) + { + build_retry_batch(this); + + /* Reset the flag for the next handshake retry request */ + this->request_handshake_retry = FALSE; + } + + if (!this->batch) + { + pb_tnc_state_t state; + + state = this->state_machine->get_state(this->state_machine); + if (this->is_server) + { + if (state == PB_STATE_SERVER_WORKING) + { + check_and_build_recommendation(this); + } + } + else + { + /** + * if the DECIDED state has been reached and no CRETRY is under way + * or if a CLOSE batch with error messages has been received, + * a PB-TNC client replies with an empty CLOSE batch. + */ + if (state == PB_STATE_DECIDED || state == PB_STATE_END) + { + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CLOSE); + } + } + } + + if (this->batch) + { + pb_tnc_batch_type_t batch_type; + chunk_t data; + + batch_type = this->batch->get_type(this->batch); + + if (this->state_machine->send_batch(this->state_machine, batch_type)) + { + this->batch->build(this->batch); + data = this->batch->get_encoding(this->batch); + DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u", + pb_tnc_batch_type_names, batch_type, data.len, + this->connection_id); + DBG3(DBG_TNC, "%B", &data); + *msglen = data.len; + + if (data.len > *buflen) + { + DBG1(DBG_TNC, "fragmentation of PB-TNC batch not supported yet"); + } + else + { + *buflen = data.len; + } + memcpy(buf, data.ptr, *buflen); + status = ALREADY_DONE; + } + else + { + DBG1(DBG_TNC, "cancelling unexpected PB-TNC batch type: %N", + pb_tnc_batch_type_names, batch_type); + status = INVALID_STATE; + } + + this->batch->destroy(this->batch); + this->batch = NULL; + } + else + { + DBG1(DBG_TNC, "no PB-TNC batch to send"); + status = INVALID_STATE; + } + this->mutex->unlock(this->mutex); + + return status; } METHOD(tls_t, is_server, bool, @@ -64,7 +601,21 @@ METHOD(tls_t, get_purpose, tls_purpose_t, METHOD(tls_t, is_complete, bool, private_tnccs_20_t *this) { - return FALSE; + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; + + if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval)) + { + DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'", + TNC_IMV_Action_Recommendation_names, rec, + TNC_IMV_Evaluation_Result_names, eval); + + return charon->imvs->enforce_recommendation(charon->imvs, rec); + } + else + { + return FALSE; + } } METHOD(tls_t, get_eap_msk, chunk_t, @@ -76,6 +627,20 @@ METHOD(tls_t, get_eap_msk, chunk_t, METHOD(tls_t, destroy, void, private_tnccs_20_t *this) { + if (this->is_server) + { + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_DELETE); + } + else + { + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_DELETE); + } + charon->tnccs->remove_connection(charon->tnccs, this->connection_id); + this->state_machine->destroy(this->state_machine); + this->mutex->destroy(this->mutex); + DESTROY_IF(this->batch); free(this); } @@ -97,6 +662,8 @@ tls_t *tnccs_20_create(bool is_server) .destroy = _destroy, }, .is_server = is_server, + .state_machine = pb_tnc_state_machine_create(is_server), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); return &this->public; |