diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-07-10 12:47:56 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-07-10 12:47:56 +0000 |
commit | eb841c5ef668a48782ef1154fda65cb6048f5885 (patch) | |
tree | 00dd0cb4313bf2291d94ed511fe51f0b4bc7ea7a /src/charon | |
parent | 738206039047924ae7e4762a53d121be1ca43000 (diff) | |
download | vyos-strongswan-eb841c5ef668a48782ef1154fda65cb6048f5885.tar.gz vyos-strongswan-eb841c5ef668a48782ef1154fda65cb6048f5885.zip |
- Updated to new upstream.
Diffstat (limited to 'src/charon')
312 files changed, 31180 insertions, 13538 deletions
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 1d7022336..9a04055c3 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -4,16 +4,15 @@ charon_SOURCES = \ bus/bus.c bus/bus.h \ bus/listeners/file_logger.c bus/listeners/file_logger.h \ bus/listeners/sys_logger.c bus/listeners/sys_logger.h \ -config/backends/backend.h config/backends/writeable_backend.h \ -config/backend_manager.c config/backend_manager.h \ +config/backend_manager.c config/backend_manager.h config/backend.h \ config/child_cfg.c config/child_cfg.h \ -config/credentials/local_credential_store.c config/credentials/local_credential_store.h \ config/ike_cfg.c config/ike_cfg.h \ config/peer_cfg.c config/peer_cfg.h \ config/proposal.c config/proposal.h \ config/traffic_selector.c config/traffic_selector.h \ -control/interfaces/interface.h \ -control/interface_manager.c control/interface_manager.h \ +config/attributes/attribute_provider.h \ +config/attributes/attribute_manager.c config/attributes/attribute_manager.h \ +control/controller.c control/controller.h \ daemon.c daemon.h \ encoding/generator.c encoding/generator.h \ encoding/message.c encoding/message.h \ @@ -63,8 +62,9 @@ processing/processor.c processing/processor.h \ sa/authenticators/authenticator.c sa/authenticators/authenticator.h \ sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \ sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \ +sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \ sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \ -sa/authenticators/rsa_authenticator.c sa/authenticators/rsa_authenticator.h \ +sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \ sa/child_sa.c sa/child_sa.h \ sa/ike_sa.c sa/ike_sa.h \ sa/ike_sa_id.c sa/ike_sa_id.h \ @@ -74,7 +74,8 @@ sa/tasks/child_create.c sa/tasks/child_create.h \ sa/tasks/child_delete.c sa/tasks/child_delete.h \ sa/tasks/child_rekey.c sa/tasks/child_rekey.h \ sa/tasks/ike_auth.c sa/tasks/ike_auth.h \ -sa/tasks/ike_cert.c sa/tasks/ike_cert.h \ +sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \ +sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \ sa/tasks/ike_config.c sa/tasks/ike_config.h \ sa/tasks/ike_delete.c sa/tasks/ike_delete.h \ sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \ @@ -84,7 +85,25 @@ sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \ sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \ sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \ sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \ -sa/tasks/task.c sa/tasks/task.h +sa/tasks/task.c sa/tasks/task.h \ +credentials/credential_manager.c credentials/credential_manager.h \ +credentials/auth_info.c credentials/auth_info.h \ +credentials/sets/auth_info_wrapper.c credentials/sets/auth_info_wrapper.h \ +credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \ +credentials/sets/cert_cache.c credentials/sets/cert_cache.h \ +credentials/credential_set.h + +INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic \ + -DIPSEC_DIR=\"${ipsecdir}\" \ + -DIPSEC_PIDDIR=\"${piddir}\" \ + -DIPSEC_PLUGINDIR=\"${plugindir}\" \ + -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ + -DRESOLV_CONF=\"${resolv_conf}\" +charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lm -ldl + +# compile options +################# # Use RAW socket if pluto gets built if USE_PLUTO @@ -93,98 +112,83 @@ else charon_SOURCES += network/socket.c endif -if USE_P2P +if USE_ME charon_SOURCES += encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \ processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \ processing/jobs/mediation_job.c processing/jobs/mediation_job.h \ sa/connect_manager.c sa/connect_manager.h \ sa/mediation_manager.c sa/mediation_manager.h \ - sa/tasks/ike_p2p.c sa/tasks/ike_p2p.h + sa/tasks/ike_me.c sa/tasks/ike_me.h endif -INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke -AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \ - -DIPSEC_EAPDIR=\"${eapdir}\" -DIPSEC_BACKENDDIR=\"${backenddir}\" -DIPSEC_INTERFACEDIR=\"${interfacedir}\" \ - -DSIM_READER_LIB=\"${simreader}\" -charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lgmp -lpthread -lm -ldl +if USE_INTEGRITY_TEST + AM_CFLAGS += -DINTEGRITY_TEST +endif -if USE_LIBCURL - charon_LDADD += -lcurl +if USE_SELF_TEST + AM_CFLAGS += -DSELF_TEST endif +# build optional plugins +######################## -# build EAP plugins -################### -eap_LTLIBRARIES = +SUBDIRS = . +PLUGINS = ${libstrongswan_plugins} -if USE_EAP_IDENTITY - eap_LTLIBRARIES += libcharon-eapidentity.la - libcharon_eapidentity_la_SOURCES = sa/authenticators/eap/eap_identity.h sa/authenticators/eap/eap_identity.c - libcharon_eapidentity_la_LDFLAGS = -module +if USE_UNIT_TESTS + SUBDIRS += plugins/unit_tester + PLUGINS += unit-tester endif -if USE_EAP_SIM - eap_LTLIBRARIES += libcharon-eapsim.la - libcharon_eapsim_la_SOURCES = sa/authenticators/eap/eap_sim.h sa/authenticators/eap/eap_sim.c - libcharon_eapsim_la_LDFLAGS = -module - - plugin_LTLIBRARIES = libcharon-eapsim-file.la - libcharon_eapsim_file_la_SOURCES = sa/authenticators/eap/sim/eap_sim_file.c - libcharon_eapsim_file_la_LDFLAGS = -module +if USE_STROKE + SUBDIRS += plugins/stroke + PLUGINS += stroke endif -if USE_EAP_MD5 - eap_LTLIBRARIES += libcharon-eapmd5.la - libcharon_eapmd5_la_SOURCES = sa/authenticators/eap/eap_md5.h sa/authenticators/eap/eap_md5.c - libcharon_eapmd5_la_LDFLAGS = -module +if USE_SMP + SUBDIRS += plugins/smp + PLUGINS += smp endif -if USE_EAP_AKA - eap_LTLIBRARIES += libcharon-eapaka.la - libcharon_eapaka_la_SOURCES = sa/authenticators/eap/eap_aka.h sa/authenticators/eap/eap_aka.c - libcharon_eapaka_la_LDFLAGS = -module +if USE_SQL + SUBDIRS += plugins/sql + PLUGINS += sql endif -# build backends -################ -backend_LTLIBRARIES = +if USE_EAP_IDENTITY + SUBDIRS += plugins/eap_identity + PLUGINS += eapidentity +endif -if USE_STROKE - backend_LTLIBRARIES += libcharon-local.la - libcharon_local_la_SOURCES = config/backends/local_backend.h config/backends/local_backend.c - libcharon_local_la_LDFLAGS = -module +if USE_EAP_SIM + SUBDIRS += plugins/eap_sim + PLUGINS += eapsim endif -if USE_LIBSQLITE - backend_LTLIBRARIES += libcharon-sqlite.la - libcharon_sqlite_la_SOURCES = config/backends/sqlite_backend.h config/backends/sqlite_backend.c - libcharon_sqlite_la_LIBADD = -lsqlite3 - libcharon_sqlite_la_LDFLAGS = -module +if USE_EAP_MD5 + SUBDIRS += plugins/eap_md5 + PLUGINS += eapmd5 endif -# build control interfaces -########################## -interface_LTLIBRARIES = +if USE_EAP_AKA + SUBDIRS += plugins/eap_aka + PLUGINS += eapaka +endif -if USE_STROKE - interface_LTLIBRARIES += libcharon-stroke.la - libcharon_stroke_la_SOURCES = control/interfaces/stroke_interface.h control/interfaces/stroke_interface.c - libcharon_stroke_la_LDFLAGS = -module +if USE_MEDSRV + SUBDIRS += plugins/medsrv + PLUGINS += medsrv endif -if USE_LIBDBUS - interface_LTLIBRARIES += libcharon-dbus.la - libcharon_dbus_la_SOURCES = control/interfaces/dbus_interface.h control/interfaces/dbus_interface.c - libcharon_dbus_la_LDFLAGS = -module - libcharon_dbus_la_LIBADD = ${dbus_LIBS} - INCLUDES += ${dbus_CFLAGS} +if USE_MEDCLI + SUBDIRS += plugins/medcli + PLUGINS += medcli endif -if USE_LIBXML - interface_LTLIBRARIES += libcharon-xml.la - libcharon_xml_la_SOURCES = control/interfaces/xml_interface.h control/interfaces/xml_interface.c - libcharon_xml_la_LDFLAGS = -module - libcharon_xml_la_LIBADD = ${xml_LIBS} - INCLUDES += ${xml_CFLAGS} +if USE_UCI + SUBDIRS += plugins/uci + PLUGINS += uci endif +AM_CFLAGS += -DPLUGINS=\""${PLUGINS}\"" + diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in index 41f1690e2..cf03a0e35 100644 --- a/src/charon/Makefile.in +++ b/src/charon/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.10 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -14,7 +14,6 @@ @SET_MAKE@ - VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -35,28 +34,43 @@ build_triplet = @build@ host_triplet = @host@ ipsec_PROGRAMS = charon$(EXEEXT) +# compile options +################# + # Use RAW socket if pluto gets built @USE_PLUTO_TRUE@am__append_1 = network/socket-raw.c @USE_PLUTO_FALSE@am__append_2 = network/socket.c -@USE_P2P_TRUE@am__append_3 = encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \ -@USE_P2P_TRUE@ processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \ -@USE_P2P_TRUE@ processing/jobs/mediation_job.c processing/jobs/mediation_job.h \ -@USE_P2P_TRUE@ sa/connect_manager.c sa/connect_manager.h \ -@USE_P2P_TRUE@ sa/mediation_manager.c sa/mediation_manager.h \ -@USE_P2P_TRUE@ sa/tasks/ike_p2p.c sa/tasks/ike_p2p.h - -@USE_LIBCURL_TRUE@am__append_4 = -lcurl -@USE_EAP_IDENTITY_TRUE@am__append_5 = libcharon-eapidentity.la -@USE_EAP_SIM_TRUE@am__append_6 = libcharon-eapsim.la -@USE_EAP_MD5_TRUE@am__append_7 = libcharon-eapmd5.la -@USE_EAP_AKA_TRUE@am__append_8 = libcharon-eapaka.la -@USE_STROKE_TRUE@am__append_9 = libcharon-local.la -@USE_LIBSQLITE_TRUE@am__append_10 = libcharon-sqlite.la -@USE_STROKE_TRUE@am__append_11 = libcharon-stroke.la -@USE_LIBDBUS_TRUE@am__append_12 = libcharon-dbus.la -@USE_LIBDBUS_TRUE@am__append_13 = ${dbus_CFLAGS} -@USE_LIBXML_TRUE@am__append_14 = libcharon-xml.la -@USE_LIBXML_TRUE@am__append_15 = ${xml_CFLAGS} +@USE_ME_TRUE@am__append_3 = encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \ +@USE_ME_TRUE@ processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \ +@USE_ME_TRUE@ processing/jobs/mediation_job.c processing/jobs/mediation_job.h \ +@USE_ME_TRUE@ sa/connect_manager.c sa/connect_manager.h \ +@USE_ME_TRUE@ sa/mediation_manager.c sa/mediation_manager.h \ +@USE_ME_TRUE@ sa/tasks/ike_me.c sa/tasks/ike_me.h + +@USE_INTEGRITY_TEST_TRUE@am__append_4 = -DINTEGRITY_TEST +@USE_SELF_TEST_TRUE@am__append_5 = -DSELF_TEST +@USE_UNIT_TESTS_TRUE@am__append_6 = plugins/unit_tester +@USE_UNIT_TESTS_TRUE@am__append_7 = unit-tester +@USE_STROKE_TRUE@am__append_8 = plugins/stroke +@USE_STROKE_TRUE@am__append_9 = stroke +@USE_SMP_TRUE@am__append_10 = plugins/smp +@USE_SMP_TRUE@am__append_11 = smp +@USE_SQL_TRUE@am__append_12 = plugins/sql +@USE_SQL_TRUE@am__append_13 = sql +@USE_EAP_IDENTITY_TRUE@am__append_14 = plugins/eap_identity +@USE_EAP_IDENTITY_TRUE@am__append_15 = eapidentity +@USE_EAP_SIM_TRUE@am__append_16 = plugins/eap_sim +@USE_EAP_SIM_TRUE@am__append_17 = eapsim +@USE_EAP_MD5_TRUE@am__append_18 = plugins/eap_md5 +@USE_EAP_MD5_TRUE@am__append_19 = eapmd5 +@USE_EAP_AKA_TRUE@am__append_20 = plugins/eap_aka +@USE_EAP_AKA_TRUE@am__append_21 = eapaka +@USE_MEDSRV_TRUE@am__append_22 = plugins/medsrv +@USE_MEDSRV_TRUE@am__append_23 = medsrv +@USE_MEDCLI_TRUE@am__append_24 = plugins/medcli +@USE_MEDCLI_TRUE@am__append_25 = medcli +@USE_UCI_TRUE@am__append_26 = plugins/uci +@USE_UCI_TRUE@am__append_27 = uci subdir = src/charon DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -65,147 +79,24 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(backenddir)" "$(DESTDIR)$(eapdir)" \ - "$(DESTDIR)$(interfacedir)" "$(DESTDIR)$(plugindir)" \ - "$(DESTDIR)$(ipsecdir)" -backendLTLIBRARIES_INSTALL = $(INSTALL) -eapLTLIBRARIES_INSTALL = $(INSTALL) -interfaceLTLIBRARIES_INSTALL = $(INSTALL) -pluginLTLIBRARIES_INSTALL = $(INSTALL) -LTLIBRARIES = $(backend_LTLIBRARIES) $(eap_LTLIBRARIES) \ - $(interface_LTLIBRARIES) $(plugin_LTLIBRARIES) -am__DEPENDENCIES_1 = -@USE_LIBDBUS_TRUE@libcharon_dbus_la_DEPENDENCIES = \ -@USE_LIBDBUS_TRUE@ $(am__DEPENDENCIES_1) -am__libcharon_dbus_la_SOURCES_DIST = \ - control/interfaces/dbus_interface.h \ - control/interfaces/dbus_interface.c -@USE_LIBDBUS_TRUE@am_libcharon_dbus_la_OBJECTS = dbus_interface.lo -libcharon_dbus_la_OBJECTS = $(am_libcharon_dbus_la_OBJECTS) -libcharon_dbus_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_dbus_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_LIBDBUS_TRUE@am_libcharon_dbus_la_rpath = -rpath $(interfacedir) -libcharon_eapaka_la_LIBADD = -am__libcharon_eapaka_la_SOURCES_DIST = \ - sa/authenticators/eap/eap_aka.h \ - sa/authenticators/eap/eap_aka.c -@USE_EAP_AKA_TRUE@am_libcharon_eapaka_la_OBJECTS = eap_aka.lo -libcharon_eapaka_la_OBJECTS = $(am_libcharon_eapaka_la_OBJECTS) -libcharon_eapaka_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_eapaka_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_EAP_AKA_TRUE@am_libcharon_eapaka_la_rpath = -rpath $(eapdir) -libcharon_eapidentity_la_LIBADD = -am__libcharon_eapidentity_la_SOURCES_DIST = \ - sa/authenticators/eap/eap_identity.h \ - sa/authenticators/eap/eap_identity.c -@USE_EAP_IDENTITY_TRUE@am_libcharon_eapidentity_la_OBJECTS = \ -@USE_EAP_IDENTITY_TRUE@ eap_identity.lo -libcharon_eapidentity_la_OBJECTS = \ - $(am_libcharon_eapidentity_la_OBJECTS) -libcharon_eapidentity_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_eapidentity_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_EAP_IDENTITY_TRUE@am_libcharon_eapidentity_la_rpath = -rpath \ -@USE_EAP_IDENTITY_TRUE@ $(eapdir) -libcharon_eapmd5_la_LIBADD = -am__libcharon_eapmd5_la_SOURCES_DIST = \ - sa/authenticators/eap/eap_md5.h \ - sa/authenticators/eap/eap_md5.c -@USE_EAP_MD5_TRUE@am_libcharon_eapmd5_la_OBJECTS = eap_md5.lo -libcharon_eapmd5_la_OBJECTS = $(am_libcharon_eapmd5_la_OBJECTS) -libcharon_eapmd5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_eapmd5_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_EAP_MD5_TRUE@am_libcharon_eapmd5_la_rpath = -rpath $(eapdir) -libcharon_eapsim_file_la_LIBADD = -am__libcharon_eapsim_file_la_SOURCES_DIST = \ - sa/authenticators/eap/sim/eap_sim_file.c -@USE_EAP_SIM_TRUE@am_libcharon_eapsim_file_la_OBJECTS = \ -@USE_EAP_SIM_TRUE@ eap_sim_file.lo -libcharon_eapsim_file_la_OBJECTS = \ - $(am_libcharon_eapsim_file_la_OBJECTS) -libcharon_eapsim_file_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_eapsim_file_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_EAP_SIM_TRUE@am_libcharon_eapsim_file_la_rpath = -rpath \ -@USE_EAP_SIM_TRUE@ $(plugindir) -libcharon_eapsim_la_LIBADD = -am__libcharon_eapsim_la_SOURCES_DIST = \ - sa/authenticators/eap/eap_sim.h \ - sa/authenticators/eap/eap_sim.c -@USE_EAP_SIM_TRUE@am_libcharon_eapsim_la_OBJECTS = eap_sim.lo -libcharon_eapsim_la_OBJECTS = $(am_libcharon_eapsim_la_OBJECTS) -libcharon_eapsim_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_eapsim_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_EAP_SIM_TRUE@am_libcharon_eapsim_la_rpath = -rpath $(eapdir) -libcharon_local_la_LIBADD = -am__libcharon_local_la_SOURCES_DIST = config/backends/local_backend.h \ - config/backends/local_backend.c -@USE_STROKE_TRUE@am_libcharon_local_la_OBJECTS = local_backend.lo -libcharon_local_la_OBJECTS = $(am_libcharon_local_la_OBJECTS) -libcharon_local_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_local_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_STROKE_TRUE@am_libcharon_local_la_rpath = -rpath $(backenddir) -libcharon_sqlite_la_DEPENDENCIES = -am__libcharon_sqlite_la_SOURCES_DIST = \ - config/backends/sqlite_backend.h \ - config/backends/sqlite_backend.c -@USE_LIBSQLITE_TRUE@am_libcharon_sqlite_la_OBJECTS = \ -@USE_LIBSQLITE_TRUE@ sqlite_backend.lo -libcharon_sqlite_la_OBJECTS = $(am_libcharon_sqlite_la_OBJECTS) -libcharon_sqlite_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_sqlite_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_LIBSQLITE_TRUE@am_libcharon_sqlite_la_rpath = -rpath \ -@USE_LIBSQLITE_TRUE@ $(backenddir) -libcharon_stroke_la_LIBADD = -am__libcharon_stroke_la_SOURCES_DIST = \ - control/interfaces/stroke_interface.h \ - control/interfaces/stroke_interface.c -@USE_STROKE_TRUE@am_libcharon_stroke_la_OBJECTS = stroke_interface.lo -libcharon_stroke_la_OBJECTS = $(am_libcharon_stroke_la_OBJECTS) -libcharon_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_stroke_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_STROKE_TRUE@am_libcharon_stroke_la_rpath = -rpath $(interfacedir) -@USE_LIBXML_TRUE@libcharon_xml_la_DEPENDENCIES = \ -@USE_LIBXML_TRUE@ $(am__DEPENDENCIES_1) -am__libcharon_xml_la_SOURCES_DIST = \ - control/interfaces/xml_interface.h \ - control/interfaces/xml_interface.c -@USE_LIBXML_TRUE@am_libcharon_xml_la_OBJECTS = xml_interface.lo -libcharon_xml_la_OBJECTS = $(am_libcharon_xml_la_OBJECTS) -libcharon_xml_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcharon_xml_la_LDFLAGS) $(LDFLAGS) -o $@ -@USE_LIBXML_TRUE@am_libcharon_xml_la_rpath = -rpath $(interfacedir) +am__installdirs = "$(DESTDIR)$(ipsecdir)" ipsecPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(ipsec_PROGRAMS) am__charon_SOURCES_DIST = bus/bus.c bus/bus.h \ bus/listeners/file_logger.c bus/listeners/file_logger.h \ bus/listeners/sys_logger.c bus/listeners/sys_logger.h \ - config/backends/backend.h config/backends/writeable_backend.h \ config/backend_manager.c config/backend_manager.h \ - config/child_cfg.c config/child_cfg.h \ - config/credentials/local_credential_store.c \ - config/credentials/local_credential_store.h config/ike_cfg.c \ - config/ike_cfg.h config/peer_cfg.c config/peer_cfg.h \ - config/proposal.c config/proposal.h config/traffic_selector.c \ - config/traffic_selector.h control/interfaces/interface.h \ - control/interface_manager.c control/interface_manager.h \ - daemon.c daemon.h encoding/generator.c encoding/generator.h \ - encoding/message.c encoding/message.h encoding/parser.c \ - encoding/parser.h encoding/payloads/auth_payload.c \ + config/backend.h config/child_cfg.c config/child_cfg.h \ + config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \ + config/peer_cfg.h config/proposal.c config/proposal.h \ + config/traffic_selector.c config/traffic_selector.h \ + config/attributes/attribute_provider.h \ + config/attributes/attribute_manager.c \ + config/attributes/attribute_manager.h control/controller.c \ + control/controller.h daemon.c daemon.h encoding/generator.c \ + encoding/generator.h encoding/message.c encoding/message.h \ + encoding/parser.c encoding/parser.h \ + encoding/payloads/auth_payload.c \ encoding/payloads/auth_payload.h \ encoding/payloads/cert_payload.c \ encoding/payloads/cert_payload.h \ @@ -273,46 +164,55 @@ am__charon_SOURCES_DIST = bus/bus.c bus/bus.h \ sa/authenticators/eap_authenticator.h \ sa/authenticators/eap/eap_method.c \ sa/authenticators/eap/eap_method.h \ + sa/authenticators/eap/eap_manager.c \ + sa/authenticators/eap/eap_manager.h \ sa/authenticators/psk_authenticator.c \ sa/authenticators/psk_authenticator.h \ - sa/authenticators/rsa_authenticator.c \ - sa/authenticators/rsa_authenticator.h sa/child_sa.c \ + sa/authenticators/pubkey_authenticator.c \ + sa/authenticators/pubkey_authenticator.h sa/child_sa.c \ sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \ sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \ sa/task_manager.c sa/task_manager.h sa/tasks/child_create.c \ sa/tasks/child_create.h sa/tasks/child_delete.c \ sa/tasks/child_delete.h sa/tasks/child_rekey.c \ sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \ - sa/tasks/ike_cert.c sa/tasks/ike_cert.h sa/tasks/ike_config.c \ - sa/tasks/ike_config.h sa/tasks/ike_delete.c \ - sa/tasks/ike_delete.h sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \ - sa/tasks/ike_init.c sa/tasks/ike_init.h sa/tasks/ike_natd.c \ - sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \ + sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \ + sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \ + sa/tasks/ike_config.c sa/tasks/ike_config.h \ + sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \ + sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \ + sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \ sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \ sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \ sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \ sa/tasks/ike_auth_lifetime.h sa/tasks/task.c sa/tasks/task.h \ - network/socket-raw.c network/socket.c \ - encoding/payloads/endpoint_notify.c \ + credentials/credential_manager.c \ + credentials/credential_manager.h credentials/auth_info.c \ + credentials/auth_info.h credentials/sets/auth_info_wrapper.c \ + credentials/sets/auth_info_wrapper.h \ + credentials/sets/ocsp_response_wrapper.c \ + credentials/sets/ocsp_response_wrapper.h \ + credentials/sets/cert_cache.c credentials/sets/cert_cache.h \ + credentials/credential_set.h network/socket-raw.c \ + network/socket.c encoding/payloads/endpoint_notify.c \ encoding/payloads/endpoint_notify.h \ processing/jobs/initiate_mediation_job.c \ processing/jobs/initiate_mediation_job.h \ processing/jobs/mediation_job.c \ processing/jobs/mediation_job.h sa/connect_manager.c \ sa/connect_manager.h sa/mediation_manager.c \ - sa/mediation_manager.h sa/tasks/ike_p2p.c sa/tasks/ike_p2p.h + sa/mediation_manager.h sa/tasks/ike_me.c sa/tasks/ike_me.h @USE_PLUTO_TRUE@am__objects_1 = socket-raw.$(OBJEXT) @USE_PLUTO_FALSE@am__objects_2 = socket.$(OBJEXT) -@USE_P2P_TRUE@am__objects_3 = endpoint_notify.$(OBJEXT) \ -@USE_P2P_TRUE@ initiate_mediation_job.$(OBJEXT) \ -@USE_P2P_TRUE@ mediation_job.$(OBJEXT) \ -@USE_P2P_TRUE@ connect_manager.$(OBJEXT) \ -@USE_P2P_TRUE@ mediation_manager.$(OBJEXT) ike_p2p.$(OBJEXT) +@USE_ME_TRUE@am__objects_3 = endpoint_notify.$(OBJEXT) \ +@USE_ME_TRUE@ initiate_mediation_job.$(OBJEXT) \ +@USE_ME_TRUE@ mediation_job.$(OBJEXT) connect_manager.$(OBJEXT) \ +@USE_ME_TRUE@ mediation_manager.$(OBJEXT) ike_me.$(OBJEXT) am_charon_OBJECTS = bus.$(OBJEXT) file_logger.$(OBJEXT) \ sys_logger.$(OBJEXT) backend_manager.$(OBJEXT) \ - child_cfg.$(OBJEXT) local_credential_store.$(OBJEXT) \ - ike_cfg.$(OBJEXT) peer_cfg.$(OBJEXT) proposal.$(OBJEXT) \ - traffic_selector.$(OBJEXT) interface_manager.$(OBJEXT) \ + child_cfg.$(OBJEXT) ike_cfg.$(OBJEXT) peer_cfg.$(OBJEXT) \ + proposal.$(OBJEXT) traffic_selector.$(OBJEXT) \ + attribute_manager.$(OBJEXT) controller.$(OBJEXT) \ daemon.$(OBJEXT) generator.$(OBJEXT) message.$(OBJEXT) \ parser.$(OBJEXT) auth_payload.$(OBJEXT) cert_payload.$(OBJEXT) \ certreq_payload.$(OBJEXT) configuration_attribute.$(OBJEXT) \ @@ -334,21 +234,24 @@ am_charon_OBJECTS = bus.$(OBJEXT) file_logger.$(OBJEXT) \ send_dpd_job.$(OBJEXT) send_keepalive_job.$(OBJEXT) \ roam_job.$(OBJEXT) scheduler.$(OBJEXT) processor.$(OBJEXT) \ authenticator.$(OBJEXT) eap_authenticator.$(OBJEXT) \ - eap_method.$(OBJEXT) psk_authenticator.$(OBJEXT) \ - rsa_authenticator.$(OBJEXT) child_sa.$(OBJEXT) \ - ike_sa.$(OBJEXT) ike_sa_id.$(OBJEXT) ike_sa_manager.$(OBJEXT) \ - task_manager.$(OBJEXT) child_create.$(OBJEXT) \ - child_delete.$(OBJEXT) child_rekey.$(OBJEXT) \ - ike_auth.$(OBJEXT) ike_cert.$(OBJEXT) ike_config.$(OBJEXT) \ - ike_delete.$(OBJEXT) ike_dpd.$(OBJEXT) ike_init.$(OBJEXT) \ - ike_natd.$(OBJEXT) ike_mobike.$(OBJEXT) ike_rekey.$(OBJEXT) \ - ike_reauth.$(OBJEXT) ike_auth_lifetime.$(OBJEXT) \ - task.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ + eap_method.$(OBJEXT) eap_manager.$(OBJEXT) \ + psk_authenticator.$(OBJEXT) pubkey_authenticator.$(OBJEXT) \ + child_sa.$(OBJEXT) ike_sa.$(OBJEXT) ike_sa_id.$(OBJEXT) \ + ike_sa_manager.$(OBJEXT) task_manager.$(OBJEXT) \ + child_create.$(OBJEXT) child_delete.$(OBJEXT) \ + child_rekey.$(OBJEXT) ike_auth.$(OBJEXT) \ + ike_cert_pre.$(OBJEXT) ike_cert_post.$(OBJEXT) \ + ike_config.$(OBJEXT) ike_delete.$(OBJEXT) ike_dpd.$(OBJEXT) \ + ike_init.$(OBJEXT) ike_natd.$(OBJEXT) ike_mobike.$(OBJEXT) \ + ike_rekey.$(OBJEXT) ike_reauth.$(OBJEXT) \ + ike_auth_lifetime.$(OBJEXT) task.$(OBJEXT) \ + credential_manager.$(OBJEXT) auth_info.$(OBJEXT) \ + auth_info_wrapper.$(OBJEXT) ocsp_response_wrapper.$(OBJEXT) \ + cert_cache.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ $(am__objects_3) charon_OBJECTS = $(am_charon_OBJECTS) charon_DEPENDENCIES = \ - $(top_builddir)/src/libstrongswan/libstrongswan.la \ - $(am__DEPENDENCIES_1) + $(top_builddir)/src/libstrongswan/libstrongswan.la DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -361,26 +264,23 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(libcharon_dbus_la_SOURCES) $(libcharon_eapaka_la_SOURCES) \ - $(libcharon_eapidentity_la_SOURCES) \ - $(libcharon_eapmd5_la_SOURCES) \ - $(libcharon_eapsim_file_la_SOURCES) \ - $(libcharon_eapsim_la_SOURCES) $(libcharon_local_la_SOURCES) \ - $(libcharon_sqlite_la_SOURCES) $(libcharon_stroke_la_SOURCES) \ - $(libcharon_xml_la_SOURCES) $(charon_SOURCES) -DIST_SOURCES = $(am__libcharon_dbus_la_SOURCES_DIST) \ - $(am__libcharon_eapaka_la_SOURCES_DIST) \ - $(am__libcharon_eapidentity_la_SOURCES_DIST) \ - $(am__libcharon_eapmd5_la_SOURCES_DIST) \ - $(am__libcharon_eapsim_file_la_SOURCES_DIST) \ - $(am__libcharon_eapsim_la_SOURCES_DIST) \ - $(am__libcharon_local_la_SOURCES_DIST) \ - $(am__libcharon_sqlite_la_SOURCES_DIST) \ - $(am__libcharon_stroke_la_SOURCES_DIST) \ - $(am__libcharon_xml_la_SOURCES_DIST) \ - $(am__charon_SOURCES_DIST) +SOURCES = $(charon_SOURCES) +DIST_SOURCES = $(am__charon_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags +DIST_SUBDIRS = . plugins/unit_tester plugins/stroke plugins/smp \ + plugins/sql plugins/eap_identity plugins/eap_sim \ + plugins/eap_md5 plugins/eap_aka plugins/medsrv plugins/medcli \ + plugins/uci DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -401,6 +301,7 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ @@ -430,6 +331,7 @@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ @@ -460,7 +362,6 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ -backenddir = @backenddir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -471,12 +372,11 @@ builddir = @builddir@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ -dbus_CFLAGS = @dbus_CFLAGS@ -dbus_LIBS = @dbus_LIBS@ docdir = @docdir@ dvidir = @dvidir@ -eapdir = @eapdir@ exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -486,12 +386,12 @@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ -interfacedir = @interfacedir@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ -ipsecuid = @ipsecuid@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ libdir = @libdir@ libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ linuxdir = @linuxdir@ localedir = @localedir@ localstatedir = @localstatedir@ @@ -504,10 +404,12 @@ plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +resolv_conf = @resolv_conf@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ simreader = @simreader@ srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ @@ -516,18 +418,19 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ charon_SOURCES = bus/bus.c bus/bus.h bus/listeners/file_logger.c \ bus/listeners/file_logger.h bus/listeners/sys_logger.c \ - bus/listeners/sys_logger.h config/backends/backend.h \ - config/backends/writeable_backend.h config/backend_manager.c \ - config/backend_manager.h config/child_cfg.c config/child_cfg.h \ - config/credentials/local_credential_store.c \ - config/credentials/local_credential_store.h config/ike_cfg.c \ - config/ike_cfg.h config/peer_cfg.c config/peer_cfg.h \ - config/proposal.c config/proposal.h config/traffic_selector.c \ - config/traffic_selector.h control/interfaces/interface.h \ - control/interface_manager.c control/interface_manager.h \ - daemon.c daemon.h encoding/generator.c encoding/generator.h \ - encoding/message.c encoding/message.h encoding/parser.c \ - encoding/parser.h encoding/payloads/auth_payload.c \ + bus/listeners/sys_logger.h config/backend_manager.c \ + config/backend_manager.h config/backend.h config/child_cfg.c \ + config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \ + config/peer_cfg.c config/peer_cfg.h config/proposal.c \ + config/proposal.h config/traffic_selector.c \ + config/traffic_selector.h \ + config/attributes/attribute_provider.h \ + config/attributes/attribute_manager.c \ + config/attributes/attribute_manager.h control/controller.c \ + control/controller.h daemon.c daemon.h encoding/generator.c \ + encoding/generator.h encoding/message.c encoding/message.h \ + encoding/parser.c encoding/parser.h \ + encoding/payloads/auth_payload.c \ encoding/payloads/auth_payload.h \ encoding/payloads/cert_payload.c \ encoding/payloads/cert_payload.h \ @@ -595,74 +498,57 @@ charon_SOURCES = bus/bus.c bus/bus.h bus/listeners/file_logger.c \ sa/authenticators/eap_authenticator.h \ sa/authenticators/eap/eap_method.c \ sa/authenticators/eap/eap_method.h \ + sa/authenticators/eap/eap_manager.c \ + sa/authenticators/eap/eap_manager.h \ sa/authenticators/psk_authenticator.c \ sa/authenticators/psk_authenticator.h \ - sa/authenticators/rsa_authenticator.c \ - sa/authenticators/rsa_authenticator.h sa/child_sa.c \ + sa/authenticators/pubkey_authenticator.c \ + sa/authenticators/pubkey_authenticator.h sa/child_sa.c \ sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \ sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \ sa/task_manager.c sa/task_manager.h sa/tasks/child_create.c \ sa/tasks/child_create.h sa/tasks/child_delete.c \ sa/tasks/child_delete.h sa/tasks/child_rekey.c \ sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \ - sa/tasks/ike_cert.c sa/tasks/ike_cert.h sa/tasks/ike_config.c \ - sa/tasks/ike_config.h sa/tasks/ike_delete.c \ - sa/tasks/ike_delete.h sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \ - sa/tasks/ike_init.c sa/tasks/ike_init.h sa/tasks/ike_natd.c \ - sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \ + sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \ + sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \ + sa/tasks/ike_config.c sa/tasks/ike_config.h \ + sa/tasks/ike_delete.c sa/tasks/ike_delete.h sa/tasks/ike_dpd.c \ + sa/tasks/ike_dpd.h sa/tasks/ike_init.c sa/tasks/ike_init.h \ + sa/tasks/ike_natd.c sa/tasks/ike_natd.h sa/tasks/ike_mobike.c \ sa/tasks/ike_mobike.h sa/tasks/ike_rekey.c \ sa/tasks/ike_rekey.h sa/tasks/ike_reauth.c \ sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \ sa/tasks/ike_auth_lifetime.h sa/tasks/task.c sa/tasks/task.h \ - $(am__append_1) $(am__append_2) $(am__append_3) -INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke \ - $(am__append_13) $(am__append_15) -AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \ - -DIPSEC_EAPDIR=\"${eapdir}\" -DIPSEC_BACKENDDIR=\"${backenddir}\" -DIPSEC_INTERFACEDIR=\"${interfacedir}\" \ - -DSIM_READER_LIB=\"${simreader}\" - -charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \ - -lgmp -lpthread -lm -ldl $(am__append_4) - -# build EAP plugins -################### -eap_LTLIBRARIES = $(am__append_5) $(am__append_6) $(am__append_7) \ - $(am__append_8) -@USE_EAP_IDENTITY_TRUE@libcharon_eapidentity_la_SOURCES = sa/authenticators/eap/eap_identity.h sa/authenticators/eap/eap_identity.c -@USE_EAP_IDENTITY_TRUE@libcharon_eapidentity_la_LDFLAGS = -module -@USE_EAP_SIM_TRUE@libcharon_eapsim_la_SOURCES = sa/authenticators/eap/eap_sim.h sa/authenticators/eap/eap_sim.c -@USE_EAP_SIM_TRUE@libcharon_eapsim_la_LDFLAGS = -module -@USE_EAP_SIM_TRUE@plugin_LTLIBRARIES = libcharon-eapsim-file.la -@USE_EAP_SIM_TRUE@libcharon_eapsim_file_la_SOURCES = sa/authenticators/eap/sim/eap_sim_file.c -@USE_EAP_SIM_TRUE@libcharon_eapsim_file_la_LDFLAGS = -module -@USE_EAP_MD5_TRUE@libcharon_eapmd5_la_SOURCES = sa/authenticators/eap/eap_md5.h sa/authenticators/eap/eap_md5.c -@USE_EAP_MD5_TRUE@libcharon_eapmd5_la_LDFLAGS = -module -@USE_EAP_AKA_TRUE@libcharon_eapaka_la_SOURCES = sa/authenticators/eap/eap_aka.h sa/authenticators/eap/eap_aka.c -@USE_EAP_AKA_TRUE@libcharon_eapaka_la_LDFLAGS = -module - -# build backends -################ -backend_LTLIBRARIES = $(am__append_9) $(am__append_10) -@USE_STROKE_TRUE@libcharon_local_la_SOURCES = config/backends/local_backend.h config/backends/local_backend.c -@USE_STROKE_TRUE@libcharon_local_la_LDFLAGS = -module -@USE_LIBSQLITE_TRUE@libcharon_sqlite_la_SOURCES = config/backends/sqlite_backend.h config/backends/sqlite_backend.c -@USE_LIBSQLITE_TRUE@libcharon_sqlite_la_LIBADD = -lsqlite3 -@USE_LIBSQLITE_TRUE@libcharon_sqlite_la_LDFLAGS = -module - -# build control interfaces -########################## -interface_LTLIBRARIES = $(am__append_11) $(am__append_12) \ - $(am__append_14) -@USE_STROKE_TRUE@libcharon_stroke_la_SOURCES = control/interfaces/stroke_interface.h control/interfaces/stroke_interface.c -@USE_STROKE_TRUE@libcharon_stroke_la_LDFLAGS = -module -@USE_LIBDBUS_TRUE@libcharon_dbus_la_SOURCES = control/interfaces/dbus_interface.h control/interfaces/dbus_interface.c -@USE_LIBDBUS_TRUE@libcharon_dbus_la_LDFLAGS = -module -@USE_LIBDBUS_TRUE@libcharon_dbus_la_LIBADD = ${dbus_LIBS} -@USE_LIBXML_TRUE@libcharon_xml_la_SOURCES = control/interfaces/xml_interface.h control/interfaces/xml_interface.c -@USE_LIBXML_TRUE@libcharon_xml_la_LDFLAGS = -module -@USE_LIBXML_TRUE@libcharon_xml_la_LIBADD = ${xml_LIBS} -all: all-am + credentials/credential_manager.c \ + credentials/credential_manager.h credentials/auth_info.c \ + credentials/auth_info.h credentials/sets/auth_info_wrapper.c \ + credentials/sets/auth_info_wrapper.h \ + credentials/sets/ocsp_response_wrapper.c \ + credentials/sets/ocsp_response_wrapper.h \ + credentials/sets/cert_cache.c credentials/sets/cert_cache.h \ + credentials/credential_set.h $(am__append_1) $(am__append_2) \ + $(am__append_3) +INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic -DIPSEC_DIR=\"${ipsecdir}\" \ + -DIPSEC_PIDDIR=\"${piddir}\" \ + -DIPSEC_PLUGINDIR=\"${plugindir}\" \ + -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ + -DRESOLV_CONF=\"${resolv_conf}\" $(am__append_4) \ + $(am__append_5) -DPLUGINS=\""${PLUGINS}\"" +charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lm -ldl + +# build optional plugins +######################## +SUBDIRS = . $(am__append_6) $(am__append_8) $(am__append_10) \ + $(am__append_12) $(am__append_14) $(am__append_16) \ + $(am__append_18) $(am__append_20) $(am__append_22) \ + $(am__append_24) $(am__append_26) +PLUGINS = ${libstrongswan_plugins} $(am__append_7) $(am__append_9) \ + $(am__append_11) $(am__append_13) $(am__append_15) \ + $(am__append_17) $(am__append_19) $(am__append_21) \ + $(am__append_23) $(am__append_25) $(am__append_27) +all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj @@ -695,134 +581,6 @@ $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-backendLTLIBRARIES: $(backend_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(backenddir)" || $(MKDIR_P) "$(DESTDIR)$(backenddir)" - @list='$(backend_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(backendLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(backenddir)/$$f'"; \ - $(LIBTOOL) --mode=install $(backendLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(backenddir)/$$f"; \ - else :; fi; \ - done - -uninstall-backendLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(backend_LTLIBRARIES)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(backenddir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(backenddir)/$$p"; \ - done - -clean-backendLTLIBRARIES: - -test -z "$(backend_LTLIBRARIES)" || rm -f $(backend_LTLIBRARIES) - @list='$(backend_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -install-eapLTLIBRARIES: $(eap_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(eapdir)" || $(MKDIR_P) "$(DESTDIR)$(eapdir)" - @list='$(eap_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(eapLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(eapdir)/$$f'"; \ - $(LIBTOOL) --mode=install $(eapLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(eapdir)/$$f"; \ - else :; fi; \ - done - -uninstall-eapLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(eap_LTLIBRARIES)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(eapdir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(eapdir)/$$p"; \ - done - -clean-eapLTLIBRARIES: - -test -z "$(eap_LTLIBRARIES)" || rm -f $(eap_LTLIBRARIES) - @list='$(eap_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -install-interfaceLTLIBRARIES: $(interface_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(interfacedir)" || $(MKDIR_P) "$(DESTDIR)$(interfacedir)" - @list='$(interface_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(interfaceLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(interfacedir)/$$f'"; \ - $(LIBTOOL) --mode=install $(interfaceLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(interfacedir)/$$f"; \ - else :; fi; \ - done - -uninstall-interfaceLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(interface_LTLIBRARIES)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(interfacedir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(interfacedir)/$$p"; \ - done - -clean-interfaceLTLIBRARIES: - -test -z "$(interface_LTLIBRARIES)" || rm -f $(interface_LTLIBRARIES) - @list='$(interface_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" - @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ - $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ - else :; fi; \ - done - -uninstall-pluginLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ - done - -clean-pluginLTLIBRARIES: - -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) - @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libcharon-dbus.la: $(libcharon_dbus_la_OBJECTS) $(libcharon_dbus_la_DEPENDENCIES) - $(libcharon_dbus_la_LINK) $(am_libcharon_dbus_la_rpath) $(libcharon_dbus_la_OBJECTS) $(libcharon_dbus_la_LIBADD) $(LIBS) -libcharon-eapaka.la: $(libcharon_eapaka_la_OBJECTS) $(libcharon_eapaka_la_DEPENDENCIES) - $(libcharon_eapaka_la_LINK) $(am_libcharon_eapaka_la_rpath) $(libcharon_eapaka_la_OBJECTS) $(libcharon_eapaka_la_LIBADD) $(LIBS) -libcharon-eapidentity.la: $(libcharon_eapidentity_la_OBJECTS) $(libcharon_eapidentity_la_DEPENDENCIES) - $(libcharon_eapidentity_la_LINK) $(am_libcharon_eapidentity_la_rpath) $(libcharon_eapidentity_la_OBJECTS) $(libcharon_eapidentity_la_LIBADD) $(LIBS) -libcharon-eapmd5.la: $(libcharon_eapmd5_la_OBJECTS) $(libcharon_eapmd5_la_DEPENDENCIES) - $(libcharon_eapmd5_la_LINK) $(am_libcharon_eapmd5_la_rpath) $(libcharon_eapmd5_la_OBJECTS) $(libcharon_eapmd5_la_LIBADD) $(LIBS) -libcharon-eapsim-file.la: $(libcharon_eapsim_file_la_OBJECTS) $(libcharon_eapsim_file_la_DEPENDENCIES) - $(libcharon_eapsim_file_la_LINK) $(am_libcharon_eapsim_file_la_rpath) $(libcharon_eapsim_file_la_OBJECTS) $(libcharon_eapsim_file_la_LIBADD) $(LIBS) -libcharon-eapsim.la: $(libcharon_eapsim_la_OBJECTS) $(libcharon_eapsim_la_DEPENDENCIES) - $(libcharon_eapsim_la_LINK) $(am_libcharon_eapsim_la_rpath) $(libcharon_eapsim_la_OBJECTS) $(libcharon_eapsim_la_LIBADD) $(LIBS) -libcharon-local.la: $(libcharon_local_la_OBJECTS) $(libcharon_local_la_DEPENDENCIES) - $(libcharon_local_la_LINK) $(am_libcharon_local_la_rpath) $(libcharon_local_la_OBJECTS) $(libcharon_local_la_LIBADD) $(LIBS) -libcharon-sqlite.la: $(libcharon_sqlite_la_OBJECTS) $(libcharon_sqlite_la_DEPENDENCIES) - $(libcharon_sqlite_la_LINK) $(am_libcharon_sqlite_la_rpath) $(libcharon_sqlite_la_OBJECTS) $(libcharon_sqlite_la_LIBADD) $(LIBS) -libcharon-stroke.la: $(libcharon_stroke_la_OBJECTS) $(libcharon_stroke_la_DEPENDENCIES) - $(libcharon_stroke_la_LINK) $(am_libcharon_stroke_la_rpath) $(libcharon_stroke_la_OBJECTS) $(libcharon_stroke_la_LIBADD) $(LIBS) -libcharon-xml.la: $(libcharon_xml_la_OBJECTS) $(libcharon_xml_la_DEPENDENCIES) - $(libcharon_xml_la_LINK) $(am_libcharon_xml_la_rpath) $(libcharon_xml_la_OBJECTS) $(libcharon_xml_la_LIBADD) $(LIBS) install-ipsecPROGRAMS: $(ipsec_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" @@ -832,8 +590,8 @@ install-ipsecPROGRAMS: $(ipsec_PROGRAMS) || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(ipsecPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(ipsecdir)/$$f'"; \ - $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(ipsecPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(ipsecdir)/$$f" || exit 1; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(ipsecPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(ipsecdir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(ipsecPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(ipsecdir)/$$f" || exit 1; \ else :; fi; \ done @@ -862,11 +620,15 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acquire_job.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attribute_manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_info.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_info_wrapper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authenticator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback_job.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certreq_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_cfg.Po@am__quote@ @@ -876,20 +638,17 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_sa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration_attribute.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp_payload.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/credential_manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus_interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_child_sa_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_ike_sa_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_payload.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_authenticator.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_identity.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_md5.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_method.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_payload.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encodings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encryption_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/endpoint_notify.Po@am__quote@ @@ -898,32 +657,31 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/id_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth_lifetime.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cert.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cert_post.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cert_pre.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_cfg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_delete.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_dpd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_header.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_me.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_mobike.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_natd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_p2p.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_reauth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_rekey.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_id.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initiate_mediation_job.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface_manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ke_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_interface.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_backend.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_credential_store.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_payload.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/payload.Po@am__quote@ @@ -933,12 +691,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal_substructure.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk_authenticator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey_authenticator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receiver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_child_sa_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rekey_ike_sa_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retransmit_job.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/roam_job.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsa_authenticator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sa_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheduler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/send_dpd_job.Po@am__quote@ @@ -946,8 +704,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sender.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket-raw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sqlite_backend.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_logger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_manager.Po@am__quote@ @@ -958,7 +714,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ts_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unknown_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendor_id_payload.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_interface.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -981,76 +736,6 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< -dbus_interface.lo: control/interfaces/dbus_interface.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dbus_interface.lo -MD -MP -MF $(DEPDIR)/dbus_interface.Tpo -c -o dbus_interface.lo `test -f 'control/interfaces/dbus_interface.c' || echo '$(srcdir)/'`control/interfaces/dbus_interface.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dbus_interface.Tpo $(DEPDIR)/dbus_interface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/interfaces/dbus_interface.c' object='dbus_interface.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 dbus_interface.lo `test -f 'control/interfaces/dbus_interface.c' || echo '$(srcdir)/'`control/interfaces/dbus_interface.c - -eap_aka.lo: sa/authenticators/eap/eap_aka.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_aka.lo -MD -MP -MF $(DEPDIR)/eap_aka.Tpo -c -o eap_aka.lo `test -f 'sa/authenticators/eap/eap_aka.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_aka.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_aka.Tpo $(DEPDIR)/eap_aka.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_aka.c' object='eap_aka.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 eap_aka.lo `test -f 'sa/authenticators/eap/eap_aka.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_aka.c - -eap_identity.lo: sa/authenticators/eap/eap_identity.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_identity.lo -MD -MP -MF $(DEPDIR)/eap_identity.Tpo -c -o eap_identity.lo `test -f 'sa/authenticators/eap/eap_identity.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_identity.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_identity.Tpo $(DEPDIR)/eap_identity.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_identity.c' object='eap_identity.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 eap_identity.lo `test -f 'sa/authenticators/eap/eap_identity.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_identity.c - -eap_md5.lo: sa/authenticators/eap/eap_md5.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_md5.lo -MD -MP -MF $(DEPDIR)/eap_md5.Tpo -c -o eap_md5.lo `test -f 'sa/authenticators/eap/eap_md5.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_md5.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_md5.Tpo $(DEPDIR)/eap_md5.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_md5.c' object='eap_md5.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 eap_md5.lo `test -f 'sa/authenticators/eap/eap_md5.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_md5.c - -eap_sim_file.lo: sa/authenticators/eap/sim/eap_sim_file.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_sim_file.lo -MD -MP -MF $(DEPDIR)/eap_sim_file.Tpo -c -o eap_sim_file.lo `test -f 'sa/authenticators/eap/sim/eap_sim_file.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim/eap_sim_file.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_sim_file.Tpo $(DEPDIR)/eap_sim_file.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/sim/eap_sim_file.c' object='eap_sim_file.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 eap_sim_file.lo `test -f 'sa/authenticators/eap/sim/eap_sim_file.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim/eap_sim_file.c - -eap_sim.lo: sa/authenticators/eap/eap_sim.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_sim.lo -MD -MP -MF $(DEPDIR)/eap_sim.Tpo -c -o eap_sim.lo `test -f 'sa/authenticators/eap/eap_sim.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_sim.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_sim.Tpo $(DEPDIR)/eap_sim.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_sim.c' object='eap_sim.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 eap_sim.lo `test -f 'sa/authenticators/eap/eap_sim.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_sim.c - -local_backend.lo: config/backends/local_backend.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT local_backend.lo -MD -MP -MF $(DEPDIR)/local_backend.Tpo -c -o local_backend.lo `test -f 'config/backends/local_backend.c' || echo '$(srcdir)/'`config/backends/local_backend.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/local_backend.Tpo $(DEPDIR)/local_backend.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/backends/local_backend.c' object='local_backend.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 local_backend.lo `test -f 'config/backends/local_backend.c' || echo '$(srcdir)/'`config/backends/local_backend.c - -sqlite_backend.lo: config/backends/sqlite_backend.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sqlite_backend.lo -MD -MP -MF $(DEPDIR)/sqlite_backend.Tpo -c -o sqlite_backend.lo `test -f 'config/backends/sqlite_backend.c' || echo '$(srcdir)/'`config/backends/sqlite_backend.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/sqlite_backend.Tpo $(DEPDIR)/sqlite_backend.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/backends/sqlite_backend.c' object='sqlite_backend.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 sqlite_backend.lo `test -f 'config/backends/sqlite_backend.c' || echo '$(srcdir)/'`config/backends/sqlite_backend.c - -stroke_interface.lo: control/interfaces/stroke_interface.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stroke_interface.lo -MD -MP -MF $(DEPDIR)/stroke_interface.Tpo -c -o stroke_interface.lo `test -f 'control/interfaces/stroke_interface.c' || echo '$(srcdir)/'`control/interfaces/stroke_interface.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stroke_interface.Tpo $(DEPDIR)/stroke_interface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/interfaces/stroke_interface.c' object='stroke_interface.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 stroke_interface.lo `test -f 'control/interfaces/stroke_interface.c' || echo '$(srcdir)/'`control/interfaces/stroke_interface.c - -xml_interface.lo: control/interfaces/xml_interface.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xml_interface.lo -MD -MP -MF $(DEPDIR)/xml_interface.Tpo -c -o xml_interface.lo `test -f 'control/interfaces/xml_interface.c' || echo '$(srcdir)/'`control/interfaces/xml_interface.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/xml_interface.Tpo $(DEPDIR)/xml_interface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/interfaces/xml_interface.c' object='xml_interface.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 xml_interface.lo `test -f 'control/interfaces/xml_interface.c' || echo '$(srcdir)/'`control/interfaces/xml_interface.c - bus.o: bus/bus.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bus.o -MD -MP -MF $(DEPDIR)/bus.Tpo -c -o bus.o `test -f 'bus/bus.c' || echo '$(srcdir)/'`bus/bus.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/bus.Tpo $(DEPDIR)/bus.Po @@ -1121,20 +806,6 @@ child_cfg.obj: config/child_cfg.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o child_cfg.obj `if test -f 'config/child_cfg.c'; then $(CYGPATH_W) 'config/child_cfg.c'; else $(CYGPATH_W) '$(srcdir)/config/child_cfg.c'; fi` -local_credential_store.o: config/credentials/local_credential_store.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT local_credential_store.o -MD -MP -MF $(DEPDIR)/local_credential_store.Tpo -c -o local_credential_store.o `test -f 'config/credentials/local_credential_store.c' || echo '$(srcdir)/'`config/credentials/local_credential_store.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/local_credential_store.Tpo $(DEPDIR)/local_credential_store.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/credentials/local_credential_store.c' object='local_credential_store.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o local_credential_store.o `test -f 'config/credentials/local_credential_store.c' || echo '$(srcdir)/'`config/credentials/local_credential_store.c - -local_credential_store.obj: config/credentials/local_credential_store.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT local_credential_store.obj -MD -MP -MF $(DEPDIR)/local_credential_store.Tpo -c -o local_credential_store.obj `if test -f 'config/credentials/local_credential_store.c'; then $(CYGPATH_W) 'config/credentials/local_credential_store.c'; else $(CYGPATH_W) '$(srcdir)/config/credentials/local_credential_store.c'; fi` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/local_credential_store.Tpo $(DEPDIR)/local_credential_store.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/credentials/local_credential_store.c' object='local_credential_store.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o local_credential_store.obj `if test -f 'config/credentials/local_credential_store.c'; then $(CYGPATH_W) 'config/credentials/local_credential_store.c'; else $(CYGPATH_W) '$(srcdir)/config/credentials/local_credential_store.c'; fi` - ike_cfg.o: config/ike_cfg.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cfg.o -MD -MP -MF $(DEPDIR)/ike_cfg.Tpo -c -o ike_cfg.o `test -f 'config/ike_cfg.c' || echo '$(srcdir)/'`config/ike_cfg.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_cfg.Tpo $(DEPDIR)/ike_cfg.Po @@ -1191,19 +862,33 @@ traffic_selector.obj: config/traffic_selector.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o traffic_selector.obj `if test -f 'config/traffic_selector.c'; then $(CYGPATH_W) 'config/traffic_selector.c'; else $(CYGPATH_W) '$(srcdir)/config/traffic_selector.c'; fi` -interface_manager.o: control/interface_manager.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT interface_manager.o -MD -MP -MF $(DEPDIR)/interface_manager.Tpo -c -o interface_manager.o `test -f 'control/interface_manager.c' || echo '$(srcdir)/'`control/interface_manager.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/interface_manager.Tpo $(DEPDIR)/interface_manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/interface_manager.c' object='interface_manager.o' libtool=no @AMDEPBACKSLASH@ +attribute_manager.o: config/attributes/attribute_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attribute_manager.o -MD -MP -MF $(DEPDIR)/attribute_manager.Tpo -c -o attribute_manager.o `test -f 'config/attributes/attribute_manager.c' || echo '$(srcdir)/'`config/attributes/attribute_manager.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/attribute_manager.Tpo $(DEPDIR)/attribute_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/attributes/attribute_manager.c' object='attribute_manager.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attribute_manager.o `test -f 'config/attributes/attribute_manager.c' || echo '$(srcdir)/'`config/attributes/attribute_manager.c + +attribute_manager.obj: config/attributes/attribute_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT attribute_manager.obj -MD -MP -MF $(DEPDIR)/attribute_manager.Tpo -c -o attribute_manager.obj `if test -f 'config/attributes/attribute_manager.c'; then $(CYGPATH_W) 'config/attributes/attribute_manager.c'; else $(CYGPATH_W) '$(srcdir)/config/attributes/attribute_manager.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/attribute_manager.Tpo $(DEPDIR)/attribute_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/attributes/attribute_manager.c' object='attribute_manager.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o interface_manager.o `test -f 'control/interface_manager.c' || echo '$(srcdir)/'`control/interface_manager.c +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o attribute_manager.obj `if test -f 'config/attributes/attribute_manager.c'; then $(CYGPATH_W) 'config/attributes/attribute_manager.c'; else $(CYGPATH_W) '$(srcdir)/config/attributes/attribute_manager.c'; fi` -interface_manager.obj: control/interface_manager.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT interface_manager.obj -MD -MP -MF $(DEPDIR)/interface_manager.Tpo -c -o interface_manager.obj `if test -f 'control/interface_manager.c'; then $(CYGPATH_W) 'control/interface_manager.c'; else $(CYGPATH_W) '$(srcdir)/control/interface_manager.c'; fi` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/interface_manager.Tpo $(DEPDIR)/interface_manager.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/interface_manager.c' object='interface_manager.obj' libtool=no @AMDEPBACKSLASH@ +controller.o: control/controller.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT controller.o -MD -MP -MF $(DEPDIR)/controller.Tpo -c -o controller.o `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/controller.Tpo $(DEPDIR)/controller.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/controller.c' object='controller.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o interface_manager.obj `if test -f 'control/interface_manager.c'; then $(CYGPATH_W) 'control/interface_manager.c'; else $(CYGPATH_W) '$(srcdir)/control/interface_manager.c'; fi` +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o controller.o `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c + +controller.obj: control/controller.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT controller.obj -MD -MP -MF $(DEPDIR)/controller.Tpo -c -o controller.obj `if test -f 'control/controller.c'; then $(CYGPATH_W) 'control/controller.c'; else $(CYGPATH_W) '$(srcdir)/control/controller.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/controller.Tpo $(DEPDIR)/controller.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='control/controller.c' object='controller.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o controller.obj `if test -f 'control/controller.c'; then $(CYGPATH_W) 'control/controller.c'; else $(CYGPATH_W) '$(srcdir)/control/controller.c'; fi` generator.o: encoding/generator.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT generator.o -MD -MP -MF $(DEPDIR)/generator.Tpo -c -o generator.o `test -f 'encoding/generator.c' || echo '$(srcdir)/'`encoding/generator.c @@ -1849,6 +1534,20 @@ eap_method.obj: sa/authenticators/eap/eap_method.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_method.obj `if test -f 'sa/authenticators/eap/eap_method.c'; then $(CYGPATH_W) 'sa/authenticators/eap/eap_method.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/eap_method.c'; fi` +eap_manager.o: sa/authenticators/eap/eap_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_manager.o -MD -MP -MF $(DEPDIR)/eap_manager.Tpo -c -o eap_manager.o `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_manager.Tpo $(DEPDIR)/eap_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_manager.c' object='eap_manager.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_manager.o `test -f 'sa/authenticators/eap/eap_manager.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_manager.c + +eap_manager.obj: sa/authenticators/eap/eap_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_manager.obj -MD -MP -MF $(DEPDIR)/eap_manager.Tpo -c -o eap_manager.obj `if test -f 'sa/authenticators/eap/eap_manager.c'; then $(CYGPATH_W) 'sa/authenticators/eap/eap_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/eap_manager.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_manager.Tpo $(DEPDIR)/eap_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/eap_manager.c' object='eap_manager.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_manager.obj `if test -f 'sa/authenticators/eap/eap_manager.c'; then $(CYGPATH_W) 'sa/authenticators/eap/eap_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/eap/eap_manager.c'; fi` + psk_authenticator.o: sa/authenticators/psk_authenticator.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT psk_authenticator.o -MD -MP -MF $(DEPDIR)/psk_authenticator.Tpo -c -o psk_authenticator.o `test -f 'sa/authenticators/psk_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/psk_authenticator.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/psk_authenticator.Tpo $(DEPDIR)/psk_authenticator.Po @@ -1863,19 +1562,19 @@ psk_authenticator.obj: sa/authenticators/psk_authenticator.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psk_authenticator.obj `if test -f 'sa/authenticators/psk_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/psk_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/psk_authenticator.c'; fi` -rsa_authenticator.o: sa/authenticators/rsa_authenticator.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsa_authenticator.o -MD -MP -MF $(DEPDIR)/rsa_authenticator.Tpo -c -o rsa_authenticator.o `test -f 'sa/authenticators/rsa_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/rsa_authenticator.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsa_authenticator.Tpo $(DEPDIR)/rsa_authenticator.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/rsa_authenticator.c' object='rsa_authenticator.o' libtool=no @AMDEPBACKSLASH@ +pubkey_authenticator.o: sa/authenticators/pubkey_authenticator.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_authenticator.o -MD -MP -MF $(DEPDIR)/pubkey_authenticator.Tpo -c -o pubkey_authenticator.o `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/pubkey_authenticator.Tpo $(DEPDIR)/pubkey_authenticator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/pubkey_authenticator.c' object='pubkey_authenticator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsa_authenticator.o `test -f 'sa/authenticators/rsa_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/rsa_authenticator.c +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_authenticator.o `test -f 'sa/authenticators/pubkey_authenticator.c' || echo '$(srcdir)/'`sa/authenticators/pubkey_authenticator.c -rsa_authenticator.obj: sa/authenticators/rsa_authenticator.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsa_authenticator.obj -MD -MP -MF $(DEPDIR)/rsa_authenticator.Tpo -c -o rsa_authenticator.obj `if test -f 'sa/authenticators/rsa_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/rsa_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/rsa_authenticator.c'; fi` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsa_authenticator.Tpo $(DEPDIR)/rsa_authenticator.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/rsa_authenticator.c' object='rsa_authenticator.obj' libtool=no @AMDEPBACKSLASH@ +pubkey_authenticator.obj: sa/authenticators/pubkey_authenticator.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pubkey_authenticator.obj -MD -MP -MF $(DEPDIR)/pubkey_authenticator.Tpo -c -o pubkey_authenticator.obj `if test -f 'sa/authenticators/pubkey_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/pubkey_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/pubkey_authenticator.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/pubkey_authenticator.Tpo $(DEPDIR)/pubkey_authenticator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/pubkey_authenticator.c' object='pubkey_authenticator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsa_authenticator.obj `if test -f 'sa/authenticators/rsa_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/rsa_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/rsa_authenticator.c'; fi` +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pubkey_authenticator.obj `if test -f 'sa/authenticators/pubkey_authenticator.c'; then $(CYGPATH_W) 'sa/authenticators/pubkey_authenticator.c'; else $(CYGPATH_W) '$(srcdir)/sa/authenticators/pubkey_authenticator.c'; fi` child_sa.o: sa/child_sa.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_sa.o -MD -MP -MF $(DEPDIR)/child_sa.Tpo -c -o child_sa.o `test -f 'sa/child_sa.c' || echo '$(srcdir)/'`sa/child_sa.c @@ -2003,19 +1702,33 @@ ike_auth.obj: sa/tasks/ike_auth.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth.obj `if test -f 'sa/tasks/ike_auth.c'; then $(CYGPATH_W) 'sa/tasks/ike_auth.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_auth.c'; fi` -ike_cert.o: sa/tasks/ike_cert.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert.o -MD -MP -MF $(DEPDIR)/ike_cert.Tpo -c -o ike_cert.o `test -f 'sa/tasks/ike_cert.c' || echo '$(srcdir)/'`sa/tasks/ike_cert.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_cert.Tpo $(DEPDIR)/ike_cert.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert.c' object='ike_cert.o' libtool=no @AMDEPBACKSLASH@ +ike_cert_pre.o: sa/tasks/ike_cert_pre.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_pre.o -MD -MP -MF $(DEPDIR)/ike_cert_pre.Tpo -c -o ike_cert_pre.o `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_cert_pre.Tpo $(DEPDIR)/ike_cert_pre.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_pre.c' object='ike_cert_pre.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_pre.o `test -f 'sa/tasks/ike_cert_pre.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_pre.c + +ike_cert_pre.obj: sa/tasks/ike_cert_pre.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_pre.obj -MD -MP -MF $(DEPDIR)/ike_cert_pre.Tpo -c -o ike_cert_pre.obj `if test -f 'sa/tasks/ike_cert_pre.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_pre.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_pre.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_cert_pre.Tpo $(DEPDIR)/ike_cert_pre.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_pre.c' object='ike_cert_pre.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_pre.obj `if test -f 'sa/tasks/ike_cert_pre.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_pre.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_pre.c'; fi` + +ike_cert_post.o: sa/tasks/ike_cert_post.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_post.o -MD -MP -MF $(DEPDIR)/ike_cert_post.Tpo -c -o ike_cert_post.o `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_cert_post.Tpo $(DEPDIR)/ike_cert_post.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_post.c' object='ike_cert_post.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert.o `test -f 'sa/tasks/ike_cert.c' || echo '$(srcdir)/'`sa/tasks/ike_cert.c +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_post.o `test -f 'sa/tasks/ike_cert_post.c' || echo '$(srcdir)/'`sa/tasks/ike_cert_post.c -ike_cert.obj: sa/tasks/ike_cert.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert.obj -MD -MP -MF $(DEPDIR)/ike_cert.Tpo -c -o ike_cert.obj `if test -f 'sa/tasks/ike_cert.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert.c'; fi` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_cert.Tpo $(DEPDIR)/ike_cert.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert.c' object='ike_cert.obj' libtool=no @AMDEPBACKSLASH@ +ike_cert_post.obj: sa/tasks/ike_cert_post.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_cert_post.obj -MD -MP -MF $(DEPDIR)/ike_cert_post.Tpo -c -o ike_cert_post.obj `if test -f 'sa/tasks/ike_cert_post.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_post.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_post.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_cert_post.Tpo $(DEPDIR)/ike_cert_post.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_cert_post.c' object='ike_cert_post.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert.obj `if test -f 'sa/tasks/ike_cert.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert.c'; fi` +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_cert_post.obj `if test -f 'sa/tasks/ike_cert_post.c'; then $(CYGPATH_W) 'sa/tasks/ike_cert_post.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_cert_post.c'; fi` ike_config.o: sa/tasks/ike_config.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_config.o -MD -MP -MF $(DEPDIR)/ike_config.Tpo -c -o ike_config.o `test -f 'sa/tasks/ike_config.c' || echo '$(srcdir)/'`sa/tasks/ike_config.c @@ -2157,6 +1870,76 @@ task.obj: sa/tasks/task.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.obj `if test -f 'sa/tasks/task.c'; then $(CYGPATH_W) 'sa/tasks/task.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/task.c'; fi` +credential_manager.o: credentials/credential_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.o -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.o `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o credential_manager.o `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c + +credential_manager.obj: credentials/credential_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.obj -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.obj `if test -f 'credentials/credential_manager.c'; then $(CYGPATH_W) 'credentials/credential_manager.c'; else $(CYGPATH_W) '$(srcdir)/credentials/credential_manager.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o credential_manager.obj `if test -f 'credentials/credential_manager.c'; then $(CYGPATH_W) 'credentials/credential_manager.c'; else $(CYGPATH_W) '$(srcdir)/credentials/credential_manager.c'; fi` + +auth_info.o: credentials/auth_info.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_info.o -MD -MP -MF $(DEPDIR)/auth_info.Tpo -c -o auth_info.o `test -f 'credentials/auth_info.c' || echo '$(srcdir)/'`credentials/auth_info.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/auth_info.Tpo $(DEPDIR)/auth_info.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/auth_info.c' object='auth_info.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_info.o `test -f 'credentials/auth_info.c' || echo '$(srcdir)/'`credentials/auth_info.c + +auth_info.obj: credentials/auth_info.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_info.obj -MD -MP -MF $(DEPDIR)/auth_info.Tpo -c -o auth_info.obj `if test -f 'credentials/auth_info.c'; then $(CYGPATH_W) 'credentials/auth_info.c'; else $(CYGPATH_W) '$(srcdir)/credentials/auth_info.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/auth_info.Tpo $(DEPDIR)/auth_info.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/auth_info.c' object='auth_info.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_info.obj `if test -f 'credentials/auth_info.c'; then $(CYGPATH_W) 'credentials/auth_info.c'; else $(CYGPATH_W) '$(srcdir)/credentials/auth_info.c'; fi` + +auth_info_wrapper.o: credentials/sets/auth_info_wrapper.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_info_wrapper.o -MD -MP -MF $(DEPDIR)/auth_info_wrapper.Tpo -c -o auth_info_wrapper.o `test -f 'credentials/sets/auth_info_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_info_wrapper.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/auth_info_wrapper.Tpo $(DEPDIR)/auth_info_wrapper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_info_wrapper.c' object='auth_info_wrapper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_info_wrapper.o `test -f 'credentials/sets/auth_info_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_info_wrapper.c + +auth_info_wrapper.obj: credentials/sets/auth_info_wrapper.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_info_wrapper.obj -MD -MP -MF $(DEPDIR)/auth_info_wrapper.Tpo -c -o auth_info_wrapper.obj `if test -f 'credentials/sets/auth_info_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/auth_info_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/auth_info_wrapper.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/auth_info_wrapper.Tpo $(DEPDIR)/auth_info_wrapper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_info_wrapper.c' object='auth_info_wrapper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_info_wrapper.obj `if test -f 'credentials/sets/auth_info_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/auth_info_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/auth_info_wrapper.c'; fi` + +ocsp_response_wrapper.o: credentials/sets/ocsp_response_wrapper.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.o -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.o `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ocsp_response_wrapper.o `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c + +ocsp_response_wrapper.obj: credentials/sets/ocsp_response_wrapper.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.obj -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.obj `if test -f 'credentials/sets/ocsp_response_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/ocsp_response_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/ocsp_response_wrapper.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ocsp_response_wrapper.obj `if test -f 'credentials/sets/ocsp_response_wrapper.c'; then $(CYGPATH_W) 'credentials/sets/ocsp_response_wrapper.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/ocsp_response_wrapper.c'; fi` + +cert_cache.o: credentials/sets/cert_cache.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.o -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.o `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_cache.o `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c + +cert_cache.obj: credentials/sets/cert_cache.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.obj -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.obj `if test -f 'credentials/sets/cert_cache.c'; then $(CYGPATH_W) 'credentials/sets/cert_cache.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/cert_cache.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_cache.obj `if test -f 'credentials/sets/cert_cache.c'; then $(CYGPATH_W) 'credentials/sets/cert_cache.c'; else $(CYGPATH_W) '$(srcdir)/credentials/sets/cert_cache.c'; fi` + socket-raw.o: network/socket-raw.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket-raw.o -MD -MP -MF $(DEPDIR)/socket-raw.Tpo -c -o socket-raw.o `test -f 'network/socket-raw.c' || echo '$(srcdir)/'`network/socket-raw.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/socket-raw.Tpo $(DEPDIR)/socket-raw.Po @@ -2255,19 +2038,19 @@ mediation_manager.obj: sa/mediation_manager.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mediation_manager.obj `if test -f 'sa/mediation_manager.c'; then $(CYGPATH_W) 'sa/mediation_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/mediation_manager.c'; fi` -ike_p2p.o: sa/tasks/ike_p2p.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_p2p.o -MD -MP -MF $(DEPDIR)/ike_p2p.Tpo -c -o ike_p2p.o `test -f 'sa/tasks/ike_p2p.c' || echo '$(srcdir)/'`sa/tasks/ike_p2p.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_p2p.Tpo $(DEPDIR)/ike_p2p.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_p2p.c' object='ike_p2p.o' libtool=no @AMDEPBACKSLASH@ +ike_me.o: sa/tasks/ike_me.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_me.o -MD -MP -MF $(DEPDIR)/ike_me.Tpo -c -o ike_me.o `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_me.Tpo $(DEPDIR)/ike_me.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_me.c' object='ike_me.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_p2p.o `test -f 'sa/tasks/ike_p2p.c' || echo '$(srcdir)/'`sa/tasks/ike_p2p.c +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_me.o `test -f 'sa/tasks/ike_me.c' || echo '$(srcdir)/'`sa/tasks/ike_me.c -ike_p2p.obj: sa/tasks/ike_p2p.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_p2p.obj -MD -MP -MF $(DEPDIR)/ike_p2p.Tpo -c -o ike_p2p.obj `if test -f 'sa/tasks/ike_p2p.c'; then $(CYGPATH_W) 'sa/tasks/ike_p2p.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_p2p.c'; fi` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_p2p.Tpo $(DEPDIR)/ike_p2p.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_p2p.c' object='ike_p2p.obj' libtool=no @AMDEPBACKSLASH@ +ike_me.obj: sa/tasks/ike_me.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_me.obj -MD -MP -MF $(DEPDIR)/ike_me.Tpo -c -o ike_me.obj `if test -f 'sa/tasks/ike_me.c'; then $(CYGPATH_W) 'sa/tasks/ike_me.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_me.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ike_me.Tpo $(DEPDIR)/ike_me.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/tasks/ike_me.c' object='ike_me.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_p2p.obj `if test -f 'sa/tasks/ike_p2p.c'; then $(CYGPATH_W) 'sa/tasks/ike_p2p.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_p2p.c'; fi` +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_me.obj `if test -f 'sa/tasks/ike_me.c'; then $(CYGPATH_W) 'sa/tasks/ike_me.c'; else $(CYGPATH_W) '$(srcdir)/sa/tasks/ike_me.c'; fi` mostlyclean-libtool: -rm -f *.lo @@ -2275,42 +2058,124 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -2349,22 +2214,40 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ + fi; \ + done check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) -installdirs: - for dir in "$(DESTDIR)$(backenddir)" "$(DESTDIR)$(eapdir)" "$(DESTDIR)$(interfacedir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)"; do \ +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(ipsecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-am +installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ @@ -2380,91 +2263,83 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -clean: clean-am +clean: clean-recursive -clean-am: clean-backendLTLIBRARIES clean-eapLTLIBRARIES clean-generic \ - clean-interfaceLTLIBRARIES clean-ipsecPROGRAMS clean-libtool \ - clean-pluginLTLIBRARIES mostlyclean-am +clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \ + mostlyclean-am -distclean: distclean-am +distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags -dvi: dvi-am +dvi: dvi-recursive dvi-am: -html: html-am +html: html-recursive -info: info-am +info: info-recursive info-am: -install-data-am: install-backendLTLIBRARIES install-eapLTLIBRARIES \ - install-interfaceLTLIBRARIES install-ipsecPROGRAMS \ - install-pluginLTLIBRARIES +install-data-am: install-ipsecPROGRAMS -install-dvi: install-dvi-am +install-dvi: install-dvi-recursive install-exec-am: -install-html: install-html-am +install-html: install-html-recursive -install-info: install-info-am +install-info: install-info-recursive install-man: -install-pdf: install-pdf-am +install-pdf: install-pdf-recursive -install-ps: install-ps-am +install-ps: install-ps-recursive installcheck-am: -maintainer-clean: maintainer-clean-am +maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-am +mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool -pdf: pdf-am +pdf: pdf-recursive pdf-am: -ps: ps-am +ps: ps-recursive ps-am: -uninstall-am: uninstall-backendLTLIBRARIES uninstall-eapLTLIBRARIES \ - uninstall-interfaceLTLIBRARIES uninstall-ipsecPROGRAMS \ - uninstall-pluginLTLIBRARIES +uninstall-am: uninstall-ipsecPROGRAMS -.MAKE: install-am install-strip +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip -.PHONY: CTAGS GTAGS all all-am check check-am clean \ - clean-backendLTLIBRARIES clean-eapLTLIBRARIES clean-generic \ - clean-interfaceLTLIBRARIES clean-ipsecPROGRAMS clean-libtool \ - clean-pluginLTLIBRARIES ctags distclean distclean-compile \ - distclean-generic distclean-libtool distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-backendLTLIBRARIES install-data install-data-am \ - install-dvi install-dvi-am install-eapLTLIBRARIES install-exec \ +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-ipsecPROGRAMS clean-libtool ctags ctags-recursive \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ - install-info-am install-interfaceLTLIBRARIES \ - install-ipsecPROGRAMS install-man install-pdf install-pdf-am \ - install-pluginLTLIBRARIES install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ + install-info-am install-ipsecPROGRAMS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am \ - uninstall-backendLTLIBRARIES uninstall-eapLTLIBRARIES \ - uninstall-interfaceLTLIBRARIES uninstall-ipsecPROGRAMS \ - uninstall-pluginLTLIBRARIES + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-ipsecPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/charon/bus/bus.c b/src/charon/bus/bus.c index e53ac43ce..1b12f8735 100644 --- a/src/charon/bus/bus.c +++ b/src/charon/bus/bus.c @@ -1,10 +1,3 @@ -/** - * @file bus.c - * - * @brief Implementation of bus_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: bus.c 3589 2008-03-13 14:14:44Z martin $ */ #include "bus.h" @@ -25,6 +20,7 @@ #include <pthread.h> #include <daemon.h> +#include <utils/mutex.h> ENUM(signal_names, SIG_ANY, SIG_MAX, /** should not get printed */ @@ -72,9 +68,9 @@ struct private_bus_t { linked_list_t *listeners; /** - * mutex to synchronize active listeners + * mutex to synchronize active listeners, recursively */ - pthread_mutex_t mutex; + mutex_t *mutex; /** * Thread local storage for a unique, simple thread ID @@ -107,7 +103,7 @@ struct entry_t { /** * condvar where active listeners wait */ - pthread_cond_t cond; + condvar_t *condvar; }; /** @@ -119,12 +115,21 @@ static entry_t *entry_create(bus_listener_t *listener, bool blocker) this->listener = listener; this->blocker = blocker; - pthread_cond_init(&this->cond, NULL); + this->condvar = condvar_create(CONDVAR_DEFAULT); return this; } /** + * destroy an entry_t + */ +static void entry_destroy(entry_t *entry) +{ + entry->condvar->destroy(entry->condvar); + free(entry); +} + +/** * Get a unique thread number for a calling thread. Since * pthread_self returns large and ugly numbers, use this function * for logging; these numbers are incremental starting at 1 @@ -151,9 +156,9 @@ static int get_thread_number(private_bus_t *this) */ static void add_listener(private_bus_t *this, bus_listener_t *listener) { - pthread_mutex_lock(&this->mutex); + this->mutex->lock(this->mutex); this->listeners->insert_last(this->listeners, entry_create(listener, FALSE)); - pthread_mutex_unlock(&this->mutex); + this->mutex->unlock(this->mutex); } /** @@ -164,19 +169,19 @@ static void remove_listener(private_bus_t *this, bus_listener_t *listener) iterator_t *iterator; entry_t *entry; - pthread_mutex_lock(&this->mutex); + this->mutex->lock(this->mutex); iterator = this->listeners->create_iterator(this->listeners, TRUE); while (iterator->iterate(iterator, (void**)&entry)) { if (entry->listener == listener) { iterator->remove(iterator); - free(entry); + entry_destroy(entry); break; } } iterator->destroy(iterator); - pthread_mutex_unlock(&this->mutex); + this->mutex->unlock(this->mutex); } typedef struct cleanup_data_t cleanup_data_t; @@ -205,7 +210,7 @@ static void listener_cleanup(cleanup_data_t *data) if (entry == data->entry) { iterator->remove(iterator); - free(entry); + entry_destroy(entry); break; } } @@ -223,21 +228,21 @@ static void listen_(private_bus_t *this, bus_listener_t *listener, job_t *job) data.this = this; data.entry = entry_create(listener, TRUE); - pthread_mutex_lock(&this->mutex); + this->mutex->lock(this->mutex); this->listeners->insert_last(this->listeners, data.entry); charon->processor->queue_job(charon->processor, job); - pthread_cleanup_push((void*)pthread_mutex_unlock, &this->mutex); + pthread_cleanup_push((void*)this->mutex->unlock, this->mutex); pthread_cleanup_push((void*)listener_cleanup, &data); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old); while (data.entry->blocker) { - pthread_cond_wait(&data.entry->cond, &this->mutex); + data.entry->condvar->wait(data.entry->condvar, this->mutex); } pthread_setcancelstate(old, NULL); pthread_cleanup_pop(FALSE); /* unlock mutex */ pthread_cleanup_pop(TRUE); - free(data.entry); + entry_destroy(data.entry); } /** @@ -248,6 +253,7 @@ static void set_sa(private_bus_t *this, ike_sa_t *ike_sa) pthread_setspecific(this->thread_sa, ike_sa); } + /** * Implementation of bus_t.vsignal. */ @@ -259,7 +265,7 @@ static void vsignal(private_bus_t *this, signal_t signal, level_t level, ike_sa_t *ike_sa; long thread; - pthread_mutex_lock(&this->mutex); + this->mutex->lock(this->mutex); ike_sa = pthread_getspecific(this->thread_sa); thread = get_thread_number(this); @@ -275,18 +281,18 @@ static void vsignal(private_bus_t *this, signal_t signal, level_t level, if (entry->blocker) { entry->blocker = FALSE; - pthread_cond_signal(&entry->cond); + entry->condvar->signal(entry->condvar); } else { - free(entry); + entry_destroy(entry); } } va_end(args_copy); } iterator->destroy(iterator); - pthread_mutex_unlock(&this->mutex); + this->mutex->unlock(this->mutex); } /** @@ -307,7 +313,8 @@ static void signal_(private_bus_t *this, signal_t signal, level_t level, */ static void destroy(private_bus_t *this) { - this->listeners->destroy_function(this->listeners, free); + this->mutex->destroy(this->mutex); + this->listeners->destroy_function(this->listeners, (void*)entry_destroy); free(this); } @@ -327,7 +334,7 @@ bus_t *bus_create() this->public.destroy = (void(*)(bus_t*)) destroy; this->listeners = linked_list_create(); - pthread_mutex_init(&this->mutex, NULL); + this->mutex = mutex_create(MUTEX_DEFAULT); pthread_key_create(&this->thread_id, NULL); pthread_key_create(&this->thread_sa, NULL); diff --git a/src/charon/bus/bus.h b/src/charon/bus/bus.h index f71018444..7fa2c42bc 100644 --- a/src/charon/bus/bus.h +++ b/src/charon/bus/bus.h @@ -1,10 +1,3 @@ -/** - * @file bus.h - * - * @brief Interface of bus_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: bus.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup bus bus + * @{ @ingroup charon */ #ifndef BUS_H_ @@ -36,7 +36,7 @@ typedef struct bus_t bus_t; /** - * @brief signals emitted by the daemon. + * signals emitted by the daemon. * * Signaling is for different purporses. First, it allows debugging via * "debugging signal messages", sencondly, it allows to follow certain @@ -52,8 +52,6 @@ typedef struct bus_t bus_t; * Debug signal betwee a START and a SUCCESS/FAILED belongs to that operation * if the IKE_SA is the same. The thread may change, as multiple threads * may be involved in a complex scenario. - * - * @ingroup bus */ enum signal_t { /** pseudo signal, representing any other signal */ @@ -157,7 +155,7 @@ enum level_t { #if DEBUG_LEVEL >= 1 /** - * @brief Log a debug message via the signal bus. + * Log a debug message via the signal bus. * * @param signal signal_t signal description * @param format printf() style format string @@ -189,7 +187,7 @@ enum level_t { #endif /* DBG4 */ /** - * @brief Raise a signal for an occured event. + * Raise a signal for an occured event. * * @param sig signal_t signal description * @param format printf() style format string @@ -198,7 +196,7 @@ enum level_t { #define SIG(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_0, format, ##__VA_ARGS__) /** - * @brief Get the type of a signal. + * Get the type of a signal. * * A signal may be a debugging signal with a specific context. They have * a level specific for their context > 0. All audit signals use the @@ -211,17 +209,15 @@ enum level_t { /** - * @brief Interface for registering at the signal bus. + * Interface for registering at the signal bus. * * To receive signals from the bus, the client implementing the * bus_listener_t interface registers itself at the signal bus. - * - * @ingroup bus */ struct bus_listener_t { /** - * @brief Send a signal to a bus listener. + * Send a signal to a bus listener. * * A numerical identification for the thread is included, as the * associated IKE_SA, if any. Signal specifies the type of @@ -231,8 +227,10 @@ struct bus_listener_t { * a "..." parameters to functions is not (cleanly) possible. * The implementing signal function returns TRUE to stay registered * to the bus, or FALSE to unregister itself. + * You should not call bus_t.signal() inside of a registered listener, + * as it WILL call itself recursively. If you do so, make shure to + * avoid infinite recursion. Watch your stack! * - * @param this listener * @param singal kind of the signal (up, down, rekeyed, ...) * @param level verbosity level of the signal * @param thread ID of the thread raised this signal @@ -246,40 +244,36 @@ struct bus_listener_t { }; /** - * @brief Signal bus which sends signals to registered listeners. + * Signal bus which sends signals to registered listeners. * * The signal bus is not much more than a multiplexer. A listener interested * in receiving event signals registers at the bus. Any signals sent to * are delivered to all registered listeners. * To deliver signals to threads, the blocking listen() call may be used * to wait for a signal. - * - * @ingroup bus */ struct bus_t { /** - * @brief Register a listener to the bus. + * Register a listener to the bus. * * A registered listener receives all signals which are sent to the bus. * The listener is passive; the thread which emitted the signal * processes the listener routine. * - * @param this bus * @param listener listener to register. */ void (*add_listener) (bus_t *this, bus_listener_t *listener); /** - * @brief Unregister a listener from the bus. + * Unregister a listener from the bus. * - * @param this bus * @param listener listener to unregister. */ void (*remove_listener) (bus_t *this, bus_listener_t *listener); /** - * @brief Register a listener and block the calling thread. + * Register a listener and block the calling thread. * * This call registers a listener and blocks the calling thread until * its listeners function returns FALSE. This allows to wait for certain @@ -287,14 +281,13 @@ struct bus_t { * registered, this allows to listen on events we initiate with the job * without missing any signals. * - * @param this bus * @param listener listener to register * @param job job to execute asynchronously when registered, or NULL */ void (*listen)(bus_t *this, bus_listener_t *listener, job_t *job); /** - * @brief Set the IKE_SA the calling thread is using. + * Set the IKE_SA the calling thread is using. * * To associate an received signal to an IKE_SA without passing it as * parameter each time, the thread registers it's used IKE_SA each @@ -302,13 +295,12 @@ struct bus_t { * the IKE_SA (by passing NULL). This IKE_SA is stored per-thread, so each * thread has one IKE_SA registered (or not). * - * @param this bus * @param ike_sa ike_sa to register, or NULL to unregister */ void (*set_sa) (bus_t *this, ike_sa_t *ike_sa); /** - * @brief Send a signal to the bus. + * Send a signal to the bus. * * The signal specifies the type of the event occured. The format string * specifies an additional informational or error message with a @@ -316,7 +308,6 @@ struct bus_t { * Some useful macros are available to shorten this call. * @see SIG(), DBG1() * - * @param this bus * @param singal kind of the signal (up, down, rekeyed, ...) * @param level verbosity level of the signal * @param format printf() style format string @@ -325,7 +316,7 @@ struct bus_t { void (*signal) (bus_t *this, signal_t signal, level_t level, char* format, ...); /** - * @brief Send a signal to the bus using va_list arguments. + * Send a signal to the bus using va_list arguments. * * Same as bus_t.signal(), but uses va_list argument list. * @@ -333,7 +324,6 @@ struct bus_t { * called extensively and therefore shouldn't allocate heap memory or * do other expensive tasks! * - * @param this bus * @param singal kind of the signal (up, down, rekeyed, ...) * @param level verbosity level of the signal * @param format printf() style format string @@ -342,20 +332,16 @@ struct bus_t { void (*vsignal) (bus_t *this, signal_t signal, level_t level, char* format, va_list args); /** - * @brief Destroy the signal bus. - * - * @param this bus to destroy + * Destroy the signal bus. */ void (*destroy) (bus_t *this); }; /** - * @brief Create the signal bus which multiplexes signals to its listeners. + * Create the signal bus which multiplexes signals to its listeners. * * @return signal bus instance - * - * @ingroup bus */ bus_t *bus_create(); -#endif /* BUS_H_ */ +#endif /* BUS_H_ @} */ diff --git a/src/charon/bus/listeners/file_logger.c b/src/charon/bus/listeners/file_logger.c index 14f9f72cf..f89da8529 100644 --- a/src/charon/bus/listeners/file_logger.c +++ b/src/charon/bus/listeners/file_logger.c @@ -1,10 +1,3 @@ -/** - * @file file_logger.c - * - * @brief Implementation of file_logger_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: file_logger.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stdio.h> diff --git a/src/charon/bus/listeners/file_logger.h b/src/charon/bus/listeners/file_logger.h index d67daba25..86b79c002 100644 --- a/src/charon/bus/listeners/file_logger.h +++ b/src/charon/bus/listeners/file_logger.h @@ -1,10 +1,3 @@ -/** - * @file file_logger.h - * - * @brief Interface of file_logger_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: file_logger.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup file_logger file_logger + * @{ @ingroup listeners */ #ifndef FILE_LOGGER_H_ @@ -28,12 +28,7 @@ typedef struct file_logger_t file_logger_t; #include <bus/bus.h> /** - * @brief Logger to files which implements bus_listener_t. - * - * @b Constructors: - * - file_logger_create() - * - * @ingroup listeners + * Logger to files which implements bus_listener_t. */ struct file_logger_t { @@ -43,31 +38,25 @@ struct file_logger_t { bus_listener_t listener; /** - * @brief Set the loglevel for a signal type. + * Set the loglevel for a signal type. * - * @param this stream_logger_t object * @param singal type of signal * @param level max level to log (0..4) */ void (*set_level) (file_logger_t *this, signal_t signal, level_t level); /** - * @brief Destroys a file_logger_t object. - * - * @param this file_logger_t object + * Destroys a file_logger_t object. */ void (*destroy) (file_logger_t *this); }; /** - * @brief Constructor to create a file_logger_t object. + * Constructor to create a file_logger_t object. * * @param out FILE to write to * @return file_logger_t object - * - * @ingroup listeners */ file_logger_t *file_logger_create(FILE *out); - -#endif /* FILE_LOGGER_H_ */ +#endif /* FILE_LOGGER_H_ @} */ diff --git a/src/charon/bus/listeners/sys_logger.c b/src/charon/bus/listeners/sys_logger.c index d26d14dc0..900fa3aa6 100644 --- a/src/charon/bus/listeners/sys_logger.c +++ b/src/charon/bus/listeners/sys_logger.c @@ -1,10 +1,3 @@ -/** - * @file sys_logger.c - * - * @brief Implementation of sys_logger_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: sys_logger.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stdio.h> diff --git a/src/charon/bus/listeners/sys_logger.h b/src/charon/bus/listeners/sys_logger.h index 091217313..0aade375a 100644 --- a/src/charon/bus/listeners/sys_logger.h +++ b/src/charon/bus/listeners/sys_logger.h @@ -1,10 +1,3 @@ -/** - * @file sys_logger.h - * - * @brief Interface of sys_logger_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: sys_logger.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup sys_logger sys_logger + * @{ @ingroup listeners */ #ifndef SYS_LOGGER_H_ @@ -30,12 +30,7 @@ typedef struct sys_logger_t sys_logger_t; #include <bus/bus.h> /** - * @brief Logger for syslog which implements bus_listener_t. - * - * @b Constructors: - * - sys_logger_create() - * - * @ingroup listeners + * Logger for syslog which implements bus_listener_t. */ struct sys_logger_t { @@ -45,31 +40,25 @@ struct sys_logger_t { bus_listener_t listener; /** - * @brief Set the loglevel for a signal type. + * Set the loglevel for a signal type. * - * @param this stream_logger_t object * @param singal type of signal * @param level max level to log */ void (*set_level) (sys_logger_t *this, signal_t signal, level_t level); /** - * @brief Destroys a sys_logger_t object. - * - * @param this sys_logger_t object + * Destroys a sys_logger_t object. */ void (*destroy) (sys_logger_t *this); }; /** - * @brief Constructor to create a sys_logger_t object. + * Constructor to create a sys_logger_t object. * * @param facility syslog facility to use * @return sys_logger_t object - * - * @ingroup listeners */ sys_logger_t *sys_logger_create(int facility); - -#endif /* SYS_LOGGER_H_ */ +#endif /* SYS_LOGGER_H_ @} */ diff --git a/src/charon/config/attributes/attribute_manager.c b/src/charon/config/attributes/attribute_manager.c new file mode 100644 index 000000000..0ec84c7be --- /dev/null +++ b/src/charon/config/attributes/attribute_manager.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "attribute_manager.h" + +#include <utils/linked_list.h> +#include <utils/mutex.h> + +typedef struct private_attribute_manager_t private_attribute_manager_t; + +/** + * private data of attribute_manager + */ +struct private_attribute_manager_t { + + /** + * public functions + */ + attribute_manager_t public; + + /** + * list of registered providers + */ + linked_list_t *providers; + + /** + * mutex to lock provider list + */ + mutex_t *mutex; +}; + +/** + * Implementation of attribute_manager_t.acquire_address. + */ +static host_t* acquire_address(private_attribute_manager_t *this, + char *pool, identification_t *id, + auth_info_t *auth, host_t *requested) +{ + enumerator_t *enumerator; + attribute_provider_t *current; + host_t *host = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, ¤t)) + { + host = current->acquire_address(current, pool, id, auth, requested); + if (host) + { + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + return host; +} + +/** + * Implementation of attribute_manager_t.release_address. + */ +static void release_address(private_attribute_manager_t *this, + char *pool, host_t *address) +{ + enumerator_t *enumerator; + attribute_provider_t *current; + + this->mutex->lock(this->mutex); + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->release_address(current, pool, address)) + { + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of attribute_manager_t.add_provider. + */ +static void add_provider(private_attribute_manager_t *this, + attribute_provider_t *provider) +{ + this->mutex->lock(this->mutex); + this->providers->insert_last(this->providers, provider); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of attribute_manager_t.remove_provider. + */ +static void remove_provider(private_attribute_manager_t *this, + attribute_provider_t *provider) +{ + this->mutex->lock(this->mutex); + this->providers->remove(this->providers, provider, NULL); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of attribute_manager_t.destroy + */ +static void destroy(private_attribute_manager_t *this) +{ + this->providers->destroy(this->providers); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +attribute_manager_t *attribute_manager_create() +{ + private_attribute_manager_t *this = malloc_thing(private_attribute_manager_t); + + this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,auth_info_t*,host_t*))acquire_address; + this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*))release_address; + this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider; + this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider; + this->public.destroy = (void(*)(attribute_manager_t*))destroy; + + this->providers = linked_list_create(); + this->mutex = mutex_create(MUTEX_DEFAULT); + + return &this->public; +} + diff --git a/src/charon/config/attributes/attribute_manager.h b/src/charon/config/attributes/attribute_manager.h new file mode 100644 index 000000000..540e054fd --- /dev/null +++ b/src/charon/config/attributes/attribute_manager.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup attribute_manager attribute_manager + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_MANAGER_H_ +#define ATTRIBUTE_MANAGER_H_ + +#include <config/attributes/attribute_provider.h> + +typedef struct attribute_manager_t attribute_manager_t; + +/** + * Provide configuration attributes to include in CFG Payloads. + */ +struct attribute_manager_t { + + /** + * Acquire a virtual IP address to assign to a peer. + * + * @param pool pool name to acquire address from + * @param id peer identity to get address for + * @param auth authorization infos of peer + * @param requested IP in configuration request + * @return allocated address, NULL to serve none + */ + host_t* (*acquire_address)(attribute_manager_t *this, + char *pool, identification_t *id, + auth_info_t *auth, host_t *requested); + + /** + * Release a previously acquired address. + * + * @param pool pool name from which the address was acquired + * @param address address to release + */ + void (*release_address)(attribute_manager_t *this, + char *pool, host_t *address); + + /** + * Register an attribute provider to the manager. + * + * @param provider attribute provider to register + */ + void (*add_provider)(attribute_manager_t *this, + attribute_provider_t *provider); + /** + * Unregister an attribute provider from the manager. + * + * @param provider attribute provider to unregister + */ + void (*remove_provider)(attribute_manager_t *this, + attribute_provider_t *provider); + /** + * Destroy a attribute_manager instance. + */ + void (*destroy)(attribute_manager_t *this); +}; + +/** + * Create a attribute_manager instance. + */ +attribute_manager_t *attribute_manager_create(); + +#endif /* ATTRIBUTE_MANAGER_H_ @}*/ diff --git a/src/charon/config/attributes/attribute_provider.h b/src/charon/config/attributes/attribute_provider.h new file mode 100644 index 000000000..1712bd188 --- /dev/null +++ b/src/charon/config/attributes/attribute_provider.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup attribute_provider attribute_provider + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_PROVIDER_H_ +#define ATTRIBUTE_PROVIDER_H_ + +#include <library.h> +#include <utils/host.h> +#include <credentials/auth_info.h> + +typedef struct attribute_provider_t attribute_provider_t; + +/** + * Interface to provide attributes to peers through attribute manager. + */ +struct attribute_provider_t { + + /** + * Acquire a virtual IP address to assign to a peer. + * + * @param pool name of the pool to acquire address from + * @param id peer ID + * @param auth authorization infos + * @param requested IP in configuration request + * @return allocated address, NULL to serve none + */ + host_t* (*acquire_address)(attribute_provider_t *this, + char *pool, identification_t *id, + auth_info_t *auth, host_t *requested); + /** + * Release a previously acquired address. + * + * @param pool name of the pool this address was acquired from + * @param address address to release + * @return TRUE if the address has been released by the provider + */ + bool (*release_address)(attribute_provider_t *this, + char *pool, host_t *address); +}; + +#endif /* ATTRIBUTE_PROVIDER_H_ @}*/ diff --git a/src/charon/config/backend.h b/src/charon/config/backend.h new file mode 100644 index 000000000..ec2c481bd --- /dev/null +++ b/src/charon/config/backend.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007-2008 Martin Willi + * 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. + * + * $Id: backend.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup backend backend + * @{ @ingroup config + */ + +#ifndef BACKEND_H_ +#define BACKEND_H_ + +typedef struct backend_t backend_t; + +#include <library.h> +#include <config/ike_cfg.h> +#include <config/peer_cfg.h> +#include <credentials/auth_info.h> +#include <utils/linked_list.h> + +/** + * The interface for a configuration backend. + * + * A configuration backend is loaded into the backend_manager. It does the actual + * configuration lookup for the method it implements. See backend_manager_t for + * more information. + */ +struct backend_t { + + /** + * Create an enumerator over all IKE configs matching two hosts. + * + * Hosts may be NULL to get all. + * + * @param me address of local host + * @param other address of remote host + * @return enumerator over ike_cfg_t's + */ + enumerator_t* (*create_ike_cfg_enumerator)(backend_t *this, + host_t *me, host_t *other); + /** + * Create an enumerator over all Peer configs matching two IDs. + * + * IDs may be NULL to get all. + * + * @param me identity of ourself + * @param other identity of remote host + * @return enumerator over peer_cfg_t + */ + enumerator_t* (*create_peer_cfg_enumerator)(backend_t *this, + identification_t *me, + identification_t *other); + /** + * Get a peer_cfg identified by it's name, or a name of its child. + * + * @param name name of peer/child cfg + * @return matching peer_config, or NULL if none found + */ + peer_cfg_t *(*get_peer_cfg_by_name)(backend_t *this, char *name); +}; + +#endif /* BACKEND_H_ @} */ diff --git a/src/charon/config/backend_manager.c b/src/charon/config/backend_manager.c index b2104acea..d77c05fd7 100644 --- a/src/charon/config/backend_manager.c +++ b/src/charon/config/backend_manager.c @@ -1,10 +1,3 @@ -/** - * @file backend_manager.c - * - * @brief Implementation of backend_manager_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,18 +11,18 @@ * 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. + * + * $Id: backend_manager.c 4044 2008-06-06 15:05:54Z martin $ */ #include "backend_manager.h" #include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <dlfcn.h> +#include <pthread.h> #include <daemon.h> #include <utils/linked_list.h> -#include <config/backends/writeable_backend.h> +#include <utils/mutex.h> typedef struct private_backend_manager_t private_backend_manager_t; @@ -50,164 +43,268 @@ struct private_backend_manager_t { linked_list_t *backends; /** - * Additional list of writable backends. + * locking mutex */ - linked_list_t *writeable; - - /** - * List of dlopen() handles we used to open backends - */ - linked_list_t *handles; + mutex_t *mutex; }; /** - * implements backend_manager_t.get_ike_cfg. + * data to pass nested IKE enumerator */ -static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, - host_t *my_host, host_t *other_host) +typedef struct { + private_backend_manager_t *this; + host_t *me; + host_t *other; +} ike_data_t; + +/** + * data to pass nested peer enumerator + */ +typedef struct { + private_backend_manager_t *this; + identification_t *me; + identification_t *other; +} peer_data_t; + +/** + * destroy IKE enumerator data and unlock list + */ +static void ike_enum_destroy(ike_data_t *data) { - backend_t *backend; - ike_cfg_t *config = NULL; - iterator_t *iterator = this->backends->create_iterator(this->backends, TRUE); - while (config == NULL && iterator->iterate(iterator, (void**)&backend)) - { - config = backend->get_ike_cfg(backend, my_host, other_host); - } - iterator->destroy(iterator); - return config; + data->this->mutex->unlock(data->this->mutex); + free(data); } /** - * implements backend_manager_t.get_peer_cfg. - */ -static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info) + * destroy PEER enumerator data and unlock list + */ +static void peer_enum_destroy(peer_data_t *data) { - backend_t *backend; - peer_cfg_t *config = NULL; - iterator_t *iterator = this->backends->create_iterator(this->backends, TRUE); - while (config == NULL && iterator->iterate(iterator, (void**)&backend)) - { - config = backend->get_peer_cfg(backend, my_id, other_id, other_ca_info); - } - iterator->destroy(iterator); - return config; + data->this->mutex->unlock(data->this->mutex); + free(data); } /** - * implements backend_manager_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *name) + * inner enumerator constructor for IKE cfgs + */ +static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data) { - backend_t *backend; - peer_cfg_t *config = NULL; - iterator_t *iterator = this->backends->create_iterator(this->backends, TRUE); - while (config == NULL && iterator->iterate(iterator, (void**)&backend)) - { - config = backend->get_peer_cfg_by_name(backend, name); - } - iterator->destroy(iterator); - return config; + return backend->create_ike_cfg_enumerator(backend, data->me, data->other); } /** - * implements backend_manager_t.add_peer_cfg. - */ -static void add_peer_cfg(private_backend_manager_t *this, peer_cfg_t *config) + * inner enumerator constructor for Peer cfgs + */ +static enumerator_t *peer_enum_create(backend_t *backend, peer_data_t *data) { - writeable_backend_t *backend; - - if (this->writeable->get_first(this->writeable, (void**)&backend) == SUCCESS) - { - backend->add_cfg(backend, config); - } + return backend->create_peer_cfg_enumerator(backend, data->me, data->other); } - /** - * implements backend_manager_t.create_iterator. - */ -static iterator_t* create_iterator(private_backend_manager_t *this) + * inner enumerator constructor for all Peer cfgs + */ +static enumerator_t *peer_enum_create_all(backend_t *backend) { - writeable_backend_t *backend; - - if (this->writeable->get_first(this->writeable, (void**)&backend) == SUCCESS) - { - return backend->create_iterator(backend); - } - /* give out an empty iterator if we have no writable backend*/ - return this->writeable->create_iterator(this->writeable, TRUE); + return backend->create_peer_cfg_enumerator(backend, NULL, NULL); } /** - * load the configuration backend modules + * implements backend_manager_t.get_ike_cfg. */ -static void load_backends(private_backend_manager_t *this) +static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, + host_t *me, host_t *other) { - struct dirent* entry; - DIR* dir; - - dir = opendir(IPSEC_BACKENDDIR); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening backend modules directory "IPSEC_BACKENDDIR); - return; - } + ike_cfg_t *current, *found = NULL; + enumerator_t *enumerator; + host_t *my_candidate, *other_candidate; + ike_data_t *data; + enum { + MATCH_NONE = 0x00, + MATCH_ANY = 0x01, + MATCH_ME = 0x04, + MATCH_OTHER = 0x08, + } prio, best = MATCH_ANY; - DBG1(DBG_CFG, "loading backend modules from '"IPSEC_BACKENDDIR"'"); - - while ((entry = readdir(dir)) != NULL) + data = malloc_thing(ike_data_t); + data->this = this; + data->me = me; + data->other = other; + + DBG2(DBG_CFG, "looking for a config for %H...%H", me, other); + + this->mutex->lock(this->mutex); + enumerator = enumerator_create_nested( + this->backends->create_enumerator(this->backends), + (void*)ike_enum_create, data, (void*)ike_enum_destroy); + while (enumerator->enumerate(enumerator, (void**)¤t)) { - char file[256]; - backend_t *backend; - backend_constructor_t constructor; - void *handle; - char *ending; - - snprintf(file, sizeof(file), IPSEC_BACKENDDIR"/%s", entry->d_name); + prio = MATCH_NONE; - ending = entry->d_name + strlen(entry->d_name) - 3; - if (ending <= entry->d_name || !streq(ending, ".so")) + my_candidate = host_create_from_dns(current->get_my_addr(current), + me->get_family(me), 0); + if (!my_candidate) { - /* skip anything which does not look like a library */ - DBG2(DBG_CFG, " skipping %s, doesn't look like a library", - entry->d_name); continue; } - /* try to load the library */ - handle = dlopen(file, RTLD_LAZY); - if (handle == NULL) + if (my_candidate->ip_equals(my_candidate, me)) { - DBG1(DBG_CFG, " opening backend module %s failed: %s", - entry->d_name, dlerror()); - continue; + prio += MATCH_ME; } - constructor = dlsym(handle, "backend_create"); - if (constructor == NULL) + else if (my_candidate->is_anyaddr(my_candidate)) { - DBG1(DBG_CFG, " backend module %s has no backend_create() " - "function, skipped", entry->d_name); - dlclose(handle); - continue; + prio += MATCH_ANY; } + my_candidate->destroy(my_candidate); - backend = constructor(); - if (backend == NULL) + other_candidate = host_create_from_dns(current->get_other_addr(current), + other->get_family(other), 0); + if (!other_candidate) { - DBG1(DBG_CFG, " unable to create instance of backend " - "module %s, skipped", entry->d_name); - dlclose(handle); continue; } - DBG1(DBG_CFG, " loaded backend module successfully from %s", entry->d_name); - this->backends->insert_last(this->backends, backend); - if (backend->is_writeable(backend)) + if (other_candidate->ip_equals(other_candidate, other)) + { + prio += MATCH_OTHER; + } + else if (other_candidate->is_anyaddr(other_candidate)) + { + prio += MATCH_ANY; + } + other_candidate->destroy(other_candidate); + + DBG2(DBG_CFG, " candidate: %s...%s, prio %d", + current->get_my_addr(current), current->get_other_addr(current), + prio); + + /* we require at least two MATCH_ANY */ + if (prio > best) { - this->writeable->insert_last(this->writeable, backend); + best = prio; + DESTROY_IF(found); + found = current; + found->get_ref(found); } - this->handles->insert_last(this->handles, handle); } - closedir(dir); + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return found; +} + + +static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this) +{ + this->mutex->lock(this->mutex); + return enumerator_create_nested( + this->backends->create_enumerator(this->backends), + (void*)peer_enum_create_all, this->mutex, + (void*)this->mutex->unlock); +} + +/** + * implements backend_manager_t.get_peer_cfg. + */ +static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, + identification_t *me, identification_t *other, + auth_info_t *auth) +{ + peer_cfg_t *current, *found = NULL; + enumerator_t *enumerator; + identification_t *my_candidate, *other_candidate; + id_match_t best = ID_MATCH_NONE; + peer_data_t *data; + + DBG2(DBG_CFG, "looking for a config for %D...%D", me, other); + + data = malloc_thing(peer_data_t); + data->this = this; + data->me = me; + data->other = other; + + this->mutex->lock(this->mutex); + enumerator = enumerator_create_nested( + this->backends->create_enumerator(this->backends), + (void*)peer_enum_create, data, (void*)peer_enum_destroy); + while (enumerator->enumerate(enumerator, ¤t)) + { + id_match_t m1, m2, sum; + + my_candidate = current->get_my_id(current); + other_candidate = current->get_other_id(current); + + /* own ID may have wildcards in both, config and request (missing IDr) */ + m1 = my_candidate->matches(my_candidate, me); + if (!m1) + { + m1 = me->matches(me, my_candidate); + } + m2 = other->matches(other, other_candidate); + sum = m1 + m2; + + if (m1 && m2) + { + if (auth->complies(auth, current->get_auth(current))) + { + DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d", + current->get_name(current), my_candidate, + other_candidate, sum); + if (sum > best) + { + DESTROY_IF(found); + found = current; + found->get_ref(found); + best = sum; + } + } + } + } + if (found) + { + DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d", + found->get_name(found), found->get_my_id(found), + found->get_other_id(found), best); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return found; +} + +/** + * implements backend_manager_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *name) +{ + backend_t *backend; + peer_cfg_t *config = NULL; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->backends->create_enumerator(this->backends); + while (config == NULL && enumerator->enumerate(enumerator, (void**)&backend)) + { + config = backend->get_peer_cfg_by_name(backend, name); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + return config; +} + +/** + * Implementation of backend_manager_t.remove_backend. + */ +static void remove_backend(private_backend_manager_t *this, backend_t *backend) +{ + this->mutex->lock(this->mutex); + this->backends->remove(this->backends, backend, NULL); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of backend_manager_t.add_backend. + */ +static void add_backend(private_backend_manager_t *this, backend_t *backend) +{ + this->mutex->lock(this->mutex); + this->backends->insert_last(this->backends, backend); + this->mutex->unlock(this->mutex); } /** @@ -215,9 +312,8 @@ static void load_backends(private_backend_manager_t *this) */ static void destroy(private_backend_manager_t *this) { - this->backends->destroy_offset(this->backends, offsetof(backend_t, destroy)); - this->writeable->destroy(this->writeable); - this->handles->destroy_function(this->handles, (void*)dlclose); + this->backends->destroy(this->backends); + this->mutex->destroy(this->mutex); free(this); } @@ -229,17 +325,15 @@ backend_manager_t *backend_manager_create() private_backend_manager_t *this = malloc_thing(private_backend_manager_t); this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg; - this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg; + this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,identification_t*,identification_t*,auth_info_t*))get_peer_cfg; this->public.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_manager_t*,char*))get_peer_cfg_by_name; - this->public.add_peer_cfg = (void (*)(backend_manager_t*,peer_cfg_t*))add_peer_cfg; - this->public.create_iterator = (iterator_t* (*)(backend_manager_t*))create_iterator; + this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*))create_peer_cfg_enumerator; + this->public.add_backend = (void(*)(backend_manager_t*, backend_t *backend))add_backend; + this->public.remove_backend = (void(*)(backend_manager_t*, backend_t *backend))remove_backend; this->public.destroy = (void (*)(backend_manager_t*))destroy; this->backends = linked_list_create(); - this->writeable = linked_list_create(); - this->handles = linked_list_create(); - - load_backends(this); + this->mutex = mutex_create(MUTEX_RECURSIVE); return &this->public; } diff --git a/src/charon/config/backend_manager.h b/src/charon/config/backend_manager.h index 7ca6d660e..6400bd7fd 100644 --- a/src/charon/config/backend_manager.h +++ b/src/charon/config/backend_manager.h @@ -1,10 +1,3 @@ -/** - * @file backend_manager.h - * - * @brief Interface backend_manager_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: backend_manager.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup backend_manager backend_manager + * @{ @ingroup config */ #ifndef BACKEND_MANAGER_H_ @@ -30,20 +30,15 @@ typedef struct backend_manager_t backend_manager_t; #include <utils/identification.h> #include <config/ike_cfg.h> #include <config/peer_cfg.h> -#include <config/backends/backend.h> +#include <config/backend.h> /** - * @brief A loader and multiplexer to use multiple backends. + * A loader and multiplexer to use multiple backends. * * Charon allows the use of multiple configuration backends simultaneously. To * access all this backends by a single call, this class wraps multiple - * backends behind a single object. It is also responsible for loading - * the backend modules and cleaning them up. - * A backend may be writeable or not. All backends implement the backend_t - * interface, those who are writeable additionally implement the - * writeable_backend_t interface. Adding configs to the backend_manager will - * be redirected to the first writeable backend. + * backends behind a single object. * @verbatim +---------+ +-----------+ +--------------+ | @@ -55,18 +50,12 @@ typedef struct backend_manager_t backend_manager_t; +---------+ +-----------+ | @endverbatim - * - * @b Constructors: - * - backend_manager_create() - * - * @ingroup config */ struct backend_manager_t { /** - * @brief Get an ike_config identified by two hosts. + * Get an ike_config identified by two hosts. * - * @param this calling object * @param my_host address of own host * @param other_host address of remote host * @return matching ike_config, or NULL if none found @@ -75,59 +64,57 @@ struct backend_manager_t { host_t *my_host, host_t *other_host); /** - * @brief Get a peer_config identified by two IDs and the peer's certificate issuer + * Get a peer_config identified by two IDs and authorization info. * - * @param this calling object * @param my_id own ID * @param other_id peer ID - * @param other_ca_info info record on issuer of peer certificate + * @param auth_info authorization info * @return matching peer_config, or NULL if none found */ - peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info); + peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this, identification_t *my_id, + identification_t *other_id, auth_info_t *auth); /** - * @brief Get a peer_config identified by it's name. + * Get a peer_config identified by it's name. * - * @param this calling object * @param name name of the peer_config * @return matching peer_config, or NULL if none found */ peer_cfg_t* (*get_peer_cfg_by_name)(backend_manager_t *this, char *name); /** - * @brief Add a peer_config to the first found writable backend. + * Create an enumerator over all peer configs. * - * @param this calling object - * @param config peer_config to add to the backend + * @return enumerator over peer configs */ - void (*add_peer_cfg)(backend_manager_t *this, peer_cfg_t *config); + enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this); /** - * @brief Create an iterator over all peer configs of the writable backend. + * Register a backend on the manager. * - * @param this calling object - * @return iterator over peer configs + * @param backend backend to register */ - iterator_t* (*create_iterator)(backend_manager_t *this); + void (*add_backend)(backend_manager_t *this, backend_t *backend); /** - * @brief Destroys a backend_manager_t object. + * Unregister a backend. * - * @param this calling object + * @param backend backend to unregister + */ + void (*remove_backend)(backend_manager_t *this, backend_t *backend); + + /** + * Destroys a backend_manager_t object. */ void (*destroy) (backend_manager_t *this); }; /** - * @brief Creates a new instance of the manager and loads all backends. + * Create an instance of the backend manager * * @return backend_manager instance - * - * @ingroup config */ backend_manager_t* backend_manager_create(void); -#endif /*BACKEND_MANAGER_H_*/ +#endif /*BACKEND_MANAGER_H_ @} */ diff --git a/src/charon/config/backends/backend.h b/src/charon/config/backends/backend.h deleted file mode 100644 index 592d1dd4c..000000000 --- a/src/charon/config/backends/backend.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file backend.h - * - * @brief Interface backend_t. - * - */ - -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -#ifndef BACKEND_H_ -#define BACKEND_H_ - -typedef struct backend_t backend_t; - -#include <library.h> -#include <config/ike_cfg.h> -#include <config/peer_cfg.h> -#include <utils/linked_list.h> - -/** - * @brief The interface for a configuration backend. - * - * A configuration backend is loaded by the backend_manager. It does the actual - * configuration lookup for the method it implements. See backend_manager_t for - * more information. - * - * @b Constructors: - * - implementations constructors - * - * @ingroup backends - */ -struct backend_t { - - /** - * @brief Get an ike_cfg identified by two hosts. - * - * @param this calling object - * @param my_host address of own host - * @param other_host address of remote host - * @return matching ike_config, or NULL if none found - */ - ike_cfg_t *(*get_ike_cfg)(backend_t *this, - host_t *my_host, host_t *other_host); - - /** - * @brief Get a peer_cfg identified by two IDs. - * - * Select a config based on the two IDs and the other's certificate issuer - * - * @param this calling object - * @param my_id own ID - * @param other_id peer ID - * @param other_ca_info info record on issuer of peer certificate - * @return matching peer_config, or NULL if none found - */ - peer_cfg_t *(*get_peer_cfg)(backend_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info); - - /** - * @brief Get a peer_cfg identified by it's name, or a name of its child. - * - * @param this calling object - * @param name - * @return matching peer_config, or NULL if none found - */ - peer_cfg_t *(*get_peer_cfg_by_name)(backend_t *this, char *name); - - /** - * @brief Check if a backend is writable and implements writable_backend_t. - * - * @param this calling object - * @return TRUE if backend implements writable_backend_t. - */ - bool (*is_writeable)(backend_t *this); - - /** - * @brief Destroy a backend. - * - * @param this calling object - */ - void (*destroy)(backend_t *this); -}; - - -/** - * Construction to create a backend. - */ -typedef backend_t*(*backend_constructor_t)(void); - -#endif /* BACKEND_H_ */ - diff --git a/src/charon/config/backends/local_backend.c b/src/charon/config/backends/local_backend.c deleted file mode 100644 index e04c72ac1..000000000 --- a/src/charon/config/backends/local_backend.c +++ /dev/null @@ -1,322 +0,0 @@ -/** - * @file local_backend.c - * - * @brief Implementation of local_backend_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * 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 <string.h> - -#include "local_backend.h" - -#include <daemon.h> -#include <utils/linked_list.h> -#include <crypto/ca.h> - - -typedef struct private_local_backend_t private_local_backend_t; - -/** - * Private data of an local_backend_t object - */ -struct private_local_backend_t { - - /** - * Public part - */ - local_backend_t public; - - /** - * list of configs - */ - linked_list_t *cfgs; - - /** - * Mutex to exclusivly access list - */ - pthread_mutex_t mutex; -}; - -/** - * implements backen_t.get_ike_cfg. - */ -static ike_cfg_t *get_ike_cfg(private_local_backend_t *this, - host_t *my_host, host_t *other_host) -{ - peer_cfg_t *peer; - ike_cfg_t *current, *found = NULL; - iterator_t *iterator; - host_t *my_candidate, *other_candidate; - enum { - MATCH_NONE = 0x00, - MATCH_ANY = 0x01, - MATCH_ME = 0x04, - MATCH_OTHER = 0x08, - } prio, best = MATCH_ANY; - - DBG2(DBG_CFG, "looking for a config for %H...%H", - my_host, other_host); - - iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex); - while (iterator->iterate(iterator, (void**)&peer)) - { - prio = MATCH_NONE; - current = peer->get_ike_cfg(peer); - my_candidate = current->get_my_host(current); - other_candidate = current->get_other_host(current); - - if (my_candidate->ip_equals(my_candidate, my_host)) - { - prio += MATCH_ME; - } - else if (my_candidate->is_anyaddr(my_candidate)) - { - prio += MATCH_ANY; - } - - if (other_candidate->ip_equals(other_candidate, other_host)) - { - prio += MATCH_OTHER; - } - else if (other_candidate->is_anyaddr(other_candidate)) - { - prio += MATCH_ANY; - } - - DBG2(DBG_CFG, " candidate '%s': %H...%H, prio %d", - peer->get_name(peer), my_candidate, other_candidate, prio); - - /* we require at least two MATCH_ANY */ - if (prio > best) - { - best = prio; - found = current; - } - } - if (found) - { - found->get_ref(found); - } - iterator->destroy(iterator); - return found; -} - -#define PRIO_NO_MATCH_FOUND 256 - -/** - * implements backend_t.get_peer. - */ -static peer_cfg_t *get_peer_cfg(private_local_backend_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info) -{ - peer_cfg_t *current, *found = NULL; - iterator_t *iterator; - identification_t *my_candidate, *other_candidate; - int best = PRIO_NO_MATCH_FOUND; - - DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id); - - iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex); - while (iterator->iterate(iterator, (void**)¤t)) - { - int wc1, wc2; - - my_candidate = current->get_my_id(current); - other_candidate = current->get_other_id(current); - - if (my_candidate->matches(my_candidate, my_id, &wc1) - && other_id->matches(other_id, other_candidate, &wc2)) - { - int prio = (wc1 + wc2) * (MAX_CA_PATH_LEN + 1); - int pathlen = 0; - identification_t *other_candidate_ca = current->get_other_ca(current); - linked_list_t *groups = current->get_groups(current); - - /* is a group membership required? */ - if (groups->get_count(groups) > 0) - { - DBG1(DBG_CFG, " group membership required"); - } - - /* are there any ca constraints? */ - if (other_candidate_ca->get_type(other_candidate_ca) != ID_ANY) - { - ca_info_t *ca_info = other_ca_info; - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - if (ca_info == NULL) - { - prio = PRIO_NO_MATCH_FOUND; - break; - } - else - { - x509_t *cacert = ca_info->get_certificate(ca_info); - identification_t *other_ca = cacert->get_subject(cacert); - - if (other_candidate_ca->equals(other_candidate_ca, other_ca)) - { - /* found a ca match */ - break; - } - if (cacert->is_self_signed(cacert)) - { - /* reached the root ca without a match */ - prio = PRIO_NO_MATCH_FOUND; - break; - } - /* move a level upward in the trust path hierarchy */ - ca_info = charon->credentials->get_issuer(charon->credentials, cacert); - } - } - if (pathlen == MAX_CA_PATH_LEN) - { - DBG1(DBG_CFG, "maximum ca path length of %d levels reached", MAX_CA_PATH_LEN); - prio = PRIO_NO_MATCH_FOUND; - } - } - if (prio == PRIO_NO_MATCH_FOUND) - { - DBG2(DBG_CFG, " candidate '%s': %D...%D, no ca match", - current->get_name(current), my_candidate, other_candidate); - } - else - { - prio += pathlen; - DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d", - current->get_name(current), my_candidate, other_candidate, prio); - - if (prio < best) - { - found = current; - best = prio; - } - } - } - } - if (found) - { - DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d", - found->get_name(found), - found->get_my_id(found), - found->get_other_id(found), - best); - found->get_ref(found); - } - iterator->destroy(iterator); - return found; -} - -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_local_backend_t *this, char *name) -{ - iterator_t *i1, *i2; - peer_cfg_t *current, *found = NULL; - child_cfg_t *child; - - i1 = this->cfgs->create_iterator(this->cfgs, TRUE); - while (i1->iterate(i1, (void**)¤t)) - { - /* compare peer_cfgs name first */ - if (streq(current->get_name(current), name)) - { - found = current; - found->get_ref(found); - break; - } - /* compare all child_cfg names otherwise */ - i2 = current->create_child_cfg_iterator(current); - while (i2->iterate(i2, (void**)&child)) - { - if (streq(child->get_name(child), name)) - { - found = current; - found->get_ref(found); - break; - } - } - i2->destroy(i2); - if (found) - { - break; - } - } - i1->destroy(i1); - return found; -} - -/** - * Implementation of backend_t.is_writable. - */ -static bool is_writeable(private_local_backend_t *this) -{ - return TRUE; -} - -/** - * Implementation of writable_backend_t.create_iterator. - */ -static iterator_t* create_iterator(private_local_backend_t *this) -{ - return this->cfgs->create_iterator_locked(this->cfgs, &this->mutex); -} - -/** - * Implementation of writable_backend_t.add_peer_cfg. - */ -static void add_cfg(private_local_backend_t *this, peer_cfg_t *config) -{ - pthread_mutex_lock(&this->mutex); - this->cfgs->insert_last(this->cfgs, config); - pthread_mutex_unlock(&this->mutex); -} - -/** - * Implementation of backend_t.destroy. - */ -static void destroy(private_local_backend_t *this) -{ - this->cfgs->destroy_offset(this->cfgs, offsetof(peer_cfg_t, destroy)); - free(this); -} - -/** - * Described in header. - */ -backend_t *backend_create(void) -{ - private_local_backend_t *this = malloc_thing(private_local_backend_t); - - this->public.backend.backend.get_ike_cfg = (ike_cfg_t* (*)(backend_t*, host_t*, host_t*))get_ike_cfg; - this->public.backend.backend.get_peer_cfg = (peer_cfg_t* (*)(backend_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg; - this->public.backend.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.backend.backend.is_writeable = (bool(*) (backend_t*))is_writeable; - this->public.backend.backend.destroy = (void (*)(backend_t*))destroy; - this->public.backend.create_iterator = (iterator_t* (*)(writeable_backend_t*))create_iterator; - this->public.backend.add_cfg = (void (*)(writeable_backend_t*,peer_cfg_t*))add_cfg; - - /* private variables */ - this->cfgs = linked_list_create(); - pthread_mutex_init(&this->mutex, NULL); - - return &this->public.backend.backend; -} diff --git a/src/charon/config/backends/local_backend.h b/src/charon/config/backends/local_backend.h deleted file mode 100644 index b33c6443b..000000000 --- a/src/charon/config/backends/local_backend.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file local_backend.h - * - * @brief Interface of local_backend_t. - * - */ - -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -#ifndef LOCAL_BACKEND_H_ -#define LOCAL_BACKEND_H_ - -typedef struct local_backend_t local_backend_t; - -#include <library.h> -#include <config/backends/writeable_backend.h> - -/** - * @brief An in-memory backend to store configurations. - * - * The local_backend_t stores the configuration in a simple list. It - * implements both, backend_t and writeable_backend_t. - * - * @b Constructors: - * - local_backend_create() - * - * @ingroup backends - */ -struct local_backend_t { - - /** - * Implements writable_backend_t interface - */ - writeable_backend_t backend; -}; - -/** - * @brief Create a backend_t instance implemented as local backend. - * - * @return backend instance - * - * @ingroup backends - */ -backend_t *backend_create(void); - -#endif /* LOCAL_BACKEND_H_ */ - diff --git a/src/charon/config/backends/sqlite_backend.c b/src/charon/config/backends/sqlite_backend.c deleted file mode 100644 index e1c96c870..000000000 --- a/src/charon/config/backends/sqlite_backend.c +++ /dev/null @@ -1,309 +0,0 @@ -/** - * @file sqlite_backend.c - * - * @brief Implementation of sqlite_backend_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * 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 <string.h> -#include <sqlite3.h> - -#include "sqlite_backend.h" - -#include <daemon.h> - - -typedef struct private_sqlite_backend_t private_sqlite_backend_t; - -/** - * Private data of an sqlite_backend_t object - */ -struct private_sqlite_backend_t { - - /** - * Public part - */ - sqlite_backend_t public; - - /** - * SQLite database handle - */ - sqlite3 *db; -}; - -/** - * implements backen_t.get_ike_cfg. - */ -static ike_cfg_t *get_ike_cfg(private_sqlite_backend_t *this, - host_t *my_host, host_t *other_host) -{ - return NULL; -} - -/** - * add TS with child "id" to "child_cfg" - */ -static void add_ts(private_sqlite_backend_t *this, child_cfg_t *child_cfg, int id) -{ - sqlite3_stmt *stmt; - - if (sqlite3_prepare_v2(this->db, - "SELECT type, protocol, start_addr, end_addr, start_port, end_port, kind " - "FROM traffic_selectors, child_config_traffic_selector " - "ON traffic_selectors.oid = child_config_traffic_selector.traffic_selector " - "WHERE child_config_traffic_selector.child_cfg = ?;", - -1, &stmt, NULL) == SQLITE_OK && - sqlite3_bind_int(stmt, 1, id) == SQLITE_OK) - { - while (sqlite3_step(stmt) == SQLITE_ROW) - { - traffic_selector_t *ts; - bool local = FALSE; - enum { - TS_LOCAL = 0, - TS_REMOTE = 1, - TS_LOCAL_DYNAMIC = 2, - TS_REMOTE_DYNAMIC = 3, - } kind; - - kind = sqlite3_column_int(stmt, 6); - switch (kind) - { - case TS_LOCAL: - local = TRUE; - /* FALL */ - case TS_REMOTE: - ts = traffic_selector_create_from_string( - sqlite3_column_int(stmt, 1), /* protocol */ - sqlite3_column_int(stmt, 0), /* type */ - (char*)sqlite3_column_text(stmt, 2), /* from addr */ - sqlite3_column_int(stmt, 4), /* from port */ - (char*)sqlite3_column_text(stmt, 3), /* to addr */ - sqlite3_column_int(stmt, 5)); /* to port */ - break; - case TS_LOCAL_DYNAMIC: - local = TRUE; - /* FALL */ - case TS_REMOTE_DYNAMIC: - ts = traffic_selector_create_dynamic( - sqlite3_column_int(stmt, 1), /* protocol */ - sqlite3_column_int(stmt, 0), /* type */ - sqlite3_column_int(stmt, 4), /* from port */ - sqlite3_column_int(stmt, 5)); /* to port */ - break; - default: - continue; - } - if (ts) - { - child_cfg->add_traffic_selector(child_cfg, local, ts); - } - } - } - sqlite3_finalize(stmt); -} - -/** - * add childrens belonging to config with "id" to "peer_cfg" - */ -static void add_children(private_sqlite_backend_t *this, peer_cfg_t *peer_cfg, int id) -{ - sqlite3_stmt *stmt; - child_cfg_t *child_cfg; - - if (sqlite3_prepare_v2(this->db, - "SELECT child_configs.oid, name, updown, hostaccess, mode, " - "lifetime, rekeytime, jitter " - "FROM child_configs, peer_config_child_config " - "ON child_configs.oid = peer_config_child_config.child_cfg " - "WHERE peer_config_child_config.peer_cfg = ?;", - -1, &stmt, NULL) == SQLITE_OK && - sqlite3_bind_int(stmt, 1, id) == SQLITE_OK) - { - while (sqlite3_step(stmt) == SQLITE_ROW) - { - child_cfg = child_cfg_create( - (char*)sqlite3_column_text(stmt, 1), /* name */ - sqlite3_column_int(stmt, 5), /* lifetime */ - sqlite3_column_int(stmt, 6), /* rekeytime */ - sqlite3_column_int(stmt, 7), /* jitter */ - (char*)sqlite3_column_text(stmt, 2), /* updown */ - sqlite3_column_int(stmt, 3), /* hostaccess */ - sqlite3_column_int(stmt, 4)); /* mode */ - add_ts(this, child_cfg, sqlite3_column_int(stmt, 0)); - child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); - peer_cfg->add_child_cfg(peer_cfg, child_cfg); - } - } - sqlite3_finalize(stmt); -} - -/** - * processing function for get_peer_cfg and get_peer_cfg_by_name - */ -static peer_cfg_t *process_peer_cfg_row(private_sqlite_backend_t *this, - sqlite3_stmt *stmt) -{ - host_t *local_host, *remote_host, *local_vip = NULL, *remote_vip = NULL; - identification_t *local_id, *remote_id; - peer_cfg_t *peer_cfg; - ike_cfg_t *ike_cfg; - - local_host = host_create_from_string((char*)sqlite3_column_text(stmt, 17), IKEV2_UDP_PORT); - remote_host = host_create_from_string((char*)sqlite3_column_text(stmt, 18), IKEV2_UDP_PORT); - if (sqlite3_column_text(stmt, 15)) - { - local_vip = host_create_from_string((char*)sqlite3_column_text(stmt, 15), 0); - } - if (sqlite3_column_text(stmt, 16)) - { - remote_vip = host_create_from_string((char*)sqlite3_column_text(stmt, 16), 0); - } - local_id = identification_create_from_string((char*)sqlite3_column_text(stmt, 2)); - remote_id = identification_create_from_string((char*)sqlite3_column_text(stmt, 3)); - if (local_host && remote_host && local_id && remote_id) - { - ike_cfg = ike_cfg_create(sqlite3_column_int(stmt, 19), FALSE, - local_host, remote_host); - ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); - peer_cfg = peer_cfg_create( - (char*)sqlite3_column_text(stmt, 1), /* name */ - 2, ike_cfg, local_id, remote_id, NULL, NULL, linked_list_create(), - sqlite3_column_int(stmt, 4), /* cert_policy */ - sqlite3_column_int(stmt, 5), /* auth_method */ - sqlite3_column_int(stmt, 6), 0 /* eap_type, vendor */ - sqlite3_column_int(stmt, 7), /* keyingtries */ - sqlite3_column_int(stmt, 8), /* rekey_time */ - sqlite3_column_int(stmt, 9), /* reauth_time */ - sqlite3_column_int(stmt, 10), /* jitter_time */ - sqlite3_column_int(stmt, 11), /* over_time */ - sqlite3_column_int(stmt, 14), /* mobike */ - sqlite3_column_int(stmt, 12), /* dpd_delay */ - sqlite3_column_int(stmt, 13), /* dpd_action */ - local_vip, remote_vip, FALSE, NULL, NULL); - add_children(this, peer_cfg, sqlite3_column_int(stmt, 0)); - return peer_cfg; - } - - DESTROY_IF(local_host); - DESTROY_IF(remote_host); - DESTROY_IF(local_id); - DESTROY_IF(remote_id); - DESTROY_IF(local_vip); - DESTROY_IF(remote_vip); - return NULL; -} - -/** - * implements backend_t.get_peer_cfg. - */ -static peer_cfg_t *get_peer_cfg(private_sqlite_backend_t *this, - identification_t *my_id, identification_t *other_id, - ca_info_t *other_ca_info) -{ - sqlite3_stmt *stmt; - char local[256], remote[256]; - peer_cfg_t *peer_cfg = NULL; - - snprintf(local, sizeof(local), "%D", my_id); - snprintf(remote, sizeof(remote), "%D", other_id); - - if (sqlite3_prepare_v2(this->db, - "SELECT peer_configs.oid, name, local_id, remote_id, cert_policy, " - "auth_method, eap_type, keyingtries, " - "rekey_time, reauth_time, jitter_time, over_time, " - "dpd_delay, dpd_action, mobike, local_vip, remote_vip, " - "local, remote, certreq " - "FROM peer_configs, ike_configs " - "ON peer_configs.ike_cfg = ike_configs.oid " - "WHERE local_id = ? and remote_id = ?;", -1, &stmt, NULL) == SQLITE_OK && - sqlite3_bind_text(stmt, 1, local, -1, SQLITE_STATIC) == SQLITE_OK && - sqlite3_bind_text(stmt, 2, remote, -1, SQLITE_STATIC) == SQLITE_OK && - sqlite3_step(stmt) == SQLITE_ROW) - { - peer_cfg = process_peer_cfg_row(this, stmt); - } - sqlite3_finalize(stmt); - return peer_cfg; -} - -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_sqlite_backend_t *this, char *name) -{ - sqlite3_stmt *stmt; - peer_cfg_t *peer_cfg = NULL; - - if (sqlite3_prepare_v2(this->db, - "SELECT peer_configs.oid, name, local_id, remote_id, cert_policy, " - "auth_method, eap_type, keyingtries, lifetime, rekeytime, jitter, " - "dpd_delay, dpd_action, reauth, mobike, local_vip, remote_vip, " - "local, remote, certreq " - "FROM peer_configs, ike_configs " - "ON peer_configs.ike_cfg = ike_configs.oid " - "WHERE name = ? ;", -1, &stmt, NULL) == SQLITE_OK && - sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC) == SQLITE_OK && - sqlite3_step(stmt) == SQLITE_ROW) - { - peer_cfg = process_peer_cfg_row(this, stmt); - } - sqlite3_finalize(stmt); - return peer_cfg; -} - -/** - * Implementation of backend_t.is_writable. - */ -static bool is_writeable(private_sqlite_backend_t *this) -{ - return FALSE; -} - -/** - * Implementation of backend_t.destroy. - */ -static void destroy(private_sqlite_backend_t *this) -{ - sqlite3_close(this->db); - free(this); -} - -/** - * Described in header. - */ -backend_t *backend_create(void) -{ - private_sqlite_backend_t *this = malloc_thing(private_sqlite_backend_t); - - this->public.backend.get_ike_cfg = (ike_cfg_t* (*)(backend_t*, host_t*, host_t*))get_ike_cfg; - this->public.backend.get_peer_cfg = (peer_cfg_t* (*)(backend_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg; - this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.backend.is_writeable = (bool(*) (backend_t*))is_writeable; - this->public.backend.destroy = (void (*)(backend_t*))destroy; - - if (sqlite3_open(IPSEC_DIR "/manager.db", &this->db) != SQLITE_OK) - { - DBG1(DBG_CFG, "opening SQLite database '" IPSEC_DIR "/manager.db' failed."); - destroy(this); - return NULL; - } - - return &this->public.backend; -} - diff --git a/src/charon/config/backends/writeable_backend.h b/src/charon/config/backends/writeable_backend.h deleted file mode 100644 index ea62f62c9..000000000 --- a/src/charon/config/backends/writeable_backend.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file writeable_backend.h - * - * @brief Interface of writeable_backend_t. - * - */ - -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -#ifndef WRITEABLE_BACKEND_H_ -#define WRITEABLE_BACKEND_H_ - -typedef struct writeable_backend_t writeable_backend_t; - -#include <library.h> -#include <config/backends/backend.h> - -/** - * @brief A writeable backend extends backend_t by modification functions. - * - * @b Constructors: - * - writeable_backend_create() - * - * @ingroup backends - */ -struct writeable_backend_t { - - /** - * Implements backend_t interface - */ - backend_t backend; - - /** - * @brief Add a peer_config to the backend. - * - * @param this calling object - * @param config peer_config to add to the backend - */ - void (*add_cfg)(writeable_backend_t *this, peer_cfg_t *config); - - /** - * @brief Create an iterator over all peer configs. - * - * @param this calling object - * @return iterator over peer configs - */ - iterator_t* (*create_iterator)(writeable_backend_t *this); -}; - -#endif /* WRITEABLE_BACKEND_H_ */ - diff --git a/src/charon/config/child_cfg.c b/src/charon/config/child_cfg.c index 5827b4f61..f929927ef 100644 --- a/src/charon/config/child_cfg.c +++ b/src/charon/config/child_cfg.c @@ -1,11 +1,5 @@ -/** - * @file child_cfg.c - * - * @brief Implementation of child_cfg_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -19,9 +13,10 @@ * 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. + * + * $Id: child_cfg.c 4062 2008-06-12 11:42:19Z martin $ */ - #include "child_cfg.h" #include <daemon.h> @@ -34,6 +29,21 @@ ENUM(mode_names, MODE_TRANSPORT, MODE_BEET, "BEET", ); +ENUM(action_names, ACTION_NONE, ACTION_RESTART, + "ACTION_NONE", + "ACTION_ROUTE", + "ACTION_RESTART", +); + +ENUM_BEGIN(ipcomp_transform_names, IPCOMP_NONE, IPCOMP_NONE, + "IPCOMP_NONE"); +ENUM_NEXT(ipcomp_transform_names, IPCOMP_OUI, IPCOMP_LZJH, IPCOMP_NONE, + "IPCOMP_OUI", + "IPCOMP_DEFLATE", + "IPCOMP_LZS", + "IPCOMP_LZJH"); +ENUM_END(ipcomp_transform_names, IPCOMP_LZJH); + typedef struct private_child_cfg_t private_child_cfg_t; /** @@ -87,6 +97,16 @@ struct private_child_cfg_t { mode_t mode; /** + * action to take on DPD + */ + action_t dpd_action; + + /** + * action to take on CHILD_SA close + */ + action_t close_action; + + /** * Time before an SA gets invalid */ u_int32_t lifetime; @@ -101,6 +121,11 @@ struct private_child_cfg_t { * substracted from rekeytime. */ u_int32_t jitter; + + /** + * enable IPComp + */ + bool use_ipcomp; }; /** @@ -120,42 +145,25 @@ static void add_proposal(private_child_cfg_t *this, proposal_t *proposal) } /** - * strip out DH groups from a proposal - */ -static void strip_dh_from_proposal(proposal_t *proposal) -{ - iterator_t *iterator; - algorithm_t *algo; - - iterator = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP); - while (iterator->iterate(iterator, (void**)&algo)) - { - iterator->remove(iterator); - free(algo); - } - iterator->destroy(iterator); -} - -/** * Implementation of child_cfg_t.get_proposals */ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *current; linked_list_t *proposals = linked_list_create(); - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, ¤t)) { current = current->clone(current); if (strip_dh) { - strip_dh_from_proposal(current); + current->strip_dh(current); } proposals->insert_last(proposals, current); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return proposals; } @@ -166,26 +174,28 @@ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) static proposal_t* select_proposal(private_child_cfg_t*this, linked_list_t *proposals, bool strip_dh) { - iterator_t *stored_iter, *supplied_iter; + enumerator_t *stored_enum, *supplied_enum; proposal_t *stored, *supplied, *selected = NULL; - stored_iter = this->proposals->create_iterator(this->proposals, TRUE); - supplied_iter = proposals->create_iterator(proposals, TRUE); + stored_enum = this->proposals->create_enumerator(this->proposals); + supplied_enum = proposals->create_enumerator(proposals); /* compare all stored proposals with all supplied. Stored ones are preferred. */ - while (stored_iter->iterate(stored_iter, (void**)&stored)) + while (stored_enum->enumerate(stored_enum, &stored)) { stored = stored->clone(stored); - supplied_iter->reset(supplied_iter); - while (supplied_iter->iterate(supplied_iter, (void**)&supplied)) + while (supplied_enum->enumerate(supplied_enum, &supplied)) { if (strip_dh) { - strip_dh_from_proposal(stored); + stored->strip_dh(stored); } selected = stored->select(stored, supplied); if (selected) { + DBG2(DBG_CFG, "received proposals: %#P", proposals); + DBG2(DBG_CFG, "configured proposals: %#P", this->proposals); + DBG2(DBG_CFG, "selected proposal: %P", selected); break; } } @@ -194,9 +204,16 @@ static proposal_t* select_proposal(private_child_cfg_t*this, { break; } + supplied_enum->destroy(supplied_enum); + supplied_enum = proposals->create_enumerator(proposals); + } + stored_enum->destroy(stored_enum); + supplied_enum->destroy(supplied_enum); + if (selected == NULL) + { + DBG1(DBG_CFG, "received proposals: %#P", proposals); + DBG1(DBG_CFG, "configured proposals: %#P", this->proposals); } - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); return selected; } @@ -223,17 +240,17 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca linked_list_t *supplied, host_t *host) { - iterator_t *i1, *i2; + enumerator_t *e1, *e2; traffic_selector_t *ts1, *ts2, *selected; linked_list_t *result = linked_list_create(); if (local) { - i1 = this->my_ts->create_iterator(this->my_ts, TRUE); + e1 = this->my_ts->create_enumerator(this->my_ts); } else { - i1 = this->other_ts->create_iterator(this->other_ts, FALSE); + e1 = this->other_ts->create_enumerator(this->other_ts); } /* no list supplied, just fetch the stored traffic selectors */ @@ -241,7 +258,7 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca { DBG2(DBG_CFG, "proposing traffic selectors for %s:", local ? "us" : "other"); - while (i1->iterate(i1, (void**)&ts1)) + while (e1->enumerate(e1, &ts1)) { /* we make a copy of the TS, this allows us to update dynamic TS' */ selected = ts1->clone(ts1); @@ -252,15 +269,15 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1); result->insert_last(result, selected); } - i1->destroy(i1); + e1->destroy(e1); } else { DBG2(DBG_CFG, "selecting traffic selectors for %s:", local ? "us" : "other"); - i2 = supplied->create_iterator(supplied, TRUE); + e2 = supplied->create_enumerator(supplied); /* iterate over all stored selectors */ - while (i1->iterate(i1, (void**)&ts1)) + while (e1->enumerate(e1, &ts1)) { /* we make a copy of the TS, as we have to update dynamic TS' */ ts1 = ts1->clone(ts1); @@ -269,9 +286,8 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca ts1->set_address(ts1, host); } - i2->reset(i2); /* iterate over all supplied traffic selectors */ - while (i2->iterate(i2, (void**)&ts2)) + while (e2->enumerate(e2, &ts2)) { selected = ts1->get_subset(ts1, ts2); if (selected) @@ -286,40 +302,44 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca ts1, ts2, selected); } } + e2->destroy(e2); + e2 = supplied->create_enumerator(supplied); ts1->destroy(ts1); } - i1->destroy(i1); - i2->destroy(i2); + e1->destroy(e1); + e2->destroy(e2); } /* remove any redundant traffic selectors in the list */ - i1 = result->create_iterator(result, TRUE); - i2 = result->create_iterator(result, TRUE); - while (i1->iterate(i1, (void**)&ts1)) + e1 = result->create_enumerator(result); + e2 = result->create_enumerator(result); + while (e1->enumerate(e1, &ts1)) { - while (i2->iterate(i2, (void**)&ts2)) + while (e2->enumerate(e2, &ts2)) { if (ts1 != ts2) { if (ts2->is_contained_in(ts2, ts1)) { - i2->remove(i2); + result->remove_at(result, e2); ts2->destroy(ts2); - i1->reset(i1); + e1->destroy(e1); + e1 = result->create_enumerator(result); break; } if (ts1->is_contained_in(ts1, ts2)) { - i1->remove(i1); + result->remove_at(result, e1); ts1->destroy(ts1); - i2->reset(i2); + e2->destroy(e2); + e2 = result->create_enumerator(result); break; } } } } - i1->destroy(i1); - i2->destroy(i2); + e1->destroy(e1); + e2->destroy(e2); return result; } @@ -357,7 +377,7 @@ static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey) } /** - * Implementation of child_cfg_t.get_name + * Implementation of child_cfg_t.get_mode */ static mode_t get_mode(private_child_cfg_t *this) { @@ -365,34 +385,57 @@ static mode_t get_mode(private_child_cfg_t *this) } /** + * Implementation of child_cfg_t.get_dpd_action + */ +static action_t get_dpd_action(private_child_cfg_t *this) +{ + return this->dpd_action; +} + +/** + * Implementation of child_cfg_t.get_close_action + */ +static action_t get_close_action(private_child_cfg_t *this) +{ + return this->close_action; +} + +/** * Implementation of child_cfg_t.get_dh_group. */ static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *proposal; - algorithm_t *algo; - diffie_hellman_group_t dh_group = MODP_NONE; + u_int16_t dh_group = MODP_NONE; - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)&proposal)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &proposal)) { - if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo)) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL)) { - dh_group = algo->algorithm; break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return dh_group; } /** + * Implementation of child_cfg_t.use_ipcomp. + */ +static bool use_ipcomp(private_child_cfg_t *this) +{ + return this->use_ipcomp; +} + +/** * Implementation of child_cfg_t.get_name */ -static void get_ref(private_child_cfg_t *this) +static child_cfg_t* get_ref(private_child_cfg_t *this) { ref_get(&this->refcount); + return &this->public; } /** @@ -419,11 +462,11 @@ static void destroy(private_child_cfg_t *this) */ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, u_int32_t rekeytime, u_int32_t jitter, - char *updown, bool hostaccess, mode_t mode) + char *updown, bool hostaccess, mode_t mode, + action_t dpd_action, action_t close_action, bool ipcomp) { private_child_cfg_t *this = malloc_thing(private_child_cfg_t); - /* public functions */ this->public.get_name = (char* (*) (child_cfg_t*))get_name; this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector; this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors; @@ -433,12 +476,14 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, this->public.get_updown = (char* (*) (child_cfg_t*))get_updown; this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess; this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode; + this->public.get_dpd_action = (action_t (*) (child_cfg_t *))get_dpd_action; + this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action; this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime; this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group; - this->public.get_ref = (void (*) (child_cfg_t*))get_ref; + this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp; + this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref; this->public.destroy = (void (*) (child_cfg_t*))destroy; - /* apply init values */ this->name = strdup(name); this->lifetime = lifetime; this->rekeytime = rekeytime; @@ -446,8 +491,9 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, this->updown = updown ? strdup(updown) : NULL; this->hostaccess = hostaccess; this->mode = mode; - - /* initialize private members*/ + this->dpd_action = dpd_action; + this->close_action = close_action; + this->use_ipcomp = ipcomp; this->refcount = 1; this->proposals = linked_list_create(); this->my_ts = linked_list_create(); @@ -455,3 +501,4 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, return &this->public; } + diff --git a/src/charon/config/child_cfg.h b/src/charon/config/child_cfg.h index e1a6553b4..6d262c217 100644 --- a/src/charon/config/child_cfg.h +++ b/src/charon/config/child_cfg.h @@ -1,11 +1,5 @@ -/** - * @file child_cfg.h - * - * @brief Interface of child_cfg_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -19,12 +13,21 @@ * 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. + * + * $Id: child_cfg.h 3920 2008-05-08 16:19:11Z tobias $ + */ + +/** + * @defgroup child_cfg child_cfg + * @{ @ingroup config */ #ifndef CHILD_CFG_H_ #define CHILD_CFG_H_ typedef enum mode_t mode_t; +typedef enum action_t action_t; +typedef enum ipcomp_transform_t ipcomp_transform_t; typedef struct child_cfg_t child_cfg_t; #include <library.h> @@ -32,11 +35,9 @@ typedef struct child_cfg_t child_cfg_t; #include <config/traffic_selector.h> /** - * @brief Mode of an CHILD_SA. + * Mode of an CHILD_SA. * * These are equal to those defined in XFRM, so don't change. - * - * @ingroup config */ enum mode_t { /** transport mode, no inner address */ @@ -53,7 +54,40 @@ enum mode_t { extern enum_name_t *mode_names; /** - * @brief A child_cfg_t defines the config template for a CHILD_SA. + * Action to take when DPD detected/connection gets closed by peer. + */ +enum action_t { + /** No action */ + ACTION_NONE, + /** Route config to reestablish on demand */ + ACTION_ROUTE, + /** Restart config immediately */ + ACTION_RESTART, +}; + +/** + * enum names for action_t. + */ +extern enum_name_t *action_names; + +/** + * IPComp transform IDs, as in RFC 4306 + */ +enum ipcomp_transform_t { + IPCOMP_NONE = 241, + IPCOMP_OUI = 1, + IPCOMP_DEFLATE = 2, + IPCOMP_LZS = 3, + IPCOMP_LZJH = 4, +}; + +/** + * enum strings for ipcomp_transform_t. + */ +extern enum_name_t *ipcomp_transform_names; + +/** + * A child_cfg_t defines the config template for a CHILD_SA. * * After creation, proposals and traffic selectors may be added to the config. * A child_cfg object is referenced multiple times, and is not thread save. @@ -62,51 +96,42 @@ extern enum_name_t *mode_names; * A reference counter handles the number of references hold to this config. * * @see peer_cfg_t to get an overview over the configurations. - * - * @b Constructors: - * - child_cfg_create() - * - * @ingroup config */ struct child_cfg_t { /** - * @brief Get the name of the child_cfg. + * Get the name of the child_cfg. * - * @param this calling object * @return child_cfg's name */ char *(*get_name) (child_cfg_t *this); /** - * @brief Add a proposal to the list. + * Add a proposal to the list. * * The proposals are stored by priority, first added * is the most prefered. * After add, proposal is owned by child_cfg. * - * @param this calling object * @param proposal proposal to add */ void (*add_proposal) (child_cfg_t *this, proposal_t *proposal); /** - * @brief Get the list of proposals for the CHILD_SA. + * Get the list of proposals for the CHILD_SA. * * Resulting list and all of its proposals must be freed after use. * - * @param this calling object * @param strip_dh TRUE strip out diffie hellman groups * @return list of proposals */ linked_list_t* (*get_proposals)(child_cfg_t *this, bool strip_dh); /** - * @brief Select a proposal from a supplied list. + * Select a proposal from a supplied list. * * Returned propsal is newly created and must be destroyed after usage. * - * @param this calling object * @param proposals list from from wich proposals are selected * @param strip_dh TRUE strip out diffie hellman groups * @return selected proposal, or NULL if nothing matches @@ -115,12 +140,11 @@ struct child_cfg_t { bool strip_dh); /** - * @brief Add a traffic selector to the config. + * Add a traffic selector to the config. * * Use the "local" parameter to add it for the local or the remote side. * After add, traffic selector is owned by child_cfg. * - * @param this calling object * @param local TRUE for local side, FALSE for remote * @param ts traffic_selector to add */ @@ -128,7 +152,7 @@ struct child_cfg_t { traffic_selector_t *ts); /** - * @brief Get a list of traffic selectors to use for the CHILD_SA. + * Get a list of traffic selectors to use for the CHILD_SA. * * The config contains two set of traffic selectors, one for the local * side, one for the remote side. @@ -139,7 +163,6 @@ struct child_cfg_t { * the "host" parameter to narrow such traffic selectors to that address. * Resulted list and its traffic selectors must be destroyed after use. * - * @param this calling object * @param local TRUE for TS on local side, FALSE for remote * @param supplied list with TS to select from, or NULL * @param host address to use for narrowing "dynamic" TS', or NULL @@ -150,23 +173,21 @@ struct child_cfg_t { host_t *host); /** - * @brief Get the updown script to run for the CHILD_SA. + * Get the updown script to run for the CHILD_SA. * - * @param this calling object * @return path to updown script */ char* (*get_updown)(child_cfg_t *this); /** - * @brief Should we allow access to the local host (gateway)? + * Should we allow access to the local host (gateway)? * - * @param this calling object * @return value of hostaccess flag */ bool (*get_hostaccess) (child_cfg_t *this); /** - * @brief Get the lifetime of a CHILD_SA. + * Get the lifetime of a CHILD_SA. * * If "rekey" is set to TRUE, a lifetime is returned before the first * rekeying should be started. If it is FALSE, the actual lifetime is @@ -174,57 +195,68 @@ struct child_cfg_t { * The rekey time automatically contains a jitter to avoid simlutaneous * rekeying. * - * @param this child_cfg * @param rekey TRUE to get rekey time * @return lifetime in seconds */ u_int32_t (*get_lifetime) (child_cfg_t *this, bool rekey); /** - * @brief Get the mode to use for the CHILD_SA. + * Get the mode to use for the CHILD_SA. * * The mode is either tunnel, transport or BEET. The peer must agree * on the method, fallback is tunnel mode. * - * @param this child_cfg - * @return lifetime in seconds + * @return ipsec mode */ mode_t (*get_mode) (child_cfg_t *this); /** - * @brief Get the DH group to use for CHILD_SA setup. + * Action to take on DPD. + * + * @return DPD action + */ + action_t (*get_dpd_action) (child_cfg_t *this); + + /** + * Action to take if CHILD_SA gets closed. + * + * @return close action + */ + action_t (*get_close_action) (child_cfg_t *this); + + /** + * Get the DH group to use for CHILD_SA setup. * - * @param this calling object - * @return dh group to use + * @return dh group to use */ diffie_hellman_group_t (*get_dh_group)(child_cfg_t *this); /** - * @brief Get a new reference. - * - * Get a new reference to this child_cfg by increasing - * it's internal reference counter. - * Do not call get_ref or any other function until you - * already have a reference. Otherwise the object may get - * destroyed while calling get_ref(), + * Check whether IPComp should be used, if the other peer supports it. * - * @param this calling object + * @return TRUE, if IPComp should be used + * FALSE, otherwise */ - void (*get_ref) (child_cfg_t *this); + bool (*use_ipcomp)(child_cfg_t *this); /** - * @brief Destroys the child_cfg object. + * Increase the reference count. + * + * @return reference to this + */ + child_cfg_t* (*get_ref) (child_cfg_t *this); + + /** + * Destroys the child_cfg object. * * Decrements the internal reference counter and * destroys the child_cfg when it reaches zero. - * - * @param this calling object */ void (*destroy) (child_cfg_t *this); }; /** - * @brief Create a configuration template for CHILD_SA setup. + * Create a configuration template for CHILD_SA setup. * * The "name" string gets cloned. * Lifetimes are in seconds. To prevent to peers to start rekeying at the @@ -240,12 +272,15 @@ struct child_cfg_t { * @param updown updown script to execute on up/down event * @param hostaccess TRUE to allow access to the local host * @param mode mode to propose for CHILD_SA, transport, tunnel or BEET + * @param dpd_action DPD action + * @param close_action close action + * @param ipcomp use IPComp, if peer supports it * @return child_cfg_t object - * - * @ingroup config */ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime, u_int32_t rekeytime, u_int32_t jitter, - char *updown, bool hostaccess, mode_t mode); + char *updown, bool hostaccess, mode_t mode, + action_t dpd_action, action_t close_action, + bool ipcomp); -#endif /* CHILD_CFG_H_ */ +#endif /* CHILD_CFG_H_ @} */ diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c deleted file mode 100644 index b838f032d..000000000 --- a/src/charon/config/credentials/local_credential_store.c +++ /dev/null @@ -1,1620 +0,0 @@ -/** - * @file local_credential_store.c - * - * @brief Implementation of local_credential_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * 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. - * - * RCSID $Id: local_credential_store.c 3346 2007-11-16 20:23:29Z andreas $ - */ - -#include <sys/stat.h> -#include <dirent.h> -#include <string.h> -#include <pthread.h> -#include <errno.h> - -#include <library.h> -#include <utils/lexparser.h> -#include <utils/linked_list.h> -#include <crypto/rsa/rsa_public_key.h> -#include <crypto/certinfo.h> -#include <crypto/x509.h> -#include <crypto/ca.h> -#include <crypto/ac.h> -#include <crypto/crl.h> -#include <asn1/ttodata.h> - -#include "local_credential_store.h" - -#define PATH_BUF 256 - -typedef struct shared_key_t shared_key_t; - -/** - * Private date of a shared_key_t object - */ -struct shared_key_t { - - /** - * shared secret - */ - chunk_t secret; - - /** - * list of peer IDs - */ - linked_list_t *peers; -}; - - -/** - * Implementation of shared_key_t.destroy. - */ -static void shared_key_destroy(shared_key_t *this) -{ - this->peers->destroy_offset(this->peers, offsetof(identification_t, destroy)); - chunk_free_randomized(&this->secret); - free(this); -} - -/** - * @brief Creates a shared_key_t object. - * - * @param shared_key shared key value - * @return shared_key_t object - * - * @ingroup config - */ -static shared_key_t *shared_key_create(chunk_t secret) -{ - shared_key_t *this = malloc_thing(shared_key_t); - - /* private data */ - this->secret = secret; - this->peers = linked_list_create(); - - return (this); -} - -/* ------------------------------------------------------------------------ * - * the ca_info_t object as a central control element - -+--------------------------------------------------------+ -| local_credential_store_t | -+--------------------------------------------------------+ - | | -+---------------------------+ +-------------------------+ -| linked_list_t *auth_certs | | linked_list_t *ca_infos | -+---------------------------+ +-------------------------+ - | | - | +------------------------- + - | | ca_info_t | - | +--------------------------+ -+---------------+ | char *name | -| x509_t |<--| x509_t *cacert | -+---------------+ | linked_list_t *attrcerts | +----------------------+ -| chunk_t keyid | | linked_list_t *certinfos |-->| certinfo_t | -+---------------+ | linked_list_t *ocspuris | +----------------------+ - | | crl_t *crl | | chunk_t serialNumber | - | | linked_list_t *crluris | | cert_status_t status | -+---------------+ | pthread_mutex_t mutex | | time_t thisUpdate | -| x509_t | +--------------------------+ | time_t nextUpdate | -+---------------+ | | bool once | -| chunk_t keyid | | +----------------------+ -+---------------+ +------------------------- + | - | | ca_info_t | +----------------------+ - | +--------------------------+ | certinfo_t | -+---------------+ | char *name | +----------------------+ -| x509_t |<--| x509_t *cacert | | chunk_t serialNumber | -+---------------+ | linked_list_t *attrcerts | | cert_status_t status | -| chunk_t keyid | | linked_list_t *certinfos | | time_t thisUpdate | -+---------------+ | linked_list_t *ocspuris | | time_t nextUpdate | - | | crl_t *crl | | bool once | - | | linked_list_t *crluris | +----------------------+ - | | pthread_mutex_t mutex; | | - | +--------------------------+ - | | - - * ------------------------------------------------------------------------ */ - -typedef struct private_local_credential_store_t private_local_credential_store_t; - -/** - * Private data of an local_credential_store_t object - */ -struct private_local_credential_store_t { - - /** - * Public part - */ - local_credential_store_t public; - - /** - * list of shared keys - */ - linked_list_t *shared_keys; - - /** - * list of EAP keys - */ - linked_list_t *eap_keys; - - /** - * list of key_entry_t's with private keys - */ - linked_list_t *private_keys; - - /** - * mutex controls access to the linked lists of secret keys - */ - pthread_mutex_t keys_mutex; - - /** - * list of X.509 certificates with public keys - */ - linked_list_t *certs; - - /** - * list of X.509 authority certificates with public keys - */ - linked_list_t *auth_certs; - - /** - * list of X.509 CA information records - */ - linked_list_t *ca_infos; - - /** - * list of X.509 attribute certificates - */ - linked_list_t *acerts; - - /** - * mutex controls access to the linked list of attribute certificates - */ - pthread_mutex_t acerts_mutex; -}; - - -/** - * Get a key from a list with shared_key_t's - */ -static status_t get_key(linked_list_t *keys, - identification_t *my_id, - identification_t *other_id, chunk_t *secret) -{ - typedef enum { - PRIO_UNDEFINED= 0x00, - PRIO_ANY_MATCH= 0x01, - PRIO_MY_MATCH= 0x02, - PRIO_OTHER_MATCH= 0x04, - } prio_t; - - prio_t best_prio = PRIO_UNDEFINED; - chunk_t found = chunk_empty; - shared_key_t *shared_key; - iterator_t *iterator; - - iterator = keys->create_iterator(keys, TRUE); - - while (iterator->iterate(iterator, (void**)&shared_key)) - { - iterator_t *peer_iterator; - identification_t *peer_id; - prio_t prio = PRIO_UNDEFINED; - - peer_iterator = shared_key->peers->create_iterator(shared_key->peers, TRUE); - - if (peer_iterator->get_count(peer_iterator) == 0) - { - /* this is a wildcard shared key */ - prio = PRIO_ANY_MATCH; - } - else - { - while (peer_iterator->iterate(peer_iterator, (void**)&peer_id)) - { - if (my_id->equals(my_id, peer_id)) - { - prio |= PRIO_MY_MATCH; - } - if (other_id->equals(other_id, peer_id)) - { - prio |= PRIO_OTHER_MATCH; - } - } - } - peer_iterator->destroy(peer_iterator); - - if (prio > best_prio) - { - best_prio = prio; - found = shared_key->secret; - } - } - iterator->destroy(iterator); - - if (best_prio == PRIO_UNDEFINED) - { - return NOT_FOUND; - } - else - { - *secret = chunk_clone(found); - return SUCCESS; - } -} - -/** - * Implementation of local_credential_store_t.get_shared_key. - */ -static status_t get_shared_key(private_local_credential_store_t *this, - identification_t *my_id, - identification_t *other_id, chunk_t *secret) -{ - status_t status; - - pthread_mutex_lock(&(this->keys_mutex)); - status = get_key(this->shared_keys, my_id, other_id, secret); - pthread_mutex_unlock(&(this->keys_mutex)); - return status; -} - -/** - * Implementation of local_credential_store_t.get_eap_key. - */ -static status_t get_eap_key(private_local_credential_store_t *this, - identification_t *my_id, - identification_t *other_id, chunk_t *secret) -{ - status_t status; - - pthread_mutex_lock(&(this->keys_mutex)); - status = get_key(this->eap_keys, my_id, other_id, secret); - pthread_mutex_unlock(&(this->keys_mutex)); - return status; -} - -/** - * Implementation of credential_store_t.get_certificate. - */ -static x509_t* get_certificate(private_local_credential_store_t *this, - identification_t *id) -{ - x509_t *found = NULL; - x509_t *current_cert; - - iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - if (id->equals(id, current_cert->get_subject(current_cert)) || - current_cert->equals_subjectAltName(current_cert, id)) - { - found = current_cert; - break; - } - } - iterator->destroy(iterator); - return found; -} - -/** - * Implementation of local_credential_store_t.get_rsa_public_key. - */ -static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *this, - identification_t *id) -{ - x509_t *cert = get_certificate(this, id); - - return (cert == NULL)? NULL:cert->get_public_key(cert); -} - -/** - * Implementation of credential_store_t.get_issuer. - */ -static ca_info_t* get_issuer(private_local_credential_store_t *this, x509_t *cert) -{ - ca_info_t *found = cert->get_ca_info(cert); - - if (found == NULL) - { - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - ca_info_t *ca_info; - - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->is_cert_issuer(ca_info, cert)) - { - found = ca_info; - cert->set_ca_info(cert, found); - break; - } - } - iterator->destroy(iterator); - } - return found; -} - -/** - * Implementation of local_credential_store_t.has_rsa_private_key. - */ -static bool has_rsa_private_key(private_local_credential_store_t *this, rsa_public_key_t *pubkey) -{ - bool found = FALSE; - rsa_private_key_t *current; - iterator_t *iterator; - - pthread_mutex_lock(&(this->keys_mutex)); - iterator = this->private_keys->create_iterator(this->private_keys, TRUE); - - while (iterator->iterate(iterator, (void**)¤t)) - { - if (current->belongs_to(current, pubkey)) - { - found = TRUE; - break; - } - } - iterator->destroy(iterator); - pthread_mutex_unlock(&(this->keys_mutex)); - return found; -} - -/** - * Implementation of credential_store_t.get_auth_certificate. - */ -static x509_t* get_auth_certificate(private_local_credential_store_t *this, - u_int auth_flags, - identification_t *id) -{ - x509_t *found = NULL; - x509_t *current_cert; - - iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - if (current_cert->has_authority_flag(current_cert, auth_flags) - && id->equals(id, current_cert->get_subject(current_cert))) - { - found = current_cert; - break; - } - } - iterator->destroy(iterator); - - return found; -} - -/** - * Implementation of credential_store_t.get_ca_certificate_by_keyid. - */ -static x509_t* get_ca_certificate_by_keyid(private_local_credential_store_t *this, - chunk_t keyid) -{ - x509_t *found = NULL; - x509_t *current_cert; - - iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - rsa_public_key_t *pubkey = current_cert->get_public_key(current_cert); - - if (current_cert->has_authority_flag(current_cert, AUTH_CA) - && chunk_equals(keyid, pubkey->get_keyid(pubkey))) - { - found = current_cert; - break; - } - } - iterator->destroy(iterator); - - return found; -} - -/** - * Find an exact copy of a certificate in a linked list - */ -static x509_t* find_certificate(linked_list_t *certs, x509_t *cert) -{ - x509_t *found_cert = NULL, *current_cert; - - iterator_t *iterator = certs->create_iterator(certs, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_cert)) - { - if (cert->equals(cert, current_cert)) - { - found_cert = current_cert; - break; - } - } - iterator->destroy(iterator); - - return found_cert; -} - -/** - * Adds crl and ocsp uris to the corresponding issuer info record - */ -static void add_uris(ca_info_t *issuer, x509_t *cert) -{ - iterator_t *iterator; - identification_t *uri; - - /* add any crl distribution points to the issuer ca info record */ - iterator = cert->create_crluri_iterator(cert); - - while (iterator->iterate(iterator, (void**)&uri)) - { - if (uri->get_type(uri) == ID_DER_ASN1_GN_URI) - { - issuer->add_crluri(issuer, uri->get_encoding(uri)); - } - } - iterator->destroy(iterator); - - /* add any ocsp access points to the issuer ca info record */ - iterator = cert->create_ocspuri_iterator(cert); - - while (iterator->iterate(iterator, (void**)&uri)) - { - if (uri->get_type(uri) == ID_DER_ASN1_GN_URI) - { - issuer->add_ocspuri(issuer, uri->get_encoding(uri)); - } - } - iterator->destroy(iterator); -} - -/** - * Implementation of credential_store_t.is_trusted - */ -static bool is_trusted(private_local_credential_store_t *this, const char *label, x509_t *cert) -{ - int pathlen; - time_t until = UNDEFINED_TIME; - x509_t *cert_to_be_trusted = cert; - - DBG1(DBG_CFG, "establishing trust in %s certificate:", label); - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - err_t ugh = NULL; - ca_info_t *issuer; - x509_t *issuer_cert; - rsa_public_key_t *issuer_public_key; - bool valid_signature; - - DBG1(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); - DBG1(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); - - ugh = cert->is_valid(cert, &until); - if (ugh != NULL) - { - DBG1(DBG_CFG, "certificate %s", ugh); - return FALSE; - } - DBG2(DBG_CFG, "certificate is valid"); - - issuer = get_issuer(this, cert); - if (issuer == NULL) - { - DBG1(DBG_CFG, "issuer not found"); - return FALSE; - } - DBG2(DBG_CFG, "issuer found"); - - issuer_cert = issuer->get_certificate(issuer); - issuer_public_key = issuer_cert->get_public_key(issuer_cert); - valid_signature = cert->verify(cert, issuer_public_key); - - if (!valid_signature) - { - DBG1(DBG_CFG, "certificate signature is invalid"); - return FALSE; - } - DBG2(DBG_CFG, "certificate signature is valid"); - - /* check if cert is a self-signed root ca */ - if (pathlen > 0 && cert->is_self_signed(cert)) - { - DBG1(DBG_CFG, "reached self-signed root ca"); - cert_to_be_trusted->set_until(cert_to_be_trusted, until); - cert_to_be_trusted->set_status(cert_to_be_trusted, CERT_GOOD); - return TRUE; - } - else - { - DBG1(DBG_CFG, "going up one step in the certificate trust chain (%d)", - pathlen + 1); - cert = issuer_cert; - } - } - DBG1(DBG_CFG, "maximum ca path length of %d levels reached", MAX_CA_PATH_LEN); - return FALSE; -} - -/** - * Implementation of credential_store_t.verify. - */ -static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found) -{ - int pathlen; - time_t until = UNDEFINED_TIME; - - x509_t *end_cert = cert; - x509_t *cert_copy = find_certificate(this->certs, end_cert); - - DBG1(DBG_CFG, "verifying end entity certificate up to trust anchor:"); - - *found = (cert_copy != NULL); - if (*found) - { - DBG2(DBG_CFG, - "end entitity certificate is already in credential store"); - } - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - bool valid_signature; - err_t ugh = NULL; - ca_info_t *issuer; - x509_t *issuer_cert; - rsa_public_key_t *issuer_public_key; - chunk_t keyid = cert->get_keyid(cert); - - DBG1(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); - DBG1(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); - DBG1(DBG_CFG, "keyid: %#B", &keyid); - - ugh = cert->is_valid(cert, &until); - if (ugh != NULL) - { - DBG1(DBG_CFG, "certificate %s", ugh); - return FALSE; - } - DBG2(DBG_CFG, "certificate is valid"); - - issuer = get_issuer(this, cert); - if (issuer == NULL) - { - DBG1(DBG_CFG, "issuer not found"); - return FALSE; - } - DBG2(DBG_CFG, "issuer found"); - - issuer_cert = issuer->get_certificate(issuer); - issuer_public_key = issuer_cert->get_public_key(issuer_cert); - valid_signature = cert->verify(cert, issuer_public_key); - - if (!valid_signature) - { - DBG1(DBG_CFG, "certificate signature is invalid"); - return FALSE; - } - DBG2(DBG_CFG, "certificate signature is valid"); - - /* check if cert is a self-signed root ca */ - if (pathlen > 0 && cert->is_self_signed(cert)) - { - DBG1(DBG_CFG, "reached self-signed root ca"); - - /* set the definite status and trust interval of the end entity certificate */ - end_cert->set_until(end_cert, until); - if (cert_copy) - { - cert_copy->set_status(cert_copy, end_cert->get_status(end_cert)); - cert_copy->set_until(cert_copy, until); - } - return TRUE; - } - else - { - bool strict; - time_t nextUpdate; - cert_status_t status; - certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert)); - - if (pathlen == 0) - { - /* add any crl and ocsp uris contained in the certificate under test */ - add_uris(issuer, cert); - } - - strict = issuer->is_strict(issuer); - DBG1(DBG_CFG, "issuer %s a strict crl policy", - strict ? "enforces":"does not enforce"); - - /* first check certificate revocation using ocsp */ - status = issuer->verify_by_ocsp(issuer, certinfo, &this->public.credential_store); - - /* if ocsp service is not available then fall back to crl */ - if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && strict)) - { - - certinfo->set_status(certinfo, CERT_UNKNOWN); - status = issuer->verify_by_crl(issuer, certinfo, CRL_DIR); - } - - nextUpdate = certinfo->get_nextUpdate(certinfo); - cert->set_status(cert, status); - - switch (status) - { - case CERT_GOOD: - /* with strict crl policy the public key must have the same - * lifetime as the validity of the ocsp status or crl lifetime - */ - if (strict) - { - cert->set_until(cert, nextUpdate); - until = (nextUpdate < until)? nextUpdate : until; - } - - /* if status information is stale */ - if (strict && nextUpdate < time(NULL)) - { - DBG2(DBG_CFG, "certificate is good but status is stale"); - certinfo->destroy(certinfo); - return FALSE; - } - DBG1(DBG_CFG, "certificate is good"); - break; - case CERT_REVOKED: - { - time_t revocationTime = certinfo->get_revocationTime(certinfo); - DBG1(DBG_CFG, - "certificate was revoked on %T, reason: %N", - &revocationTime, crl_reason_names, - certinfo->get_revocationReason(certinfo)); - - /* set revocationTime */ - cert->set_until(cert, revocationTime); - - /* update status of end certificate in the credential store */ - if (cert_copy) - { - if (pathlen > 0) - { - cert_copy->set_status(cert_copy, CERT_UNTRUSTED); - } - else - { - cert_copy->set_status(cert_copy, CERT_REVOKED); - cert_copy->set_until(cert_copy, - certinfo->get_revocationTime(certinfo)); - } - } - certinfo->destroy(certinfo); - return FALSE; - } - case CERT_UNKNOWN: - case CERT_UNDEFINED: - default: - DBG1(DBG_CFG, "certificate status unknown"); - if (strict) - { - /* update status of end certificate in the credential store */ - if (cert_copy) - { - cert_copy->set_status(cert_copy, CERT_UNTRUSTED); - } - certinfo->destroy(certinfo); - return FALSE; - } - break; - } - certinfo->destroy(certinfo); - } - DBG1(DBG_CFG, "going up one step in the certificate trust chain (%d)", - pathlen + 1); - cert = issuer_cert; - } - DBG1(DBG_CFG, "maximum ca path length of %d levels reached", MAX_CA_PATH_LEN); - return FALSE; -} - -/** - * Implementation of local_credential_store_t.rsa_signature. - */ -static status_t rsa_signature(private_local_credential_store_t *this, - rsa_public_key_t *pubkey, - hash_algorithm_t hash_algorithm, - chunk_t data, chunk_t *signature) -{ - rsa_private_key_t *current, *key = NULL; - iterator_t *iterator; - status_t status; - chunk_t keyid = pubkey->get_keyid(pubkey); - - DBG2(DBG_IKE, "looking for RSA private key with keyid %#B...", &keyid); - pthread_mutex_lock(&(this->keys_mutex)); - - iterator = this->private_keys->create_iterator(this->private_keys, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (current->belongs_to(current, pubkey)) - { - key = current; - break; - } - } - iterator->destroy(iterator); - - if (key) - { - DBG2(DBG_IKE, " matching RSA private key found"); - status = key->build_emsa_pkcs1_signature(key, hash_algorithm, data, signature); - } - else - { - DBG1(DBG_IKE, "no RSA private key found with keyid %#B", &keyid); - status = NOT_FOUND; - } - pthread_mutex_unlock(&(this->keys_mutex)); - return status; -} - -/** - * Implementation of local_credential_store_t.verify_signature. - */ -static status_t verify_signature(private_local_credential_store_t *this, - chunk_t hash, chunk_t signature, - identification_t *id, ca_info_t **issuer_p) -{ - iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE); - status_t sig_status; - x509_t *cert; - - /* default return values in case of failure */ - sig_status = NOT_FOUND; - *issuer_p = NULL; - - while (iterator->iterate(iterator, (void**)&cert)) - { - if (id->equals(id, cert->get_subject(cert)) - || cert->equals_subjectAltName(cert, id)) - { - rsa_public_key_t *public_key = cert->get_public_key(cert); - cert_status_t cert_status = cert->get_status(cert); - - DBG2(DBG_CFG, "found candidate peer certificate"); - - if (cert_status == CERT_UNDEFINED || cert->get_until(cert) < time(NULL)) - { - bool found; - - if (!verify(this, cert, &found)) - { - sig_status = VERIFY_ERROR; - DBG1(DBG_CFG, "candidate peer certificate was not successfully verified"); - continue; - } - *issuer_p = get_issuer(this, cert); - } - else - { - ca_info_t *issuer = get_issuer(this, cert); - chunk_t keyid = public_key->get_keyid(public_key); - - DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); - DBG2(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); - DBG2(DBG_CFG, "keyid: %#B", &keyid); - - if (issuer == NULL) - { - DBG1(DBG_CFG, "candidate peer certificate has no retrievable issuer"); - sig_status = NOT_FOUND; - continue; - } - if (cert_status == CERT_REVOKED || cert_status == CERT_UNTRUSTED - || ((issuer)->is_strict(issuer) && cert_status != CERT_GOOD)) - { - DBG1(DBG_CFG, "candidate peer certificate has an inacceptable status: %N", cert_status_names, cert_status); - sig_status = VERIFY_ERROR; - continue; - } - *issuer_p = issuer; - } - sig_status = public_key->verify_emsa_pkcs1_signature(public_key, HASH_UNKNOWN, hash, signature); - if (sig_status == SUCCESS) - { - DBG2(DBG_CFG, "candidate peer certificate has a matching RSA public key"); - break; - } - else - { - DBG1(DBG_CFG, "candidate peer certificate has a non-matching RSA public key"); - *issuer_p = NULL; - } - } - } - iterator->destroy(iterator); - if (sig_status == NOT_FOUND) - { - DBG1(DBG_CFG, "no candidate peer certificate found"); - } - return sig_status; -} - -/** - * Add a unique certificate to a linked list - */ -static x509_t* add_certificate(linked_list_t *certs, x509_t *cert) -{ - x509_t *found_cert = find_certificate(certs, cert); - - if (found_cert) - { - /* add the authority flags */ - found_cert->add_authority_flags(found_cert, cert->get_authority_flags(cert)); - - cert->destroy(cert); - return found_cert; - } - else - { - certs->insert_last(certs, (void*)cert); - return cert; - } -} - -/** - * Add a unique ca info record to a linked list - */ -static ca_info_t* add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_info) -{ - ca_info_t *current_ca_info; - ca_info_t *found_ca_info = NULL; - - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - - while (iterator->iterate(iterator, (void**)¤t_ca_info)) - { - if (current_ca_info->equals(current_ca_info, ca_info)) - { - found_ca_info = current_ca_info; - break; - } - } - iterator->destroy(iterator); - - if (found_ca_info) - { - current_ca_info->add_info(current_ca_info, ca_info); - ca_info->destroy(ca_info); - ca_info = found_ca_info; - } - else - { - this->ca_infos->insert_last(this->ca_infos, (void*)ca_info); - } - return ca_info; -} - -/** - * Release ca info record of a given name - */ -static status_t release_ca_info(private_local_credential_store_t *this, const char *name) -{ - status_t status = NOT_FOUND; - ca_info_t *ca_info; - - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->equals_name_release_info(ca_info, name)) - { - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; -} - -/** - * Implements local_credential_store_t.add_end_certificate - */ -static x509_t* add_end_certificate(private_local_credential_store_t *this, x509_t *cert) -{ - x509_t *ret_cert = add_certificate(this->certs, cert); - - /* add crl and ocsp uris the first time the certificate is added */ - if (ret_cert == cert) - { - ca_info_t *issuer = get_issuer(this, cert); - - if (issuer) - { - add_uris(issuer, cert); - } - } - return ret_cert; -} - -/** - * Implements local_credential_store_t.add_auth_certificate - */ -static x509_t* add_auth_certificate(private_local_credential_store_t *this, x509_t *cert, u_int auth_flags) -{ - cert->add_authority_flags(cert, auth_flags); - return add_certificate(this->auth_certs, cert); -} - -/** - * Implements local_credential_store_t.create_cert_iterator - */ -static iterator_t* create_cert_iterator(private_local_credential_store_t *this) -{ - return this->certs->create_iterator(this->certs, TRUE); -} - -/** - * Implements local_credential_store_t.create_cacert_iterator - */ -static iterator_t* create_auth_cert_iterator(private_local_credential_store_t *this) -{ - return this->auth_certs->create_iterator(this->auth_certs, TRUE); -} - -/** - * Implements local_credential_store_t.create_cainfo_iterator - */ -static iterator_t* create_cainfo_iterator(private_local_credential_store_t *this) -{ - return this->ca_infos->create_iterator(this->ca_infos, TRUE); -} - -/** - * Implements local_credential_store_t.create_acert_iterator - */ -static iterator_t* create_acert_iterator(private_local_credential_store_t *this) -{ - return this->acerts->create_iterator_locked(this->acerts, &this->acerts_mutex); -} - -/** - * Implements local_credential_store_t.load_auth_certificates - */ -static void load_auth_certificates(private_local_credential_store_t *this, - u_int auth_flag, - const char* label, - const char* path) -{ - struct dirent* entry; - struct stat stb; - DIR* dir; - - DBG1(DBG_CFG, "loading %s certificates from '%s'", label, path); - - dir = opendir(path); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening %s certs directory '%s'", label, path); - return; - } - - while ((entry = readdir(dir)) != NULL) - { - char file[PATH_BUF]; - - snprintf(file, sizeof(file), "%s/%s", path, entry->d_name); - - if (stat(file, &stb) == -1) - { - continue; - } - /* try to parse all regular files */ - if (stb.st_mode & S_IFREG) - { - x509_t *cert = x509_create_from_file(file, label); - - if (cert) - { - err_t ugh = cert->is_valid(cert, NULL); - - if (ugh != NULL) - { - DBG1(DBG_CFG, "warning: %s certificate %s", label, ugh); - } - - if (auth_flag == AUTH_CA && !cert->is_ca(cert)) - { - DBG1(DBG_CFG, " CA basic constraints flag not set, cert discarded"); - cert->destroy(cert); - } - else - { - x509_t *ret_cert; - - cert->add_authority_flags(cert, auth_flag); - - ret_cert = add_certificate(this->auth_certs, cert); - - if (auth_flag == AUTH_CA && ret_cert == cert) - { - ca_info_t *ca_info = ca_info_create(NULL, cert); - - add_ca_info(this, ca_info); - } - } - } - } - } - closedir(dir); -} - -/** - * Implements local_credential_store_t.load_ca_certificates - */ -static void load_ca_certificates(private_local_credential_store_t *this) -{ - load_auth_certificates(this, AUTH_CA, "ca", CA_CERTIFICATE_DIR); - - /* add any crl and ocsp uris found in the ca certificates to the - * corresponding issuer info record. We can do this only after all - * ca certificates have been loaded and the ca hierarchy is known. - */ - { - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - ca_info_t *ca_info; - - while (iterator->iterate(iterator, (void **)&ca_info)) - { - if (ca_info->is_ca(ca_info)) - { - x509_t *cacert = ca_info->get_certificate(ca_info); - ca_info_t *issuer = get_issuer(this, cacert); - - if (issuer) - { - add_uris(issuer, cacert); - } - } - } - iterator->destroy(iterator); - } -} - -/** - * Implements local_credential_store_t.load_aa_certificates - */ -static void load_aa_certificates(private_local_credential_store_t *this) -{ - load_auth_certificates(this, AUTH_AA, "aa", AA_CERTIFICATE_DIR); -} - -/** - * Add a unique attribute certificate to a linked list - */ -static void add_attr_certificate(private_local_credential_store_t *this, x509ac_t *cert) -{ - iterator_t *iterator; - x509ac_t *current_cert; - bool found = FALSE; - - pthread_mutex_lock(&(this->acerts_mutex)); - iterator = this->acerts->create_iterator(this->acerts, TRUE); - - while (iterator->iterate(iterator, (void **)¤t_cert)) - { - if (cert->equals_holder(cert, current_cert)) - { - if (cert->is_newer(cert, current_cert)) - { - iterator->replace(iterator, NULL, (void *)cert); - current_cert->destroy(current_cert); - DBG1(DBG_CFG, " this attr cert is newer - existing attr cert replaced"); - } - else - { - cert->destroy(cert); - DBG1(DBG_CFG, " this attr cert is not newer - existing attr cert retained"); - } - found = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (!found) - { - this->acerts->insert_last(this->acerts, (void *)cert); - } - pthread_mutex_unlock(&(this->acerts_mutex)); -} - -/** - * Implements local_credential_store_t.load_attr_certificates - */ -static void load_attr_certificates(private_local_credential_store_t *this) -{ - struct dirent* entry; - struct stat stb; - DIR* dir; - - const char *path = ATTR_CERTIFICATE_DIR; - - DBG1(DBG_CFG, "loading attribute certificates from '%s'", path); - - dir = opendir(ATTR_CERTIFICATE_DIR); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening attribute certs directory '%s'", path); - return; - } - - while ((entry = readdir(dir)) != NULL) - { - char file[PATH_BUF]; - - snprintf(file, sizeof(file), "%s/%s", path, entry->d_name); - - if (stat(file, &stb) == -1) - { - continue; - } - /* try to parse all regular files */ - if (stb.st_mode & S_IFREG) - { - x509ac_t *cert = x509ac_create_from_file(file); - - if (cert) - { - err_t ugh = cert->is_valid(cert, NULL); - - if (ugh != NULL) - { - DBG1(DBG_CFG, "warning: attribute certificate %s", ugh); - } - add_attr_certificate(this, cert); - } - } - } - closedir(dir); - - -} - -/** - * Implements local_credential_store_t.load_ocsp_certificates - */ -static void load_ocsp_certificates(private_local_credential_store_t *this) -{ - load_auth_certificates(this, AUTH_OCSP, "ocsp", OCSP_CERTIFICATE_DIR); -} - -/** - * Add the latest crl to the issuing ca - */ -static void add_crl(private_local_credential_store_t *this, crl_t *crl, const char *path) -{ - iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); - ca_info_t *ca_info; - bool found = FALSE; - - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->is_ca(ca_info) && ca_info->is_crl_issuer(ca_info, crl)) - { - char buffer[BUF_LEN]; - chunk_t uri = { buffer, 7 + strlen(path) }; - - ca_info->add_crl(ca_info, crl); - if (uri.len < BUF_LEN) - { - snprintf(buffer, BUF_LEN, "file://%s", path); - ca_info->add_crluri(ca_info, uri); - } - found = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (!found) - { - crl->destroy(crl); - DBG2(DBG_CFG, " no issuing ca found for this crl - discarded"); - } -} - -/** - * Implements local_credential_store_t.load_crls - */ -static void load_crls(private_local_credential_store_t *this) -{ - struct dirent* entry; - struct stat stb; - DIR* dir; - crl_t *crl; - - DBG1(DBG_CFG, "loading crls from '%s'", CRL_DIR); - - dir = opendir(CRL_DIR); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening crl directory '%s'", CRL_DIR); - return; - } - - while ((entry = readdir(dir)) != NULL) - { - char file[PATH_BUF]; - - snprintf(file, sizeof(file), "%s/%s", CRL_DIR, entry->d_name); - - if (stat(file, &stb) == -1) - { - continue; - } - /* try to parse all regular files */ - if (stb.st_mode & S_IFREG) - { - crl = crl_create_from_file(file); - if (crl) - { - DBG1(DBG_CFG, " crl is %s", crl->is_valid(crl)? "valid":"stale"); - add_crl(this, crl, file); - } - } - } - closedir(dir); -} - -/** - * Convert a string of characters into a binary secret - * A string between single or double quotes is treated as ASCII characters - * A string prepended by 0x is treated as HEX and prepended by 0s as Base64 - */ -static err_t extract_secret(chunk_t *secret, chunk_t *line) -{ - chunk_t raw_secret; - char delimiter = ' '; - bool quotes = FALSE; - - if (!eat_whitespace(line)) - { - return "missing secret"; - } - - if (*line->ptr == '\'' || *line->ptr == '"') - { - quotes = TRUE; - delimiter = *line->ptr; - line->ptr++; line->len--; - } - - if (!extract_token(&raw_secret, delimiter, line)) - { - if (delimiter == ' ') - { - raw_secret = *line; - } - else - { - return "missing second delimiter"; - } - } - - if (quotes) - { - /* treat as an ASCII string */ - *secret = chunk_clone(raw_secret); - } - else - { - size_t len; - err_t ugh; - - /* secret converted to binary form doesn't use more space than the raw_secret */ - *secret = chunk_alloc(raw_secret.len); - - /* convert from HEX or Base64 to binary */ - ugh = ttodata(raw_secret.ptr, raw_secret.len, 0, secret->ptr, secret->len, &len); - - if (ugh != NULL) - { - chunk_free_randomized(secret); - return ugh; - } - secret->len = len; - } - return NULL; -} - -/** - * Implements local_credential_store_t.load_secrets - */ -static void load_secrets(private_local_credential_store_t *this, bool reload) -{ - FILE *fd = fopen(SECRETS_FILE, "r"); - - if (fd) - { - size_t bytes; - int line_nr = 0; - chunk_t chunk, src, line; - - DBG1(DBG_CFG, "%sloading secrets from \"%s\"", - reload? "re":"", SECRETS_FILE); - - fseek(fd, 0, SEEK_END); - chunk.len = ftell(fd); - rewind(fd); - chunk.ptr = malloc(chunk.len); - bytes = fread(chunk.ptr, 1, chunk.len, fd); - fclose(fd); - src = chunk; - - pthread_mutex_lock(&(this->keys_mutex)); - if (reload) - { - DBG1(DBG_CFG, " forgetting old secrets"); - this->private_keys->destroy_offset(this->private_keys, - offsetof(rsa_private_key_t, destroy)); - this->private_keys = linked_list_create(); - - this->shared_keys->destroy_function(this->shared_keys, - (void*)shared_key_destroy); - this->shared_keys = linked_list_create(); - - this->eap_keys->destroy_function(this->eap_keys, - (void*)shared_key_destroy); - this->eap_keys = linked_list_create(); - } - - while (fetchline(&src, &line)) - { - chunk_t ids, token; - bool is_eap = FALSE; - - line_nr++; - - if (!eat_whitespace(&line)) - { - continue; - } - if (!extract_last_token(&ids, ':', &line)) - { - DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr); - goto error; - } - /* NULL terminate the ids string by replacing the : separator */ - *(ids.ptr + ids.len) = '\0'; - - if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) - { - DBG1(DBG_CFG, "line %d: missing token", line_nr); - goto error; - } - if (match("RSA", &token)) - { - char path[PATH_BUF]; - chunk_t filename; - chunk_t secret = chunk_empty; - chunk_t *passphrase = NULL; - - rsa_private_key_t *key; - - err_t ugh = extract_value(&filename, &line); - - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); - goto error; - } - if (filename.len == 0) - { - DBG1(DBG_CFG, "line %d: empty filename", line_nr); - goto error; - } - if (*filename.ptr == '/') - { - /* absolute path name */ - snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr); - } - else - { - /* relative path name */ - snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR, - filename.len, filename.ptr); - } - - /* check for optional passphrase */ - if (eat_whitespace(&line)) - { - ugh = extract_secret(&secret, &line); - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh); - goto error; - } - if (secret.len > 0) - passphrase = &secret; - } - key = rsa_private_key_create_from_file(path, passphrase); - if (key) - { - this->private_keys->insert_last(this->private_keys, (void*)key); - } - chunk_free_randomized(&secret); - } - else if ( match("PSK", &token) || - ((match("EAP", &token) || match("XAUTH", &token)) && (is_eap = TRUE))) - { - shared_key_t *shared_key; - chunk_t secret = chunk_empty; - - err_t ugh = extract_secret(&secret, &line); - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh); - goto error; - } - - DBG1(DBG_CFG, " loading %s key for %s", - is_eap ? "EAP" : "shared", - ids.len > 0 ? (char*)ids.ptr : "%any"); - - DBG4(DBG_CFG, " secret:", secret); - - shared_key = shared_key_create(secret); - if (is_eap) - { - this->eap_keys->insert_last(this->eap_keys, (void*)shared_key); - } - else - { - this->shared_keys->insert_last(this->shared_keys, (void*)shared_key); - } - while (ids.len > 0) - { - chunk_t id; - identification_t *peer_id; - - ugh = extract_value(&id, &ids); - if (ugh != NULL) - { - DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); - goto error; - } - if (id.len == 0) - { - continue; - } - - /* NULL terminate the ID string */ - *(id.ptr + id.len) = '\0'; - - peer_id = identification_create_from_string(id.ptr); - if (peer_id == NULL) - { - DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr); - goto error; - } - - if (peer_id->get_type(peer_id) == ID_ANY) - { - peer_id->destroy(peer_id); - continue; - } - shared_key->peers->insert_last(shared_key->peers, (void*)peer_id); - } - } - else if (match("PIN", &token)) - { - - } - else - { - DBG1(DBG_CFG, "line %d: token must be either " - "RSA, PSK, EAP, or PIN", line_nr, token.len); - goto error; - } - } -error: - chunk_free_randomized(&chunk); - pthread_mutex_unlock(&(this->keys_mutex)); - } - else - { - DBG1(DBG_CFG, "could not open file '%s': %s", SECRETS_FILE, - strerror(errno)); - } -} - -/** - * Implementation of local_credential_store_t.destroy. - */ -static void destroy(private_local_credential_store_t *this) -{ - this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy)); - this->auth_certs->destroy_offset(this->auth_certs, offsetof(x509_t, destroy)); - this->ca_infos->destroy_offset(this->ca_infos, offsetof(ca_info_t, destroy)); - - pthread_mutex_lock(&(this->acerts_mutex)); - this->acerts->destroy_offset(this->acerts, offsetof(x509ac_t, destroy)); - pthread_mutex_unlock(&(this->acerts_mutex)); - - pthread_mutex_lock(&(this->keys_mutex)); - this->private_keys->destroy_offset(this->private_keys, offsetof(rsa_private_key_t, destroy)); - this->shared_keys->destroy_function(this->shared_keys, (void*)shared_key_destroy); - this->eap_keys->destroy_function(this->eap_keys, (void*)shared_key_destroy); - pthread_mutex_unlock(&(this->keys_mutex)); - - free(this); -} - -/** - * Described in header. - */ -local_credential_store_t * local_credential_store_create(void) -{ - private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t); - - /* public functions */ - this->public.credential_store.get_shared_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_shared_key; - this->public.credential_store.get_eap_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_eap_key; - this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key; - this->public.credential_store.has_rsa_private_key = (bool (*) (credential_store_t*,rsa_public_key_t*))has_rsa_private_key; - this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate; - this->public.credential_store.get_auth_certificate = (x509_t* (*) (credential_store_t*,u_int,identification_t*))get_auth_certificate; - this->public.credential_store.get_ca_certificate_by_keyid = (x509_t* (*) (credential_store_t*,chunk_t))get_ca_certificate_by_keyid; - this->public.credential_store.get_issuer = (ca_info_t* (*) (credential_store_t*,x509_t*))get_issuer; - this->public.credential_store.is_trusted = (bool (*) (credential_store_t*,const char*,x509_t*))is_trusted; - this->public.credential_store.rsa_signature = (status_t (*) (credential_store_t*,rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t*))rsa_signature; - this->public.credential_store.verify_signature = (status_t (*) (credential_store_t*,chunk_t,chunk_t,identification_t*,ca_info_t**))verify_signature; - this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify; - this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate; - this->public.credential_store.add_auth_certificate = (x509_t* (*) (credential_store_t*,x509_t*,u_int))add_auth_certificate; - this->public.credential_store.add_ca_info = (ca_info_t* (*) (credential_store_t*,ca_info_t*))add_ca_info; - this->public.credential_store.release_ca_info = (status_t (*) (credential_store_t*,const char*))release_ca_info; - this->public.credential_store.create_cert_iterator = (iterator_t* (*) (credential_store_t*))create_cert_iterator; - this->public.credential_store.create_auth_cert_iterator = (iterator_t* (*) (credential_store_t*))create_auth_cert_iterator; - this->public.credential_store.create_cainfo_iterator = (iterator_t* (*) (credential_store_t*))create_cainfo_iterator; - this->public.credential_store.create_acert_iterator = (iterator_t* (*) (credential_store_t*))create_acert_iterator; - this->public.credential_store.load_ca_certificates = (void (*) (credential_store_t*))load_ca_certificates; - this->public.credential_store.load_aa_certificates = (void (*) (credential_store_t*))load_aa_certificates; - this->public.credential_store.load_attr_certificates = (void (*) (credential_store_t*))load_attr_certificates; - this->public.credential_store.load_ocsp_certificates = (void (*) (credential_store_t*))load_ocsp_certificates; - this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls; - this->public.credential_store.load_secrets = (void (*) (credential_store_t*,bool))load_secrets; - this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy; - - /* initialize the mutexes */ - pthread_mutex_init(&(this->keys_mutex), NULL); - pthread_mutex_init(&(this->acerts_mutex), NULL); - - /* private variables */ - this->shared_keys = linked_list_create(); - this->eap_keys = linked_list_create(); - this->private_keys = linked_list_create(); - this->certs = linked_list_create(); - this->auth_certs = linked_list_create(); - this->ca_infos = linked_list_create(); - this->acerts = linked_list_create(); - - return (&this->public); -} diff --git a/src/charon/config/credentials/local_credential_store.h b/src/charon/config/credentials/local_credential_store.h deleted file mode 100644 index 87a12663a..000000000 --- a/src/charon/config/credentials/local_credential_store.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file local_credential_store.h - * - * @brief Interface of local_credential_store_t. - * - */ - -/* - * Copyright (C) 2006 Martin Willi - * 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. - */ - -#ifndef LOCAL_CREDENTIAL_H_ -#define LOCAL_CREDENTIAL_H_ - -typedef struct local_credential_store_t local_credential_store_t; - -#include <library.h> -#include <credential_store.h> -#include <daemon.h> - - -/** - * @brief A credential_store_t implementation using simple credentail lists. - * - * The local_credential_store_t class implements the credential_store_t interface - * as simple as possible. The credentials are stored in lists, and are loaded from - * files on the disk. - * Shared secret are not handled yet, so get_shared_secret always returns NOT_FOUND. - * - * @b Constructors: - * - local_credential_store_create(bool strict) - * - * @ingroup config - */ -struct local_credential_store_t { - - /** - * Implements credential_store_t interface - */ - credential_store_t credential_store; -}; - -/** - * @brief Creates a local_credential_store_t instance. - * - * @return credential store instance. - * - * @ingroup config - */ -local_credential_store_t *local_credential_store_create(void); - -#endif /* LOCAL_CREDENTIAL_H_ */ diff --git a/src/charon/config/ike_cfg.c b/src/charon/config/ike_cfg.c index abb300aab..8beccdc29 100644 --- a/src/charon/config/ike_cfg.c +++ b/src/charon/config/ike_cfg.c @@ -1,10 +1,3 @@ -/** - * @file ike_cfg.c - * - * @brief Implementation of ike_cfg_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,12 +12,16 @@ * 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. + * + * $Id: ike_cfg.c 4062 2008-06-12 11:42:19Z martin $ */ #include "ike_cfg.h" #include <string.h> +#include <daemon.h> + typedef struct private_ike_cfg_t private_ike_cfg_t; @@ -46,12 +43,12 @@ struct private_ike_cfg_t { /** * Address of local host */ - host_t *my_host; + char *me; /** * Address of remote host */ - host_t *other_host; + char *other; /** * should we send a certificate request? @@ -86,19 +83,19 @@ static bool force_encap_meth(private_ike_cfg_t *this) } /** - * Implementation of ike_cfg_t.get_my_host. + * Implementation of ike_cfg_t.get_my_addr. */ -static host_t *get_my_host (private_ike_cfg_t *this) +static char *get_my_addr(private_ike_cfg_t *this) { - return this->my_host; + return this->me; } /** - * Implementation of ike_cfg_t.get_other_host. + * Implementation of ike_cfg_t.get_other_addr. */ -static host_t *get_other_host (private_ike_cfg_t *this) +static char *get_other_addr(private_ike_cfg_t *this) { - return this->other_host; + return this->other; } /** @@ -141,6 +138,7 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, stored_iter = this->proposals->create_iterator(this->proposals, TRUE); supplied_iter = proposals->create_iterator(proposals, TRUE); + /* compare all stored proposals with all supplied. Stored ones are preferred.*/ while (stored_iter->iterate(stored_iter, (void**)&stored)) { @@ -154,6 +152,9 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, /* they match, return */ stored_iter->destroy(stored_iter); supplied_iter->destroy(supplied_iter); + DBG2(DBG_CFG, "received proposals: %#P", proposals); + DBG2(DBG_CFG, "configured proposals: %#P", this->proposals); + DBG2(DBG_CFG, "selected proposal: %P", selected); return selected; } } @@ -161,6 +162,8 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */ stored_iter->destroy(stored_iter); supplied_iter->destroy(supplied_iter); + DBG1(DBG_CFG, "received proposals: %#P", proposals); + DBG1(DBG_CFG, "configured proposals: %#P", this->proposals); return NULL; } @@ -170,30 +173,71 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, */ static diffie_hellman_group_t get_dh_group(private_ike_cfg_t *this) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *proposal; - algorithm_t *algo; - diffie_hellman_group_t dh_group = MODP_NONE; + u_int16_t dh_group = MODP_NONE; - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)&proposal)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &proposal)) { - if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo)) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL)) { - dh_group = algo->algorithm; break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return dh_group; } /** + * Implementation of ike_cfg_t.equals. + */ +static bool equals(private_ike_cfg_t *this, private_ike_cfg_t *other) +{ + enumerator_t *e1, *e2; + proposal_t *p1, *p2; + bool eq = TRUE; + + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + if (this->proposals->get_count(this->proposals) != + other->proposals->get_count(other->proposals)) + { + return FALSE; + } + e1 = this->proposals->create_enumerator(this->proposals); + e2 = this->proposals->create_enumerator(this->proposals); + while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2)) + { + if (!p1->equals(p1, p2)) + { + eq = FALSE; + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + + return (eq && + this->certreq == other->certreq && + this->force_encap == other->force_encap && + streq(this->me, other->me) && + streq(this->other, other->other)); +} + +/** * Implementation of ike_cfg_t.get_ref. */ -static void get_ref(private_ike_cfg_t *this) +static ike_cfg_t* get_ref(private_ike_cfg_t *this) { ref_get(&this->refcount); + return &this->public; } /** @@ -205,8 +249,8 @@ static void destroy(private_ike_cfg_t *this) { this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); - this->my_host->destroy(this->my_host); - this->other_host->destroy(this->other_host); + free(this->me); + free(this->other); free(this); } } @@ -215,29 +259,29 @@ static void destroy(private_ike_cfg_t *this) * Described in header. */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - host_t *my_host, host_t *other_host) + char *me, char *other) { private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t); /* public functions */ this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq; this->public.force_encap = (bool (*) (ike_cfg_t *))force_encap_meth; - this->public.get_my_host = (host_t*(*)(ike_cfg_t*))get_my_host; - this->public.get_other_host = (host_t*(*)(ike_cfg_t*))get_other_host; + this->public.get_my_addr = (char*(*)(ike_cfg_t*))get_my_addr; + this->public.get_other_addr = (char*(*)(ike_cfg_t*))get_other_addr; this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal; this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals; this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal; this->public.get_dh_group = (diffie_hellman_group_t(*)(ike_cfg_t*)) get_dh_group; - this->public.get_ref = (void(*)(ike_cfg_t*))get_ref; + this->public.equals = (bool(*)(ike_cfg_t*,ike_cfg_t*)) equals; + this->public.get_ref = (ike_cfg_t*(*)(ike_cfg_t*))get_ref; this->public.destroy = (void(*)(ike_cfg_t*))destroy; /* private variables */ this->refcount = 1; this->certreq = certreq; this->force_encap = force_encap; - this->my_host = my_host; - this->other_host = other_host; - + this->me = strdup(me); + this->other = strdup(other); this->proposals = linked_list_create(); return &this->public; diff --git a/src/charon/config/ike_cfg.h b/src/charon/config/ike_cfg.h index 5165d12a6..6169af96b 100644 --- a/src/charon/config/ike_cfg.h +++ b/src/charon/config/ike_cfg.h @@ -1,10 +1,3 @@ -/** - * @file ike_cfg.h - * - * @brief Interface of ike_cfg_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: ike_cfg.h 4044 2008-06-06 15:05:54Z martin $ + */ + +/** + * @defgroup ike_cfg ike_cfg + * @{ @ingroup config */ #ifndef IKE_CFG_H_ @@ -34,128 +34,113 @@ typedef struct ike_cfg_t ike_cfg_t; #include <crypto/diffie_hellman.h> /** - * @brief An ike_cfg_t defines the rules to set up an IKE_SA. + * An ike_cfg_t defines the rules to set up an IKE_SA. * * @see peer_cfg_t to get an overview over the configurations. - * - * @b Constructors: - * - ike_cfg_create() - * - * @ingroup config */ struct ike_cfg_t { /** - * @brief Get own address. + * Get own address. * - * @param this calling object - * @return host information as host_t object + * @return string of address/DNS name */ - host_t* (*get_my_host) (ike_cfg_t *this); + char* (*get_my_addr) (ike_cfg_t *this); /** - * @brief Get peers address. + * Get peers address. * - * @param this calling object - * @return host information as host_t object + * @return string of address/DNS name */ - host_t* (*get_other_host) (ike_cfg_t *this); + char* (*get_other_addr) (ike_cfg_t *this); /** - * @brief Adds a proposal to the list. + * Adds a proposal to the list. * * The first added proposal has the highest priority, the last * added the lowest. * - * @param this calling object * @param proposal proposal to add */ void (*add_proposal) (ike_cfg_t *this, proposal_t *proposal); /** - * @brief Returns a list of all supported proposals. + * Returns a list of all supported proposals. * * Returned list and its proposals must be destroyed after use. * - * @param this calling object * @return list containing all the proposals */ linked_list_t* (*get_proposals) (ike_cfg_t *this); /** - * @brief Select a proposed from suggested proposals. + * Select a proposed from suggested proposals. * * Returned proposal must be destroyed after use. * - * @param this calling object * @param proposals list of proposals to select from * @return selected proposal, or NULL if none matches. */ proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals); /** - * @brief Should we send a certificate request in IKE_SA_INIT? + * Should we send a certificate request in IKE_SA_INIT? * - * @param this calling object * @return certificate request sending policy */ bool (*send_certreq) (ike_cfg_t *this); /** - * @brief Enforce UDP encapsulation by faking NATD notifies? + * Enforce UDP encapsulation by faking NATD notifies? * - * @param this calling object * @return TRUE to enfoce UDP encapsulation */ bool (*force_encap) (ike_cfg_t *this); /** - * @brief Get the DH group to use for IKE_SA setup. + * Get the DH group to use for IKE_SA setup. * - * @param this calling object * @return dh group to use for initialization */ diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this); /** - * @brief Get a new reference to this ike_cfg. + * Check if two IKE configs are equal. * - * Get a new reference to this ike_cfg by increasing - * it's internal reference counter. - * Do not call get_ref or any other function until you - * already have a reference. Otherwise the object may get - * destroyed while calling get_ref(), + * @param other other to check for equality + * @return TRUE if other equal to this + */ + bool (*equals)(ike_cfg_t *this, ike_cfg_t *other); + + /** + * Increase reference count. * - * @param this calling object + * @return reference to this */ - void (*get_ref) (ike_cfg_t *this); + ike_cfg_t* (*get_ref) (ike_cfg_t *this); /** - * @brief Destroys a ike_cfg_t object. + * Destroys a ike_cfg_t object. * * Decrements the internal reference counter and * destroys the ike_cfg when it reaches zero. - * - * @param this calling object */ void (*destroy) (ike_cfg_t *this); }; /** - * @brief Creates a ike_cfg_t object. + * Creates a ike_cfg_t object. * * Supplied hosts become owned by ike_cfg, the name gets cloned. * * @param name ike_cfg identifier * @param certreq TRUE to send a certificate request * @param force_encap enforce UDP encapsulation by faking NATD notify - * @param my_host host_t representing local address - * @param other_host host_t representing remote address + * @param me address/DNS name of local peer + * @param other address/DNS name of remote peer * @return ike_cfg_t object. - * - * @ingroup config */ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, - host_t *my_host, host_t *other_host); + char *me, char *other); -#endif /* IKE_CFG_H_ */ +#endif /* IKE_CFG_H_ @} */ diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c index 0b5d391c4..0e56759c2 100644 --- a/src/charon/config/peer_cfg.c +++ b/src/charon/config/peer_cfg.c @@ -1,12 +1,5 @@ -/** - * @file peer_cfg.c - * - * @brief Implementation of peer_cfg_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +13,8 @@ * 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. + * + * $Id: peer_cfg.c 4051 2008-06-10 09:08:27Z tobias $ */ #include <string.h> @@ -29,19 +24,23 @@ #include <utils/linked_list.h> #include <utils/identification.h> -#include <crypto/ietf_attr_list.h> ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND, "CERT_ALWAYS_SEND", "CERT_SEND_IF_ASKED", - "CERT_NEVER_SEND" + "CERT_NEVER_SEND", ); -ENUM(dpd_action_names, DPD_NONE, DPD_RESTART, - "DPD_NONE", - "DPD_CLEAR", - "DPD_ROUTE", - "DPD_RESTART" +ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP, + "UNIQUE_NO", + "UNIQUE_REPLACE", + "UNIQUE_KEEP", +); + +ENUM(config_auth_method_names, CONF_AUTH_PUBKEY, CONF_AUTH_EAP, + "CONF_AUTH_PUBKEY", + "CONF_AUTH_PSK", + "CONF_AUTH_EAP", ); typedef struct private_peer_cfg_t private_peer_cfg_t; @@ -97,29 +96,19 @@ struct private_peer_cfg_t { identification_t *other_id; /** - * we have a cert issued by this CA - */ - identification_t *my_ca; - - /** - * we require the other end to have a cert issued by this CA - */ - identification_t *other_ca; - - /** - * we require the other end to belong to at least one group + * should we send a certificate */ - linked_list_t *groups; + cert_policy_t cert_policy; /** - * should we send a certificate + * uniqueness of an IKE_SA */ - cert_policy_t cert_policy; + unique_policy_t unique; /** * Method to use for own authentication data */ - auth_method_t auth_method; + config_auth_method_t auth_method; /** * EAP type to use for peer authentication @@ -162,42 +151,42 @@ struct private_peer_cfg_t { u_int32_t over_time; /** - * What to do with an SA when other peer seams to be dead? + * DPD check intervall */ - bool dpd_delay; + u_int32_t dpd; /** - * What to do with CHILDren when other peer seams to be dead? + * virtual IP to use locally */ - bool dpd_action; + host_t *virtual_ip; /** - * virtual IP to use locally + * pool to acquire configuration attributes from */ - host_t *my_virtual_ip; + char *pool; /** - * virtual IP to use remotly + * required authorization constraints */ - host_t *other_virtual_ip; + auth_info_t *auth; -#ifdef P2P +#ifdef ME /** * Is this a mediation connection? */ - bool p2p_mediation; + bool mediation; /** * Name of the mediation connection to mediate through */ - peer_cfg_t *p2p_mediated_by; + peer_cfg_t *mediated_by; /** * ID of our peer at the mediation server (= leftid of the peer's conn with * the mediation server) */ identification_t *peer_id; -#endif /* P2P */ +#endif /* ME */ }; /** @@ -235,12 +224,26 @@ static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg) } /** - * Implementation of peer_cfg_t.create_child_cfg_iterator. + * Implementation of peer_cfg_t.remove_child_cfg. + */ +static void remove_child_cfg(private_peer_cfg_t *this, enumerator_t *enumerator) +{ + pthread_mutex_lock(&this->mutex); + this->child_cfgs->remove_at(this->child_cfgs, enumerator); + pthread_mutex_unlock(&this->mutex); +} + +/** + * Implementation of peer_cfg_t.create_child_cfg_enumerator. */ -static iterator_t* create_child_cfg_iterator(private_peer_cfg_t *this) +static enumerator_t* create_child_cfg_enumerator(private_peer_cfg_t *this) { - return this->child_cfgs->create_iterator_locked(this->child_cfgs, - &this->mutex); + enumerator_t *enumerator; + + pthread_mutex_lock(&this->mutex); + enumerator = this->child_cfgs->create_enumerator(this->child_cfgs); + return enumerator_create_cleaner(enumerator, + (void*)pthread_mutex_unlock, &this->mutex); } /** @@ -267,20 +270,19 @@ static child_cfg_t* select_child_cfg(private_peer_cfg_t *this, host_t *my_host, host_t *other_host) { child_cfg_t *current, *found = NULL; - iterator_t *iterator; + enumerator_t *enumerator; - iterator = create_child_cfg_iterator(this); - while (iterator->iterate(iterator, (void**)¤t)) + enumerator = create_child_cfg_enumerator(this); + while (enumerator->enumerate(enumerator, ¤t)) { if (contains_ts(current, TRUE, my_ts, my_host) && contains_ts(current, FALSE, other_ts, other_host)) { - found = current; - found->get_ref(found); + found = current->get_ref(current); break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return found; } @@ -301,47 +303,31 @@ static identification_t *get_other_id(private_peer_cfg_t *this) } /** - * Implementation of peer_cfg_t.get_my_ca - */ -static identification_t *get_my_ca(private_peer_cfg_t *this) -{ - return this->my_ca; -} - -/** - * Implementation of peer_cfg_t.get_other_ca - */ -static identification_t *get_other_ca(private_peer_cfg_t *this) -{ - return this->other_ca; -} - -/** - * Implementation of peer_cfg_t.get_groups + * Implementation of peer_cfg_t.get_cert_policy. */ -static linked_list_t *get_groups(private_peer_cfg_t *this) +static cert_policy_t get_cert_policy(private_peer_cfg_t *this) { - return this->groups; + return this->cert_policy; } /** - * Implementation of peer_cfg_t.get_cert_policy. + * Implementation of peer_cfg_t.get_unique_policy. */ -static cert_policy_t get_cert_policy(private_peer_cfg_t *this) +static unique_policy_t get_unique_policy(private_peer_cfg_t *this) { - return this->cert_policy; + return this->unique; } /** - * Implementation of connection_t.auth_method_t. + * Implementation of peer_cfg_t.get_auth_method. */ -static auth_method_t get_auth_method(private_peer_cfg_t *this) +static config_auth_method_t get_auth_method(private_peer_cfg_t *this) { return this->auth_method; } /** - * Implementation of connection_t.get_eap_type. + * Implementation of peer_cfg_t.get_eap_type. */ static eap_type_t get_eap_type(private_peer_cfg_t *this, u_int32_t *vendor) { @@ -350,7 +336,7 @@ static eap_type_t get_eap_type(private_peer_cfg_t *this, u_int32_t *vendor) } /** - * Implementation of connection_t.get_keyingtries. + * Implementation of peer_cfg_t.get_keyingtries. */ static u_int32_t get_keyingtries(private_peer_cfg_t *this) { @@ -406,60 +392,44 @@ static bool use_mobike(private_peer_cfg_t *this) } /** - * Implements peer_cfg_t.get_dpd_delay + * Implements peer_cfg_t.get_dpd */ -static u_int32_t get_dpd_delay(private_peer_cfg_t *this) +static u_int32_t get_dpd(private_peer_cfg_t *this) { - return this->dpd_delay; + return this->dpd; } /** - * Implements peer_cfg_t.get_dpd_action + * Implementation of peer_cfg_t.get_virtual_ip. */ -static dpd_action_t get_dpd_action(private_peer_cfg_t *this) +static host_t* get_virtual_ip(private_peer_cfg_t *this) { - return this->dpd_action; + return this->virtual_ip; } - + /** - * Implementation of peer_cfg_t.get_my_virtual_ip. + * Implementation of peer_cfg_t.get_pool. */ -static host_t* get_my_virtual_ip(private_peer_cfg_t *this) +static char* get_pool(private_peer_cfg_t *this) { - if (this->my_virtual_ip == NULL) - { - return NULL; - } - return this->my_virtual_ip->clone(this->my_virtual_ip); + return this->pool; } - + /** - * Implementation of peer_cfg_t.get_other_virtual_ip. + * Implementation of peer_cfg_t.get_auth. */ -static host_t* get_other_virtual_ip(private_peer_cfg_t *this, host_t *suggestion) +static auth_info_t* get_auth(private_peer_cfg_t *this) { - if (this->other_virtual_ip == NULL) - { /* disallow */ - return NULL; - } - if (!this->other_virtual_ip->is_anyaddr(this->other_virtual_ip)) - { /* force own configuration */ - return this->other_virtual_ip->clone(this->other_virtual_ip); - } - if (suggestion == NULL || suggestion->is_anyaddr(suggestion)) - { - return NULL; - } - return suggestion->clone(suggestion); + return this->auth; } -#ifdef P2P +#ifdef ME /** * Implementation of peer_cfg_t.is_mediation. */ static bool is_mediation(private_peer_cfg_t *this) { - return this->p2p_mediation; + return this->mediation; } /** @@ -467,11 +437,7 @@ static bool is_mediation(private_peer_cfg_t *this) */ static peer_cfg_t* get_mediated_by(private_peer_cfg_t *this) { - if (this->p2p_mediated_by) { - this->p2p_mediated_by->get_ref(this->p2p_mediated_by); - return this->p2p_mediated_by; - } - return NULL; + return this->mediated_by; } /** @@ -481,14 +447,61 @@ static identification_t* get_peer_id(private_peer_cfg_t *this) { return this->peer_id; } -#endif /* P2P */ +#endif /* ME */ + +/** + * Implementation of peer_cfg_t.equals. + */ +static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other) +{ + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + + return ( + this->ike_version == other->ike_version && + this->my_id->equals(this->my_id, other->my_id) && + this->other_id->equals(this->other_id, other->other_id) && + this->cert_policy == other->cert_policy && + this->unique == other->unique && + this->auth_method == other->auth_method && + this->eap_type == other->eap_type && + this->eap_vendor == other->eap_vendor && + this->keyingtries == other->keyingtries && + this->use_mobike == other->use_mobike && + this->rekey_time == other->rekey_time && + this->reauth_time == other->reauth_time && + this->jitter_time == other->jitter_time && + this->over_time == other->over_time && + this->dpd == other->dpd && + (this->virtual_ip == other->virtual_ip || + (this->virtual_ip && other->virtual_ip && + this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) && + (this->pool == other->pool || + (this->pool && other->pool && streq(this->pool, other->pool))) && + this->auth->equals(this->auth, other->auth) +#ifdef ME + && this->mediation == other->mediation && + this->mediated_by == other->mediated_by && + (this->peer_id == other->peer_id || + (this->peer_id && other->peer_id && + this->peer_id->equals(this->peer_id, other->peer_id))) +#endif /* ME */ + ); +} /** * Implements peer_cfg_t.get_ref. */ -static void get_ref(private_peer_cfg_t *this) +static peer_cfg_t* get_ref(private_peer_cfg_t *this) { ref_get(&this->refcount); + return &this->public; } /** @@ -502,16 +515,14 @@ static void destroy(private_peer_cfg_t *this) this->child_cfgs->destroy_offset(this->child_cfgs, offsetof(child_cfg_t, destroy)); this->my_id->destroy(this->my_id); this->other_id->destroy(this->other_id); - DESTROY_IF(this->my_ca); - DESTROY_IF(this->other_ca); - DESTROY_IF(this->my_virtual_ip); - DESTROY_IF(this->other_virtual_ip); -#ifdef P2P - DESTROY_IF(this->p2p_mediated_by); + DESTROY_IF(this->virtual_ip); + this->auth->destroy(this->auth); +#ifdef ME + DESTROY_IF(this->mediated_by); DESTROY_IF(this->peer_id); -#endif /* P2P */ - ietfAttr_list_destroy(this->groups); +#endif /* ME */ free(this->name); + free(this->pool); free(this); } } @@ -521,16 +532,14 @@ static void destroy(private_peer_cfg_t *this) */ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, identification_t *my_id, identification_t *other_id, - identification_t *my_ca, identification_t *other_ca, - linked_list_t *groups, cert_policy_t cert_policy, - auth_method_t auth_method, eap_type_t eap_type, + cert_policy_t cert_policy, unique_policy_t unique, + config_auth_method_t auth_method, eap_type_t eap_type, u_int32_t eap_vendor, u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t reauth_time, u_int32_t jitter_time, - u_int32_t over_time, bool mobike, - u_int32_t dpd_delay, dpd_action_t dpd_action, - host_t *my_virtual_ip, host_t *other_virtual_ip, - bool p2p_mediation, peer_cfg_t *p2p_mediated_by, + u_int32_t over_time, bool mobike, u_int32_t dpd, + host_t *virtual_ip, char *pool, + bool mediation, peer_cfg_t *mediated_by, identification_t *peer_id) { private_peer_cfg_t *this = malloc_thing(private_peer_cfg_t); @@ -540,32 +549,32 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, this->public.get_ike_version = (u_int(*) (peer_cfg_t *))get_ike_version; this->public.get_ike_cfg = (ike_cfg_t* (*) (peer_cfg_t *))get_ike_cfg; this->public.add_child_cfg = (void (*) (peer_cfg_t *, child_cfg_t*))add_child_cfg; - this->public.create_child_cfg_iterator = (iterator_t* (*) (peer_cfg_t *))create_child_cfg_iterator; + this->public.remove_child_cfg = (void(*)(peer_cfg_t*, enumerator_t*))remove_child_cfg; + this->public.create_child_cfg_enumerator = (enumerator_t* (*) (peer_cfg_t *))create_child_cfg_enumerator; this->public.select_child_cfg = (child_cfg_t* (*) (peer_cfg_t *,linked_list_t*,linked_list_t*,host_t*,host_t*))select_child_cfg; this->public.get_my_id = (identification_t* (*)(peer_cfg_t*))get_my_id; this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id; - this->public.get_my_ca = (identification_t* (*)(peer_cfg_t *))get_my_ca; - this->public.get_other_ca = (identification_t* (*)(peer_cfg_t *))get_other_ca; - this->public.get_groups = (linked_list_t* (*)(peer_cfg_t *))get_groups; this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy; - this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method; + this->public.get_unique_policy = (unique_policy_t (*) (peer_cfg_t *))get_unique_policy; + this->public.get_auth_method = (config_auth_method_t (*) (peer_cfg_t *))get_auth_method; this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *,u_int32_t*))get_eap_type; this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries; this->public.get_rekey_time = (u_int32_t(*)(peer_cfg_t*))get_rekey_time; this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time; this->public.get_over_time = (u_int32_t(*)(peer_cfg_t*))get_over_time; this->public.use_mobike = (bool (*) (peer_cfg_t *))use_mobike; - this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay; - this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action; - this->public.get_my_virtual_ip = (host_t* (*) (peer_cfg_t *))get_my_virtual_ip; - this->public.get_other_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_other_virtual_ip; - this->public.get_ref = (void(*)(peer_cfg_t *))get_ref; + this->public.get_dpd = (u_int32_t (*) (peer_cfg_t *))get_dpd; + this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *))get_virtual_ip; + this->public.get_pool = (char*(*)(peer_cfg_t*))get_pool; + this->public.get_auth = (auth_info_t*(*)(peer_cfg_t*))get_auth; + this->public.equals = (bool(*)(peer_cfg_t*, peer_cfg_t *other))equals; + this->public.get_ref = (peer_cfg_t*(*)(peer_cfg_t *))get_ref; this->public.destroy = (void(*)(peer_cfg_t *))destroy; -#ifdef P2P +#ifdef ME this->public.is_mediation = (bool (*) (peer_cfg_t *))is_mediation; this->public.get_mediated_by = (peer_cfg_t* (*) (peer_cfg_t *))get_mediated_by; this->public.get_peer_id = (identification_t* (*) (peer_cfg_t *))get_peer_id; -#endif /* P2P */ +#endif /* ME */ /* apply init values */ this->name = strdup(name); @@ -575,10 +584,8 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, pthread_mutex_init(&this->mutex, NULL); this->my_id = my_id; this->other_id = other_id; - this->my_ca = my_ca; - this->other_ca = other_ca; - this->groups = groups; this->cert_policy = cert_policy; + this->unique = unique; this->auth_method = auth_method; this->eap_type = eap_type; this->eap_vendor = eap_vendor; @@ -596,16 +603,19 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, this->jitter_time = jitter_time; this->over_time = over_time; this->use_mobike = mobike; - this->dpd_delay = dpd_delay; - this->dpd_action = dpd_action; - this->my_virtual_ip = my_virtual_ip; - this->other_virtual_ip = other_virtual_ip; + this->dpd = dpd; + this->virtual_ip = virtual_ip; + this->pool = pool ? strdup(pool) : NULL; + this->auth = auth_info_create(); this->refcount = 1; -#ifdef P2P - this->p2p_mediation = p2p_mediation; - this->p2p_mediated_by = p2p_mediated_by; +#ifdef ME + this->mediation = mediation; + this->mediated_by = mediated_by; this->peer_id = peer_id; -#endif /* P2P */ +#else /* ME */ + DESTROY_IF(mediated_by); + DESTROY_IF(peer_id); +#endif /* ME */ return &this->public; } diff --git a/src/charon/config/peer_cfg.h b/src/charon/config/peer_cfg.h index 7f1dbcab6..5662b48df 100644 --- a/src/charon/config/peer_cfg.h +++ b/src/charon/config/peer_cfg.h @@ -1,12 +1,5 @@ -/** - * @file peer_cfg.h - * - * @brief Interface of peer_cfg_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,32 +13,39 @@ * 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. + * + * $Id: peer_cfg.h 4054 2008-06-10 20:31:53Z andreas $ + */ + +/** + * @defgroup peer_cfg peer_cfg + * @{ @ingroup config */ #ifndef PEER_CFG_H_ #define PEER_CFG_H_ -typedef enum dpd_action_t dpd_action_t; typedef enum cert_policy_t cert_policy_t; +typedef enum unique_policy_t unique_policy_t; +typedef enum config_auth_method_t config_auth_method_t; typedef struct peer_cfg_t peer_cfg_t; #include <library.h> #include <utils/identification.h> -#include <utils/linked_list.h> +#include <utils/enumerator.h> #include <config/traffic_selector.h> #include <config/proposal.h> #include <config/ike_cfg.h> #include <config/child_cfg.h> #include <sa/authenticators/authenticator.h> #include <sa/authenticators/eap/eap_method.h> +#include <credentials/auth_info.h> /** * Certificate sending policy. This is also used for certificate * requests when using this definition for the other peer. If * it is CERT_NEVER_SEND, a certreq is omitted, otherwise its * included. - * - * @ingroup config * * @warning These definitions must be the same as in pluto/starter, * as they are sent over the stroke socket. @@ -61,36 +61,45 @@ enum cert_policy_t { /** * enum strings for cert_policy_t - * - * @ingroup config */ extern enum_name_t *cert_policy_names; /** - * @brief Actions to take when a peer does not respond (dead peer detected). - * - * These values are the same as in pluto/starter, so do not modify them! - * - * @ingroup config + * Uniqueness of an IKE_SA, used to drop multiple connections with one peer. */ -enum dpd_action_t { - /** DPD disabled */ - DPD_NONE, - /** remove CHILD_SAs without replacement */ - DPD_CLEAR, - /** route the CHILD_SAs to resetup when needed */ - DPD_ROUTE, - /** restart CHILD_SAs in a new IKE_SA, immediately */ - DPD_RESTART, +enum unique_policy_t { + /** do not check for client uniqueness */ + UNIQUE_NO, + /** replace unique IKE_SAs if new ones get established */ + UNIQUE_REPLACE, + /** keep existing IKE_SAs, close the new ones on connection attept */ + UNIQUE_KEEP, }; /** - * enum names for dpd_action_t. + * enum strings for unique_policy_t */ -extern enum_name_t *dpd_action_names; +extern enum_name_t *unique_policy_names; /** - * @brief Configuration of a peer, specified by IDs. + * Authentication method for this IKE_SA. + */ +enum config_auth_method_t { + /** authentication using public keys (RSA, ECDSA) */ + CONF_AUTH_PUBKEY = 1, + /** authentication using a pre-shared secret */ + CONF_AUTH_PSK = 2, + /** authentication using EAP */ + CONF_AUTH_EAP = 3, +}; + +/** + * enum strings for config_auth_method_t + */ +extern enum_name_t *config_auth_method_names; + +/** + * Configuration of a peer, specified by IDs. * * The peer config defines a connection between two given IDs. It contains * exactly one ike_cfg_t, which is use for initiation. Additionally, it contains @@ -106,61 +115,67 @@ extern enum_name_t *dpd_action_names; | - ... | | - dpd config | | - ... |-+ +---------------+ | - ... | +---------------+ +-------------------+ + ^ + | + +-------------------+ + | auth_info | + +-------------------+ + | auth_items | + +-------------------+ @endverbatim - * - * @b Constructors: - * - peer_cfg_create() - * - * @ingroup config + * The auth_info_t object associated to the peer_cfg holds additional + * authorization constraints. A peer who wants to use a config needs to fullfil + * the requirements defined in auth_info. */ struct peer_cfg_t { /** - * @brief Get the name of the peer_cfg. + * Get the name of the peer_cfg. * * Returned object is not getting cloned. * - * @param this calling object * @return peer_cfg's name */ char* (*get_name) (peer_cfg_t *this); /** - * @brief Get the IKE version to use for initiating. + * Get the IKE version to use for initiating. * - * @param this calling object * @return IKE major version */ u_int (*get_ike_version)(peer_cfg_t *this); /** - * @brief Get the IKE config to use for initiaton. + * Get the IKE config to use for initiaton. * - * @param this calling object * @return the IKE config to use */ ike_cfg_t* (*get_ike_cfg) (peer_cfg_t *this); /** - * @brief Attach a CHILD config. + * Attach a CHILD config. * - * @param this calling object * @param child_cfg CHILD config to add */ void (*add_child_cfg) (peer_cfg_t *this, child_cfg_t *child_cfg); /** - * @brief Create an iterator for all attached CHILD configs. + * Detach a CHILD config, pointed to by an enumerator. + * + * @param enumerator enumerator indicating element position + */ + void (*remove_child_cfg)(peer_cfg_t *this, enumerator_t *enumerator); + + /** + * Create an enumerator for all attached CHILD configs. * - * @param this calling object - * @return an iterator over all CHILD configs. + * @return an enumerator over all CHILD configs. */ - iterator_t* (*create_child_cfg_iterator) (peer_cfg_t *this); + enumerator_t* (*create_child_cfg_enumerator) (peer_cfg_t *this); /** - * @brief Select a CHILD config from traffic selectors. + * Select a CHILD config from traffic selectors. * - * @param this calling object * @param my_ts TS for local side * @param other_ts TS for remote side * @param my_host host to narrow down dynamic TS for local side @@ -172,213 +187,176 @@ struct peer_cfg_t { host_t *other_host); /** - * @brief Get own ID. + * Get the authentication constraint items. + * + * @return auth_info object to manipulate requirements + */ + auth_info_t* (*get_auth)(peer_cfg_t *this); + + /** + * Get own ID. * - * @param this calling object * @return own id */ identification_t* (*get_my_id)(peer_cfg_t *this); /** - * @brief Get peers ID. + * Get peers ID. * - * @param this calling object * @return other id */ identification_t* (*get_other_id)(peer_cfg_t *this); - - /** - * @brief Get own CA. - * - * @param this calling object - * @return own ca - */ - identification_t* (*get_my_ca)(peer_cfg_t *this); /** - * @brief Get peer CA. - * - * @param this calling object - * @return other ca - */ - identification_t* (*get_other_ca)(peer_cfg_t *this); - - /** - * @brief Get list of group attributes. - * - * @param this calling object - * @return linked list of group attributes + * Should be sent a certificate for this connection? + * + * @return certificate sending policy */ - linked_list_t* (*get_groups)(peer_cfg_t *this); + cert_policy_t (*get_cert_policy) (peer_cfg_t *this); /** - * @brief Should be sent a certificate for this connection? + * How to handle uniqueness of IKE_SAs? * - * @param this calling object - * @return certificate sending policy + * @return unique policy */ - cert_policy_t (*get_cert_policy) (peer_cfg_t *this); + unique_policy_t (*get_unique_policy) (peer_cfg_t *this); /** - * @brief Get the authentication method to use to authenticate us. + * Get the authentication method to use to authenticate us. * - * @param this calling object * @return authentication method */ - auth_method_t (*get_auth_method) (peer_cfg_t *this); + config_auth_method_t (*get_auth_method) (peer_cfg_t *this); /** - * @brief Get the EAP type to use for peer authentication. + * Get the EAP type to use for peer authentication. * * If vendor specific types are used, a vendor ID != 0 is returned to * to vendor argument. Then the returned type is specific for that * vendor ID. * - * @param this calling object * @param vendor receives vendor specifier, 0 for predefined EAP types * @return authentication method */ eap_type_t (*get_eap_type) (peer_cfg_t *this, u_int32_t *vendor); /** - * @brief Get the max number of retries after timeout. + * Get the max number of retries after timeout. * - * @param this calling object * @return max number retries */ u_int32_t (*get_keyingtries) (peer_cfg_t *this); /** - * @brief Get a time to start rekeying (is randomized with jitter). + * Get a time to start rekeying (is randomized with jitter). * - * @param this calling object * @return time in s when to start rekeying, 0 disables rekeying */ u_int32_t (*get_rekey_time)(peer_cfg_t *this); /** - * @brief Get a time to start reauthentication (is randomized with jitter). + * Get a time to start reauthentication (is randomized with jitter). * - * @param this calling object * @return time in s when to start reauthentication, 0 disables it */ u_int32_t (*get_reauth_time)(peer_cfg_t *this); /** - * @brief Get the timeout of a rekeying/reauthenticating SA. + * Get the timeout of a rekeying/reauthenticating SA. * - * @param thsi calling object * @return timeout in s */ u_int32_t (*get_over_time)(peer_cfg_t *this); /** - * @brief Use MOBIKE (RFC4555) if peer supports it? + * Use MOBIKE (RFC4555) if peer supports it? * - * @param this calling object * @return TRUE to enable MOBIKE support */ bool (*use_mobike) (peer_cfg_t *this); /** - * @brief Get the DPD check interval. + * Get the DPD check interval. * - * @param this calling object * @return dpd_delay in seconds */ - u_int32_t (*get_dpd_delay) (peer_cfg_t *this); + u_int32_t (*get_dpd) (peer_cfg_t *this); /** - * @brief What should be done with a CHILD_SA, when other peer does not respond. - * - * @param this calling object - * @return dpd action - */ - dpd_action_t (*get_dpd_action) (peer_cfg_t *this); - - /** - * @brief Get a virtual IP for the local peer. + * Get a virtual IP for the local peer. * * If no virtual IP should be used, NULL is returned. %any means to request * a virtual IP using configuration payloads. A specific address is also * used for a request and may be changed by the server. * - * @param this peer_cfg * @param suggestion NULL, %any or specific - * @return clone of an IP, %any or NULL + * @return virtual IP, %any or NULL */ - host_t* (*get_my_virtual_ip) (peer_cfg_t *this); + host_t* (*get_virtual_ip) (peer_cfg_t *this); /** - * @brief Get a virtual IP for the remote peer. - * - * An IP may be supplied, if one was requested by the initiator. However, - * the suggestion is not more as it says, any address may be returned, even - * NULL to not use virtual IPs. + * Get the name of the pool to acquire configuration attributes from. * - * @param this peer_cfg - * @param suggestion NULL, %any or specific - * @return clone of an IP to use + * @return pool name, NULL if none defined */ - host_t* (*get_other_virtual_ip) (peer_cfg_t *this, host_t *suggestion); - -#ifdef P2P + char* (*get_pool)(peer_cfg_t *this); + +#ifdef ME /** - * @brief Is this a mediation connection? + * Is this a mediation connection? * - * @param this peer_cfg * @return TRUE, if this is a mediation connection */ bool (*is_mediation) (peer_cfg_t *this); /** - * @brief Get peer_cfg of the connection this one is mediated through. + * Get peer_cfg of the connection this one is mediated through. * - * @param this peer_cfg - * @return reference to peer_cfg of the mediation connection + * @return the peer_cfg of the mediation connection */ peer_cfg_t* (*get_mediated_by) (peer_cfg_t *this); /** - * @brief Get the id of the other peer at the mediation server. + * Get the id of the other peer at the mediation server. * * This is the leftid of the peer's connection with the mediation server. * * If it is not configured, it is assumed to be the same as the right id * of this connection. * - * @param this peer_cfg * @return the id of the other peer */ identification_t* (*get_peer_id) (peer_cfg_t *this); -#endif /* P2P */ +#endif /* ME */ + + /** + * Check if two peer configurations are equal. + * + * This method does not compare associated ike/child_cfg. + * + * @param other candidate to check for equality against this + * @return TRUE if peer_cfg and ike_cfg are equal + */ + bool (*equals)(peer_cfg_t *this, peer_cfg_t *other); /** - * @brief Get a new reference. + * Increase reference count. * - * Get a new reference to this peer_cfg by increasing - * it's internal reference counter. - * Do not call get_ref or any other function until you - * already have a reference. Otherwise the object may get - * destroyed while calling get_ref(), - * - * @param this calling object + * @return reference to this */ - void (*get_ref) (peer_cfg_t *this); + peer_cfg_t* (*get_ref) (peer_cfg_t *this); /** - * @brief Destroys the peer_cfg object. + * Destroys the peer_cfg object. * * Decrements the internal reference counter and * destroys the peer_cfg when it reaches zero. - * - * @param this calling object */ void (*destroy) (peer_cfg_t *this); }; /** - * @brief Create a configuration object for IKE_AUTH and later. + * Create a configuration object for IKE_AUTH and later. * * name-string gets cloned, ID's not. * Virtual IPs are used if they are != NULL. A %any host means the virtual @@ -392,10 +370,8 @@ struct peer_cfg_t { * @param ike_cfg IKE config to use when acting as initiator * @param my_id identification_t for ourselves * @param other_id identification_t for the remote guy - * @param my_ca CA to use for us - * @param other_ca CA to use for other - * @param groups list of group memberships * @param cert_policy should we send a certificate payload? + * @param unique uniqueness of an IKE_SA * @param auth_method auth method to use to authenticate us * @param eap_type EAP type to use for peer authentication * @param eap_vendor EAP vendor identifier, if vendor specific type is used @@ -406,29 +382,24 @@ struct peer_cfg_t { * @param over_time maximum overtime before closing a rekeying/reauth SA * @param reauth sould be done reauthentication instead of rekeying? * @param mobike use MOBIKE (RFC4555) if peer supports it - * @param dpd_delay after how many seconds of inactivity to check DPD - * @param dpd_action what to do with CHILD_SAs when detected a dead peer - * @param my_virtual_ip virtual IP for local host, or NULL - * @param other_virtual_ip virtual IP for remote host, or NULL - * @param p2p_mediation TRUE if this is a mediation connection - * @param p2p_mediated_by name of the mediation connection to mediate through + * @param dpd DPD check interval, 0 to disable + * @param virtual_ip virtual IP for local host, or NULL + * @param pool pool name to get configuration attributes from, or NULL + * @param mediation TRUE if this is a mediation connection + * @param mediated_by peer_cfg_t of the mediation connection to mediate through * @param peer_id ID that identifies our peer at the mediation server * @return peer_cfg_t object - * - * @ingroup config */ peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg, identification_t *my_id, identification_t *other_id, - identification_t *my_ca, identification_t *other_ca, - linked_list_t *groups, cert_policy_t cert_policy, - auth_method_t auth_method, eap_type_t eap_type, + cert_policy_t cert_policy, unique_policy_t unique, + config_auth_method_t auth_method, eap_type_t eap_type, u_int32_t eap_vendor, u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t reauth_time, u_int32_t jitter_time, - u_int32_t over_time, bool mobike, - u_int32_t dpd_delay, dpd_action_t dpd_action, - host_t *my_virtual_ip, host_t *other_virtual_ip, - bool p2p_mediation, peer_cfg_t *p2p_mediated_by, + u_int32_t over_time, bool mobike, u_int32_t dpd, + host_t *virtual_ip, char *pool, + bool mediation, peer_cfg_t *mediated_by, identification_t *peer_id); -#endif /* PEER_CFG_H_ */ +#endif /* PEER_CFG_H_ @} */ diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c index cff9859c1..803cf8ae4 100644 --- a/src/charon/config/proposal.c +++ b/src/charon/config/proposal.c @@ -1,11 +1,5 @@ -/** - * @file proposal.c - * - * @brief Implementation of proposal_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -18,6 +12,8 @@ * 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. + * + * $Id: proposal.c 4062 2008-06-12 11:42:19Z martin $ */ #include <string.h> @@ -51,11 +47,12 @@ ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, ENUM_END(transform_type_names, EXTENDED_SEQUENCE_NUMBERS); ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS, - "NO_EXT_SEQ_NUMBERS", - "EXT_SEQ_NUMBERS", + "NO_EXT_SEQ", + "EXT_SEQ", ); typedef struct private_proposal_t private_proposal_t; +typedef struct algorithm_t algorithm_t; /** * Private data of an proposal_t object @@ -104,9 +101,24 @@ struct private_proposal_t { }; /** + * Struct used to store different kinds of algorithms. + */ +struct algorithm_t { + /** + * Value from an encryption_algorithm_t/integrity_algorithm_t/... + */ + u_int16_t algorithm; + + /** + * the associated key size in bits, or zero if not needed + */ + u_int16_t key_size; +}; + +/** * Add algorithm/keysize to a algorithm list */ -static void add_algo(linked_list_t *list, u_int16_t algo, size_t key_size) +static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size) { algorithm_t *algo_key; @@ -119,7 +131,8 @@ static void add_algo(linked_list_t *list, u_int16_t algo, size_t key_size) /** * Implements proposal_t.add_algorithm */ -static void add_algorithm(private_proposal_t *this, transform_type_t type, u_int16_t algo, size_t key_size) +static void add_algorithm(private_proposal_t *this, transform_type_t type, + u_int16_t algo, u_int16_t key_size) { switch (type) { @@ -144,41 +157,68 @@ static void add_algorithm(private_proposal_t *this, transform_type_t type, u_int } /** - * Implements proposal_t.create_algorithm_iterator. + * filter function for peer configs + */ +static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg, + void **unused, u_int16_t *key_size) +{ + algorithm_t *algo = *in; + *alg = algo->algorithm; + if (key_size) + { + *key_size = algo->key_size; + } + return TRUE; +} + +/** + * Implements proposal_t.create_enumerator. */ -static iterator_t *create_algorithm_iterator(private_proposal_t *this, transform_type_t type) +static enumerator_t *create_enumerator(private_proposal_t *this, + transform_type_t type) { + linked_list_t *list; + switch (type) { case ENCRYPTION_ALGORITHM: - return this->encryption_algos->create_iterator(this->encryption_algos, TRUE); + list = this->encryption_algos; + break; case INTEGRITY_ALGORITHM: - return this->integrity_algos->create_iterator(this->integrity_algos, TRUE); + list = this->integrity_algos; + break; case PSEUDO_RANDOM_FUNCTION: - return this->prf_algos->create_iterator(this->prf_algos, TRUE); + list = this->prf_algos; + break; case DIFFIE_HELLMAN_GROUP: - return this->dh_groups->create_iterator(this->dh_groups, TRUE); + list = this->dh_groups; + break; case EXTENDED_SEQUENCE_NUMBERS: - return this->esns->create_iterator(this->esns, TRUE); - default: + list = this->esns; break; + default: + return NULL; } - return NULL; + return enumerator_create_filter(list->create_enumerator(list), + (void*)alg_filter, NULL, NULL); } /** * Implements proposal_t.get_algorithm. */ -static bool get_algorithm(private_proposal_t *this, transform_type_t type, algorithm_t** algo) +static bool get_algorithm(private_proposal_t *this, transform_type_t type, + u_int16_t *alg, u_int16_t *key_size) { - iterator_t *iterator = create_algorithm_iterator(this, type); - if (iterator->iterate(iterator, (void**)algo)) + enumerator_t *enumerator; + bool found = FALSE; + + enumerator = create_enumerator(this, type); + if (enumerator->enumerate(enumerator, alg, key_size)) { - iterator->destroy(iterator); - return TRUE; + found = TRUE; } - iterator->destroy(iterator); - return FALSE; + enumerator->destroy(enumerator); + return found; } /** @@ -186,14 +226,15 @@ static bool get_algorithm(private_proposal_t *this, transform_type_t type, algor */ static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group) { - algorithm_t *current; - iterator_t *iterator; bool result = FALSE; - iterator = this->dh_groups->create_iterator(this->dh_groups, TRUE); - if (iterator->get_count(iterator)) + if (this->dh_groups->get_count(this->dh_groups)) { - while (iterator->iterate(iterator, (void**)¤t)) + algorithm_t *current; + enumerator_t *enumerator; + + enumerator = this->dh_groups->create_enumerator(this->dh_groups); + while (enumerator->enumerate(enumerator, (void**)¤t)) { if (current->algorithm == group) { @@ -201,22 +242,54 @@ static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group) break; } } + enumerator->destroy(enumerator); } else if (group == MODP_NONE) { result = TRUE; } - iterator->destroy(iterator); return result; } /** + * Implementation of proposal_t.strip_dh. + */ +static void strip_dh(private_proposal_t *this) +{ + algorithm_t *alg; + + while (this->dh_groups->remove_last(this->dh_groups, (void**)&alg) == SUCCESS) + { + free(alg); + } +} + +/** + * Returns true if the given alg is an authenticated encryption algorithm + */ +static bool is_authenticated_encryption(u_int16_t alg) +{ + switch(alg) + { + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + return TRUE; + } + return FALSE; +} + +/** * Find a matching alg/keysize in two linked lists */ -static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, u_int16_t *alg, size_t *key_size) +static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, + u_int16_t *alg, size_t *key_size) { - iterator_t *first_iter, *second_iter; - algorithm_t *first_alg, *second_alg; + enumerator_t *e1, *e2; + algorithm_t *alg1, *alg2; /* if in both are zero algorithms specified, we HAVE a match */ if (first->get_count(first) == 0 && second->get_count(second) == 0) @@ -225,30 +298,31 @@ static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, return TRUE; } - first_iter = first->create_iterator(first, TRUE); - second_iter = second->create_iterator(second, TRUE); + e1 = first->create_enumerator(first); + e2 = second->create_enumerator(second); /* compare algs, order of algs in "first" is preferred */ - while (first_iter->iterate(first_iter, (void**)&first_alg)) + while (e1->enumerate(e1, &alg1)) { - second_iter->reset(second_iter); - while (second_iter->iterate(second_iter, (void**)&second_alg)) + e2->destroy(e2); + e2 = second->create_enumerator(second); + while (e2->enumerate(e2, &alg2)) { - if (first_alg->algorithm == second_alg->algorithm && - first_alg->key_size == second_alg->key_size) + if (alg1->algorithm == alg2->algorithm && + alg1->key_size == alg2->key_size) { /* ok, we have an algorithm */ - *alg = first_alg->algorithm; - *key_size = first_alg->key_size; + *alg = alg1->algorithm; + *key_size = alg1->key_size; *add = TRUE; - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); + e1->destroy(e1); + e2->destroy(e2); return TRUE; } } } /* no match in all comparisons */ - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); + e1->destroy(e1); + e2->destroy(e2); return FALSE; } @@ -274,45 +348,57 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t selected = proposal_create(this->protocol); /* select encryption algorithm */ - if (select_algo(this->encryption_algos, other->encryption_algos, &add, &algo, &key_size)) + if (select_algo(this->encryption_algos, other->encryption_algos, + &add, &algo, &key_size)) { if (add) { - selected->add_algorithm(selected, ENCRYPTION_ALGORITHM, algo, key_size); + selected->add_algorithm(selected, ENCRYPTION_ALGORITHM, + algo, key_size); } } else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable ENCRYPTION_ALGORITHM found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, ENCRYPTION_ALGORITHM); return NULL; } /* select integrity algorithm */ - if (select_algo(this->integrity_algos, other->integrity_algos, &add, &algo, &key_size)) + if (!is_authenticated_encryption(algo)) { - if (add) + if (select_algo(this->integrity_algos, other->integrity_algos, + &add, &algo, &key_size)) { - selected->add_algorithm(selected, INTEGRITY_ALGORITHM, algo, key_size); + if (add) + { + selected->add_algorithm(selected, INTEGRITY_ALGORITHM, + algo, key_size); + } + } + else + { + selected->destroy(selected); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, INTEGRITY_ALGORITHM); + return NULL; } - } - else - { - selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable INTEGRITY_ALGORITHM found, skipping"); - return NULL; } /* select prf algorithm */ - if (select_algo(this->prf_algos, other->prf_algos, &add, &algo, &key_size)) + if (select_algo(this->prf_algos, other->prf_algos, + &add, &algo, &key_size)) { if (add) { - selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION, algo, key_size); + selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION, + algo, key_size); } } else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable PSEUDO_RANDOM_FUNCTION found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, PSEUDO_RANDOM_FUNCTION); return NULL; } /* select a DH-group */ @@ -326,7 +412,8 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable DIFFIE_HELLMAN_GROUP found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, DIFFIE_HELLMAN_GROUP); return NULL; } /* select if we use ESNs */ @@ -340,7 +427,8 @@ static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t else { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable EXTENDED_SEQUENCE_NUMBERS found, skipping"); + DBG2(DBG_CFG, " no acceptable %N found", + transform_type_names, EXTENDED_SEQUENCE_NUMBERS); return NULL; } DBG2(DBG_CFG, " proposal matches"); @@ -382,14 +470,67 @@ static u_int64_t get_spi(private_proposal_t *this) static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list) { algorithm_t *algo, *clone_algo; - iterator_t *iterator = list->create_iterator(list, TRUE); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator_t *enumerator; + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &algo)) { clone_algo = malloc_thing(algorithm_t); memcpy(clone_algo, algo, sizeof(algorithm_t)); clone_list->insert_last(clone_list, (void*)clone_algo); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); +} + +/** + * check if an algorithm list equals + */ +static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2) +{ + enumerator_t *e1, *e2; + algorithm_t *alg1, *alg2; + bool equals = TRUE; + + if (l1->get_count(l1) != l2->get_count(l2)) + { + return FALSE; + } + + e1 = l1->create_enumerator(l1); + e2 = l2->create_enumerator(l2); + while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2)) + { + if (alg1->algorithm != alg2->algorithm || + alg1->key_size != alg2->key_size) + { + equals = FALSE; + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + return equals; +} + +/** + * Implementation of proposal_t.equals. + */ +static bool equals(private_proposal_t *this, private_proposal_t *other) +{ + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + return ( + algo_list_equals(this->encryption_algos, other->encryption_algos) && + algo_list_equals(this->integrity_algos, other->integrity_algos) && + algo_list_equals(this->prf_algos, other->prf_algos) && + algo_list_equals(this->dh_groups, other->dh_groups) && + algo_list_equals(this->esns, other->esns)); } /** @@ -411,6 +552,38 @@ static proposal_t *clone_(private_proposal_t *this) } /** + * Checks the proposal read from a string. + */ +static void check_proposal(private_proposal_t *this) +{ + enumerator_t *e; + algorithm_t *alg; + bool all_aead = TRUE; + + e = this->encryption_algos->create_enumerator(this->encryption_algos); + while (e->enumerate(e, &alg)) + { + if (!is_authenticated_encryption(alg->algorithm)) + { + all_aead = FALSE; + break; + } + } + e->destroy(e); + + if (all_aead) + { + /* if all encryption algorithms in the proposal are authenticated encryption + * algorithms we MUST NOT propose any integrity algorithms */ + while (this->integrity_algos->remove_last(this->integrity_algos, + (void**)&alg) == SUCCESS) + { + free(alg); + } + } +} + +/** * add a algorithm identified by a string to the proposal. * TODO: we could use gperf here. */ @@ -432,6 +605,70 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) { add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); } + else if (strstr(alg.ptr, "ccm")) + { + u_int16_t key_size, icv_size; + + if (sscanf(alg.ptr, "aes%huccm%hu", &key_size, &icv_size) == 2) + { + if (key_size == 128 || key_size == 192 || key_size == 256) + { + switch (icv_size) + { + case 8: /* octets */ + case 64: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_CCM_ICV8, key_size); + break; + case 12: /* octets */ + case 96: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_CCM_ICV12, key_size); + break; + case 16: /* octets */ + case 128: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_CCM_ICV16, key_size); + break; + default: + /* invalid ICV size */ + break; + } + } + } + } + else if (strstr(alg.ptr, "gcm")) + { + u_int16_t key_size, icv_size; + + if (sscanf(alg.ptr, "aes%hugcm%hu", &key_size, &icv_size) == 2) + { + if (key_size == 128 || key_size == 192 || key_size == 256) + { + switch (icv_size) + { + case 8: /* octets */ + case 64: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_GCM_ICV8, key_size); + break; + case 12: /* octets */ + case 96: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_GCM_ICV12, key_size); + break; + case 16: /* octets */ + case 128: /* bits */ + add_algorithm(this, ENCRYPTION_ALGORITHM, + ENCR_AES_GCM_ICV16, key_size); + break; + default: + /* invalid ICV size */ + break; + } + } + } + } else if (strncmp(alg.ptr, "3des", alg.len) == 0) { add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); @@ -499,7 +736,7 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); if (this->protocol == PROTO_IKE) { - add_algorithm(this, PSEUDO_RANDOM_FUNCTION, AUTH_AES_XCBC_96, 0); + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0); } } else if (strncmp(alg.ptr, "modp768", alg.len) == 0) @@ -526,6 +763,26 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) { add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0); } + else if (strncmp(alg.ptr, "ecp192", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp224", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp256", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp384", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0); + } + else if (strncmp(alg.ptr, "ecp521", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0); + } else { return FAILED; @@ -534,6 +791,109 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) } /** + * print all algorithms of a kind to stream + */ +static int print_alg(private_proposal_t *this, FILE *stream, u_int kind, + void *names, bool *first) +{ + enumerator_t *enumerator; + size_t written = 0; + u_int16_t alg, size; + + enumerator = create_enumerator(this, kind); + while (enumerator->enumerate(enumerator, &alg, &size)) + { + if (*first) + { + written += fprintf(stream, "%N", names, alg); + *first = FALSE; + } + else + { + written += fprintf(stream, "/%N", names, alg); + } + if (size) + { + written += fprintf(stream, "-%d", size); + } + } + enumerator->destroy(enumerator); + return written; +} + +/** + * output handler in printf() + */ +static int print(FILE *stream, const struct printf_info *info, + const void *const *args) +{ + private_proposal_t *this = *((private_proposal_t**)(args[0])); + linked_list_t *list = *((linked_list_t**)(args[0])); + enumerator_t *enumerator; + size_t written = 0; + bool first = TRUE; + + if (this == NULL) + { + return fprintf(stream, "(null)"); + } + + if (info->alt) + { + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &this)) + { /* call recursivly */ + if (first) + { + written += fprintf(stream, "%P", this); + first = FALSE; + } + else + { + written += fprintf(stream, ", %P", this); + } + } + enumerator->destroy(enumerator); + return written; + } + + written = fprintf(stream, "%N:", protocol_id_names, this->protocol); + written += print_alg(this, stream, ENCRYPTION_ALGORITHM, + encryption_algorithm_names, &first); + written += print_alg(this, stream, INTEGRITY_ALGORITHM, + integrity_algorithm_names, &first); + written += print_alg(this, stream, PSEUDO_RANDOM_FUNCTION, + pseudo_random_function_names, &first); + written += print_alg(this, stream, DIFFIE_HELLMAN_GROUP, + diffie_hellman_group_names, &first); + written += print_alg(this, stream, EXTENDED_SEQUENCE_NUMBERS, + extended_sequence_numbers_names, &first); + return written; +} + +/** + * arginfo handler for printf() proposal + */ +static int arginfo(const struct printf_info *info, size_t n, int *argtypes) +{ + if (n > 0) + { + argtypes[0] = PA_POINTER; + } + return 1; +} + +/** + * return printf hook functions for a proposal + */ +printf_hook_functions_t proposal_get_printf_hooks() +{ + printf_hook_functions_t hooks = {print, arginfo}; + + return hooks; +} + +/** * Implements proposal_t.destroy. */ static void destroy(private_proposal_t *this) @@ -553,14 +913,16 @@ proposal_t *proposal_create(protocol_id_t protocol) { private_proposal_t *this = malloc_thing(private_proposal_t); - this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,size_t))add_algorithm; - this->public.create_algorithm_iterator = (iterator_t* (*)(proposal_t*,transform_type_t))create_algorithm_iterator; - this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,algorithm_t**))get_algorithm; + this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,u_int16_t))add_algorithm; + this->public.create_enumerator = (enumerator_t* (*)(proposal_t*,transform_type_t))create_enumerator; + this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,u_int16_t*,u_int16_t*))get_algorithm; this->public.has_dh_group = (bool (*)(proposal_t*,diffie_hellman_group_t))has_dh_group; + this->public.strip_dh = (void(*)(proposal_t*))strip_dh; this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal; this->public.get_protocol = (protocol_id_t(*)(proposal_t*))get_protocol; this->public.set_spi = (void(*)(proposal_t*,u_int64_t))set_spi; this->public.get_spi = (u_int64_t(*)(proposal_t*))get_spi; + this->public.equals = (bool(*)(proposal_t*, proposal_t *other))equals; this->public.clone = (proposal_t*(*)(proposal_t*))clone_; this->public.destroy = (void(*)(proposal_t*))destroy; @@ -590,17 +952,19 @@ proposal_t *proposal_create_default(protocol_id_t protocol) add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_384, 0); add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_512, 0); - add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0); add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0); @@ -662,6 +1026,8 @@ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs return NULL; } + check_proposal(this); + if (protocol == PROTO_AH || protocol == PROTO_ESP) { add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); diff --git a/src/charon/config/proposal.h b/src/charon/config/proposal.h index 379550f44..fb7dc9dfa 100644 --- a/src/charon/config/proposal.h +++ b/src/charon/config/proposal.h @@ -1,10 +1,3 @@ -/** - * @file proposal.h - * - * @brief Interface of proposal_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: proposal.h 4062 2008-06-12 11:42:19Z martin $ + */ + +/** + * @defgroup proposal proposal + * @{ @ingroup config */ #ifndef PROPOSAL_H_ @@ -26,7 +26,6 @@ typedef enum protocol_id_t protocol_id_t; typedef enum transform_type_t transform_type_t; typedef enum extended_sequence_numbers_t extended_sequence_numbers_t; -typedef struct algorithm_t algorithm_t; typedef struct proposal_t proposal_t; #include <library.h> @@ -40,8 +39,6 @@ typedef struct proposal_t proposal_t; /** * Protocol ID of a proposal. - * - * @ingroup config */ enum protocol_id_t { PROTO_NONE = 0, @@ -52,16 +49,12 @@ enum protocol_id_t { /** * enum names for protocol_id_t - * - * @ingroup config */ extern enum_name_t *protocol_id_names; /** * Type of a transform, as in IKEv2 RFC 3.3.2. - * - * @ingroup config */ enum transform_type_t { UNDEFINED_TRANSFORM_TYPE = 241, @@ -74,16 +67,12 @@ enum transform_type_t { /** * enum names for transform_type_t. - * - * @ingroup config */ extern enum_name_t *transform_type_names; /** * Extended sequence numbers, as in IKEv2 RFC 3.3.2. - * - * @ingroup config */ enum extended_sequence_numbers_t { NO_EXT_SEQ_NUMBERS = 0, @@ -92,48 +81,21 @@ enum extended_sequence_numbers_t { /** * enum strings for extended_sequence_numbers_t. - * - * @ingroup config */ extern enum_name_t *extended_sequence_numbers_names; - - -/** - * Struct used to store different kinds of algorithms. The internal - * lists of algorithms contain such structures. - * - * @ingroup config - */ -struct algorithm_t { - /** - * Value from an encryption_algorithm_t/integrity_algorithm_t/... - */ - u_int16_t algorithm; - - /** - * the associated key size in bits, or zero if not needed - */ - u_int16_t key_size; -}; - /** - * @brief Stores a set of algorithms used for an SA. + * Stores a set of algorithms used for an SA. * * A proposal stores algorithms for a specific * protocol. It can store algorithms for one protocol. * Proposals with multiple protocols are not supported, * as it's not specified in RFC4301 anymore. - * - * @b Constructors: - * - proposal_create() - * - * @ingroup config */ struct proposal_t { /** - * @brief Add an algorithm to the proposal. + * Add an algorithm to the proposal. * * The algorithms are stored by priority, first added * is the most preferred. @@ -144,120 +106,119 @@ struct proposal_t { * integrity_algorithm_t, dh_group_number_t and * extended_sequence_numbers_t. * - * @param this calling object - * @param type kind of algorithm - * @param alg identifier for algorithm - * @param key_size key size to use + * @param type kind of algorithm + * @param alg identifier for algorithm + * @param key_size key size to use */ - void (*add_algorithm) (proposal_t *this, transform_type_t type, u_int16_t alg, size_t key_size); + void (*add_algorithm) (proposal_t *this, transform_type_t type, + u_int16_t alg, u_int16_t key_size); /** - * @brief Get an iterator over algorithms for a specifc algo type. + * Get an enumerator over algorithms for a specifc algo type. * - * @param this calling object - * @param type kind of algorithm - * @return iterator over algorithm_t's + * @param type kind of algorithm + * @return enumerator over u_int16_t alg, u_int16_t key_size */ - iterator_t *(*create_algorithm_iterator) (proposal_t *this, transform_type_t type); + enumerator_t *(*create_enumerator) (proposal_t *this, transform_type_t type); /** - * @brief Get the algorithm for a type to use. + * Get the algorithm for a type to use. * * If there are multiple algorithms, only the first is returned. * - * @param this calling object - * @param type kind of algorithm - * @param[out] algo pointer which receives algorithm and key size - * @return TRUE if algorithm of this kind available + * @param type kind of algorithm + * @param alg pointer which receives algorithm + * @param key_size pointer which receives the key size + * @return TRUE if algorithm of this kind available */ - bool (*get_algorithm) (proposal_t *this, transform_type_t type, algorithm_t** algo); + bool (*get_algorithm) (proposal_t *this, transform_type_t type, + u_int16_t *alg, u_int16_t *key_size); /** - * @brief Check if the proposal has a specific DH group. + * Check if the proposal has a specific DH group. * - * @param this calling object - * @param group group to check for - * @return TRUE if algorithm included + * @param group group to check for + * @return TRUE if algorithm included */ bool (*has_dh_group) (proposal_t *this, diffie_hellman_group_t group); + + /** + * Strip DH groups from proposal to use it without PFS. + */ + void (*strip_dh)(proposal_t *this); /** - * @brief Compare two proposal, and select a matching subset. + * Compare two proposal, and select a matching subset. * * If the proposals are for the same protocols (AH/ESP), they are * compared. If they have at least one algorithm of each type * in common, a resulting proposal of this kind is created. * - * @param this calling object - * @param other proposal to compair agains - * @return - * - selected proposal, if possible - * - NULL, if proposals don't match + * @param other proposal to compair agains + * @return selected proposal, NULL if proposals don't match */ proposal_t *(*select) (proposal_t *this, proposal_t *other); /** - * @brief Get the protocol ID of the proposal. + * Get the protocol ID of the proposal. * - * @param this calling object - * @return protocol of the proposal + * @return protocol of the proposal */ protocol_id_t (*get_protocol) (proposal_t *this); /** - * @brief Get the SPI of the proposal. + * Get the SPI of the proposal. * - * @param this calling object - * @return spi for proto + * @return spi for proto */ u_int64_t (*get_spi) (proposal_t *this); /** - * @brief Set the SPI of the proposal. + * Set the SPI of the proposal. * - * @param this calling object - * @param spi spi to set for proto + * @param spi spi to set for proto */ void (*set_spi) (proposal_t *this, u_int64_t spi); /** - * @brief Clone a proposal. + * Check for the eqality of two proposals. + * + * @param other other proposal to check for equality + * @return TRUE if other equal to this + */ + bool (*equals)(proposal_t *this, proposal_t *other); + + /** + * Clone a proposal. * - * @param this proposal to clone - * @return clone of it + * @return clone of proposal */ proposal_t *(*clone) (proposal_t *this); /** - * @brief Destroys the proposal object. - * - * @param this calling object + * Destroys the proposal object. */ void (*destroy) (proposal_t *this); }; /** - * @brief Create a child proposal for AH, ESP or IKE. + * Create a child proposal for AH, ESP or IKE. * * @param protocol protocol, such as PROTO_ESP * @return proposal_t object - * - * @ingroup config */ proposal_t *proposal_create(protocol_id_t protocol); /** - * @brief Create a default proposal if nothing further specified. + * Create a default proposal if nothing further specified. * * @param protocol protocol, such as PROTO_ESP * @return proposal_t object - * - * @ingroup config */ proposal_t *proposal_create_default(protocol_id_t protocol); /** - * @brief Create a proposal from a string identifying the algorithms. + * Create a proposal from a string identifying the algorithms. * * The string is in the same form as a in the ipsec.conf file. * E.g.: aes128-sha2_256-modp2048 @@ -268,9 +229,17 @@ proposal_t *proposal_create_default(protocol_id_t protocol); * @param protocol protocol, such as PROTO_ESP * @param algs algorithms as string * @return proposal_t object - * - * @ingroup config */ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs); -#endif /* PROPOSAL_H_ */ +/** + * Get printf hooks for a proposal. + * + * Arguments are: + * proposal_t *proposal + * With the #-specifier, arguments are: + * linked_list_t *list containing proposal_t* + */ +printf_hook_functions_t proposal_get_printf_hooks(); + +#endif /* PROPOSAL_H_ @} */ diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c index da39c434d..f41c39d30 100644 --- a/src/charon/config/traffic_selector.c +++ b/src/charon/config/traffic_selector.c @@ -1,10 +1,3 @@ -/** - * @file traffic_selector.c - * - * @brief Implementation of traffic_selector_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi @@ -20,6 +13,8 @@ * 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. + * + * $Id: traffic_selector.c 3658 2008-03-26 10:06:45Z martin $ */ #include <arpa/inet.h> @@ -276,11 +271,25 @@ static int print(FILE *stream, const struct printf_info *info, } /** - * register printf() handlers + * arginfo handler for printf() traffic selector + */ +static int arginfo(const struct printf_info *info, size_t n, int *argtypes) +{ + if (n > 0) + { + argtypes[0] = PA_POINTER; + } + return 1; +} + +/** + * return printf hook functions for a chunk */ -static void __attribute__ ((constructor))print_register() +printf_hook_functions_t traffic_selector_get_printf_hooks() { - register_printf_function(PRINTF_TRAFFIC_SELECTOR, print, arginfo_ptr); + printf_hook_functions_t hooks = {print, arginfo}; + + return hooks; } /** @@ -709,6 +718,7 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, } default: { + net->destroy(net); free(this); return NULL; } @@ -718,6 +728,7 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, this->from_port = port; this->to_port = port; } + net->destroy(net); return (&this->public); } @@ -770,12 +781,11 @@ traffic_selector_t *traffic_selector_create_from_string( /* * see header */ -traffic_selector_t *traffic_selector_create_dynamic( - u_int8_t protocol, ts_type_t type, +traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol, u_int16_t from_port, u_int16_t to_port) { - private_traffic_selector_t *this = traffic_selector_create(protocol, type, - from_port, to_port); + private_traffic_selector_t *this = traffic_selector_create( + protocol, TS_IPV4_ADDR_RANGE, from_port, to_port); memset(this->from6, 0, sizeof(this->from6)); memset(this->to6, 0xFF, sizeof(this->to6)); @@ -818,4 +828,3 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, return this; } -/* vim: set ts=4 sw=4 noet: */ diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h index 0e798fc6a..4b079a8e0 100644 --- a/src/charon/config/traffic_selector.h +++ b/src/charon/config/traffic_selector.h @@ -1,10 +1,3 @@ -/** - * @file traffic_selector.h - * - * @brief Interface of traffic_selector_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -20,6 +13,13 @@ * 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. + * + * $Id: traffic_selector.h 3658 2008-03-26 10:06:45Z martin $ + */ + +/** + * @defgroup traffic_selector traffic_selector + * @{ @ingroup config */ #ifndef TRAFFIC_SELECTOR_H_ @@ -33,8 +33,6 @@ typedef struct traffic_selector_t traffic_selector_t; /** * Traffic selector types. - * - * @ingroup config */ enum ts_type_t { @@ -63,29 +61,20 @@ enum ts_type_t { extern enum_name_t *ts_type_name; /** - * @brief Object representing a traffic selector entry. + * Object representing a traffic selector entry. * * A traffic selector defines an range of addresses * and a range of ports. IPv6 is not fully supported yet. - * - * @b Constructors: - * - traffic_selector_create_from_bytes() - * - traffic_selector_create_from_string() - * - * @todo Add IPv6 support - * - * @ingroup config */ struct traffic_selector_t { /** - * @brief Compare two traffic selectors, and create a new one + * Compare two traffic selectors, and create a new one * which is the largest subset of both (subnet & port). * * Resulting traffic_selector is newly created and must be destroyed. * - * @param this first to compare - * @param other second to compare + * @param other traffic selector to compare * @return * - created subset of them * - or NULL if no match between this and other @@ -94,73 +83,66 @@ struct traffic_selector_t { traffic_selector_t *other); /** - * @brief Clone a traffic selector. + * Clone a traffic selector. * - * @param this traffic selector to clone * @return clone of it */ traffic_selector_t *(*clone) (traffic_selector_t *this); /** - * @brief Get starting address of this ts as a chunk. + * Get starting address of this ts as a chunk. * * Chunk is in network order gets allocated. * - * @param this called object * @return chunk containing the address */ chunk_t (*get_from_address) (traffic_selector_t *this); /** - * @brief Get ending address of this ts as a chunk. + * Get ending address of this ts as a chunk. * * Chunk is in network order gets allocated. * - * @param this called object * @return chunk containing the address */ chunk_t (*get_to_address) (traffic_selector_t *this); /** - * @brief Get starting port of this ts. + * Get starting port of this ts. * * Port is in host order, since the parser converts it. * Size depends on protocol. * - * @param this called object * @return port */ u_int16_t (*get_from_port) (traffic_selector_t *this); /** - * @brief Get ending port of this ts. + * Get ending port of this ts. * * Port is in host order, since the parser converts it. * Size depends on protocol. * - * @param this called object * @return port */ u_int16_t (*get_to_port) (traffic_selector_t *this); /** - * @brief Get the type of the traffic selector. + * Get the type of the traffic selector. * - * @param this called object * @return ts_type_t specifying the type */ ts_type_t (*get_type) (traffic_selector_t *this); /** - * @brief Get the protocol id of this ts. + * Get the protocol id of this ts. * - * @param this called object * @return protocol id */ u_int8_t (*get_protocol) (traffic_selector_t *this); /** - * @brief Check if the traffic selector is for a single host. + * Check if the traffic selector is for a single host. * * Traffic selector may describe the end of *-to-host tunnel. In this * case, the address range is a single address equal to the hosts @@ -168,61 +150,54 @@ struct traffic_selector_t { * If host is NULL, the traffic selector is checked if it is a single host, * but not a specific one. * - * @param this called object * @param host host_t specifying the address range */ bool (*is_host) (traffic_selector_t *this, host_t* host); /** - * @brief Update the address of a traffic selector. + * Update the address of a traffic selector. * * Update the address range of a traffic selector, if it is * constructed with the traffic_selector_create_dynamic(). * - * @param this called object * @param host host_t specifying the address */ void (*set_address) (traffic_selector_t *this, host_t* host); /** - * @brief Compare two traffic selectors for equality. + * Compare two traffic selectors for equality. * - * @param this first to compare - * @param other second to compare with first + * @param other ts to compare with this * @return pointer to a string. */ bool (*equals) (traffic_selector_t *this, traffic_selector_t *other); /** - * @brief Check if a traffic selector is contained completly in another. + * Check if a traffic selector is contained completly in another. * * contains() allows to check if multiple traffic selectors are redundant. * - * @param this ts that is contained in another * @param other ts that contains this * @return TRUE if other contains this completly, FALSE otherwise */ bool (*is_contained_in) (traffic_selector_t *this, traffic_selector_t *other); /** - * @brief Check if a specific host is included in the address range of + * Check if a specific host is included in the address range of * this traffic selector. * - * @param this called object * @param host the host to check */ bool (*includes) (traffic_selector_t *this, host_t *host); /** - * @brief Destroys the ts object - * - * @param this called object + * Destroys the ts object */ void (*destroy) (traffic_selector_t *this); }; /** - * @brief Create a new traffic selector using human readable params. + * Create a new traffic selector using human readable params. * * @param protocol protocol for this ts, such as TCP or UDP * @param type type of following addresses, such as TS_IPV4_ADDR_RANGE @@ -233,8 +208,6 @@ struct traffic_selector_t { * @return * - traffic_selector_t object * - NULL if invalid address strings/protocol - * - * @ingroup config */ traffic_selector_t *traffic_selector_create_from_string( u_int8_t protocol, ts_type_t type, @@ -242,7 +215,7 @@ traffic_selector_t *traffic_selector_create_from_string( char *to_addr, u_int16_t to_port); /** - * @brief Create a new traffic selector using data read from the net. + * Create a new traffic selector using data read from the net. * * There exists a mix of network and host order in the params. * But the parser gives us this data in this format, so we @@ -255,8 +228,6 @@ traffic_selector_t *traffic_selector_create_from_string( * @param to_address end of address range as string, network * @param to_port port number, host order * @return traffic_selector_t object - * - * @ingroup config */ traffic_selector_t *traffic_selector_create_from_bytes( u_int8_t protocol, ts_type_t type, @@ -264,7 +235,7 @@ traffic_selector_t *traffic_selector_create_from_bytes( chunk_t to_address, u_int16_t to_port); /** - * @brief Create a new traffic selector defining a whole subnet. + * Create a new traffic selector defining a whole subnet. * * In most cases, definition of a traffic selector for full subnets * is sufficient. This constructor creates a traffic selector for @@ -278,15 +249,13 @@ traffic_selector_t *traffic_selector_create_from_bytes( * @return * - traffic_selector_t object * - NULL if address family of net not supported - * - * @ingroup config */ traffic_selector_t *traffic_selector_create_from_subnet( host_t *net, u_int8_t netbits, u_int8_t protocol, u_int16_t port); /** - * @brief Create a traffic selector for host-to-host cases. + * Create a traffic selector for host-to-host cases. * * For host2host or virtual IP setups, the traffic selectors gets * created at runtime using the external/virtual IP. Using this constructor, @@ -294,19 +263,23 @@ traffic_selector_t *traffic_selector_create_from_subnet( * * * @param protocol upper layer protocl to allow - * @param type family type * @param from_port start of allowed port range * @param to_port end of range * @return * - traffic_selector_t object * - NULL if type not supported - * - * @ingroup config */ -traffic_selector_t *traffic_selector_create_dynamic( - u_int8_t protocol, ts_type_t type, +traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol, u_int16_t from_port, u_int16_t to_port); -#endif /* TRAFFIC_SELECTOR_H_ */ +/** + * Get printf hooks for a traffic selector. + * + * Arguments are: + * traffic_selector_t *ts + * With the #-specifier, arguments are: + * linked_list_t *list containing traffic_selector_t* + */ +printf_hook_functions_t traffic_selector_get_printf_hooks(); -/* vim: set ts=4 sw=4 noet: */ +#endif /* TRAFFIC_SELECTOR_H_ @} */ diff --git a/src/charon/control/interface_manager.c b/src/charon/control/controller.c index 4d5aa2ea6..2d1decd88 100644 --- a/src/charon/control/interface_manager.c +++ b/src/charon/control/controller.c @@ -1,10 +1,3 @@ -/** - * @file interface_manager.c - * - * @brief Implementation of interface_manager_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,9 +11,11 @@ * 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. + * + * $Id: controller.c 3820 2008-04-17 11:22:37Z martin $ */ -#include "interface_manager.h" +#include "controller.h" #include <sys/types.h> #include <dirent.h> @@ -29,31 +24,20 @@ #include <daemon.h> #include <library.h> -#include <control/interfaces/interface.h> -typedef struct private_interface_manager_t private_interface_manager_t; +typedef struct private_controller_t private_controller_t; typedef struct interface_bus_listener_t interface_bus_listener_t; /** * Private data of an stroke_t object. */ -struct private_interface_manager_t { +struct private_controller_t { /** * Public part of stroke_t object. */ - interface_manager_t public; - - /** - * a list of all loaded interfaces - */ - linked_list_t *interfaces; - - /** - * dlopen() handles of interfaces - */ - linked_list_t *handles; + controller_t public; }; @@ -80,7 +64,7 @@ struct interface_bus_listener_t { /** * interface callback (listener gets redirected to here) */ - interface_manager_cb_t callback; + controller_cb_t callback; /** * user parameter to pass to callback @@ -122,19 +106,11 @@ struct interface_job_t { }; /** - * Implements the famous nop operation + * Implementation of controller_t.create_ike_sa_iterator. */ -static void nop(job_t *job) +static enumerator_t* create_ike_sa_enumerator(controller_t *this) { - /* NOP */ -} - -/** - * Implementation of interface_manager_t.create_ike_sa_iterator. - */ -static iterator_t* create_ike_sa_iterator(interface_manager_t *this) -{ - return charon->ike_sa_manager->create_iterator(charon->ike_sa_manager); + return charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager); } /** @@ -173,11 +149,11 @@ static status_t initiate_execute(interface_job_t *job) ike_sa_t *ike_sa; interface_bus_listener_t *listener = &job->listener; peer_cfg_t *peer_cfg = listener->peer_cfg; - + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, peer_cfg); listener->ike_sa = ike_sa; - + if (ike_sa->get_peer_cfg(ike_sa) == NULL) { ike_sa->set_peer_cfg(ike_sa, peer_cfg); @@ -193,11 +169,11 @@ static status_t initiate_execute(interface_job_t *job) } /** - * Implementation of interface_manager_t.initiate. + * Implementation of controller_t.initiate. */ -static status_t initiate(private_interface_manager_t *this, +static status_t initiate(private_controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - interface_manager_cb_t callback, void *param) + controller_cb_t callback, void *param) { interface_job_t job; @@ -273,10 +249,10 @@ static status_t terminate_ike_execute(interface_job_t *job) } /** - * Implementation of interface_manager_t.terminate_ike. + * Implementation of controller_t.terminate_ike. */ -static status_t terminate_ike(interface_manager_t *this, u_int32_t unique_id, - interface_manager_cb_t callback, void *param) +static status_t terminate_ike(controller_t *this, u_int32_t unique_id, + controller_cb_t callback, void *param) { interface_job_t job; @@ -375,10 +351,10 @@ static status_t terminate_child_execute(interface_job_t *job) } /** - * Implementation of interface_manager_t.terminate_child. + * Implementation of controller_t.terminate_child. */ -static status_t terminate_child(interface_manager_t *this, u_int32_t reqid, - interface_manager_cb_t callback, void *param) +static status_t terminate_child(controller_t *this, u_int32_t reqid, + controller_cb_t callback, void *param) { interface_job_t job; @@ -434,7 +410,6 @@ static status_t route_execute(interface_job_t *job) ike_sa_t *ike_sa; interface_bus_listener_t *listener = &job->listener; peer_cfg_t *peer_cfg = listener->peer_cfg; - ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, peer_cfg); listener->ike_sa = ike_sa; @@ -452,11 +427,11 @@ static status_t route_execute(interface_job_t *job) } /** - * Implementation of interface_manager_t.route. + * Implementation of controller_t.route. */ -static status_t route(interface_manager_t *this, +static status_t route(controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - interface_manager_cb_t callback, void *param) + controller_cb_t callback, void *param) { interface_job_t job; @@ -530,10 +505,10 @@ static status_t unroute_execute(interface_job_t *job) } /** - * Implementation of interface_manager_t.unroute. + * Implementation of controller_t.unroute. */ -static status_t unroute(interface_manager_t *this, u_int32_t reqid, - interface_manager_cb_t callback, void *param) +static status_t unroute(controller_t *this, u_int32_t reqid, + controller_cb_t callback, void *param) { interface_job_t job; @@ -555,76 +530,9 @@ static status_t unroute(interface_manager_t *this, u_int32_t reqid, } /** - * load the control interface modules - */ -static void load_interfaces(private_interface_manager_t *this) -{ - struct dirent* entry; - DIR* dir; - - dir = opendir(IPSEC_INTERFACEDIR); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening interface modules directory "IPSEC_INTERFACEDIR); - return; - } - - DBG1(DBG_CFG, "loading control interface modules from '"IPSEC_INTERFACEDIR"'"); - - while ((entry = readdir(dir)) != NULL) - { - char file[256]; - interface_t *interface; - interface_constructor_t constructor; - void *handle; - char *ending; - - snprintf(file, sizeof(file), IPSEC_INTERFACEDIR"/%s", entry->d_name); - - ending = entry->d_name + strlen(entry->d_name) - 3; - if (ending <= entry->d_name || !streq(ending, ".so")) - { - /* skip anything which does not look like a library */ - DBG2(DBG_CFG, " skipping %s, doesn't look like a library", - entry->d_name); - continue; - } - /* try to load the library */ - handle = dlopen(file, RTLD_LAZY); - if (handle == NULL) - { - DBG1(DBG_CFG, " opening control interface module %s failed: %s", - entry->d_name, dlerror()); - continue; - } - constructor = dlsym(handle, "interface_create"); - if (constructor == NULL) - { - DBG1(DBG_CFG, " interface module %s has no interface_create() " - "function, skipped", entry->d_name); - dlclose(handle); - continue; - } - - interface = constructor(); - if (interface == NULL) - { - DBG1(DBG_CFG, " unable to create instance of interface " - "module %s, skipped", entry->d_name); - dlclose(handle); - continue; - } - DBG1(DBG_CFG, " loaded control interface module successfully from %s", entry->d_name); - this->interfaces->insert_last(this->interfaces, interface); - this->handles->insert_last(this->handles, handle); - } - closedir(dir); -} - -/** * See header */ -bool interface_manager_cb_empty(void *param, signal_t signal, level_t level, +bool controller_cb_empty(void *param, signal_t signal, level_t level, ike_sa_t *ike_sa, char *format, va_list args) { return TRUE; @@ -633,32 +541,25 @@ bool interface_manager_cb_empty(void *param, signal_t signal, level_t level, /** * Implementation of stroke_t.destroy. */ -static void destroy(private_interface_manager_t *this) +static void destroy(private_controller_t *this) { - this->interfaces->destroy_offset(this->interfaces, offsetof(interface_t, destroy)); - this->handles->destroy_function(this->handles, (void*)dlclose); free(this); } /* * Described in header-file */ -interface_manager_t *interface_manager_create(void) +controller_t *controller_create(void) { - private_interface_manager_t *this = malloc_thing(private_interface_manager_t); - - this->public.create_ike_sa_iterator = (iterator_t*(*)(interface_manager_t*))create_ike_sa_iterator; - this->public.initiate = (status_t(*)(interface_manager_t*,peer_cfg_t*,child_cfg_t*,bool(*)(void*,signal_t,level_t,ike_sa_t*,char*,va_list),void*))initiate; - this->public.terminate_ike = (status_t(*)(interface_manager_t*,u_int32_t,interface_manager_cb_t, void*))terminate_ike; - this->public.terminate_child = (status_t(*)(interface_manager_t*,u_int32_t,interface_manager_cb_t, void *param))terminate_child; - this->public.route = (status_t(*)(interface_manager_t*,peer_cfg_t*, child_cfg_t*,interface_manager_cb_t,void*))route; - this->public.unroute = (status_t(*)(interface_manager_t*,u_int32_t,interface_manager_cb_t,void*))unroute; - this->public.destroy = (void (*)(interface_manager_t*))destroy; - - this->interfaces = linked_list_create(); - this->handles = linked_list_create(); + private_controller_t *this = malloc_thing(private_controller_t); - load_interfaces(this); + this->public.create_ike_sa_enumerator = (enumerator_t*(*)(controller_t*))create_ike_sa_enumerator; + this->public.initiate = (status_t(*)(controller_t*,peer_cfg_t*,child_cfg_t*,bool(*)(void*,signal_t,level_t,ike_sa_t*,char*,va_list),void*))initiate; + this->public.terminate_ike = (status_t(*)(controller_t*,u_int32_t,controller_cb_t, void*))terminate_ike; + this->public.terminate_child = (status_t(*)(controller_t*,u_int32_t,controller_cb_t, void *param))terminate_child; + this->public.route = (status_t(*)(controller_t*,peer_cfg_t*, child_cfg_t*,controller_cb_t,void*))route; + this->public.unroute = (status_t(*)(controller_t*,u_int32_t,controller_cb_t,void*))unroute; + this->public.destroy = (void (*)(controller_t*))destroy; return &this->public; } diff --git a/src/charon/control/interface_manager.h b/src/charon/control/controller.h index 3ee1f0e39..643611965 100644 --- a/src/charon/control/interface_manager.h +++ b/src/charon/control/controller.h @@ -1,10 +1,3 @@ -/** - * @file interface_manager.h - * - * @brief Interface of interface_manager_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,15 +11,22 @@ * 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. + * + * $Id: controller.h 3804 2008-04-14 11:37:46Z martin $ */ -#ifndef INTERFACE_MANAGER_H_ -#define INTERFACE_MANAGER_H_ +/** + * @defgroup controller_i controller + * @{ @ingroup control + */ + +#ifndef CONTROLLER_H_ +#define CONTROLLER_H_ #include <bus/bus.h> /** - * callback to log things triggered by interface_manager. + * callback to log things triggered by controller. * * @param param echoed parameter supplied when function invoked * @param signal type of signal @@ -35,74 +35,51 @@ * @param format printf like format string * @param args list of arguments to use for format * @return FALSE to return from invoked function - * @ingroup control */ -typedef bool(*interface_manager_cb_t)(void* param, signal_t signal, level_t level, +typedef bool(*controller_cb_t)(void* param, signal_t signal, level_t level, ike_sa_t* ike_sa, char* format, va_list args); /** - * @brief Empty callback function for interface_manager_t functions. + * Empty callback function for controller_t functions. * * If you wan't to do a syncrhonous call, but don't need a callback, pass - * this function to the interface_managers methods. + * this function to the controllers methods. */ -bool interface_manager_cb_empty(void *param, signal_t signal, level_t level, +bool controller_cb_empty(void *param, signal_t signal, level_t level, ike_sa_t *ike_sa, char *format, va_list args); -typedef struct interface_manager_t interface_manager_t; +typedef struct controller_t controller_t; /** - * @brief The interface_manager loads control interfaces and has helper methods. + * The controller provides a simple interface to run actions. * - * One job of the interface manager is to load pluggable control interface - * modules, implemented as interface_t. - * @verbatim - - +---------+ +------------+ +--------------+ | - | | | |<----- +--------------+ | | - | daemon |<-----| interface- | +--------------+ |-+ <==|==> IPC - | core | | manager |<----| interfaces |-+ | - | |<-----| | +--------------+ | - | | | | | - +---------+ +------------+ | - - @endverbatim - * The manager does not really use the interfaces, instead, the interface - * use the manager to fullfill their tasks (initiating, terminating, ...). - * The interface_manager starts actions by creating jobs. It then tries to + * The controller starts actions by creating jobs. It then tries to * evaluate the result of the operation by listening on the bus. * * Passing NULL as callback to the managers function calls them asynchronously. * If a callback is specified, they are called synchronoulsy. There is a default - * callback "interface_manager_cb_empty" if you wan't to call a function + * callback "controller_cb_empty" if you wan't to call a function * synchronously, but don't need a callback. - * - * @b Constructors: - * - interface_manager_create() - * - * @ingroup control */ -struct interface_manager_t { +struct controller_t { /** - * @brief Create an iterator for all IKE_SAs. + * Create an enumerator for all IKE_SAs. * - * The iterator blocks the IKE_SA manager until it gets destroyed. Do + * The enumerator blocks the IKE_SA manager until it gets destroyed. Do * not call another interface/manager method while the iterator is alive. * - * @param this calling object - * @return iterator, locks IKE_SA manager until destroyed + * @return enumerator, locks IKE_SA manager until destroyed */ - iterator_t* (*create_ike_sa_iterator)(interface_manager_t *this); + enumerator_t* (*create_ike_sa_enumerator)(controller_t *this); /** - * @brief Initiate a CHILD_SA, and if required, an IKE_SA. + * Initiate a CHILD_SA, and if required, an IKE_SA. * * The inititate() function is synchronous and thus blocks until the * IKE_SA is established or failed. Because of this, the initiate() function * contains a thread cancellation point. * - * @param this calling object * @param peer_cfg peer_cfg to use for IKE_SA setup * @param child_cfg child_cfg to set up CHILD_SA from * @param cb logging callback @@ -112,18 +89,17 @@ struct interface_manager_t { * - FAILED, if setup failed * - NEED_MORE, if callback returned FALSE */ - status_t (*initiate)(interface_manager_t *this, + status_t (*initiate)(controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - interface_manager_cb_t callback, void *param); + controller_cb_t callback, void *param); /** - * @brief Terminate an IKE_SA and all of its CHILD_SAs. + * Terminate an IKE_SA and all of its CHILD_SAs. * * The terminate() function is synchronous and thus blocks until the * IKE_SA is properly deleted, or the delete timed out. * The terminate() function contains a thread cancellation point. * - * @param this calling object * @param unique_id unique id of the IKE_SA to terminate. * @param cb logging callback * @param param parameter to include in each call of cb @@ -132,13 +108,12 @@ struct interface_manager_t { * - NOT_FOUND, if no such CHILD_SA found * - NEED_MORE, if callback returned FALSE */ - status_t (*terminate_ike)(interface_manager_t *this, u_int32_t unique_id, - interface_manager_cb_t callback, void *param); + status_t (*terminate_ike)(controller_t *this, u_int32_t unique_id, + controller_cb_t callback, void *param); /** - * @brief Terminate a CHILD_SA. + * Terminate a CHILD_SA. * - * @param this calling object * @param reqid reqid of the CHILD_SA to terminate * @param cb logging callback * @param param parameter to include in each call of cb @@ -147,13 +122,12 @@ struct interface_manager_t { * - NOT_FOUND, if no such CHILD_SA found * - NEED_MORE, if callback returned FALSE */ - status_t (*terminate_child)(interface_manager_t *this, u_int32_t reqid, - interface_manager_cb_t callback, void *param); + status_t (*terminate_child)(controller_t *this, u_int32_t reqid, + controller_cb_t callback, void *param); /** - * @brief Route a CHILD_SA (install triggering policies). + * Route a CHILD_SA (install triggering policies). * - * @param this calling object * @param peer_cfg peer_cfg to use for IKE_SA setup, if triggered * @param child_cfg child_cfg to route * @param cb logging callback @@ -163,16 +137,15 @@ struct interface_manager_t { * - FAILED, if routing failed * - NEED_MORE, if callback returned FALSE */ - status_t (*route)(interface_manager_t *this, + status_t (*route)(controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - interface_manager_cb_t callback, void *param); + controller_cb_t callback, void *param); /** - * @brief Unroute a routed CHILD_SA (uninstall triggering policies). + * Unroute a routed CHILD_SA (uninstall triggering policies). * * Only the route is removed, not the CHILD_SAs the route triggered. * - * @param this calling object * @param reqid reqid of the CHILD_SA to unroute * @param cb logging callback * @param param parameter to include in each call of cb @@ -181,26 +154,21 @@ struct interface_manager_t { * - NOT_FOUND, if no such CHILD_SA routed * - NEED_MORE, if callback returned FALSE */ - status_t (*unroute)(interface_manager_t *this, u_int32_t reqid, - interface_manager_cb_t callback, void *param); + status_t (*unroute)(controller_t *this, u_int32_t reqid, + controller_cb_t callback, void *param); /** - * @brief Destroy a interface_manager_t instance. - * - * @param this interface_manager_t objec to destroy + * Destroy a controller_t instance. */ - void (*destroy) (interface_manager_t *this); + void (*destroy) (controller_t *this); }; /** - * @brief Creates a interface_manager instance and loads all interface modules. - * - * @return interface_manager_t object + * Creates a controller instance. * - * @ingroup control + * @return controller_t object */ -interface_manager_t *interface_manager_create(void); - -#endif /* INTERFACE_MANAGER_H_ */ +controller_t *controller_create(void); +#endif /* CONTROLLER_H_ @} */ diff --git a/src/charon/control/interfaces/dbus_interface.c b/src/charon/control/interfaces/dbus_interface.c deleted file mode 100644 index 39226aaef..000000000 --- a/src/charon/control/interfaces/dbus_interface.c +++ /dev/null @@ -1,427 +0,0 @@ -/** - * @file dbus_interface.c - * - * @brief Implementation of dbus_interface_t. - * - */ - -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -#define DBUS_API_SUBJECT_TO_CHANGE -#include <dbus/dbus.h> -#include <NetworkManager/NetworkManager.h> -#include <NetworkManager/NetworkManagerVPN.h> -#include <stdlib.h> - -#include "dbus_interface.h" - -#include <library.h> -#include <daemon.h> -#include <processing/jobs/callback_job.h> - - -#define NM_DBUS_SERVICE_STRONG "org.freedesktop.NetworkManager.strongswan" -#define NM_DBUS_INTERFACE_STRONG "org.freedesktop.NetworkManager.strongswan" -#define NM_DBUS_PATH_STRONG "/org/freedesktop/NetworkManager/strongswan" - -typedef struct private_dbus_interface_t private_dbus_interface_t; - -/** - * Private data of an dbus_interface_t object. - */ -struct private_dbus_interface_t { - - /** - * Public part of dbus_t object. - */ - dbus_interface_t public; - - /** - * DBUS connection - */ - DBusConnection* conn; - - /** - * error value used here and there - */ - DBusError err; - - /** - * state of the daemon - */ - NMVPNState state; - - /** - * job accepting stroke messages - */ - callback_job_t *job; - - /** - * name of the currently active connection - */ - char *name; -}; - -/** - * set daemon state and send StateChange signal to the bus - */ -static void set_state(private_dbus_interface_t *this, NMVPNState state) -{ - DBusMessage* msg; - - msg = dbus_message_new_signal(NM_DBUS_PATH_STRONG, NM_DBUS_INTERFACE_STRONG, NM_DBUS_VPN_SIGNAL_STATE_CHANGE); - - if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &this->state, - DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID) || - !dbus_connection_send(this->conn, msg, NULL)) - { - DBG1(DBG_CFG, "unable to send DBUS StateChange signal"); - } - dbus_connection_flush(this->conn); - dbus_message_unref(msg); - this->state = state; -} - - -/** - * get the child_cfg with the same name as the peer cfg - */ -static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name) -{ - child_cfg_t *current, *found = NULL; - iterator_t *iterator; - - iterator = peer_cfg->create_child_cfg_iterator(peer_cfg); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (streq(current->get_name(current), name)) - { - found = current; - found->get_ref(found); - break; - } - } - iterator->destroy(iterator); - return found; -} - - -/** - * process NetworkManagers startConnection method call - */ -static bool start_connection(private_dbus_interface_t *this, DBusMessage* msg) -{ - DBusMessage *reply, *signal; - char *name, *user, **data, **passwords, **routes; - int data_count, passwords_count, routes_count; - u_int32_t me, other, p2p, netmask, mss; - char *dev, *domain, *banner; - const dbus_int32_t array[] = {}; - const dbus_int32_t *varray = array; - peer_cfg_t *peer_cfg; - child_cfg_t *child_cfg; - status_t status = FAILED; - - dbus_error_free(&this->err); - - if (!dbus_message_get_args(msg, &this->err, - DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &passwords_count, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data, &data_count, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &routes, &routes_count, - DBUS_TYPE_INVALID)) - { - return FALSE; - } - set_state(this, NM_VPN_STATE_STARTING); - - peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name); - if (peer_cfg) - { - free(this->name); - this->name = strdup(peer_cfg->get_name(peer_cfg)); - child_cfg = get_child_from_peer(peer_cfg, name); - if (child_cfg) - { - status = charon->interfaces->initiate(charon->interfaces, - peer_cfg, child_cfg, interface_manager_cb_empty, NULL); - } - else - { - peer_cfg->destroy(peer_cfg); - } - } - reply = dbus_message_new_method_return(msg); - dbus_connection_send(this->conn, reply, NULL); - dbus_message_unref(reply); - - if (status == SUCCESS) - { - - set_state(this, NM_VPN_STATE_STARTED); - signal = dbus_message_new_signal(NM_DBUS_PATH_STRONG, - NM_DBUS_INTERFACE_STRONG, - NM_DBUS_VPN_SIGNAL_IP4_CONFIG); - me = other = p2p = mss = netmask = 0; - dev = domain = banner = ""; - if (dbus_message_append_args(signal, - DBUS_TYPE_UINT32, &other, - DBUS_TYPE_STRING, &dev, - DBUS_TYPE_UINT32, &me, - DBUS_TYPE_UINT32, &p2p, - DBUS_TYPE_UINT32, &netmask, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0, - DBUS_TYPE_UINT32, &mss, - DBUS_TYPE_STRING, &domain, - DBUS_TYPE_STRING, &banner, DBUS_TYPE_INVALID)) - { - dbus_connection_send(this->conn, signal, NULL); - } - dbus_message_unref(signal); - } - else - { - set_state(this, NM_VPN_STATE_STOPPED); - } - - dbus_connection_flush(this->conn); - return TRUE; -} - -/** - * process NetworkManagers stopConnection method call - */ -static bool stop_connection(private_dbus_interface_t *this, DBusMessage* msg) -{ - u_int32_t id; - iterator_t *iterator; - ike_sa_t *ike_sa; - - if (this->name == NULL) - { - return FALSE; - } - - dbus_error_free(&this->err); - - set_state(this, NM_VPN_STATE_STOPPING); - - iterator = charon->interfaces->create_ike_sa_iterator(charon->interfaces); - while (iterator->iterate(iterator, (void**)&ike_sa)) - { - child_sa_t *child_sa; - iterator_t *children; - - if (this->name && streq(this->name, ike_sa->get_name(ike_sa))) - { - id = ike_sa->get_unique_id(ike_sa); - iterator->destroy(iterator); - charon->interfaces->terminate_ike(charon->interfaces, id, NULL, NULL); - set_state(this, NM_VPN_STATE_STOPPED); - return TRUE;; - } - children = ike_sa->create_child_sa_iterator(ike_sa); - while (children->iterate(children, (void**)&child_sa)) - { - if (this->name && streq(this->name, child_sa->get_name(child_sa))) - { - id = child_sa->get_reqid(child_sa); - children->destroy(children); - iterator->destroy(iterator); - charon->interfaces->terminate_child(charon->interfaces, id, NULL, NULL); - set_state(this, NM_VPN_STATE_STOPPED); - return TRUE; - } - } - children->destroy(children); - } - iterator->destroy(iterator); - set_state(this, NM_VPN_STATE_STOPPED); - return TRUE; -} - -/** - * process NetworkManagers getState method call - */ -static bool get_state(private_dbus_interface_t *this, DBusMessage* msg) -{ - DBusMessage* reply; - reply = dbus_message_new_method_return(msg); - if (!reply || !dbus_message_append_args(reply, - DBUS_TYPE_UINT32, &this->state, - DBUS_TYPE_INVALID)) - { - return FALSE; - } - dbus_connection_send(this->conn, reply, NULL); - return TRUE; -} - -/** - * Handle incoming messages - */ -static DBusHandlerResult message_handler(DBusConnection *con, DBusMessage *msg, - private_dbus_interface_t *this) -{ - bool handled; - - if (dbus_message_is_method_call(msg, NM_DBUS_INTERFACE_STRONG, - "startConnection")) - { - handled = start_connection(this, msg); - } - else if (dbus_message_is_method_call(msg, NM_DBUS_INTERFACE_STRONG, - "stopConnection")) - { - handled = stop_connection(this, msg); - } - else if (dbus_message_is_method_call(msg, NM_DBUS_INTERFACE_STRONG, - "getState")) - { - handled = get_state(this, msg); - } - else - { - DBG1(DBG_CFG, "ignoring DBUS message %s.%s", - dbus_message_get_interface(msg), dbus_message_get_member(msg)); - handled = FALSE; - } - - if (handled) - { - return DBUS_HANDLER_RESULT_HANDLED; - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -/** - * Handle received signals - -static DBusHandlerResult signal_handler(DBusConnection *con, DBusMessage *msg, - private_dbus_interface_t *this) -{ - bool handled; - - if (dbus_message_is_signal(msg, NM_DBUS_INTERFACE, "VPNConnectionStateChange")) - { - NMVPNState state; - char *name; - - if (dbus_message_get_args(msg, &this->err, DBUS_TYPE_STRING, &name, - DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID)) - { - DBG1(DBG_CFG, "got state %d for %s", state, name); - } - handled = TRUE; - } - else - { - DBG1(DBG_CFG, "ignoring DBUS signal %s.%s", - dbus_message_get_interface(msg), dbus_message_get_member(msg)); - handled = FALSE; - } - if (handled) - { - return DBUS_HANDLER_RESULT_HANDLED; - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} */ - -/** - * dispatcher function processed by a seperate thread - */ -static job_requeue_t dispatch(private_dbus_interface_t *this) -{ - if (dbus_connection_read_write_dispatch(this->conn, -1)) - { - return JOB_REQUEUE_DIRECT; - } - return JOB_REQUEUE_NONE; -} - -/** - * Implementation of interface_t.destroy. - */ -static void destroy(private_dbus_interface_t *this) -{ - this->job->cancel(this->job); - dbus_connection_close(this->conn); - dbus_error_free(&this->err); - dbus_shutdown(); - free(this->name); - free(this); -} - -/* - * Described in header file - */ -interface_t *interface_create() -{ - int ret; - DBusObjectPathVTable v = {NULL, (void*)&message_handler, NULL, NULL, NULL, NULL}; - private_dbus_interface_t *this = malloc_thing(private_dbus_interface_t); - - this->public.interface.destroy = (void (*)(interface_t*))destroy; - - dbus_error_init(&this->err); - this->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &this->err); - if (dbus_error_is_set(&this->err)) - { - DBG1(DBG_CFG, "unable to open DBUS connection: %s", this->err.message); - charon->kill(charon, "DBUS initialization failed"); - } - dbus_connection_set_exit_on_disconnect(this->conn, FALSE); - - ret = dbus_bus_request_name(this->conn, NM_DBUS_SERVICE_STRONG, - DBUS_NAME_FLAG_REPLACE_EXISTING , &this->err); - if (dbus_error_is_set(&this->err)) - { - DBG1(DBG_CFG, "unable to set DBUS name: %s", this->err.message); - charon->kill(charon, "unable to set DBUS name"); - } - if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) - { - charon->kill(charon, "DBUS name already owned"); - } - if (!dbus_connection_register_object_path(this->conn, NM_DBUS_PATH_STRONG, &v, this)) - { - charon->kill(charon, "unable to register DBUS message handler"); - } - /* - if (!dbus_connection_add_filter(this->conn, (void*)signal_handler, this, NULL)) - { - charon->kill(charon, "unable to register DBUS signal handler"); - } - - dbus_bus_add_match(this->conn, "type='signal', " - "interface='" NM_DBUS_INTERFACE_VPN "'," - "path='" NM_DBUS_PATH_VPN "'", &this->err); - if (dbus_error_is_set (&this->err)) - { - charon->kill(charon, "unable to add DBUS signal match"); - }*/ - - this->name = NULL; - this->state = NM_VPN_STATE_INIT; - set_state(this, NM_VPN_STATE_STOPPED); - - this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL); - charon->processor->queue_job(charon->processor, (job_t*)this->job); - - return &this->public.interface; -} - diff --git a/src/charon/control/interfaces/interface.h b/src/charon/control/interfaces/interface.h deleted file mode 100644 index 955f4a4eb..000000000 --- a/src/charon/control/interfaces/interface.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file interface.h - * - * @brief Interface of interface_t. - * - */ - -/* - * Copyright (C) 2007 Martin Willi - * 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. - */ - -#ifndef INTERFACE_H_ -#define INTERFACE_H_ - -typedef struct interface_t interface_t; - -/** - * @brief Interface for a controller. - * - * An interface controls the daemon by calling functions on the - * interface_manager. All interfaces are manager by the interface_manager - * in a generic way, so they need their own class. - * - * @b Constructors: - * - interface_create() of one of the modules - * - * @ingroup interfaces - */ -struct interface_t { - - /** - * @brief Destroy all interfaces - * - * @param this stroke_t objec to destroy - */ - void (*destroy) (interface_t *this); -}; - - -/** - * Constructor in a control interface module to create the interface. - * - * @ingroup interfaces - */ -typedef interface_t*(*interface_constructor_t)(void); - -#endif /* INTERFACE_H_ */ - diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c deleted file mode 100755 index 3b4b246bd..000000000 --- a/src/charon/control/interfaces/stroke_interface.c +++ /dev/null @@ -1,1818 +0,0 @@ -/** - * @file stroke_interface.c - * - * @brief Implementation of stroke_interface_t. - * - */ - -/* - * Copyright (C) 2007 Tobias Brunner - * Copyright (C) 2006-2007 Martin Willi - * 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 <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/fcntl.h> -#include <unistd.h> -#include <dirent.h> -#include <errno.h> -#include <pthread.h> -#include <signal.h> - -#include "stroke_interface.h" - -#include <library.h> -#include <stroke.h> -#include <daemon.h> -#include <crypto/x509.h> -#include <crypto/ietf_attr_list.h> -#include <crypto/ac.h> -#include <crypto/ca.h> -#include <crypto/crl.h> -#include <control/interface_manager.h> -#include <control/interfaces/interface.h> -#include <utils/leak_detective.h> -#include <processing/jobs/callback_job.h> - -#define IKE_PORT 500 -#define PATH_BUF 256 -#define STROKE_THREADS 3 - -typedef struct private_stroke_interface_t private_stroke_interface_t; - -/** - * Private data of an stroke_interfacet object. - */ -struct private_stroke_interface_t { - - /** - * Public part of stroke_interfacet object. - */ - stroke_interface_t public; - - /** - * Unix socket to listen for strokes - */ - int socket; - - /** - * job accepting stroke messages - */ - callback_job_t *job; -}; - -typedef struct stroke_log_info_t stroke_log_info_t; - -/** - * helper struct to say what and where to log when using controller callback - */ -struct stroke_log_info_t { - - /** - * level to log up to - */ - level_t level; - - /** - * where to write log - */ - FILE* out; -}; - -/** - * Helper function which corrects the string pointers - * in a stroke_msg_t. Strings in a stroke_msg sent over "wire" - * contains RELATIVE addresses (relative to the beginning of the - * stroke_msg). They must be corrected if they reach our address - * space... - */ -static void pop_string(stroke_msg_t *msg, char **string) -{ - if (*string == NULL) - return; - - /* check for sanity of string pointer and string */ - if (string < (char**)msg - || string > (char**)msg + sizeof(stroke_msg_t) - || (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) - || (unsigned long)*string > msg->length) - { - *string = "(invalid pointer in stroke msg)"; - } - else - { - *string = (char*)msg + (unsigned long)*string; - } -} - -/** - * Load end entitity certificate - */ -static x509_t* load_end_certificate(const char *filename, identification_t **idp) -{ - char path[PATH_BUF]; - x509_t *cert; - - if (*filename == '/') - { - /* absolute path name */ - snprintf(path, sizeof(path), "%s", filename); - } - else - { - /* relative path name */ - snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename); - } - - cert = x509_create_from_file(path, "end entity"); - - if (cert) - { - identification_t *id = *idp; - identification_t *subject = cert->get_subject(cert); - - err_t ugh = cert->is_valid(cert, NULL); - - if (ugh != NULL) - { - DBG1(DBG_CFG, "warning: certificate %s", ugh); - } - if (!id->equals(id, subject) && !cert->equals_subjectAltName(cert, id)) - { - id->destroy(id); - id = subject; - *idp = id->clone(id); - } - return charon->credentials->add_end_certificate(charon->credentials, cert); - } - return NULL; -} - -/** - * Load ca certificate - */ -static x509_t* load_ca_certificate(const char *filename) -{ - char path[PATH_BUF]; - x509_t *cert; - - if (*filename == '/') - { - /* absolute path name */ - snprintf(path, sizeof(path), "%s", filename); - } - else - { - /* relative path name */ - snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename); - } - - cert = x509_create_from_file(path, "ca"); - - if (cert) - { - if (cert->is_ca(cert)) - { - return charon->credentials->add_auth_certificate(charon->credentials, cert, AUTH_CA); - } - else - { - DBG1(DBG_CFG, " CA basic constraints flag not set, cert discarded"); - cert->destroy(cert); - } - } - return NULL; -} - -/** - * Pop the strings of a stroke_end_t struct and log them for debugging purposes - */ -static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end) -{ - pop_string(msg, &end->address); - pop_string(msg, &end->subnet); - pop_string(msg, &end->sourceip); - pop_string(msg, &end->id); - pop_string(msg, &end->cert); - pop_string(msg, &end->ca); - pop_string(msg, &end->groups); - pop_string(msg, &end->updown); - - DBG2(DBG_CFG, " %s=%s", label, end->address); - DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnet); - DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip); - DBG2(DBG_CFG, " %sid=%s", label, end->id); - DBG2(DBG_CFG, " %scert=%s", label, end->cert); - DBG2(DBG_CFG, " %sca=%s", label, end->ca); - DBG2(DBG_CFG, " %sgroups=%s", label, end->groups); - DBG2(DBG_CFG, " %supdown=%s", label, end->updown); -} - -/** - * Add a connection to the configuration list - */ -static void stroke_add_conn(stroke_msg_t *msg, FILE *out) -{ - ike_cfg_t *ike_cfg; - peer_cfg_t *peer_cfg; - peer_cfg_t *mediated_by_cfg = NULL; - child_cfg_t *child_cfg; - identification_t *my_id, *other_id; - identification_t *my_ca = NULL; - identification_t *other_ca = NULL; - identification_t *peer_id = NULL; - bool my_ca_same = FALSE; - bool other_ca_same =FALSE; - host_t *my_host, *other_host, *my_subnet, *other_subnet; - host_t *my_vip = NULL, *other_vip = NULL; - linked_list_t *other_groups = linked_list_create(); - proposal_t *proposal; - traffic_selector_t *my_ts, *other_ts; - char *interface; - bool use_existing = FALSE; - iterator_t *iterator; - u_int32_t vendor; - - pop_string(msg, &msg->add_conn.name); - DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name); - DBG2(DBG_CFG, "conn %s", msg->add_conn.name); - pop_end(msg, "left", &msg->add_conn.me); - pop_end(msg, "right", &msg->add_conn.other); - pop_string(msg, &msg->add_conn.algorithms.ike); - pop_string(msg, &msg->add_conn.algorithms.esp); - DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike); - DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp); - pop_string(msg, &msg->add_conn.p2p.mediated_by); - pop_string(msg, &msg->add_conn.p2p.peerid); - DBG2(DBG_CFG, " p2p_mediation=%s", msg->add_conn.p2p.mediation ? "yes" : "no"); - DBG2(DBG_CFG, " p2p_mediated_by=%s", msg->add_conn.p2p.mediated_by); - DBG2(DBG_CFG, " p2p_peerid=%s", msg->add_conn.p2p.peerid); - - my_host = msg->add_conn.me.address ? - host_create_from_string(msg->add_conn.me.address, IKE_PORT) : NULL; - if (my_host == NULL) - { - DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.me.address); - return; - } - - other_host = msg->add_conn.other.address ? - host_create_from_string(msg->add_conn.other.address, IKE_PORT) : NULL; - if (other_host == NULL) - { - DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.other.address); - my_host->destroy(my_host); - return; - } - - interface = charon->kernel_interface->get_interface(charon->kernel_interface, - other_host); - if (interface) - { - stroke_end_t tmp_end; - host_t *tmp_host; - - DBG2(DBG_CFG, "left is other host, swapping ends\n"); - - tmp_host = my_host; - my_host = other_host; - other_host = tmp_host; - - tmp_end = msg->add_conn.me; - msg->add_conn.me = msg->add_conn.other; - msg->add_conn.other = tmp_end; - free(interface); - } - else - { - interface = charon->kernel_interface->get_interface( - charon->kernel_interface, my_host); - if (!interface) - { - DBG1(DBG_CFG, "left nor right host is our side, assuming left=local"); - } - else - { - free(interface); - } - } - - my_id = identification_create_from_string(msg->add_conn.me.id ? - msg->add_conn.me.id : msg->add_conn.me.address); - if (my_id == NULL) - { - DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id); - goto destroy_hosts; - } - - other_id = identification_create_from_string(msg->add_conn.other.id ? - msg->add_conn.other.id : msg->add_conn.other.address); - if (other_id == NULL) - { - DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id); - my_id->destroy(my_id); - goto destroy_hosts; - } - -#ifdef P2P - if (msg->add_conn.p2p.mediation && msg->add_conn.p2p.mediated_by) - { - DBG1(DBG_CFG, "a mediation connection cannot be a" - " mediated connection at the same time, aborting"); - goto destroy_ids; - } - - if (msg->add_conn.p2p.mediated_by) - { - mediated_by_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, msg->add_conn.p2p.mediated_by); - if (!mediated_by_cfg) - { - DBG1(DBG_CFG, "mediation connection '%s' not found, aborting", - msg->add_conn.p2p.mediated_by); - goto destroy_ids; - } - - if (!mediated_by_cfg->is_mediation(mediated_by_cfg)) - { - DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is" - "no mediation connection, aborting", - msg->add_conn.p2p.mediated_by, msg->add_conn.name); - goto destroy_ids; - } - } - - if (msg->add_conn.p2p.peerid) - { - peer_id = identification_create_from_string(msg->add_conn.p2p.peerid); - if (!peer_id) - { - DBG1(DBG_CFG, "invalid peer ID: %s\n", msg->add_conn.p2p.peerid); - goto destroy_ids; - } - } - else - { - /* no peer ID supplied, assume right ID */ - peer_id = other_id->clone(other_id); - } -#endif /* P2P */ - - my_subnet = host_create_from_string(msg->add_conn.me.subnet ? - msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT); - if (my_subnet == NULL) - { - DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet); - goto destroy_ids; - } - - other_subnet = host_create_from_string(msg->add_conn.other.subnet ? - msg->add_conn.other.subnet : msg->add_conn.other.address, IKE_PORT); - if (other_subnet == NULL) - { - DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet); - my_subnet->destroy(my_subnet); - goto destroy_ids; - } - - if (msg->add_conn.me.virtual_ip && msg->add_conn.me.sourceip) - { - my_vip = host_create_from_string(msg->add_conn.me.sourceip, 0); - } - if (msg->add_conn.other.virtual_ip && msg->add_conn.other.sourceip) - { - other_vip = host_create_from_string(msg->add_conn.other.sourceip, 0); - } - - if (msg->add_conn.me.tohost) - { - my_ts = traffic_selector_create_dynamic(msg->add_conn.me.protocol, - my_host->get_family(my_host) == AF_INET ? - TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE, - msg->add_conn.me.port ? msg->add_conn.me.port : 0, - msg->add_conn.me.port ? msg->add_conn.me.port : 65535); - } - else - { - my_ts = traffic_selector_create_from_subnet(my_subnet, - msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 0, - msg->add_conn.me.protocol, msg->add_conn.me.port); - } - my_subnet->destroy(my_subnet); - - if (msg->add_conn.other.tohost) - { - other_ts = traffic_selector_create_dynamic(msg->add_conn.other.protocol, - other_host->get_family(other_host) == AF_INET ? - TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE, - msg->add_conn.other.port ? msg->add_conn.other.port : 0, - msg->add_conn.other.port ? msg->add_conn.other.port : 65535); - } - else - { - other_ts = traffic_selector_create_from_subnet(other_subnet, - msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 0, - msg->add_conn.other.protocol, msg->add_conn.other.port); - } - other_subnet->destroy(other_subnet); - - if (msg->add_conn.me.ca) - { - if (streq(msg->add_conn.me.ca, "%same")) - { - my_ca_same = TRUE; - } - else - { - my_ca = identification_create_from_string(msg->add_conn.me.ca); - } - } - if (msg->add_conn.other.ca) - { - if (streq(msg->add_conn.other.ca, "%same")) - { - other_ca_same = TRUE; - } - else - { - other_ca = identification_create_from_string(msg->add_conn.other.ca); - } - } - if (msg->add_conn.me.cert) - { - x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id); - - if (cert) - { - ca_info_t *ca_info; - - if (cert->is_self_signed(cert)) - { - /* a self-signed certificate is its own ca */ - ca_info = ca_info_create(NULL, cert); - ca_info = charon->credentials->add_ca_info(charon->credentials, ca_info); - cert->set_ca_info(cert, ca_info); - } - else - { - /* get_issuer() automatically sets cert->ca_info */ - ca_info = charon->credentials->get_issuer(charon->credentials, cert); - } - if (my_ca == NULL && !my_ca_same) - { - identification_t *issuer = cert->get_issuer(cert); - - my_ca = issuer->clone(issuer); - } - } - } - if (msg->add_conn.other.cert) - { - x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id); - - if (cert) - { - ca_info_t *ca_info; - - if (cert->is_self_signed(cert)) - { - /* a self-signed certificate is its own ca */ - ca_info = ca_info_create(NULL, cert); - ca_info = charon->credentials->add_ca_info(charon->credentials, ca_info); - cert->set_ca_info(cert, ca_info); - } - else - { - /* get_issuer() automatically sets cert->ca_info */ - ca_info = charon->credentials->get_issuer(charon->credentials, cert); - } - if (other_ca == NULL && !other_ca_same) - { - identification_t *issuer = cert->get_issuer(cert); - - other_ca = issuer->clone(issuer); - } - } - } - if (other_ca_same && my_ca) - { - other_ca = my_ca->clone(my_ca); - } - else if (my_ca_same && other_ca) - { - my_ca = other_ca->clone(other_ca); - } - if (my_ca == NULL) - { - my_ca = identification_create_from_string("%any"); - } - if (other_ca == NULL) - { - other_ca = identification_create_from_string("%any"); - } - DBG2(DBG_CFG, " my ca: '%D'", my_ca); - DBG2(DBG_CFG, " other ca:'%D'", other_ca); - - if (msg->add_conn.other.groups) - { - ietfAttr_list_create_from_string(msg->add_conn.other.groups, other_groups); - } - - /* have a look for an (almost) identical peer config to reuse */ - iterator = charon->backends->create_iterator(charon->backends); - while (iterator->iterate(iterator, (void**)&peer_cfg)) - { - host_t *my_vip_conf, *other_vip_conf; - bool my_vip_equals = FALSE, other_vip_equals = FALSE; - - my_vip_conf = peer_cfg->get_my_virtual_ip(peer_cfg); - if ((my_vip && my_vip_conf && my_vip->equals(my_vip, my_vip_conf)) || - (!my_vip_conf && !my_vip)) - { - my_vip_equals = TRUE; - } - DESTROY_IF(my_vip_conf); - other_vip_conf = peer_cfg->get_other_virtual_ip(peer_cfg, NULL); - if ((other_vip && other_vip_conf && other_vip->equals(other_vip, other_vip_conf)) || - (!other_vip_conf && !other_vip)) - { - other_vip_equals = TRUE; - } - DESTROY_IF(other_vip_conf); - - ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg)) - && other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg)) - && my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg)) - && other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg)) - && other_ca->equals(other_ca, peer_cfg->get_other_ca(peer_cfg)) - && ietfAttr_list_equals(other_groups, peer_cfg->get_groups(peer_cfg)) - && peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) - && peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method - && peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type - && vendor == msg->add_conn.eap_vendor - && my_vip_equals && other_vip_equals) - { - DBG1(DBG_CFG, "reusing existing configuration '%s'", - peer_cfg->get_name(peer_cfg)); - use_existing = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (use_existing) - { - DESTROY_IF(my_vip); - DESTROY_IF(other_vip); - my_host->destroy(my_host); - my_id->destroy(my_id); - my_ca->destroy(my_ca); - other_host->destroy(other_host); - other_id->destroy(other_id); - other_ca->destroy(other_ca); - DESTROY_IF(peer_id); - DESTROY_IF(mediated_by_cfg); - ietfAttr_list_destroy(other_groups); - } - else - { - ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND, - msg->add_conn.force_encap, my_host, other_host); - - if (msg->add_conn.algorithms.ike) - { - char *proposal_string; - char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1; - - if (*strict == '!') - *strict = '\0'; - else - strict = NULL; - - while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ","))) - { - proposal = proposal_create_from_string(PROTO_IKE, proposal_string); - if (proposal == NULL) - { - DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string); - my_id->destroy(my_id); - other_id->destroy(other_id); - my_ts->destroy(my_ts); - other_ts->destroy(other_ts); - my_ca->destroy(my_ca); - other_ca->destroy(other_ca); - ike_cfg->destroy(ike_cfg); - return; - } - ike_cfg->add_proposal(ike_cfg, proposal); - } - if (!strict) - { - proposal = proposal_create_default(PROTO_IKE); - ike_cfg->add_proposal(ike_cfg, proposal); - } - } - else - { - proposal = proposal_create_default(PROTO_IKE); - ike_cfg->add_proposal(ike_cfg, proposal); - } - - u_int32_t rekey = 0, reauth = 0, over, jitter; - - jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100; - over = msg->add_conn.rekey.margin; - if (msg->add_conn.rekey.reauth) - { - reauth = msg->add_conn.rekey.ike_lifetime - over; - } - else - { - rekey = msg->add_conn.rekey.ike_lifetime - over; - } - - peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1, - ike_cfg, my_id, other_id, my_ca, other_ca, other_groups, - msg->add_conn.me.sendcert, msg->add_conn.auth_method, - msg->add_conn.eap_type, msg->add_conn.eap_vendor, - msg->add_conn.rekey.tries, rekey, reauth, jitter, over, - msg->add_conn.mobike, - msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip, - msg->add_conn.p2p.mediation, mediated_by_cfg, peer_id); - } - - child_cfg = child_cfg_create( - msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime, - msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin, - msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100, - msg->add_conn.me.updown, msg->add_conn.me.hostaccess, - msg->add_conn.mode); - - peer_cfg->add_child_cfg(peer_cfg, child_cfg); - - child_cfg->add_traffic_selector(child_cfg, TRUE, my_ts); - child_cfg->add_traffic_selector(child_cfg, FALSE, other_ts); - - if (msg->add_conn.algorithms.esp) - { - char *proposal_string; - char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1; - - if (*strict == '!') - *strict = '\0'; - else - strict = NULL; - - while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ","))) - { - proposal = proposal_create_from_string(PROTO_ESP, proposal_string); - if (proposal == NULL) - { - DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string); - peer_cfg->destroy(peer_cfg); - return; - } - child_cfg->add_proposal(child_cfg, proposal); - } - if (!strict) - { - proposal = proposal_create_default(PROTO_ESP); - child_cfg->add_proposal(child_cfg, proposal); - } - } - else - { - proposal = proposal_create_default(PROTO_ESP); - child_cfg->add_proposal(child_cfg, proposal); - } - - if (!use_existing) - { - /* add config to backend */ - charon->backends->add_peer_cfg(charon->backends, peer_cfg); - DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]", - msg->add_conn.name, my_host, my_id, other_host, other_id); - } - return; - - /* mopping up after parsing errors */ - -destroy_ids: - my_id->destroy(my_id); - other_id->destroy(other_id); - DESTROY_IF(mediated_by_cfg); - DESTROY_IF(peer_id); - -destroy_hosts: - my_host->destroy(my_host); - other_host->destroy(other_host); -} - -/** - * Delete a connection from the list - */ -static void stroke_del_conn(stroke_msg_t *msg, FILE *out) -{ - iterator_t *peer_iter, *child_iter; - peer_cfg_t *peer; - child_cfg_t *child; - - pop_string(msg, &(msg->del_conn.name)); - DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name); - - peer_iter = charon->backends->create_iterator(charon->backends); - while (peer_iter->iterate(peer_iter, (void**)&peer)) - { - /* remove peer config with such a name */ - if (streq(peer->get_name(peer), msg->del_conn.name)) - { - peer_iter->remove(peer_iter); - peer->destroy(peer); - continue; - } - /* remove any child with such a name */ - child_iter = peer->create_child_cfg_iterator(peer); - while (child_iter->iterate(child_iter, (void**)&child)) - { - if (streq(child->get_name(child), msg->del_conn.name)) - { - child_iter->remove(child_iter); - child->destroy(child); - } - } - child_iter->destroy(child_iter); - } - peer_iter->destroy(peer_iter); - - fprintf(out, "deleted connection '%s'\n", msg->del_conn.name); -} - -/** - * get the child_cfg with the same name as the peer cfg - */ -static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name) -{ - child_cfg_t *current, *found = NULL; - iterator_t *iterator; - - iterator = peer_cfg->create_child_cfg_iterator(peer_cfg); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (streq(current->get_name(current), name)) - { - found = current; - found->get_ref(found); - break; - } - } - iterator->destroy(iterator); - return found; -} - -/** - * logging to the stroke interface - */ -static bool stroke_log(stroke_log_info_t *info, signal_t signal, level_t level, - ike_sa_t *ike_sa, char *format, va_list args) -{ - if (level <= info->level) - { - if (vfprintf(info->out, format, args) < 0 || - fprintf(info->out, "\n") < 0 || - fflush(info->out) != 0) - { - return FALSE; - } - } - return TRUE; -} - -/** - * initiate a connection by name - */ -static void stroke_initiate(stroke_msg_t *msg, FILE *out) -{ - peer_cfg_t *peer_cfg; - child_cfg_t *child_cfg; - stroke_log_info_t info; - - pop_string(msg, &(msg->initiate.name)); - DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name); - - peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, - msg->initiate.name); - if (peer_cfg == NULL) - { - fprintf(out, "no config named '%s'\n", msg->initiate.name); - return; - } - if (peer_cfg->get_ike_version(peer_cfg) != 2) - { - DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config", - peer_cfg->get_ike_version(peer_cfg)); - peer_cfg->destroy(peer_cfg); - return; - } - - child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name); - if (child_cfg == NULL) - { - fprintf(out, "no child config named '%s'\n", msg->initiate.name); - peer_cfg->destroy(peer_cfg); - return; - } - - if (msg->output_verbosity < 0) - { - charon->interfaces->initiate(charon->interfaces, peer_cfg, child_cfg, - NULL, NULL); - } - else - { - info.out = out; - info.level = msg->output_verbosity; - charon->interfaces->initiate(charon->interfaces, peer_cfg, child_cfg, - (interface_manager_cb_t)stroke_log, &info); - } -} - -/** - * route a policy (install SPD entries) - */ -static void stroke_route(stroke_msg_t *msg, FILE *out) -{ - peer_cfg_t *peer_cfg; - child_cfg_t *child_cfg; - stroke_log_info_t info; - - pop_string(msg, &(msg->route.name)); - DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name); - - peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, - msg->route.name); - if (peer_cfg == NULL) - { - fprintf(out, "no config named '%s'\n", msg->route.name); - return; - } - if (peer_cfg->get_ike_version(peer_cfg) != 2) - { - peer_cfg->destroy(peer_cfg); - return; - } - - child_cfg = get_child_from_peer(peer_cfg, msg->route.name); - if (child_cfg == NULL) - { - fprintf(out, "no child config named '%s'\n", msg->route.name); - peer_cfg->destroy(peer_cfg); - return; - } - - info.out = out; - info.level = msg->output_verbosity; - charon->interfaces->route(charon->interfaces, peer_cfg, child_cfg, - (interface_manager_cb_t)stroke_log, &info); - peer_cfg->destroy(peer_cfg); - child_cfg->destroy(child_cfg); -} - -/** - * unroute a policy - */ -static void stroke_unroute(stroke_msg_t *msg, FILE *out) -{ - char *name; - ike_sa_t *ike_sa; - iterator_t *iterator; - stroke_log_info_t info; - - pop_string(msg, &(msg->terminate.name)); - name = msg->terminate.name; - - info.out = out; - info.level = msg->output_verbosity; - - iterator = charon->interfaces->create_ike_sa_iterator(charon->interfaces); - while (iterator->iterate(iterator, (void**)&ike_sa)) - { - child_sa_t *child_sa; - iterator_t *children; - u_int32_t id; - - children = ike_sa->create_child_sa_iterator(ike_sa); - while (children->iterate(children, (void**)&child_sa)) - { - if (child_sa->get_state(child_sa) == CHILD_ROUTED && - streq(name, child_sa->get_name(child_sa))) - { - id = child_sa->get_reqid(child_sa); - children->destroy(children); - iterator->destroy(iterator); - charon->interfaces->unroute(charon->interfaces, id, - (interface_manager_cb_t)stroke_log, &info); - return; - } - } - children->destroy(children); - } - iterator->destroy(iterator); - DBG1(DBG_CFG, "no such SA found"); -} - -/** - * terminate a connection by name - */ -static void stroke_terminate(stroke_msg_t *msg, FILE *out) -{ - char *string, *pos = NULL, *name = NULL; - u_int32_t id = 0; - bool child; - int len; - ike_sa_t *ike_sa; - iterator_t *iterator; - stroke_log_info_t info; - - pop_string(msg, &(msg->terminate.name)); - string = msg->terminate.name; - DBG1(DBG_CFG, "received stroke: terminate '%s'", string); - - len = strlen(string); - if (len < 1) - { - DBG1(DBG_CFG, "error parsing string"); - return; - } - switch (string[len-1]) - { - case '}': - child = TRUE; - pos = strchr(string, '{'); - break; - case ']': - child = FALSE; - pos = strchr(string, '['); - break; - default: - name = string; - child = FALSE; - break; - } - - if (name) - { - /* is a single name */ - } - else if (pos == string + len - 2) - { /* is name[] or name{} */ - string[len-2] = '\0'; - name = string; - } - else - { /* is name[123] or name{23} */ - string[len-1] = '\0'; - id = atoi(pos + 1); - if (id == 0) - { - DBG1(DBG_CFG, "error parsing string"); - return; - } - } - - info.out = out; - info.level = msg->output_verbosity; - - iterator = charon->interfaces->create_ike_sa_iterator(charon->interfaces); - while (iterator->iterate(iterator, (void**)&ike_sa)) - { - child_sa_t *child_sa; - iterator_t *children; - - if (child) - { - children = ike_sa->create_child_sa_iterator(ike_sa); - while (children->iterate(children, (void**)&child_sa)) - { - if ((name && streq(name, child_sa->get_name(child_sa))) || - (id && id == child_sa->get_reqid(child_sa))) - { - id = child_sa->get_reqid(child_sa); - children->destroy(children); - iterator->destroy(iterator); - - charon->interfaces->terminate_child(charon->interfaces, id, - (interface_manager_cb_t)stroke_log, &info); - return; - } - } - children->destroy(children); - } - else if ((name && streq(name, ike_sa->get_name(ike_sa))) || - (id && id == ike_sa->get_unique_id(ike_sa))) - { - id = ike_sa->get_unique_id(ike_sa); - /* unlock manager first */ - iterator->destroy(iterator); - - charon->interfaces->terminate_ike(charon->interfaces, id, - (interface_manager_cb_t)stroke_log, &info); - return; - } - - } - iterator->destroy(iterator); - DBG1(DBG_CFG, "no such SA found"); -} - -/** - * Add a ca information record to the cainfo list - */ -static void stroke_add_ca(stroke_msg_t *msg, FILE *out) -{ - x509_t *cacert; - ca_info_t *ca_info; - - pop_string(msg, &msg->add_ca.name); - pop_string(msg, &msg->add_ca.cacert); - pop_string(msg, &msg->add_ca.crluri); - pop_string(msg, &msg->add_ca.crluri2); - pop_string(msg, &msg->add_ca.ocspuri); - pop_string(msg, &msg->add_ca.ocspuri2); - - DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name); - - DBG2(DBG_CFG, "ca %s", msg->add_ca.name); - DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert); - DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri); - DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2); - DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri); - DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2); - - if (msg->add_ca.cacert == NULL) - { - DBG1(DBG_CFG, "missing cacert parameter\n"); - return; - } - - cacert = load_ca_certificate(msg->add_ca.cacert); - - if (cacert == NULL) - { - return; - } - ca_info = ca_info_create(msg->add_ca.name, cacert); - - if (msg->add_ca.crluri) - { - chunk_t uri = { msg->add_ca.crluri, strlen(msg->add_ca.crluri) }; - - ca_info->add_crluri(ca_info, uri); - } - if (msg->add_ca.crluri2) - { - chunk_t uri = { msg->add_ca.crluri2, strlen(msg->add_ca.crluri2) }; - - ca_info->add_crluri(ca_info, uri); - } - if (msg->add_ca.ocspuri) - { - chunk_t uri = { msg->add_ca.ocspuri, strlen(msg->add_ca.ocspuri) }; - - ca_info->add_ocspuri(ca_info, uri); - } - if (msg->add_ca.ocspuri2) - { - chunk_t uri = { msg->add_ca.ocspuri2, strlen(msg->add_ca.ocspuri2) }; - - ca_info->add_ocspuri(ca_info, uri); - } - charon->credentials->add_ca_info(charon->credentials, ca_info); - DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name); - -} - -/** - * Delete a ca information record from the cainfo list - */ -static void stroke_del_ca(stroke_msg_t *msg, FILE *out) -{ - status_t status; - - pop_string(msg, &(msg->del_ca.name)); - DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name); - - status = charon->credentials->release_ca_info(charon->credentials, - msg->del_ca.name); - - if (status == SUCCESS) - { - fprintf(out, "deleted ca '%s'\n", msg->del_ca.name); - } - else - { - fprintf(out, "no ca named '%s'\n", msg->del_ca.name); - } -} - -/** - * log an IKE_SA to out - */ -static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) -{ - ike_sa_id_t *id = ike_sa->get_id(ike_sa); - u_int32_t rekey, reauth; - - fprintf(out, "%12s[%d]: %N, %H[%D]...%H[%D]\n", - ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), - ike_sa_state_names, ike_sa->get_state(ike_sa), - ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa), - ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa)); - - if (all) - { - fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s", - ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), - id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "", - id->get_responder_spi(id), id->is_initiator(id) ? "" : "*"); - - rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY_TIME); - reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH_TIME); - if (rekey) - { - fprintf(out, ", rekeying in %V", &rekey); - } - if (reauth) - { - fprintf(out, ", reauthentication in %V", &reauth); - } - if (!rekey && !reauth) - { - fprintf(out, ", rekeying disabled"); - } - fprintf(out, "\n"); - } -} - -/** - * log an CHILD_SA to out - */ -static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) -{ - u_int32_t rekey, now = time(NULL); - u_int32_t use_in, use_out, use_fwd; - encryption_algorithm_t encr_alg; - integrity_algorithm_t int_alg; - size_t encr_len, int_len; - mode_t mode; - - child_sa->get_stats(child_sa, &mode, &encr_alg, &encr_len, - &int_alg, &int_len, &rekey, &use_in, &use_out, - &use_fwd); - - fprintf(out, "%12s{%d}: %N, %N", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), - child_sa_state_names, child_sa->get_state(child_sa), - mode_names, mode); - - if (child_sa->get_state(child_sa) == CHILD_INSTALLED) - { - fprintf(out, ", %N SPIs: %.8x_i %.8x_o", - protocol_id_names, child_sa->get_protocol(child_sa), - htonl(child_sa->get_spi(child_sa, TRUE)), - htonl(child_sa->get_spi(child_sa, FALSE))); - - if (all) - { - fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa), - child_sa->get_reqid(child_sa)); - - - if (child_sa->get_protocol(child_sa) == PROTO_ESP) - { - fprintf(out, "%N", encryption_algorithm_names, encr_alg); - - if (encr_len) - { - fprintf(out, "-%d", encr_len); - } - fprintf(out, "/"); - } - - fprintf(out, "%N", integrity_algorithm_names, int_alg); - if (int_len) - { - fprintf(out, "-%d", int_len); - } - fprintf(out, ", rekeying "); - - if (rekey) - { - fprintf(out, "in %#V", &now, &rekey); - } - else - { - fprintf(out, "disabled"); - } - - fprintf(out, ", last use: "); - use_in = max(use_in, use_fwd); - if (use_in) - { - fprintf(out, "%ds_i ", now - use_in); - } - else - { - fprintf(out, "no_i "); - } - if (use_out) - { - fprintf(out, "%ds_o ", now - use_out); - } - else - { - fprintf(out, "no_o "); - } - } - } - - fprintf(out, "\n%12s{%d}: %#R=== %#R\n", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); -} - -/** - * show status of daemon - */ -static void stroke_status(stroke_msg_t *msg, FILE *out, bool all) -{ - iterator_t *iterator, *children; - host_t *host; - peer_cfg_t *peer_cfg; - ike_cfg_t *ike_cfg; - child_cfg_t *child_cfg; - ike_sa_t *ike_sa; - char *name = NULL; - - if (msg->status.name) - { - pop_string(msg, &(msg->status.name)); - name = msg->status.name; - } - - if (all) - { - leak_detective_status(out); - - fprintf(out, "Performance:\n"); - fprintf(out, " worker threads: %d idle of %d,", - charon->processor->get_idle_threads(charon->processor), - charon->processor->get_total_threads(charon->processor)); - fprintf(out, " job queue load: %d,", - charon->processor->get_job_load(charon->processor)); - fprintf(out, " scheduled events: %d\n", - charon->scheduler->get_job_load(charon->scheduler)); - iterator = charon->kernel_interface->create_address_iterator( - charon->kernel_interface); - fprintf(out, "Listening IP addresses:\n"); - while (iterator->iterate(iterator, (void**)&host)) - { - fprintf(out, " %H\n", host); - } - iterator->destroy(iterator); - - fprintf(out, "Connections:\n"); - iterator = charon->backends->create_iterator(charon->backends); - while (iterator->iterate(iterator, (void**)&peer_cfg)) - { - if (peer_cfg->get_ike_version(peer_cfg) != 2 || - (name && !streq(name, peer_cfg->get_name(peer_cfg)))) - { - continue; - } - - ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - fprintf(out, "%12s: %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg), - ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg), - ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg)); - { - identification_t *my_ca = peer_cfg->get_my_ca(peer_cfg); - identification_t *other_ca = peer_cfg->get_other_ca(peer_cfg); - linked_list_t *groups = peer_cfg->get_groups(peer_cfg); - - if (my_ca->get_type(my_ca) != ID_ANY - || other_ca->get_type(other_ca) != ID_ANY) - { - fprintf(out, "%12s: CAs: '%D'...'%D'\n", peer_cfg->get_name(peer_cfg), - my_ca, other_ca); - } - if (groups->get_count(groups) > 0) - { - fprintf(out, "%12s: groups: ", peer_cfg->get_name(peer_cfg)); - ietfAttr_list_list(groups, out); - fprintf(out, "\n"); - } - - } - children = peer_cfg->create_child_cfg_iterator(peer_cfg); - while (children->iterate(children, (void**)&child_cfg)) - { - linked_list_t *my_ts, *other_ts; - my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); - other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL); - fprintf(out, "%12s: %#R=== %#R\n", child_cfg->get_name(child_cfg), - my_ts, other_ts); - my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); - other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); - } - children->destroy(children); - } - iterator->destroy(iterator); - } - - iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager); - if (all && iterator->get_count(iterator) > 0) - { - fprintf(out, "Security Associations:\n"); - } - while (iterator->iterate(iterator, (void**)&ike_sa)) - { - bool ike_printed = FALSE; - child_sa_t *child_sa; - iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa); - - if (name == NULL || streq(name, ike_sa->get_name(ike_sa))) - { - log_ike_sa(out, ike_sa, all); - ike_printed = TRUE; - } - - while (children->iterate(children, (void**)&child_sa)) - { - if (name == NULL || streq(name, child_sa->get_name(child_sa))) - { - if (!ike_printed) - { - log_ike_sa(out, ike_sa, all); - ike_printed = TRUE; - } - log_child_sa(out, child_sa, all); - } - } - children->destroy(children); - } - iterator->destroy(iterator); -} - -/** - * list all authority certificates matching a specified flag - */ -static void list_auth_certificates(u_int flag, const char *label, - bool utc, FILE *out) -{ - bool first = TRUE; - x509_t *cert; - - iterator_t *iterator = charon->credentials->create_auth_cert_iterator(charon->credentials); - - while (iterator->iterate(iterator, (void**)&cert)) - { - if (cert->has_authority_flag(cert, flag)) - { - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of X.509 %s Certificates:\n", label); - fprintf(out, "\n"); - first = FALSE; - } - cert->list(cert, out, utc); - fprintf(out, "\n"); - } - } - iterator->destroy(iterator); -} - -/** - * list various information - */ -static void stroke_list(stroke_msg_t *msg, FILE *out) -{ - iterator_t *iterator; - - if (msg->list.flags & LIST_CERTS) - { - x509_t *cert; - - iterator = charon->credentials->create_cert_iterator(charon->credentials); - if (iterator->get_count(iterator)) - { - fprintf(out, "\n"); - fprintf(out, "List of X.509 End Entity Certificates:\n"); - fprintf(out, "\n"); - } - while (iterator->iterate(iterator, (void**)&cert)) - { - cert->list(cert, out, msg->list.utc); - if (charon->credentials->has_rsa_private_key( - charon->credentials, cert->get_public_key(cert))) - { - fprintf(out, ", has private key"); - } - fprintf(out, "\n"); - - } - iterator->destroy(iterator); - } - if (msg->list.flags & LIST_CACERTS) - { - list_auth_certificates(AUTH_CA, "CA", msg->list.utc, out); - } - if (msg->list.flags & LIST_OCSPCERTS) - { - list_auth_certificates(AUTH_OCSP, "OCSP", msg->list.utc, out); - } - if (msg->list.flags & LIST_AACERTS) - { - list_auth_certificates(AUTH_AA, "AA", msg->list.utc, out); - } - if (msg->list.flags & LIST_ACERTS) - { - x509ac_t *cert; - - iterator = charon->credentials->create_acert_iterator(charon->credentials); - if (iterator->get_count(iterator)) - { - fprintf(out, "\n"); - fprintf(out, "List of X.509 Attribute Certificates:\n"); - fprintf(out, "\n"); - } - while (iterator->iterate(iterator, (void**)&cert)) - { - cert->list(cert, out, msg->list.utc); - } - iterator->destroy(iterator); - } - if (msg->list.flags & LIST_CAINFOS) - { - ca_info_t *ca_info; - bool first = TRUE; - - iterator = charon->credentials->create_cainfo_iterator(charon->credentials); - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->is_ca(ca_info)) - { - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of X.509 CA Information Records:\n"); - fprintf(out, "\n"); - first = FALSE; - } - ca_info->list(ca_info, out, msg->list.utc); - } - } - iterator->destroy(iterator); - } - if (msg->list.flags & LIST_CRLS) - { - ca_info_t *ca_info; - bool first = TRUE; - - iterator = charon->credentials->create_cainfo_iterator(charon->credentials); - while (iterator->iterate(iterator, (void **)&ca_info)) - { - if (ca_info->is_ca(ca_info) && ca_info->has_crl(ca_info)) - { - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of X.509 CRLs:\n"); - fprintf(out, "\n"); - first = FALSE; - } - ca_info->list_crl(ca_info, out, msg->list.utc); - } - } - iterator->destroy(iterator); - } - if (msg->list.flags & LIST_OCSP) - { - ca_info_t *ca_info; - bool first = TRUE; - - iterator = charon->credentials->create_cainfo_iterator(charon->credentials); - while (iterator->iterate(iterator, (void **)&ca_info)) - { - if (ca_info->is_ca(ca_info) && ca_info->has_certinfos(ca_info)) - { - if (first) - { - fprintf(out, "\n"); - fprintf(out, "List of OCSP responses:\n"); - first = FALSE; - } - fprintf(out, "\n"); - ca_info->list_certinfos(ca_info, out, msg->list.utc); - } - } - iterator->destroy(iterator); - } -} - -/** - * reread various information - */ -static void stroke_reread(stroke_msg_t *msg, FILE *out) -{ - if (msg->reread.flags & REREAD_SECRETS) - { - charon->credentials->load_secrets(charon->credentials, TRUE); - } - if (msg->reread.flags & REREAD_CACERTS) - { - charon->credentials->load_ca_certificates(charon->credentials); - } - if (msg->reread.flags & REREAD_OCSPCERTS) - { - charon->credentials->load_ocsp_certificates(charon->credentials); - } - if (msg->reread.flags & REREAD_AACERTS) - { - charon->credentials->load_aa_certificates(charon->credentials); - } - if (msg->reread.flags & REREAD_ACERTS) - { - charon->credentials->load_attr_certificates(charon->credentials); - } - if (msg->reread.flags & REREAD_CRLS) - { - charon->credentials->load_crls(charon->credentials); - } -} - -/** - * purge various information - */ -static void stroke_purge(stroke_msg_t *msg, FILE *out) -{ - if (msg->purge.flags & PURGE_OCSP) - { - iterator_t *iterator = charon->credentials->create_cainfo_iterator(charon->credentials); - ca_info_t *ca_info; - - while (iterator->iterate(iterator, (void**)&ca_info)) - { - if (ca_info->is_ca(ca_info)) - { - ca_info->purge_ocsp(ca_info); - } - } - iterator->destroy(iterator); - } -} - -signal_t get_signal_from_logtype(char *type) -{ - if (strcasecmp(type, "any") == 0) return SIG_ANY; - else if (strcasecmp(type, "mgr") == 0) return DBG_MGR; - else if (strcasecmp(type, "ike") == 0) return DBG_IKE; - else if (strcasecmp(type, "chd") == 0) return DBG_CHD; - else if (strcasecmp(type, "job") == 0) return DBG_JOB; - else if (strcasecmp(type, "cfg") == 0) return DBG_CFG; - else if (strcasecmp(type, "knl") == 0) return DBG_KNL; - else if (strcasecmp(type, "net") == 0) return DBG_NET; - else if (strcasecmp(type, "enc") == 0) return DBG_ENC; - else if (strcasecmp(type, "lib") == 0) return DBG_LIB; - else return -1; -} - -/** - * set the verbosity debug output - */ -static void stroke_loglevel(stroke_msg_t *msg, FILE *out) -{ - signal_t signal; - - pop_string(msg, &(msg->loglevel.type)); - DBG1(DBG_CFG, "received stroke: loglevel %d for %s", - msg->loglevel.level, msg->loglevel.type); - - signal = get_signal_from_logtype(msg->loglevel.type); - if (signal < 0) - { - fprintf(out, "invalid type (%s)!\n", msg->loglevel.type); - return; - } - - charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level); - charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level); -} - -/** - * process a stroke request from the socket pointed by "fd" - */ -static job_requeue_t stroke_process(int *fdp) -{ - stroke_msg_t *msg; - u_int16_t msg_length; - ssize_t bytes_read; - FILE *out; - int strokefd = *fdp; - - /* peek the length */ - bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK); - if (bytes_read != sizeof(msg_length)) - { - DBG1(DBG_CFG, "reading length of stroke message failed: %s", - strerror(errno)); - close(strokefd); - return JOB_REQUEUE_NONE; - } - - /* read message */ - msg = malloc(msg_length); - bytes_read = recv(strokefd, msg, msg_length, 0); - if (bytes_read != msg_length) - { - DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno)); - close(strokefd); - return JOB_REQUEUE_NONE; - } - - out = fdopen(strokefd, "w"); - if (out == NULL) - { - DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno)); - close(strokefd); - free(msg); - return JOB_REQUEUE_NONE; - } - - DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length); - - /* the stroke_* functions are blocking, as they listen on the bus. Add - * cancellation handlers. */ - pthread_cleanup_push((void*)fclose, out); - pthread_cleanup_push(free, msg); - - switch (msg->type) - { - case STR_INITIATE: - stroke_initiate(msg, out); - break; - case STR_ROUTE: - stroke_route(msg, out); - break; - case STR_UNROUTE: - stroke_unroute(msg, out); - break; - case STR_TERMINATE: - stroke_terminate(msg, out); - break; - case STR_STATUS: - stroke_status(msg, out, FALSE); - break; - case STR_STATUS_ALL: - stroke_status(msg, out, TRUE); - break; - case STR_ADD_CONN: - stroke_add_conn(msg, out); - break; - case STR_DEL_CONN: - stroke_del_conn(msg, out); - break; - case STR_ADD_CA: - stroke_add_ca(msg, out); - break; - case STR_DEL_CA: - stroke_del_ca(msg, out); - break; - case STR_LOGLEVEL: - stroke_loglevel(msg, out); - break; - case STR_LIST: - stroke_list(msg, out); - break; - case STR_REREAD: - stroke_reread(msg, out); - break; - case STR_PURGE: - stroke_purge(msg, out); - break; - default: - DBG1(DBG_CFG, "received unknown stroke"); - } - /* remove and execute cancellation handlers */ - pthread_cleanup_pop(1); - pthread_cleanup_pop(1); - - return JOB_REQUEUE_NONE; -} - -/** - * Implementation of private_stroke_interface_t.stroke_receive. - */ -static job_requeue_t stroke_receive(private_stroke_interface_t *this) -{ - struct sockaddr_un strokeaddr; - int strokeaddrlen = sizeof(strokeaddr); - int strokefd, *fdp; - int oldstate; - callback_job_t *job; - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen); - pthread_setcancelstate(oldstate, NULL); - - if (strokefd < 0) - { - DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno)); - return JOB_REQUEUE_FAIR; - } - - fdp = malloc_thing(int); - *fdp = strokefd; - job = callback_job_create((callback_job_cb_t)stroke_process, fdp, free, this->job); - charon->processor->queue_job(charon->processor, (job_t*)job); - - return JOB_REQUEUE_FAIR; -} - -/** - * Implementation of interface_t.destroy. - */ -static void destroy(private_stroke_interface_t *this) -{ - this->job->cancel(this->job); - free(this); -} - -/* - * Described in header-file - */ -interface_t *interface_create() -{ - struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET}; - private_stroke_interface_t *this = malloc_thing(private_stroke_interface_t); - mode_t old; - - /* public functions */ - this->public.interface.destroy = (void (*)(interface_t*))destroy; - - /* set up unix socket */ - this->socket = socket(AF_UNIX, SOCK_STREAM, 0); - if (this->socket == -1) - { - DBG1(DBG_CFG, "could not create stroke socket"); - free(this); - return NULL; - } - - unlink(socket_addr.sun_path); - old = umask(~(S_IRWXU | S_IRWXG)); - if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0) - { - DBG1(DBG_CFG, "could not bind stroke socket: %s", strerror(errno)); - close(this->socket); - free(this); - return NULL; - } - umask(old); - if (chown(socket_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0) - { - DBG1(DBG_CFG, "changing stroke socket permissions failed: %s", - strerror(errno)); - } - - if (listen(this->socket, 0) < 0) - { - DBG1(DBG_CFG, "could not listen on stroke socket: %s", strerror(errno)); - close(this->socket); - unlink(socket_addr.sun_path); - free(this); - return NULL; - } - - this->job = callback_job_create((callback_job_cb_t)stroke_receive, - this, NULL, NULL); - charon->processor->queue_job(charon->processor, (job_t*)this->job); - - return &this->public.interface; -} - diff --git a/src/charon/credentials/auth_info.c b/src/charon/credentials/auth_info.c new file mode 100644 index 000000000..cd748bc97 --- /dev/null +++ b/src/charon/credentials/auth_info.c @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2007 Martin Willi + * 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. + * + * $Id: auth_info.c 3838 2008-04-18 11:24:45Z tobias $ + */ + + +#include "auth_info.h" + +#include <daemon.h> +#include <utils/linked_list.h> +#include <utils/identification.h> +#include <credentials/certificates/certificate.h> + +ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP, + "AUTHN_CA_CERT", + "AUTHN_CA_CERT_KEYID", + "AUTHN_CA_CERT_NAME", + "AUTHN_IM_CERT", + "AUTHN_SUBJECT_CERT", + "AUTHN_IM_HASH_URL", + "AUTHN_SUBJECT_HASH_URL", + "AUTHZ_PUBKEY", + "AUTHZ_PSK", + "AUTHZ_EAP", + "AUTHZ_CA_CERT", + "AUTHZ_CA_CERT_NAME", + "AUTHZ_IM_CERT", + "AUTHZ_SUBJECT_CERT", + "AUTHZ_CRL_VALIDATION", + "AUTHZ_OCSP_VALIDATION", + "AUTHZ_AC_GROUP", +); + +typedef struct private_auth_info_t private_auth_info_t; + +/** + * private data of item_set + */ +struct private_auth_info_t { + + /** + * public functions + */ + auth_info_t public; + + /** + * list of item_t's + */ + linked_list_t *items; +}; + +typedef struct item_t item_t; + +struct item_t { + /** type of this item */ + auth_item_t type; + /** associated privlege value, if any */ + void *value; +}; + +/** + * enumerator for auth_info_wrapper_t.create_cert_enumerator() + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** inner enumerator from linked_list_t */ + enumerator_t *inner; + /** the current item */ + item_t *item; +} item_enumerator_t; + +/** + * enumerate function for item_enumerator_t + */ +static bool enumerate(item_enumerator_t *this, auth_item_t *type, void **value) +{ + if (this->inner->enumerate(this->inner, &this->item)) + { + *type = this->item->type; + *value = this->item->value; + return TRUE; + } + return FALSE; +} + +/** + * destroy function for item_enumerator_t + */ +static void item_enumerator_destroy(item_enumerator_t *this) +{ + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of auth_info_t.create_item_enumerator. + */ +static enumerator_t* create_item_enumerator(private_auth_info_t *this) +{ + item_enumerator_t *enumerator; + + enumerator = malloc_thing(item_enumerator_t); + enumerator->item = NULL; + enumerator->inner = this->items->create_enumerator(this->items); + enumerator->public.enumerate = (void*)enumerate; + enumerator->public.destroy = (void*)item_enumerator_destroy; + return &enumerator->public; +} + +static void destroy_item_value(item_t *item); + +/** + * Implementation of auth_info_t.replace_item. + */ +static void replace_item(item_enumerator_t *enumerator, auth_item_t type, void *value) +{ + destroy_item_value(enumerator->item); + enumerator->item->type = type; + enumerator->item->value = value; +} + +/** + * Implementation of auth_info_t.get_item. + */ +static bool get_item(private_auth_info_t *this, auth_item_t type, void** value) +{ + enumerator_t *enumerator; + void *current_value; + auth_item_t current_type; + bool found = FALSE; + + enumerator = create_item_enumerator(this); + while (enumerator->enumerate(enumerator, ¤t_type, ¤t_value)) + { + if (type == current_type) + { + *value = current_value; + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * Implementation of auth_info_t.add_item. + */ +static void add_item(private_auth_info_t *this, auth_item_t type, void *value) +{ + item_t *item = malloc_thing(item_t); + + item->type = type; + switch (type) + { + case AUTHZ_PUBKEY: + { + public_key_t *key = (public_key_t*)value; + + item->value = key->get_ref(key); + break; + } + case AUTHZ_PSK: + { + shared_key_t *key = (shared_key_t*)value; + + item->value = key->get_ref(key); + break; + } + case AUTHN_IM_HASH_URL: + case AUTHN_SUBJECT_HASH_URL: + { + item->value = strdup(value); + break; + } + case AUTHN_CA_CERT: + case AUTHN_IM_CERT: + case AUTHN_SUBJECT_CERT: + case AUTHZ_CA_CERT: + case AUTHZ_IM_CERT: + case AUTHZ_SUBJECT_CERT: + { + certificate_t *cert = (certificate_t*)value; + + item->value = cert->get_ref(cert); + break; + } + case AUTHZ_CRL_VALIDATION: + case AUTHZ_OCSP_VALIDATION: + { + cert_validation_t *validation = malloc_thing(cert_validation_t); + + *validation = *(cert_validation_t*)value; + item->value = validation; + break; + } + case AUTHZ_EAP: + { + eap_method_t *method = malloc_thing(eap_method_t); + + *method = *(eap_method_t*)value; + item->value = method; + break; + } + case AUTHN_CA_CERT_KEYID: + case AUTHN_CA_CERT_NAME: + case AUTHZ_CA_CERT_NAME: + case AUTHZ_AC_GROUP: + { + identification_t *id = (identification_t*)value; + + item->value = id->clone(id); + break; + } + } + this->items->insert_last(this->items, item); +} + + +/** + * Implementation of auth_info_t.complies. + */ +static bool complies(private_auth_info_t *this, auth_info_t *constraints) +{ + enumerator_t *enumerator; + bool success = TRUE; + auth_item_t t1, t2; + void *value; + + enumerator = constraints->create_item_enumerator(constraints); + while (enumerator->enumerate(enumerator, &t1, &value)) + { + switch (t1) + { + case AUTHN_CA_CERT_KEYID: + case AUTHN_CA_CERT: + case AUTHN_CA_CERT_NAME: + case AUTHN_IM_CERT: + case AUTHN_SUBJECT_CERT: + case AUTHN_IM_HASH_URL: + case AUTHN_SUBJECT_HASH_URL: + { /* skip non-authorization tokens */ + continue; + } + case AUTHZ_CRL_VALIDATION: + case AUTHZ_OCSP_VALIDATION: + { + cert_validation_t *valid; + + /* OCSP validation is also sufficient for CRL constraint, but + * not vice-versa */ + if (!get_item(this, t1, (void**)&valid) && + t1 == AUTHZ_CRL_VALIDATION && + !get_item(this, AUTHZ_OCSP_VALIDATION, (void**)&valid)) + { + DBG1(DBG_CFG, "constraint check failed: %N requires at " + "least %N, but no check done", auth_item_names, t1, + cert_validation_names, *(cert_validation_t*)value); + success = FALSE; + break; + } + switch (*(cert_validation_t*)value) + { + case VALIDATION_SKIPPED: + if (*valid == VALIDATION_SKIPPED) + { + break; + } /* FALL */ + case VALIDATION_GOOD: + if (*valid == VALIDATION_GOOD) + { + break; + } /* FALL */ + default: + DBG1(DBG_CFG, "constraint check failed: %N is %N, but " + "requires at least %N", auth_item_names, t1, + cert_validation_names, *valid, + cert_validation_names, *(cert_validation_t*)value); + success = FALSE; + break; + } + break; + } + case AUTHZ_CA_CERT: + { + enumerator_t *enumerator; + certificate_t *c1, *c2; + + c1 = (certificate_t*)value; + + success = FALSE; + enumerator = create_item_enumerator(this); + while (enumerator->enumerate(enumerator, &t2, &c2)) + { + if ((t2 == AUTHZ_CA_CERT || t2 == AUTHZ_IM_CERT) && + c1->equals(c1, c2)) + { + success = TRUE; + } + } + enumerator->destroy(enumerator); + if (!success) + { + DBG1(DBG_CFG, "constraint check failed: peer not " + "authenticated by CA '%D'.", c1->get_subject(c1)); + } + break; + } + case AUTHZ_CA_CERT_NAME: + { + enumerator_t *enumerator; + certificate_t *cert; + identification_t *id; + + id = (identification_t*)value; + success = FALSE; + enumerator = create_item_enumerator(this); + while (enumerator->enumerate(enumerator, &t2, &cert)) + { + if ((t2 == AUTHZ_CA_CERT || t2 == AUTHZ_IM_CERT) && + cert->has_subject(cert, id)) + { + success = TRUE; + } + } + enumerator->destroy(enumerator); + if (!success) + { + DBG1(DBG_CFG, "constraint check failed: peer not " + "authenticated by CA '%D'.", id); + } + break; + } + case AUTHZ_PUBKEY: + case AUTHZ_PSK: + case AUTHZ_IM_CERT: + case AUTHZ_SUBJECT_CERT: + case AUTHZ_EAP: + case AUTHZ_AC_GROUP: + { + DBG1(DBG_CFG, "constraint check %N not implemented!", + auth_item_names, t1); + success = FALSE; + break; + } + } + if (!success) + { + break; + } + } + enumerator->destroy(enumerator); + return success; +} + +/** + * Implementation of auth_info_t.merge. + */ +static void merge(private_auth_info_t *this, private_auth_info_t *other) +{ + item_t *item; + + while (other->items->remove_first(other->items, (void**)&item) == SUCCESS) + { + this->items->insert_last(this->items, item); + } +} + +/** + * Implementation of auth_info_t.equals. + */ +static bool equals(private_auth_info_t *this, private_auth_info_t *other) +{ + enumerator_t *e1, *e2; + item_t *i1, *i2; + bool equal = TRUE, found; + + e1 = this->items->create_enumerator(this->items); + while (e1->enumerate(e1, &i1)) + { + found = FALSE; + e2 = other->items->create_enumerator(other->items); + while (e2->enumerate(e2, &i2)) + { + if (i1->type == i2->type) + { + switch (i1->type) + { + case AUTHZ_CRL_VALIDATION: + case AUTHZ_OCSP_VALIDATION: + { + cert_validation_t c1, c2; + + c1 = *(cert_validation_t*)i1->value; + c2 = *(cert_validation_t*)i2->value; + + if (c1 == c2) + { + found = TRUE; + break; + } + continue; + } + case AUTHN_IM_HASH_URL: + case AUTHN_SUBJECT_HASH_URL: + { + if (streq(i1->value, i2->value)) + { + found = TRUE; + break; + } + continue; + } + case AUTHN_CA_CERT: + case AUTHN_IM_CERT: + case AUTHN_SUBJECT_CERT: + case AUTHZ_CA_CERT: + case AUTHZ_IM_CERT: + case AUTHZ_SUBJECT_CERT: + { + certificate_t *c1, *c2; + + c1 = (certificate_t*)i1->value; + c2 = (certificate_t*)i2->value; + + if (c1->equals(c1, c2)) + { + found = TRUE; + break; + } + continue; + } + case AUTHN_CA_CERT_KEYID: + case AUTHN_CA_CERT_NAME: + case AUTHZ_CA_CERT_NAME: + { + identification_t *c1, *c2; + + c1 = (identification_t*)i1->value; + c2 = (identification_t*)i2->value; + + if (c1->equals(c1, c2)) + { + found = TRUE; + break; + } + continue; + } + case AUTHZ_PUBKEY: + case AUTHZ_PSK: + case AUTHZ_EAP: + case AUTHZ_AC_GROUP: + /* TODO: implement value comparison */ + break; + } + break; + } + } + e2->destroy(e2); + if (!found) + { + equal = FALSE; + break; + } + } + e1->destroy(e1); + return equal; +} + +/** + * Destroy the value associated with an item + */ +static void destroy_item_value(item_t *item) +{ + switch (item->type) + { + case AUTHZ_PUBKEY: + { + public_key_t *key = (public_key_t*)item->value; + key->destroy(key); + break; + } + case AUTHZ_PSK: + { + shared_key_t *key = (shared_key_t*)item->value; + key->destroy(key); + break; + } + case AUTHN_CA_CERT: + case AUTHN_IM_CERT: + case AUTHN_SUBJECT_CERT: + case AUTHZ_CA_CERT: + case AUTHZ_IM_CERT: + case AUTHZ_SUBJECT_CERT: + { + certificate_t *cert = (certificate_t*)item->value; + cert->destroy(cert); + break; + } + case AUTHN_IM_HASH_URL: + case AUTHN_SUBJECT_HASH_URL: + case AUTHZ_CRL_VALIDATION: + case AUTHZ_OCSP_VALIDATION: + case AUTHZ_EAP: + { + free(item->value); + break; + } + case AUTHN_CA_CERT_KEYID: + case AUTHN_CA_CERT_NAME: + case AUTHZ_CA_CERT_NAME: + case AUTHZ_AC_GROUP: + { + identification_t *id = (identification_t*)item->value; + id->destroy(id); + break; + } + } +} + +/** + * Implementation of auth_info_t.destroy + */ +static void destroy(private_auth_info_t *this) +{ + item_t *item; + + while (this->items->remove_last(this->items, (void**)&item) == SUCCESS) + { + destroy_item_value(item); + free(item); + } + this->items->destroy(this->items); + free(this); +} + +/* + * see header file + */ +auth_info_t *auth_info_create() +{ + private_auth_info_t *this = malloc_thing(private_auth_info_t); + + this->public.add_item = (void(*)(auth_info_t*, auth_item_t type, void *value))add_item; + this->public.get_item = (bool(*)(auth_info_t*, auth_item_t type, void **value))get_item; + this->public.replace_item = (void(*)(enumerator_t*,auth_item_t,void*))replace_item; + this->public.create_item_enumerator = (enumerator_t*(*)(auth_info_t*))create_item_enumerator; + this->public.complies = (bool(*)(auth_info_t*, auth_info_t *))complies; + this->public.merge = (void(*)(auth_info_t*, auth_info_t *other))merge; + this->public.equals = (bool(*)(auth_info_t*, auth_info_t *other))equals; + this->public.destroy = (void(*)(auth_info_t*))destroy; + + this->items = linked_list_create(); + + return &this->public; +} + diff --git a/src/charon/credentials/auth_info.h b/src/charon/credentials/auth_info.h new file mode 100644 index 000000000..5fe2919f8 --- /dev/null +++ b/src/charon/credentials/auth_info.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2007 Martin Willi + * 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 auth_info auth_info + * @{ @ingroup ccredentials + */ + +#ifndef AUTH_INFO_H_ +#define AUTH_INFO_H_ + +#include <utils/enumerator.h> + +typedef struct auth_info_t auth_info_t; +typedef enum auth_item_t auth_item_t; + +/** + * Authentication/Authorization process helper item. + * + * For the authentication process, further information may be needed. These + * items are defined as auth_item_t and have a AUTHN prefix. + * The authentication process returns important data for the authorization + * process, these items are defined with a AUTHZ prefix. + * Authentication uses AUTHN items and creates AUTHZ items during authentication, + * authorization reads AUTHZ values to give out privileges. + * + * +---+ +---------------------+ + * | A | | A | + * | u | | u +-----------+ | + * | t | | t | Required | | + * | h | | h | auth_info | | + * | e | | o +-----------+ | + * | n | | r | | + * +-----------+ | t | | i | | + * | Provided | | i | | z V | + * | auth_info |--| c |-------------| a ----> match? ----|-------> + * +-----------+ | a | | t | + * | t | | i | + * | i | | o | + * | o | | n | + * | n | | | + * +---+ +---------------------+ + */ +enum auth_item_t { + + /* + * items provided to authentication process + */ + + /** CA certificate to use for authentication, value is certificate_t* */ + AUTHN_CA_CERT, + /** Keyid of a CA certificate to use, value is identification_t* */ + AUTHN_CA_CERT_KEYID, + /** subject DN of a CA certificate to use, value is identification_t* */ + AUTHN_CA_CERT_NAME, + /** intermediate certificate, value is certificate_t* */ + AUTHN_IM_CERT, + /** certificate for trustchain verification, value is certificate_t* */ + AUTHN_SUBJECT_CERT, + /** intermediate certificate supplied as hash and url */ + AUTHN_IM_HASH_URL, + /** end-entity certificate supplied as hash and url */ + AUTHN_SUBJECT_HASH_URL, + + /* + * item provided to authorization process + */ + + /** subject has been authenticated by public key, value is public_key_t* */ + AUTHZ_PUBKEY, + /** subject has ben authenticated using preshared secrets, value is shared_key_t* */ + AUTHZ_PSK, + /** subject has been authenticated using EAP, value is eap_method_t */ + AUTHZ_EAP, + /** certificate authority, value is certificate_t* */ + AUTHZ_CA_CERT, + /** subject DN of a certificate authority, value is identification_t* */ + AUTHZ_CA_CERT_NAME, + /** intermediate certificate in trustchain, value is certificate_t* */ + AUTHZ_IM_CERT, + /** subject certificate, value is certificate_t* */ + AUTHZ_SUBJECT_CERT, + /** result of a CRL validation, value is cert_validation_t */ + AUTHZ_CRL_VALIDATION, + /** result of a OCSP validation, value is cert_validation_t */ + AUTHZ_OCSP_VALIDATION, + /** subject is in attribute certificate group, value is identification_t* */ + AUTHZ_AC_GROUP, +}; + + +/** + * enum name for auth_item_t. + */ +extern enum_name_t *auth_item_names; + +/** + * The auth_info class contains auth_item_t's used for AA. + * + * A auth_info allows the separation of authentication and authorization. + */ +struct auth_info_t { + + /** + * Add an item to the set. + * + * @param type auth_info type + * @param value associated value to auth_info type, if any + */ + void (*add_item)(auth_info_t *this, auth_item_t type, void *value); + + /** + * Get an item. + * + * @param type auth_info type to get + * @param value pointer to a pointer receiving item + * @return bool if item has been found + */ + bool (*get_item)(auth_info_t *this, auth_item_t type, void **value); + + /** + * Replace an item. + * + * @param type new auth_info type + * @param value pointer to the new value + */ + void (*replace_item)(enumerator_t *this, auth_item_t type, void *value); + + /** + * Create an enumerator over all items. + * + * @return enumerator over (auth_item_t type, void *value) + */ + enumerator_t* (*create_item_enumerator)(auth_info_t *this); + + /** + * Check if this fulfills a set of required constraints. + * + * @param constraints required authorization infos + * @return TRUE if this complies with constraints + */ + bool (*complies)(auth_info_t *this, auth_info_t *constraints); + + /** + * Merge items from other into this. + * + * Items do not get cloned, but moved from other to this. + * + * @param other items to read for merge + */ + void (*merge)(auth_info_t *this, auth_info_t *other); + + /** + * Check two auth_infos for equality. + * + * @param other other item to compaire against this + * @return TRUE if auth infos identical + */ + bool (*equals)(auth_info_t *this, auth_info_t *other); + + /** + * Destroy a auth_info instance with all associated values. + */ + void (*destroy)(auth_info_t *this); +}; + +/** + * Create a auth_info instance. + */ +auth_info_t *auth_info_create(); + +#endif /* AUTH_INFO_H_ @}*/ diff --git a/src/charon/credentials/credential_manager.c b/src/charon/credentials/credential_manager.c new file mode 100644 index 000000000..251559141 --- /dev/null +++ b/src/charon/credentials/credential_manager.c @@ -0,0 +1,1540 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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. + * + * $Id: credential_manager.c 3953 2008-05-14 06:49:31Z martin $ + */ + +/* some clibs need it for rwlocks */ +#define _GNU_SOURCE +#include <pthread.h> + +#include "credential_manager.h" + +#include <daemon.h> +#include <utils/linked_list.h> +#include <credentials/sets/cert_cache.h> +#include <credentials/sets/auth_info_wrapper.h> +#include <credentials/sets/ocsp_response_wrapper.h> +#include <credentials/certificates/x509.h> +#include <credentials/certificates/crl.h> +#include <credentials/certificates/ocsp_request.h> +#include <credentials/certificates/ocsp_response.h> + +#define MAX_CA_LEVELS 6 + +typedef struct private_credential_manager_t private_credential_manager_t; + +/** + * private data of credential_manager + */ +struct private_credential_manager_t { + + /** + * public functions + */ + credential_manager_t public; + + /** + * list of credential sets + */ + linked_list_t *sets; + + /** + * thread local set of credentials, linked_list_t with credential_set_t's + */ + pthread_key_t local_sets; + + /** + * trust relationship and certificate cache + */ + cert_cache_t *cache; + + /** + * read-write lock to sets list + */ + pthread_rwlock_t lock; +}; + +/** data to pass to create_private_enumerator */ +typedef struct { + private_credential_manager_t *this; + key_type_t type; + identification_t* keyid; +} private_data_t; + +/** data to pass to create_cert_enumerator */ +typedef struct { + private_credential_manager_t *this; + certificate_type_t cert; + key_type_t key; + identification_t *id; + bool trusted; +} cert_data_t; + +/** data to pass to create_cdp_enumerator */ +typedef struct { + private_credential_manager_t *this; + certificate_type_t type; + identification_t *id; +} cdp_data_t; + +/** data to pass to create_shared_enumerator */ +typedef struct { + private_credential_manager_t *this; + shared_key_type_t type; + identification_t *me; + identification_t *other; +} shared_data_t; + +/** enumerator over local and global sets */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** enumerator over global sets */ + enumerator_t *global; + /** enumerator over local sets */ + enumerator_t *local; +} sets_enumerator_t; + +/** + * destroy a sets_enumerator_t + */ +static void sets_enumerator_destroy(sets_enumerator_t *this) +{ + DESTROY_IF(this->global); + DESTROY_IF(this->local); + free(this); +} + +/** + * sets_enumerator_t.enumerate + */ +static bool sets_enumerator_enumerate(sets_enumerator_t *this, + credential_set_t **set) +{ + if (this->global) + { + if (this->global->enumerate(this->global, set)) + { + return TRUE; + } + /* end of global sets, look for local */ + this->global->destroy(this->global); + this->global = NULL; + } + if (this->local) + { + return this->local->enumerate(this->local, set); + } + return FALSE; +} + +/** + * create an enumerator over both, global and local sets + */ +static enumerator_t *create_sets_enumerator(private_credential_manager_t *this) +{ + linked_list_t *local; + sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t); + + enumerator->public.enumerate = (void*)sets_enumerator_enumerate; + enumerator->public.destroy = (void*)sets_enumerator_destroy; + enumerator->global = this->sets->create_enumerator(this->sets); + enumerator->local = NULL; + local = pthread_getspecific(this->local_sets); + if (local) + { + enumerator->local = local->create_enumerator(local); + } + return &enumerator->public; +} + +/** + * cleanup function for cert data + */ +static void destroy_cert_data(cert_data_t *data) +{ + pthread_rwlock_unlock(&data->this->lock); + free(data); +} + +/** + * enumerator constructor for certificates + */ +static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data) +{ + return set->create_cert_enumerator(set, data->cert, data->key, + data->id, data->trusted); +} + +/** + * Implementation of credential_manager_t.create_cert_enumerator. + */ +static enumerator_t *create_cert_enumerator(private_credential_manager_t *this, + certificate_type_t certificate, key_type_t key, + identification_t *id, bool trusted) +{ + cert_data_t *data = malloc_thing(cert_data_t); + data->this = this; + data->cert = certificate; + data->key = key; + data->id = id; + data->trusted = trusted; + + pthread_rwlock_rdlock(&this->lock); + return enumerator_create_nested(create_sets_enumerator(this), + (void*)create_cert, data, + (void*)destroy_cert_data); +} + +/** + * Implementation of credential_manager_t.get_cert. + */ +static certificate_t *get_cert(private_credential_manager_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + certificate_t *current, *found = NULL; + enumerator_t *enumerator; + + enumerator = create_cert_enumerator(this, cert, key, id, trusted); + if (enumerator->enumerate(enumerator, ¤t)) + { + /* TODO: best match? order by keyid, subject, sualtname */ + found = current->get_ref(current); + } + enumerator->destroy(enumerator); + return found; +} + + +/** + * cleanup function for cdp data + */ +static void destroy_cdp_data(cdp_data_t *data) +{ + pthread_rwlock_unlock(&data->this->lock); + free(data); +} + +/** + * enumerator constructor for CDPs + */ +static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data) +{ + return set->create_cdp_enumerator(set, data->type, data->id); +} +/** + * Implementation of credential_manager_t.create_cdp_enumerator. + */ +static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this, + certificate_type_t type, identification_t *id) +{ + cdp_data_t *data = malloc_thing(cdp_data_t); + data->this = this; + data->type = type; + data->id = id; + + pthread_rwlock_rdlock(&this->lock); + return enumerator_create_nested(create_sets_enumerator(this), + (void*)create_cdp, data, + (void*)destroy_cdp_data); +} + +/** + * cleanup function for private data + */ +static void destroy_private_data(private_data_t *data) +{ + pthread_rwlock_unlock(&data->this->lock); + free(data); +} + +/** + * enumerator constructor for private keys + */ +static enumerator_t *create_private(credential_set_t *set, private_data_t *data) +{ + return set->create_private_enumerator(set, data->type, data->keyid); +} + +/** + * Implementation of credential_manager_t.get_private_by_keyid. + */ +static enumerator_t* create_private_enumerator( + private_credential_manager_t *this, + key_type_t key, identification_t *keyid) +{ + private_data_t *data; + + data = malloc_thing(private_data_t); + data->this = this; + data->type = key; + data->keyid = keyid; + pthread_rwlock_rdlock(&this->lock); + return enumerator_create_nested(create_sets_enumerator(this), + (void*)create_private, data, + (void*)destroy_private_data); +} + +/** + * Implementation of credential_manager_t.get_private_by_keyid. + */ +static private_key_t *get_private_by_keyid(private_credential_manager_t *this, + key_type_t key, identification_t *keyid) +{ + private_key_t *found = NULL; + enumerator_t *enumerator; + + enumerator = create_private_enumerator(this, key, keyid); + if (enumerator->enumerate(enumerator, &found)) + { + found->get_ref(found); + } + enumerator->destroy(enumerator); + return found; +} + +/** + * cleanup function for shared data + */ +static void destroy_shared_data(shared_data_t *data) +{ + pthread_rwlock_unlock(&data->this->lock); + free(data); +} + +/** + * enumerator constructor for shared keys + */ +static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data) +{ + return set->create_shared_enumerator(set, data->type, data->me, data->other); +} + +/** + * Implementation of credential_manager_t.create_shared_enumerator. + */ +static enumerator_t *create_shared_enumerator(private_credential_manager_t *this, + shared_key_type_t type, + identification_t *me, identification_t *other) +{ + shared_data_t *data = malloc_thing(shared_data_t); + data->this = this; + data->type = type; + data->me = me; + data->other = other; + + pthread_rwlock_rdlock(&this->lock); + return enumerator_create_nested(create_sets_enumerator(this), + (void*)create_shared, data, + (void*)destroy_shared_data); +} + +/** + * Implementation of credential_manager_t.get_shared. + */ +static shared_key_t *get_shared(private_credential_manager_t *this, + shared_key_type_t type, identification_t *me, + identification_t *other) +{ + shared_key_t *current, *found = NULL; + id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE; + id_match_t *match_me, *match_other; + enumerator_t *enumerator; + + enumerator = create_shared_enumerator(this, type, me, other); + while (enumerator->enumerate(enumerator, ¤t, &match_me, &match_other)) + { + if (match_other > best_other || + (match_other == best_other && match_me > best_me)) + { + DESTROY_IF(found); + found = current->get_ref(current); + best_me = match_me; + best_other = match_other; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * add a credential set to the thread local list + */ +static void add_local_set(private_credential_manager_t *this, + credential_set_t *set) +{ + linked_list_t *sets; + + sets = pthread_getspecific(this->local_sets); + if (!sets) + { /* first invocation */ + sets = linked_list_create(); + pthread_setspecific(this->local_sets, sets); + } + sets->insert_last(sets, set); +} + +/** + * remove a credential set from the thread local list + */ +static void remove_local_set(private_credential_manager_t *this, + credential_set_t *set) +{ + linked_list_t *sets; + + sets = pthread_getspecific(this->local_sets); + sets->remove(sets, set, NULL); +} + +/** + * Implementation of credential_manager_t.cache_cert. + */ +static void cache_cert(private_credential_manager_t *this, certificate_t *cert) +{ + credential_set_t *set; + enumerator_t *enumerator; + + pthread_rwlock_rdlock(&this->lock); + enumerator = this->sets->create_enumerator(this->sets); + while (enumerator->enumerate(enumerator, &set)) + { + set->cache_cert(set, cert); + } + enumerator->destroy(enumerator); + pthread_rwlock_unlock(&this->lock); +} + +/** + * forward declaration + */ +static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this, + key_type_t type, identification_t *id, bool crl, bool ocsp); + +/** + * Do an OCSP request + */ +static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url, + certificate_t *subject, certificate_t *issuer) +{ + certificate_t *request, *response; + chunk_t send, receive; + + /* TODO: requestor name, signature */ + request = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST, + BUILD_CA_CERT, issuer->get_ref(issuer), + BUILD_CERT, subject->get_ref(subject), BUILD_END); + if (!request) + { + DBG1(DBG_CFG, "generating ocsp request failed"); + return NULL; + } + + send = request->get_encoding(request); + request->destroy(request); + + DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url); + if (lib->fetcher->fetch(lib->fetcher, url, &receive, + FETCH_REQUEST_DATA, send, + FETCH_REQUEST_TYPE, "application/ocsp-request", + FETCH_END) != SUCCESS) + { + DBG1(DBG_CFG, "ocsp request to %s failed", url); + chunk_free(&send); + return NULL; + } + chunk_free(&send); + + response = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE, + BUILD_BLOB_ASN1_DER, receive, BUILD_END); + if (!response) + { + DBG1(DBG_CFG, "parsing ocsp response failed"); + return NULL; + } + return response; +} + +/** + * check the signature of an OCSP response + */ +static bool verify_ocsp(private_credential_manager_t *this, + ocsp_response_t *response) +{ + certificate_t *issuer, *subject; + identification_t *responder; + ocsp_response_wrapper_t *wrapper; + enumerator_t *enumerator; + bool verified = FALSE; + + wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); + add_local_set(this, &wrapper->set); + + subject = &response->certificate; + responder = subject->get_issuer(subject); + enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE, FALSE); + while (enumerator->enumerate(enumerator, &issuer, NULL)) + { + if (this->cache->issued_by(this->cache, subject, issuer)) + { + DBG1(DBG_CFG, " ocsp response correctly signed by \"%D\"", + issuer->get_subject(issuer)); + verified = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + remove_local_set(this, &wrapper->set); + wrapper->destroy(wrapper); + return verified; +} + +/** + * Get the better of two OCSP responses, and check for usable OCSP info + */ +static certificate_t *get_better_ocsp(private_credential_manager_t *this, + certificate_t *cand, certificate_t *best, + x509_t *subject, x509_t *issuer, + cert_validation_t *valid, bool cache) +{ + ocsp_response_t *response; + time_t revocation, this_update, next_update, valid_until; + crl_reason_t reason; + bool revoked = FALSE; + + response = (ocsp_response_t*)cand; + + /* check ocsp signature */ + if (!verify_ocsp(this, response)) + { + DBG1(DBG_CFG, "ocsp response verification failed"); + cand->destroy(cand); + return best; + } + /* check if response contains our certificate */ + switch (response->get_status(response, subject, issuer, &revocation, &reason, + &this_update, &next_update)) + { + case VALIDATION_REVOKED: + /* subject has been revoked by a valid OCSP response */ + DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", + &revocation, crl_reason_names, reason); + revoked = TRUE; + break; + case VALIDATION_GOOD: + /* results in either good or stale */ + break; + default: + case VALIDATION_FAILED: + /* candidate unusable, does not contain our cert */ + DBG1(DBG_CFG, " ocsp response contains no status on our certificate"); + cand->destroy(cand); + return best; + } + + /* select the better of the two responses */ + if (best == NULL || cand->is_newer(cand, best)) + { + DESTROY_IF(best); + best = cand; + if (best->get_validity(best, NULL, NULL, &valid_until)) + { + DBG1(DBG_CFG, " ocsp response is valid: until %#T", + &valid_until, FALSE); + *valid = VALIDATION_GOOD; + if (cache) + { /* cache non-stale only, stale certs get refetched */ + cache_cert(this, best); + } + } + else + { + DBG1(DBG_CFG, " ocsp response is stale: since %#T", + &valid_until, FALSE); + *valid = VALIDATION_STALE; + } + } + else + { + *valid = VALIDATION_STALE; + cand->destroy(cand); + } + if (revoked) + { /* revoked always counts, even if stale */ + *valid = VALIDATION_REVOKED; + } + return best; +} + +/** + * validate a x509 certificate using OCSP + */ +static cert_validation_t check_ocsp(private_credential_manager_t *this, + x509_t *subject, x509_t *issuer, + auth_info_t *auth) +{ + enumerator_t *enumerator; + cert_validation_t valid = VALIDATION_SKIPPED; + certificate_t *best = NULL, *current; + identification_t *keyid = NULL; + public_key_t *public; + char *uri = NULL; + + /** lookup cache for valid OCSP responses */ + enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE, + KEY_ANY, NULL, FALSE); + while (enumerator->enumerate(enumerator, ¤t)) + { + current->get_ref(current); + best = get_better_ocsp(this, current, best, subject, issuer, + &valid, FALSE); + if (best && valid != VALIDATION_STALE) + { + DBG1(DBG_CFG, " using cached ocsp response"); + break; + } + } + enumerator->destroy(enumerator); + + /* derive the authorityKeyIdentifier from the issuer's public key */ + current = &issuer->interface; + public = current->get_public_key(current); + if (public) + { + keyid = public->get_id(public, ID_PUBKEY_SHA1); + } + /** fetch from configured OCSP responder URLs */ + if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) + { + enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid); + while (enumerator->enumerate(enumerator, &uri)) + { + current = fetch_ocsp(this, uri, &subject->interface, + &issuer->interface); + if (current) + { + best = get_better_ocsp(this, current, best, subject, issuer, + &valid, TRUE); + if (best && valid != VALIDATION_STALE) + { + break; + } + } + } + enumerator->destroy(enumerator); + } + DESTROY_IF(public); + + /* fallback to URL fetching from subject certificate's URIs */ + if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) + { + enumerator = subject->create_ocsp_uri_enumerator(subject); + while (enumerator->enumerate(enumerator, &uri)) + { + current = fetch_ocsp(this, uri, &subject->interface, + &issuer->interface); + if (current) + { + best = get_better_ocsp(this, current, best, subject, issuer, + &valid, TRUE); + if (best && valid != VALIDATION_STALE) + { + break; + } + } + } + enumerator->destroy(enumerator); + } + /* an uri was found, but no result. switch validation state to failed */ + if (valid == VALIDATION_SKIPPED && uri) + { + valid = VALIDATION_FAILED; + } + if (auth) + { + auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid); + } + DESTROY_IF(best); + return valid; +} + +/** + * fetch a CRL from an URL + */ +static certificate_t* fetch_crl(private_credential_manager_t *this, char *url) +{ + certificate_t *crl; + chunk_t chunk; + + DBG1(DBG_CFG, " fetching crl from '%s' ...", url); + if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS) + { + DBG1(DBG_CFG, "crl fetching failed"); + return NULL; + } + crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, + BUILD_BLOB_ASN1_DER, chunk, BUILD_END); + if (!crl) + { + DBG1(DBG_CFG, "crl fetched successfully but parsing failed"); + return NULL; + } + return crl; +} + +/** + * check the signature of an CRL + */ +static bool verify_crl(private_credential_manager_t *this, certificate_t *crl) +{ + certificate_t *issuer; + enumerator_t *enumerator; + bool verified = FALSE; + + enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl), + FALSE, FALSE); + while (enumerator->enumerate(enumerator, &issuer, NULL)) + { + if (this->cache->issued_by(this->cache, crl, issuer)) + { + DBG1(DBG_CFG, " crl correctly signed by \"%D\"", + issuer->get_subject(issuer)); + verified = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return verified; +} + +/** + * Get the better of two CRLs, and check for usable CRL info + */ +static certificate_t *get_better_crl(private_credential_manager_t *this, + certificate_t *cand, certificate_t *best, + x509_t *subject, x509_t *issuer, + cert_validation_t *valid, bool cache) +{ + enumerator_t *enumerator; + time_t revocation, valid_until; + crl_reason_t reason; + chunk_t serial; + crl_t *crl; + + /* check CRL signature */ + if (!verify_crl(this, cand)) + { + DBG1(DBG_CFG, "crl response verification failed"); + cand->destroy(cand); + return best; + } + + crl = (crl_t*)cand; + enumerator = crl->create_enumerator(crl); + while (enumerator->enumerate(enumerator, &serial, &revocation, &reason)) + { + if (chunk_equals(serial, subject->get_serial(subject))) + { + DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", + &revocation, crl_reason_names, reason); + *valid = VALIDATION_REVOKED; + enumerator->destroy(enumerator); + DESTROY_IF(best); + return cand; + } + } + enumerator->destroy(enumerator); + + /* select the better of the two CRLs */ + if (best == NULL || cand->is_newer(cand, best)) + { + DESTROY_IF(best); + best = cand; + if (best->get_validity(best, NULL, NULL, &valid_until)) + { + DBG1(DBG_CFG, " crl is valid: until %#T", &valid_until, FALSE); + *valid = VALIDATION_GOOD; + if (cache) + { /* we cache non-stale crls only, as a stale crls are refetched */ + cache_cert(this, best); + } + } + else + { + DBG1(DBG_CFG, " crl is stale: since %#T", &valid_until, FALSE); + *valid = VALIDATION_STALE; + } + } + else + { + *valid = VALIDATION_STALE; + cand->destroy(cand); + } + return best; +} + +/** + * validate a x509 certificate using CRL + */ +static cert_validation_t check_crl(private_credential_manager_t *this, + x509_t *subject, x509_t *issuer, + auth_info_t *auth) +{ + cert_validation_t valid = VALIDATION_SKIPPED; + identification_t *keyid = NULL; + certificate_t *best = NULL; + certificate_t *current; + public_key_t *public; + enumerator_t *enumerator; + char *uri; + + /* derive the authorityKeyIdentifier from the issuer's public key */ + current = &issuer->interface; + public = current->get_public_key(current); + if (public) + { + keyid = public->get_id(public, ID_PUBKEY_SHA1); + } + + /* find a cached crl by authorityKeyIdentifier */ + if (keyid) + { + enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY, + keyid, FALSE); + while (enumerator->enumerate(enumerator, ¤t)) + { + current->get_ref(current); + best = get_better_crl(this, current, best, subject, issuer, + &valid, FALSE); + if (best && valid != VALIDATION_STALE) + { + DBG1(DBG_CFG, " using cached crl"); + break; + } + } + enumerator->destroy(enumerator); + } + + /* fallback to fetching crls from credential sets cdps */ + if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) + { + enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid); + + while (enumerator->enumerate(enumerator, &uri)) + { + current = fetch_crl(this, uri); + if (current) + { + best = get_better_crl(this, current, best, subject, issuer, + &valid, TRUE); + if (best && valid != VALIDATION_STALE) + { + break; + } + } + } + enumerator->destroy(enumerator); + } + DESTROY_IF(public); + + /* fallback to fetching crls from cdps from subject's certificate */ + if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) + { + enumerator = subject->create_crl_uri_enumerator(subject); + + while (enumerator->enumerate(enumerator, &uri)) + { + current = fetch_crl(this, uri); + if (current) + { + best = get_better_crl(this, current, best, subject, issuer, + &valid, TRUE); + if (best && valid != VALIDATION_STALE) + { + break; + } + } + } + enumerator->destroy(enumerator); + } + + /* an uri was found, but no result. switch validation state to failed */ + if (valid == VALIDATION_SKIPPED && uri) + { + valid = VALIDATION_FAILED; + } + if (auth) + { + auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid); + } + DESTROY_IF(best); + return valid; +} + +/** + * check a certificate for its lifetime + */ +static bool check_certificate(private_credential_manager_t *this, + certificate_t *subject, certificate_t *issuer, + bool crl, bool ocsp, auth_info_t *auth) +{ + time_t not_before, not_after; + + if (!subject->get_validity(subject, NULL, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)", + ¬_before, ¬_after); + return FALSE; + } + if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", + ¬_before, ¬_after); + return FALSE; + } + if (issuer->get_type(issuer) == CERT_X509 && + subject->get_type(subject) == CERT_X509) + { + if (ocsp || crl) + { + DBG1(DBG_CFG, "checking certificate status of \"%D\"", + subject->get_subject(subject)); + } + if (ocsp) + { + switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth)) + { + case VALIDATION_GOOD: + DBG1(DBG_CFG, "certificate status is good"); + return TRUE; + case VALIDATION_REVOKED: + /* has already been logged */ + return FALSE; + case VALIDATION_SKIPPED: + DBG2(DBG_CFG, "ocsp check skipped, no ocsp found"); + break; + case VALIDATION_STALE: + DBG1(DBG_CFG, "ocsp information stale, fallback to crl"); + break; + case VALIDATION_FAILED: + DBG1(DBG_CFG, "ocsp check failed, fallback to crl"); + break; + } + } + if (crl) + { + switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth)) + { + case VALIDATION_GOOD: + DBG1(DBG_CFG, "certificate status is good"); + return TRUE; + case VALIDATION_REVOKED: + /* has already been logged */ + return FALSE; + case VALIDATION_FAILED: + case VALIDATION_SKIPPED: + DBG1(DBG_CFG, "certificate status is not available"); + break; + case VALIDATION_STALE: + DBG1(DBG_CFG, "certificate status is unknown, crl is stale"); + break; + } + } + } + return TRUE; +} + +/** + * Get a trusted certificate from a credential set + */ +static certificate_t *get_pretrusted_cert(private_credential_manager_t *this, + key_type_t type, identification_t *id) +{ + certificate_t *subject; + public_key_t *public; + + subject = get_cert(this, CERT_ANY, type, id, TRUE); + if (!subject) + { + return NULL; + } + public = subject->get_public_key(subject); + if (!public) + { + subject->destroy(subject); + return NULL; + } + public->destroy(public); + return subject; +} + +/** + * Get the issuing certificate of a subject certificate + */ +static certificate_t *get_issuer_cert(private_credential_manager_t *this, + certificate_t *subject, bool trusted) +{ + enumerator_t *enumerator; + certificate_t *issuer = NULL, *candidate; + + enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY, + subject->get_issuer(subject), trusted); + while (enumerator->enumerate(enumerator, &candidate)) + { + if (this->cache->issued_by(this->cache, subject, candidate)) + { + issuer = candidate->get_ref(candidate); + break; + } + } + enumerator->destroy(enumerator); + return issuer; +} + +/** + * try to verify the trust chain of subject, return TRUE if trusted + */ +static bool verify_trust_chain(private_credential_manager_t *this, + certificate_t *subject, auth_info_t *result, + bool trusted, bool crl, bool ocsp) +{ + certificate_t *current, *issuer; + auth_info_t *auth; + u_int level = 0; + + auth = auth_info_create(); + current = subject->get_ref(subject); + while (level++ < MAX_CA_LEVELS) + { + issuer = get_issuer_cert(this, current, TRUE); + if (issuer) + { + /* accept only self-signed CAs as trust anchor */ + if (this->cache->issued_by(this->cache, issuer, issuer)) + { + auth->add_item(auth, AUTHZ_CA_CERT, issuer); + DBG1(DBG_CFG, " using trusted ca certificate \"%D\"", + issuer->get_subject(issuer)); + trusted = TRUE; + } + else + { + auth->add_item(auth, AUTHZ_IM_CERT, issuer); + DBG1(DBG_CFG, " using trusted intermediate ca certificate " + "\"%D\"", issuer->get_subject(issuer)); + } + } + else + { + issuer = get_issuer_cert(this, current, FALSE); + if (issuer) + { + if (current->equals(current, issuer)) + { + DBG1(DBG_CFG, " self-signed certificate \"%D\" is not trusted", + current->get_subject(current)); + issuer->destroy(issuer); + break; + } + auth->add_item(auth, AUTHZ_IM_CERT, issuer); + DBG1(DBG_CFG, " using untrusted intermediate certificate " + "\"%D\"", issuer->get_subject(issuer)); + } + else + { + DBG1(DBG_CFG, "no issuer certificate found for \"%D\"", + current->get_subject(current)); + break; + } + } + if (!check_certificate(this, current, issuer, crl, ocsp, + current == subject ? auth : NULL)) + { + trusted = FALSE; + issuer->destroy(issuer); + break; + } + current->destroy(current); + current = issuer; + if (trusted) + { + break; + } + } + current->destroy(current); + if (level > MAX_CA_LEVELS) + { + DBG1(DBG_CFG, "maximum ca path length of %d levels reached", level); + } + if (trusted) + { + result->merge(result, auth); + } + auth->destroy(auth); + return trusted; +} + +/** + * enumerator for trusted certificates + */ +typedef struct { + /** implements enumerator_t interface */ + enumerator_t public; + /** enumerator over candidate peer certificates */ + enumerator_t *candidates; + /** reference to the credential_manager */ + private_credential_manager_t *this; + /** type of the requested key */ + key_type_t type; + /** identity the requested key belongs to */ + identification_t *id; + /** TRUE to do CRL checking */ + bool crl; + /** TRUE to do OCSP checking */ + bool ocsp; + /** pretrusted certificate we have served at first invocation */ + certificate_t *pretrusted; + /** currently enumerating auth info */ + auth_info_t *auth; +} trusted_enumerator_t; + +/** + * Implements trusted_enumerator_t.enumerate + */ +static bool trusted_enumerate(trusted_enumerator_t *this, + certificate_t **cert, auth_info_t **auth) +{ + certificate_t *current; + + DESTROY_IF(this->auth); + this->auth = auth_info_create(); + + if (!this->candidates) + { + /* first invocation, build enumerator for next one */ + this->candidates = create_cert_enumerator(this->this, CERT_ANY, + this->type, this->id, FALSE); + /* check if we have a trusted certificate for that peer */ + this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id); + if (this->pretrusted) + { + /* if we find a trusted self signed certificate, we just accept it. + * However, in order to fulfill authorization rules, we try to build + * the trust chain if it is not self signed */ + if (this->this->cache->issued_by(this->this->cache, + this->pretrusted, this->pretrusted) || + verify_trust_chain(this->this, this->pretrusted, this->auth, + TRUE, this->crl, this->ocsp)) + { + DBG1(DBG_CFG, " using trusted certificate \"%D\"", + this->pretrusted->get_subject(this->pretrusted)); + *cert = this->pretrusted; + if (auth) + { + *auth = this->auth; + } + return TRUE; + } + } + } + /* try to verify the trust chain for each certificate found */ + while (this->candidates->enumerate(this->candidates, ¤t)) + { + if (this->pretrusted && + this->pretrusted->equals(this->pretrusted, current)) + { /* skip pretrusted certificate we already served */ + continue; + } + + DBG1(DBG_CFG, " using certificate \"%D\"", + current->get_subject(current)); + if (verify_trust_chain(this->this, current, this->auth, FALSE, + this->crl, this->ocsp)) + { + *cert = current; + if (auth) + { + *auth = this->auth; + } + return TRUE; + } + } + return FALSE; +} + +/** + * Implements trusted_enumerator_t.destroy + */ +static void trusted_destroy(trusted_enumerator_t *this) +{ + DESTROY_IF(this->pretrusted); + DESTROY_IF(this->auth); + DESTROY_IF(this->candidates); + free(this); +} + +/** + * create an enumerator over trusted certificates and their trustchain + */ +static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this, + key_type_t type, identification_t *id, bool crl, bool ocsp) +{ + trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t); + + enumerator->public.enumerate = (void*)trusted_enumerate; + enumerator->public.destroy = (void*)trusted_destroy; + + enumerator->candidates = NULL; + enumerator->this = this; + enumerator->type = type; + enumerator->id = id; + enumerator->crl = crl; + enumerator->ocsp = ocsp; + enumerator->pretrusted = NULL; + enumerator->auth = NULL; + + return &enumerator->public; +} + +/** + * enumerator for public keys + */ +typedef struct { + /** implements enumerator_t interface */ + enumerator_t public; + /** enumerator over candidate peer certificates */ + enumerator_t *inner; + /** reference to the credential_manager */ + private_credential_manager_t *this; + /** currently enumerating key */ + public_key_t *current; + /** credset wrapper around auth */ + auth_info_wrapper_t *wrapper; +} public_enumerator_t; + +/** + * Implements public_enumerator_t.enumerate + */ +static bool public_enumerate(public_enumerator_t *this, + public_key_t **key, auth_info_t **auth) +{ + certificate_t *cert; + + while (this->inner->enumerate(this->inner, &cert, auth)) + { + DESTROY_IF(this->current); + this->current = cert->get_public_key(cert); + if (this->current) + { + *key = this->current; + return TRUE; + } + } + return FALSE; +} + +/** + * Implements public_enumerator_t.destroy + */ +static void public_destroy(public_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + if (this->wrapper) + { + remove_local_set(this->this, &this->wrapper->set); + this->wrapper->destroy(this->wrapper); + } + pthread_rwlock_unlock(&this->this->lock); + free(this); +} + +/** + * Implementation of credential_manager_t.create_public_enumerator. + */ +static enumerator_t* create_public_enumerator(private_credential_manager_t *this, + key_type_t type, identification_t *id, auth_info_t *auth) +{ + public_enumerator_t *enumerator = malloc_thing(public_enumerator_t); + + enumerator->public.enumerate = (void*)public_enumerate; + enumerator->public.destroy = (void*)public_destroy; + enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE); + enumerator->this = this; + enumerator->current = NULL; + enumerator->wrapper = NULL; + if (auth) + { + enumerator->wrapper = auth_info_wrapper_create(auth); + add_local_set(this, &enumerator->wrapper->set); + } + pthread_rwlock_rdlock(&this->lock); + return &enumerator->public; +} + +/** + * Check if a certificate's keyid is contained in the auth helper + */ +static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert) +{ + enumerator_t *enumerator; + identification_t *value; + auth_item_t type; + bool found = FALSE; + + enumerator = auth->create_item_enumerator(auth); + while (enumerator->enumerate(enumerator, &type, &value)) + { + if (type == AUTHN_CA_CERT && cert->equals(cert, (certificate_t*)value)) + { + found = TRUE; + break; + } + if (type == AUTHN_CA_CERT_KEYID) + { + public_key_t *public; + identification_t *certid, *keyid; + + public = cert->get_public_key(cert); + if (public) + { + keyid = (identification_t*)value; + certid = public->get_id(public, keyid->get_type(keyid)); + if (certid && certid->equals(certid, keyid)) + { + public->destroy(public); + found = TRUE; + break; + } + public->destroy(public); + } + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * build a trustchain from subject up to a trust anchor in trusted + */ +static auth_info_t *build_trustchain(private_credential_manager_t *this, + certificate_t *subject, auth_info_t *auth) +{ + certificate_t *issuer, *current; + auth_info_t *trustchain; + u_int level = 0; + + trustchain = auth_info_create(); + + if (!auth->get_item(auth, AUTHN_CA_CERT, (void**)¤t)) + { + /* no trust anchor specified, return this cert only */ + trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, subject); + return trustchain; + } + current = subject->get_ref(subject); + while (TRUE) + { + if (auth_contains_cacert(auth, current)) + { + trustchain->add_item(trustchain, AUTHZ_CA_CERT, current); + current->destroy(current); + return trustchain; + } + if (subject == current) + { + trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, current); + } + else + { + trustchain->add_item(trustchain, AUTHZ_IM_CERT, current); + } + issuer = get_issuer_cert(this, current, FALSE); + if (!issuer || issuer->equals(issuer, current) || level > MAX_CA_LEVELS) + { + DESTROY_IF(issuer); + current->destroy(current); + break; + } + current->destroy(current); + current = issuer; + level++; + } + trustchain->destroy(trustchain); + return NULL; +} + +/** + * find a private key of a give certificate + */ +static private_key_t *get_private_by_cert(private_credential_manager_t *this, + certificate_t *cert, key_type_t type) +{ + private_key_t *private = NULL; + identification_t* keyid; + public_key_t *public; + + public = cert->get_public_key(cert); + if (public) + { + keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1); + if (keyid) + { + private = get_private_by_keyid(this, type, keyid); + } + public->destroy(public); + } + return private; +} + +/** + * Implementation of credential_manager_t.get_private. + */ +static private_key_t *get_private(private_credential_manager_t *this, + key_type_t type, identification_t *id, + auth_info_t *auth) +{ + enumerator_t *enumerator; + certificate_t *cert; + private_key_t *private = NULL; + auth_info_t *trustchain; + + /* check if this is a lookup by key ID, and do it if so */ + if (id) + { + switch (id->get_type(id)) + { + case ID_PUBKEY_SHA1: + case ID_PUBKEY_INFO_SHA1: + case ID_KEY_ID: + return get_private_by_keyid(this, type, id); + default: + break; + } + } + + /* try to build a trustchain for each certificate found */ + enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); + while (enumerator->enumerate(enumerator, &cert)) + { + private = get_private_by_cert(this, cert, type); + if (private) + { + trustchain = build_trustchain(this, cert, auth); + if (trustchain) + { + auth->merge(auth, trustchain); + trustchain->destroy(trustchain); + break; + } + private->destroy(private); + private = NULL; + } + } + enumerator->destroy(enumerator); + /* if no valid trustchain was found, fall back to the first usable cert */ + if (!private) + { + enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); + while (enumerator->enumerate(enumerator, &cert)) + { + private = get_private_by_cert(this, cert, type); + if (private) + { + auth->add_item(auth, AUTHZ_SUBJECT_CERT, cert); + break; + } + } + enumerator->destroy(enumerator); + } + return private; +} + +/** + * Implementation of credential_manager_t.flush_cache. + */ +static void flush_cache(private_credential_manager_t *this, + certificate_type_t type) +{ + this->cache->flush(this->cache, type); +} + +/** + * Implementation of credential_manager_t.add_set. + */ +static void add_set(private_credential_manager_t *this, + credential_set_t *set) +{ + pthread_rwlock_wrlock(&this->lock); + this->sets->insert_last(this->sets, set); + pthread_rwlock_unlock(&this->lock); +} + +/** + * Implementation of credential_manager_t.remove_set. + */ +static void remove_set(private_credential_manager_t *this, credential_set_t *set) +{ + pthread_rwlock_wrlock(&this->lock); + this->sets->remove(this->sets, set, NULL); + pthread_rwlock_unlock(&this->lock); +} + +/** + * Implementation of credential_manager_t.destroy + */ +static void destroy(private_credential_manager_t *this) +{ + this->sets->remove(this->sets, this->cache, NULL); + this->sets->destroy(this->sets); + pthread_key_delete(this->local_sets); + this->cache->destroy(this->cache); + pthread_rwlock_destroy(&this->lock); + free(this); +} + +/* + * see header file + */ +credential_manager_t *credential_manager_create() +{ + private_credential_manager_t *this = malloc_thing(private_credential_manager_t); + + this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator; + this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator; + this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, certificate_type_t type, identification_t *id))create_cdp_enumerator; + this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert; + this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared; + this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_info_t*))get_private; + this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_info_t *aut))create_public_enumerator; + this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache; + this->public.cache_cert = (void(*)(credential_manager_t*, certificate_t *cert))cache_cert; + this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set; + this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set; + this->public.destroy = (void(*)(credential_manager_t*))destroy; + + this->sets = linked_list_create(); + pthread_key_create(&this->local_sets, (void*)this->sets->destroy); + this->cache = cert_cache_create(); + this->sets->insert_first(this->sets, this->cache); + pthread_rwlock_init(&this->lock, NULL); + + return &this->public; +} + diff --git a/src/charon/credentials/credential_manager.h b/src/charon/credentials/credential_manager.h new file mode 100644 index 000000000..3a64437e6 --- /dev/null +++ b/src/charon/credentials/credential_manager.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2007-2008 Martin Willi + * 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. + * + * $Id: credential_manager.h 3835 2008-04-18 10:11:41Z tobias $ + */ + +/** + * @defgroup credential_manager credential_manager + * @{ @ingroup ccredentials + */ + +#ifndef CREDENTIAL_MANAGER_H_ +#define CREDENTIAL_MANAGER_H_ + +#include <utils/identification.h> +#include <utils/enumerator.h> +#include <credentials/auth_info.h> +#include <credentials/credential_set.h> +#include <credentials/keys/private_key.h> +#include <credentials/keys/shared_key.h> +#include <credentials/certificates/certificate.h> + +typedef struct credential_manager_t credential_manager_t; + +/** + * Manages credentials using credential_sets. + * + * The credential manager is the entry point of the credential framework. It + * uses so called "sets" to access credentials in a modular fashion, these + * are implemented through the credential_set_t interface. + * The manager additionally does trust chain verification and trust status + * chaching. A set may call the managers methods if it needs credentials itself, + * the manager uses recursive locking. + * + * @verbatim + + +-------+ +----------------+ + | A | | | +------------------+ + | u | -----> | | ------> | +------------------+ + | t | | credential- | | | +------------------+ + | h | -----> | manager | ------> +--| | credential- | => IPC + | e | | | +--| sets | + | n | +--> | | ------> +------------------+ + | t | | | | | + | i | | | | | + | c | | +----------------+ | + | a | | | + | t | +----------------------------------------------+ + | o | may be recursive + | r | + +-------+ + + @endverbatim + * + * The credential manager uses rwlocks for performance reasons, credential + * sets must be fully thread save. + */ +struct credential_manager_t { + + /** + * Create an enumerator over all certificates. + * + * @param cert kind of certificate + * @param key kind of key in certificate + * @param id subject this certificate belongs to + * @param trusted TRUE to list trusted certificates only + * @return enumerator over the certificates + */ + enumerator_t *(*create_cert_enumerator)(credential_manager_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted); + /** + * Create an enumerator over all shared keys. + * + * The enumerator enumerates over: + * shared_key_t*, id_match_t me, id_match_t other + * But must accepts values for the id_matches. + * + * @param type kind of requested shared key + * @param first first subject between key is shared + * @param second second subject between key is shared + * @return enumerator over shared keys + */ + enumerator_t *(*create_shared_enumerator)(credential_manager_t *this, + shared_key_type_t type, + identification_t *first, identification_t *second); + /** + * Create an enumerator over all Certificate Distribution Points. + * + * @param type kind of certificate the point distributes + * @param id identification of the distributed certificate + * @return enumerator of CDPs as char* + */ + enumerator_t *(*create_cdp_enumerator)(credential_manager_t *this, + certificate_type_t type, identification_t *id); + /** + * Get a trusted or untrusted certificate. + * + * @param cert kind of certificate + * @param key kind of key in certificate + * @param id subject this certificate belongs to + * @param trusted TRUE to get a trusted certificate only + * @return certificate, if found, NULL otherwise + */ + certificate_t *(*get_cert)(credential_manager_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted); + /** + * Get the best matching shared key for two IDs. + * + * @param type kind of requested shared key + * @param me own identity + * @param other peers identity + * @param auth auth_info helper + * @return shared_key_t, NULL if none found + */ + shared_key_t *(*get_shared)(credential_manager_t *this, shared_key_type_t type, + identification_t *me, identification_t *other); + /** + * Get a private key to create a signature. + * + * The get_private() method gets a secret private key identified by either + * the keyid itself or an id the key belongs to. + * The auth parameter contains additional information, such as receipients + * trusted CA certs. Auth gets filled with subject and CA certificates + * needed to validate a created signature. + * + * @param type type of the key to get + * @param id identification the key belongs to + * @param auth auth_info helper, including trusted CA certificates + * @return private_key_t, NULL if none found + */ + private_key_t* (*get_private)(credential_manager_t *this, key_type_t type, + identification_t *id, auth_info_t *auth); + + /** + * Create an enumerator over trusted public keys. + * + * This method gets a an enumerator over trusted public keys to verify a + * signature created by id. The auth parameter contains additional + * authentication infos, e.g. peer and intermediate certificates. + * The resulting enumerator enumerates over public_key_t *, auth_info_t *, + * where the auth info contains gained privileges for the authorization + * process. + * + * @param type type of the key to get + * @param id owner of the key, signer of the signature + * @param auth authentication infos + * @return enumerator + */ + enumerator_t* (*create_public_enumerator)(credential_manager_t *this, + key_type_t type, identification_t *id, auth_info_t *auth); + + /** + * Cache a certificate by invoking cache_cert() on all registerd sets. + * + * @param cert certificate to cache + */ + void (*cache_cert)(credential_manager_t *this, certificate_t *cert); + + /** + * Flush the certificate cache. + * + * Only the managers local cache is flushed, but not the sets cache filled + * by the cache_cert() method. + * + * @param type type of certificate to flush, or CERT_ANY + */ + void (*flush_cache)(credential_manager_t *this, certificate_type_t type); + + /** + * Register a credential set to the manager. + * + * @param set set to register + */ + void (*add_set)(credential_manager_t *this, credential_set_t *set); + + /** + * Unregister a credential set from the manager. + * + * @param set set to unregister + */ + void (*remove_set)(credential_manager_t *this, credential_set_t *set); + + /** + * Destroy a credential_manager instance. + */ + void (*destroy)(credential_manager_t *this); +}; + +/** + * Create a credential_manager instance. + */ +credential_manager_t *credential_manager_create(); + +#endif /* CREDENTIAL_MANAGER_H_ @} */ diff --git a/src/charon/credentials/credential_set.h b/src/charon/credentials/credential_set.h new file mode 100644 index 000000000..b5f3b95cd --- /dev/null +++ b/src/charon/credentials/credential_set.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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. + * + * $Id: credential_set.h 3820 2008-04-17 11:22:37Z martin $ + */ + +/** + * @defgroup credential_set credential_set + * @{ @ingroup ccredentials + */ + +#ifndef CREDENTIAL_SET_H_ +#define CREDENTIAL_SET_H_ + +#include <credentials/keys/public_key.h> +#include <credentials/keys/shared_key.h> +#include <credentials/certificates/certificate.h> + +typedef struct credential_set_t credential_set_t; + +/** + * A set of credentials. + * + * Contains private keys, shared keys and different kinds of certificates. + * Enumerators are used because queries might return multiple matches. + * Filter parameters restrict enumeration over specific items only. + * See credential_manager_t for an overview of the credential framework. + */ +struct credential_set_t { + + /** + * Create an enumerator over private keys (private_key_t). + * + * The id is either a key identifier of the requested key, or an identity + * of the key owner. + * + * @param type type of requested private key + * @param id key identifier/owner + * @return enumerator over private_key_t's. + */ + enumerator_t *(*create_private_enumerator)(credential_set_t *this, + key_type_t type, identification_t *id); + /** + * Create an enumerator over certificates (certificate_t). + * + * @param cert kind of certificate + * @param key kind of key in certificate + * @param id identity (subject) this certificate belongs to + * @param trusted whether the certificate must be trustworthy + * @return enumerator as described above + */ + enumerator_t *(*create_cert_enumerator)(credential_set_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted); + /** + * Create an enumerator over shared keys (shared_key_t). + * + * The enumerator enumerates over: + * shared_key_t*, id_match_t me, id_match_t other + * But must accept NULL values for the id_matches. + * + * @param type kind of requested shared key + * @param me own identity + * @param other other identity who owns that secret + * @return enumerator as described above + */ + enumerator_t *(*create_shared_enumerator)(credential_set_t *this, + shared_key_type_t type, + identification_t *me, identification_t *other); + + /** + * Create an enumerator over certificate distribution points. + * + * @param type type of the certificate to get a CDP + * @param id identification of the distributed certificate + * @return an enumerator over CDPs as char* + */ + enumerator_t *(*create_cdp_enumerator)(credential_set_t *this, + certificate_type_t type, identification_t *id); + + /** + * Cache a certificate in the credential set. + * + * The caching policy is implementation dependent, the sets may cache the + * certificate in-memory, persistent on disk or not at all. + * + * @param cert certificate to cache + */ + void (*cache_cert)(credential_set_t *this, certificate_t *cert); +}; + +#endif /* CREDENTIAL_SET_H_ @} */ diff --git a/src/charon/credentials/sets/auth_info_wrapper.c b/src/charon/credentials/sets/auth_info_wrapper.c new file mode 100644 index 000000000..32783ff93 --- /dev/null +++ b/src/charon/credentials/sets/auth_info_wrapper.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include <daemon.h> + +#include "auth_info_wrapper.h" + +typedef struct private_auth_info_wrapper_t private_auth_info_wrapper_t; + +/** + * private data of auth_info_wrapper + */ +struct private_auth_info_wrapper_t { + + /** + * public functions + */ + auth_info_wrapper_t public; + + /** + * wrapped auth info + */ + auth_info_t *auth; +}; + +/** + * enumerator for auth_info_wrapper_t.create_cert_enumerator() + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** inner enumerator from auth_info */ + enumerator_t *inner; + /** wrapped auth info */ + auth_info_t *auth; + /** enumerated cert type */ + certificate_type_t cert; + /** enumerated key type */ + key_type_t key; + /** enumerated id */ + identification_t *id; +} wrapper_enumerator_t; + +/** + * Tries to fetch a certificate that was supplied as "Hash and URL" (replaces the + * item's type and value in place). + */ +static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void **value) +{ + char *url = (char*)*value; + if (!url) + { + /* fetching the certificate previously failed */ + return FALSE; + } + + chunk_t data; + certificate_t *cert; + + DBG1(DBG_CFG, " fetching certificate from '%s' ...", url); + if (lib->fetcher->fetch(lib->fetcher, url, &data) != SUCCESS) + { + DBG1(DBG_CFG, " fetching certificate failed"); + /* we set the item to NULL, so we can skip it */ + enumerator->auth->replace_item(enumerator->inner, *type, NULL); + return FALSE; + } + + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, data, BUILD_END); + + if (!cert) + { + DBG1(DBG_CFG, " parsing fetched certificate failed"); + /* we set the item to NULL, so we can skip it */ + enumerator->auth->replace_item(enumerator->inner, *type, NULL); + return FALSE; + } + + DBG1(DBG_CFG, " fetched certificate \"%D\"", cert->get_subject(cert)); + charon->credentials->cache_cert(charon->credentials, cert); + + *type = (*type == AUTHN_IM_HASH_URL) ? AUTHN_IM_CERT : AUTHN_SUBJECT_CERT; + *value = cert; + enumerator->auth->replace_item(enumerator->inner, *type, cert); + + return TRUE; +} + +/** + * enumerate function for wrapper_enumerator_t + */ +static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) +{ + auth_item_t type; + certificate_t *current; + public_key_t *public; + + while (this->inner->enumerate(this->inner, &type, ¤t)) + { + if (type == AUTHN_IM_HASH_URL || + type == AUTHN_SUBJECT_HASH_URL) + { + if (!fetch_cert(this, &type, (void**)¤t)) + { + continue; + } + } + else if (type != AUTHN_SUBJECT_CERT && + type != AUTHN_IM_CERT) + { + continue; + } + + if (this->cert != CERT_ANY && this->cert != current->get_type(current)) + { /* CERT type requested, but does not match */ + continue; + } + public = current->get_public_key(current); + if (this->key != KEY_ANY && !public) + { /* key type requested, but no public key */ + DESTROY_IF(public); + continue; + } + if (this->key != KEY_ANY && public && this->key != public->get_type(public)) + { /* key type requested, but public key has another type */ + DESTROY_IF(public); + continue; + } + DESTROY_IF(public); + if (this->id && !current->has_subject(current, this->id)) + { /* subject requested, but does not match */ + continue; + } + *cert = current; + return TRUE; + } + return FALSE; +} + +/** + * destroy function for wrapper_enumerator_t + */ +static void wrapper_enumerator_destroy(wrapper_enumerator_t *this) +{ + this->inner->destroy(this->inner); + free(this); +} + +/** + * implementation of auth_info_wrapper_t.set.create_cert_enumerator + */ +static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + wrapper_enumerator_t *enumerator; + + if (trusted) + { + return NULL; + } + enumerator = malloc_thing(wrapper_enumerator_t); + enumerator->auth = this->auth; + enumerator->cert = cert; + enumerator->key = key; + enumerator->id = id; + enumerator->inner = this->auth->create_item_enumerator(this->auth); + enumerator->public.enumerate = (void*)enumerate; + enumerator->public.destroy = (void*)wrapper_enumerator_destroy; + return &enumerator->public; +} + +/** + * Implementation of auth_info_wrapper_t.destroy + */ +static void destroy(private_auth_info_wrapper_t *this) +{ + free(this); +} + +/* + * see header file + */ +auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth) +{ + private_auth_info_wrapper_t *this = malloc_thing(private_auth_info_wrapper_t); + + this->public.set.create_private_enumerator = (void*)return_null; + this->public.set.create_cert_enumerator = (void*)create_enumerator; + this->public.set.create_shared_enumerator = (void*)return_null; + this->public.set.create_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)nop; + this->public.destroy = (void(*)(auth_info_wrapper_t*))destroy; + + this->auth = auth; + + return &this->public; +} + diff --git a/src/charon/credentials/sets/auth_info_wrapper.h b/src/charon/credentials/sets/auth_info_wrapper.h new file mode 100644 index 000000000..c382e9870 --- /dev/null +++ b/src/charon/credentials/sets/auth_info_wrapper.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup auth_info_wrapper auth_info_wrapper + * @{ @ingroup sets + */ + +#ifndef AUTH_INFO_WRAPPER_H_ +#define AUTH_INFO_WRAPPER_H_ + +#include <credentials/credential_set.h> +#include <credentials/auth_info.h> + +typedef struct auth_info_wrapper_t auth_info_wrapper_t; + +/** + * A wrapper around auth_info_t to handle it like a credential set. + */ +struct auth_info_wrapper_t { + + /** + * implements credential_set_t + */ + credential_set_t set; + + /** + * Destroy a auth_info_wrapper instance. + */ + void (*destroy)(auth_info_wrapper_t *this); +}; + +/** + * Create a auth_info_wrapper instance. + * + * @param auth the wrapped auth info + * @return wrapper around auth + */ +auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth); + +#endif /* AUTH_INFO_WRAPPER_H_ @}*/ diff --git a/src/charon/credentials/sets/cert_cache.c b/src/charon/credentials/sets/cert_cache.c new file mode 100644 index 000000000..8af8bb619 --- /dev/null +++ b/src/charon/credentials/sets/cert_cache.c @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "cert_cache.h" + +#include <daemon.h> +#include <utils/linked_list.h> +#include <utils/mutex.h> + +#define CACHE_SIZE 30 + +typedef struct private_cert_cache_t private_cert_cache_t; +typedef struct relation_t relation_t; + +/** + * private data of cert_cache + */ +struct private_cert_cache_t { + + /** + * public functions + */ + cert_cache_t public; + + /** + * list of trusted subject-issuer relations, as relation_t + */ + linked_list_t *relations; + + /** + * do we have an active enumerator + */ + bool enumerating; + + /** + * have we increased the cache without a check_cache? + */ + bool check_required; + + /** + * mutex to lock relations list + */ + mutex_t *mutex; +}; + +/** + * A trusted relation between subject and issuer + */ +struct relation_t { + /** subject of this relation */ + certificate_t *subject; + /** issuer of this relation */ + certificate_t *issuer; + /** time of last use */ + time_t last_use; +}; + +/** + * destroy a relation_t structure + */ +static void relation_destroy(relation_t *this) +{ + this->subject->destroy(this->subject); + this->issuer->destroy(this->issuer); + free(this); +} + +/** + * check the cache for oversize + */ +static void check_cache(private_cert_cache_t *this) +{ + if (this->enumerating) + { + this->check_required = TRUE; + } + else + { + while (this->relations->get_count(this->relations) > CACHE_SIZE) + { + relation_t *oldest = NULL, *current; + enumerator_t *enumerator; + + enumerator = this->relations->create_enumerator(this->relations); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (oldest == NULL || oldest->last_use <= current->last_use) + { + oldest = current; + } + } + enumerator->destroy(enumerator); + this->relations->remove(this->relations, oldest, NULL); + relation_destroy(oldest); + } + this->check_required = FALSE; + } +} + +/** + * Implementation of cert_cache_t.issued_by. + */ +static bool issued_by(private_cert_cache_t *this, + certificate_t *subject, certificate_t *issuer) +{ + relation_t *found = NULL, *current; + enumerator_t *enumerator; + + /* lookup cache */ + this->mutex->lock(this->mutex); + enumerator = this->relations->create_enumerator(this->relations); + while (enumerator->enumerate(enumerator, ¤t)) + { + bool match = FALSE; + + /* check for equal certificates */ + if (subject->equals(subject, current->subject)) + { + match = TRUE; + subject = current->subject; + } + if (issuer->equals(issuer, current->issuer)) + { + issuer = current->issuer; + /* if both certs match, we already have a relation */ + if (match) + { + current->last_use = time(NULL); + found = current; + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + if (found) + { + return TRUE; + } + /* no cache hit, check signature */ + if (!subject->issued_by(subject, issuer)) + { + return FALSE; + } + /* cache if good, respect cache limit */ + found = malloc_thing(relation_t); + found->subject = subject->get_ref(subject); + found->issuer = issuer->get_ref(issuer); + found->last_use = time(NULL); + this->mutex->lock(this->mutex); + this->relations->insert_last(this->relations, found); + check_cache(this); + this->mutex->unlock(this->mutex); + return TRUE; +} + +/** + * data associated to a cert enumeration + */ +typedef struct { + /** type of requested certificate */ + certificate_type_t cert; + /** type of requested key */ + key_type_t key; + /** ID to get a cert from */ + identification_t *id; + /** reverse pointer to cache */ + private_cert_cache_t *this; +} cert_data_t; + +/** + * filter function for certs enumerator + */ +static bool certs_filter(cert_data_t *data, relation_t **in, certificate_t **out) +{ + public_key_t *public; + certificate_t *cert; + + cert = (*in)->subject; + if (data->key == KEY_ANY && data->id && + (data->cert == CERT_ANY || data->cert == CERT_X509_CRL) && + cert->get_type(cert) == CERT_X509_CRL) + { /* CRL lookup is done using issuer/authkeyidentifier */ + if (cert->has_issuer(cert, data->id)) + { + *out = cert; + return TRUE; + } + } + + if ((data->cert == CERT_ANY || cert->get_type(cert) == data->cert) && + (!data->id || cert->has_subject(cert, data->id))) + { + if (data->key == KEY_ANY) + { + *out = cert; + return TRUE; + } + public = cert->get_public_key(cert); + if (public) + { + if (public->get_type(public) == data->key) + { + public->destroy(public); + *out = cert; + return TRUE; + } + public->destroy(public); + } + } + return FALSE; +} + +/** + * clean up enumeration data + */ +static void certs_destroy(cert_data_t *data) +{ + data->this->enumerating--; + if (data->this->check_required) + { + check_cache(data->this); + } + data->this->mutex->unlock(data->this->mutex); + free(data); +} + +/** + * implementation of credential_set_t.create_cert_enumerator + */ +static enumerator_t *create_enumerator(private_cert_cache_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + cert_data_t *data; + + if (trusted) + { + return NULL; + } + data = malloc_thing(cert_data_t); + data->cert = cert; + data->key = key; + data->id = id; + data->this = this; + + this->mutex->lock(this->mutex); + this->enumerating++; + return enumerator_create_filter( + this->relations->create_enumerator(this->relations), + (void*)certs_filter, data, (void*)certs_destroy); +} + +/** + * Implementation of credential_set_t.cache_cert. + */ +static void cache_cert(private_cert_cache_t *this, certificate_t *cert) +{ + /* TODO: implement caching */ +} + +/** + * Implementation of cert_cache_t.flush. + */ +static void flush(private_cert_cache_t *this, certificate_type_t type) +{ + enumerator_t *enumerator; + relation_t *relation; + + this->mutex->lock(this->mutex); + enumerator = this->relations->create_enumerator(this->relations); + while (enumerator->enumerate(enumerator, &relation)) + { + if (type == CERT_ANY || + type == relation->subject->get_type(relation->subject)) + { + this->relations->remove_at(this->relations, enumerator); + relation_destroy(relation); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of cert_cache_t.destroy + */ +static void destroy(private_cert_cache_t *this) +{ + this->relations->destroy_function(this->relations, (void*)relation_destroy); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +cert_cache_t *cert_cache_create() +{ + private_cert_cache_t *this = malloc_thing(private_cert_cache_t); + + this->public.set.create_private_enumerator = (void*)return_null; + this->public.set.create_cert_enumerator = (void*)create_enumerator; + this->public.set.create_shared_enumerator = (void*)return_null; + this->public.set.create_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)cache_cert; + this->public.issued_by = (bool(*)(cert_cache_t*, certificate_t *subject, certificate_t *issuer))issued_by; + this->public.flush = (void(*)(cert_cache_t*, certificate_type_t type))flush; + this->public.destroy = (void(*)(cert_cache_t*))destroy; + + this->relations = linked_list_create(); + this->enumerating = FALSE; + this->check_required = FALSE; + this->mutex = mutex_create(MUTEX_RECURSIVE); + + return &this->public; +} + diff --git a/src/charon/credentials/sets/cert_cache.h b/src/charon/credentials/sets/cert_cache.h new file mode 100644 index 000000000..281189d53 --- /dev/null +++ b/src/charon/credentials/sets/cert_cache.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup cert_cache cert_cache + * @{ @ingroup sets + */ + +#ifndef CERT_CACHE_H_ +#define CERT_CACHE_H_ + +#include <credentials/credential_set.h> + +typedef struct cert_cache_t cert_cache_t; + +/** + * Certificate signature verification and certificate cache. + * + * This cache serves all certificates seen in its issued_by method + * and serves them as untrusted through the credential set interface. Further, + * it caches valid subject-issuer relationships to speed up the issued_by + * method. + */ +struct cert_cache_t { + + /** + * Implements credential_set_t. + */ + credential_set_t set; + + /** + * Caching wrapper around certificate_t.issued_by. + * + * @param subject certificate to verify + * @param issuer issuing certificate to verify subject + * @return TRUE if subject issued by issuer + */ + bool (*issued_by)(cert_cache_t *this, + certificate_t *subject, certificate_t *issuer); + + /** + * Flush the certificate cache. + * + * @param type type of certificate to flush, or CERT_ANY + */ + void (*flush)(cert_cache_t *this, certificate_type_t type); + + /** + * Destroy a cert_cache instance. + */ + void (*destroy)(cert_cache_t *this); +}; + +/** + * Create a cert_cache instance. + */ +cert_cache_t *cert_cache_create(); + +#endif /* CERT_CACHE_H_ @}*/ diff --git a/src/charon/credentials/sets/ocsp_response_wrapper.c b/src/charon/credentials/sets/ocsp_response_wrapper.c new file mode 100644 index 000000000..c4d3a5b0f --- /dev/null +++ b/src/charon/credentials/sets/ocsp_response_wrapper.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "ocsp_response_wrapper.h" + +typedef struct private_ocsp_response_wrapper_t private_ocsp_response_wrapper_t; + +/** + * private data of ocsp_response_wrapper + */ +struct private_ocsp_response_wrapper_t { + + /** + * public functions + */ + ocsp_response_wrapper_t public; + + /** + * wrapped OCSP response + */ + ocsp_response_t *response; +}; + +/** + * enumerator for ocsp_response_wrapper_t.create_cert_enumerator() + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** enumerator over ocsp response */ + enumerator_t *inner; + /** type of cert */ + certificate_type_t cert; + /** type of key */ + key_type_t key; + /** filtering identity */ + identification_t *id; +} wrapper_enumerator_t; + +/** + * enumerate function wrapper_enumerator_t + */ +static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) +{ + certificate_t *current; + public_key_t *public; + + while (this->inner->enumerate(this->inner, ¤t)) + { + if (this->cert != CERT_ANY && this->cert != current->get_type(current)) + { /* CERT type requested, but does not match */ + continue; + } + public = current->get_public_key(current); + if (this->key != KEY_ANY && !public) + { /* key type requested, but no public key */ + DESTROY_IF(public); + continue; + } + if (this->key != KEY_ANY && public && this->key != public->get_type(public)) + { /* key type requested, but public key has another type */ + DESTROY_IF(public); + continue; + } + DESTROY_IF(public); + if (this->id && !current->has_subject(current, this->id)) + { /* subject requested, but does not match */ + continue; + } + *cert = current; + return TRUE; + } + return FALSE; +} + +/** + * destroy function for wrapper_enumerator_t + */ +static void enumerator_destroy(wrapper_enumerator_t *this) +{ + this->inner->destroy(this->inner); + free(this); +} + +/** + * implementation of ocsp_response_wrapper_t.set.create_cert_enumerator + */ +static enumerator_t *create_enumerator(private_ocsp_response_wrapper_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + wrapper_enumerator_t *enumerator; + + if (trusted) + { + return NULL; + } + + enumerator = malloc_thing(wrapper_enumerator_t); + enumerator->cert = cert; + enumerator->key = key; + enumerator->id = id; + enumerator->inner = this->response->create_cert_enumerator(this->response); + enumerator->public.enumerate = (void*)enumerate; + enumerator->public.destroy = (void*)enumerator_destroy; + return &enumerator->public; +} + +/** + * Implementation of ocsp_response_wrapper_t.destroy + */ +static void destroy(private_ocsp_response_wrapper_t *this) +{ + free(this); +} + +/* + * see header file + */ +ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response) +{ + private_ocsp_response_wrapper_t *this = malloc_thing(private_ocsp_response_wrapper_t); + + this->public.set.create_private_enumerator = (void*)return_null; + this->public.set.create_cert_enumerator = (void*)create_enumerator; + this->public.set.create_shared_enumerator = (void*)return_null; + this->public.set.create_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)nop; + this->public.destroy = (void(*)(ocsp_response_wrapper_t*))destroy; + + this->response = response; + + return &this->public; +} + diff --git a/src/charon/credentials/sets/ocsp_response_wrapper.h b/src/charon/credentials/sets/ocsp_response_wrapper.h new file mode 100644 index 000000000..6d32c2ca8 --- /dev/null +++ b/src/charon/credentials/sets/ocsp_response_wrapper.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup ocsp_response_wrapper ocsp_response_wrapper + * @{ @ingroup sets + */ + +#ifndef OCSP_RESPONSE_WRAPPER_H_ +#define OCSP_RESPONSE_WRAPPER_H_ + +#include <credentials/credential_set.h> +#include <credentials/certificates/ocsp_response.h> + +typedef struct ocsp_response_wrapper_t ocsp_response_wrapper_t; + +/** + * A wrapper around ocsp_response_t to handle it like a credential set. + */ +struct ocsp_response_wrapper_t { + + /** + * implements credential_set_t + */ + credential_set_t set; + + /** + * Destroy a ocsp_response_wrapper instance. + */ + void (*destroy)(ocsp_response_wrapper_t *this); +}; + +/** + * Create a ocsp_response_wrapper instance. + * + * @param response the wrapped OCSP response + * @return wrapper around response + */ +ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response); + +#endif /* OCSP_RESPONSE_WRAPPER_H_ @}*/ diff --git a/src/charon/daemon.c b/src/charon/daemon.c index ee9710424..1ab88104a 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -1,13 +1,7 @@ -/** - * @file daemon.c - * - * @brief Implementation of daemon_t and main of IKEv2-Daemon. - * - */ - -/* Copyright (C) 2006-2007 Tobias Brunner +/* + * Copyright (C) 2006-2007 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -22,6 +16,11 @@ * for more details. */ +#ifdef HAVE_DLADDR +# define _GNU_SOURCE +# include <dlfcn.h> +#endif /* HAVE_DLADDR */ + #include <stdio.h> #include <linux/capability.h> #include <sys/prctl.h> @@ -34,6 +33,8 @@ #include <string.h> #include <getopt.h> #include <errno.h> +#include <pwd.h> +#include <grp.h> #ifdef HAVE_BACKTRACE # include <execinfo.h> #endif /* HAVE_BACKTRACE */ @@ -41,11 +42,8 @@ #include "daemon.h" #include <library.h> -#include <crypto/ca.h> -#include <utils/fetcher.h> -#include <config/credentials/local_credential_store.h> -#include <config/backends/local_backend.h> -#include <sa/authenticators/eap/eap_method.h> +#include <config/traffic_selector.h> +#include <config/proposal.h> /* on some distros, a capset definition is missing */ #ifdef NO_CAPSET_DEFINED @@ -108,11 +106,14 @@ static void dbg_stderr(int level, char *fmt, ...) { va_list args; - va_start(args, fmt); - fprintf(stderr, "00[LIB] "); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - va_end(args); + if (level <= 1) + { + va_start(args, fmt); + fprintf(stderr, "00[LIB] "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } } /** @@ -171,17 +172,28 @@ static void run(private_daemon_t *this) static void destroy(private_daemon_t *this) { /* terminate all idle threads */ - this->public.processor->set_threads(this->public.processor, 0); + if (this->public.processor) + { + this->public.processor->set_threads(this->public.processor, 0); + } /* close all IKE_SAs */ + if (this->public.ike_sa_manager) + { + this->public.ike_sa_manager->flush(this->public.ike_sa_manager); + } + /* unload plugins to release threads */ + lib->plugins->unload(lib->plugins); DESTROY_IF(this->public.ike_sa_manager); DESTROY_IF(this->public.kernel_interface); DESTROY_IF(this->public.scheduler); - DESTROY_IF(this->public.interfaces); -#ifdef P2P + DESTROY_IF(this->public.controller); + DESTROY_IF(this->public.eap); +#ifdef ME DESTROY_IF(this->public.connect_manager); DESTROY_IF(this->public.mediation_manager); -#endif /* P2P */ +#endif /* ME */ DESTROY_IF(this->public.backends); + DESTROY_IF(this->public.attributes); DESTROY_IF(this->public.credentials); DESTROY_IF(this->public.sender); DESTROY_IF(this->public.receiver); @@ -204,11 +216,17 @@ static void destroy(private_daemon_t *this) static void kill_daemon(private_daemon_t *this, char *reason) { /* we send SIGTERM, so the daemon can cleanly shut down */ - DBG1(DBG_DMN, "killing daemon: %s", reason); + if (this->public.bus) + { + DBG1(DBG_DMN, "killing daemon: %s", reason); + } + else + { + fprintf(stderr, "killing daemon: %s\n", reason); + } if (this->main_thread_id == pthread_self()) { /* initialization failed, terminate daemon */ - destroy(this); unlink(PID_FILE); exit(-1); } @@ -230,22 +248,18 @@ static void drop_capabilities(private_daemon_t *this, bool full) struct __user_cap_data_struct data; /* CAP_NET_ADMIN is needed to use netlink */ - u_int32_t keep = (1<<CAP_NET_ADMIN); + u_int32_t keep = (1<<CAP_NET_ADMIN) | (1<<CAP_SYS_NICE); if (full) { -# if IPSEC_GID - if (setgid(IPSEC_GID) != 0) + if (setgid(charon->gid) != 0) { - kill_daemon(this, "changing GID to unprivileged group failed"); + kill_daemon(this, "change to unprivileged group failed"); } -# endif -# if IPSEC_UID - if (setuid(IPSEC_UID) != 0) + if (setuid(charon->uid) != 0) { - kill_daemon(this, "changing UID to unprivileged user failed"); + kill_daemon(this, "change to unprivileged user failed"); } -# endif } else { @@ -263,7 +277,13 @@ static void drop_capabilities(private_daemon_t *this, bool full) keep |= (1<<CAP_SETGID); } + /* we use the old capset version for now. For systems with version 2 + * available, we specifiy version 1 excplicitly. */ +#ifdef _LINUX_CAPABILITY_VERSION_1 + hdr.version = _LINUX_CAPABILITY_VERSION_1; +#else hdr.version = _LINUX_CAPABILITY_VERSION; +#endif hdr.pid = 0; data.inheritable = data.effective = data.permitted = keep; @@ -274,6 +294,39 @@ static void drop_capabilities(private_daemon_t *this, bool full) } /** + * lookup UID and GID + */ +static void lookup_uid_gid(private_daemon_t *this) +{ +#ifdef IPSEC_USER + { + char buf[1024]; + struct passwd passwd, *pwp; + + if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 || + pwp == NULL) + { + kill_daemon(this, "resolving user '"IPSEC_USER"' failed"); + } + charon->uid = pwp->pw_uid; + } +#endif +#ifdef IPSEC_GROUP + { + char buf[1024]; + struct group group, *grp; + + if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 || + grp == NULL) + { + kill_daemon(this, "reslvoing group '"IPSEC_GROUP"' failed"); + } + charon->gid = grp->gr_gid; + } +#endif +} + +/** * Initialize the daemon */ static bool initialize(private_daemon_t *this, bool syslog, level_t levels[]) @@ -321,31 +374,42 @@ static bool initialize(private_daemon_t *this, bool syslog, level_t levels[]) return FALSE; } #endif /* INTEGRITY_TEST */ - - this->public.ike_sa_manager = ike_sa_manager_create(); - this->public.processor = processor_create(); - this->public.scheduler = scheduler_create(); /* load secrets, ca certificates and crls */ - this->public.credentials = (credential_store_t*)local_credential_store_create(); - this->public.credentials->load_ca_certificates(this->public.credentials); - this->public.credentials->load_aa_certificates(this->public.credentials); - this->public.credentials->load_attr_certificates(this->public.credentials); - this->public.credentials->load_ocsp_certificates(this->public.credentials); - this->public.credentials->load_crls(this->public.credentials); - this->public.credentials->load_secrets(this->public.credentials, FALSE); - - this->public.interfaces = interface_manager_create(); + this->public.processor = processor_create(); + this->public.scheduler = scheduler_create(); + this->public.credentials = credential_manager_create(); + this->public.controller = controller_create(); + this->public.eap = eap_manager_create(); this->public.backends = backend_manager_create(); + this->public.attributes = attribute_manager_create(); this->public.kernel_interface = kernel_interface_create(); this->public.socket = socket_create(); + + /* load plugins, further infrastructure may need it */ + lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR, + lib->settings->get_str(lib->settings, "charon.load", PLUGINS)); + + this->public.ike_sa_manager = ike_sa_manager_create(); + if (this->public.ike_sa_manager == NULL) + { + return FALSE; + } this->public.sender = sender_create(); this->public.receiver = receiver_create(); + if (this->public.receiver == NULL) + { + return FALSE; + } -#ifdef P2P +#ifdef ME this->public.connect_manager = connect_manager_create(); + if (this->public.connect_manager == NULL) + { + return FALSE; + } this->public.mediation_manager = mediation_manager_create(); -#endif /* P2P */ +#endif /* ME */ return TRUE; } @@ -369,7 +433,25 @@ static void segv_handler(int signal) for (i = 0; i < size; i++) { - DBG1(DBG_DMN, " %s", strings[i]); +#ifdef HAVE_DLADDR + Dl_info info; + + if (dladdr(array[i], &info)) + { + void *ptr = array[i]; + if (strstr(info.dli_fname, ".so")) + { + ptr = (void*)(array[i] - info.dli_fbase); + } + DBG1(DBG_DMN, " %s [%p]", info.dli_fname, ptr); + } + else + { +#endif /* HAVE_DLADDR */ + DBG1(DBG_DMN, " %s", strings[i]); +#ifdef HAVE_DLADDR + } +#endif /* HAVE_DLADDR */ } free (strings); #else /* !HAVE_BACKTRACE */ @@ -396,16 +478,24 @@ private_daemon_t *daemon_create(void) this->public.ike_sa_manager = NULL; this->public.credentials = NULL; this->public.backends = NULL; + this->public.attributes = NULL; this->public.sender= NULL; this->public.receiver = NULL; this->public.scheduler = NULL; this->public.kernel_interface = NULL; this->public.processor = NULL; - this->public.interfaces = NULL; + this->public.controller = NULL; + this->public.eap = NULL; this->public.bus = NULL; this->public.outlog = NULL; this->public.syslog = NULL; this->public.authlog = NULL; +#ifdef ME + this->public.connect_manager = NULL; + this->public.mediation_manager = NULL; +#endif /* ME */ + this->public.uid = 0; + this->public.gid = 0; this->main_thread_id = pthread_self(); @@ -440,10 +530,6 @@ static void usage(const char *msg) fprintf(stderr, "Usage: charon\n" " [--help]\n" " [--version]\n" - " [--strictcrlpolicy]\n" - " [--cachecrls]\n" - " [--crlcheckinterval <interval>]\n" - " [--eapdir <dir>]\n" " [--use-syslog]\n" " [--debug-<type> <level>]\n" " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|enc|lib)\n" @@ -459,11 +545,7 @@ static void usage(const char *msg) */ int main(int argc, char *argv[]) { - u_int crl_check_interval = 0; - strict_t strict_crl_policy = STRICT_NO; - bool cache_crls = FALSE; bool use_syslog = FALSE; - char *eapdir = IPSEC_EAPDIR; private_daemon_t *private_charon; FILE *pid_file; @@ -471,9 +553,20 @@ int main(int argc, char *argv[]) level_t levels[DBG_MAX]; int signal; + /* logging for library during initialization, as we have no bus yet */ + dbg = dbg_stderr; + + /* initialize library */ + library_init(STRONGSWAN_CONF); + lib->printf_hook->add_handler(lib->printf_hook, 'R', + traffic_selector_get_printf_hooks()); + lib->printf_hook->add_handler(lib->printf_hook, 'P', + proposal_get_printf_hooks()); private_charon = daemon_create(); charon = (daemon_t*)private_charon; + lookup_uid_gid(private_charon); + /* drop the capabilities we won't need for initialization */ prctl(PR_SET_KEEPCAPS, 1); drop_capabilities(private_charon, FALSE); @@ -491,10 +584,6 @@ int main(int argc, char *argv[]) { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "use-syslog", no_argument, NULL, 'l' }, - { "strictcrlpolicy", required_argument, NULL, 'r' }, - { "cachecrls", no_argument, NULL, 'C' }, - { "crlcheckinterval", required_argument, NULL, 'x' }, - { "eapdir", required_argument, NULL, 'e' }, /* TODO: handle "debug-all" */ { "debug-dmn", required_argument, &signal, DBG_DMN }, { "debug-mgr", required_argument, &signal, DBG_MGR }, @@ -523,18 +612,6 @@ int main(int argc, char *argv[]) case 'l': use_syslog = TRUE; continue; - case 'r': - strict_crl_policy = atoi(optarg); - continue; - case 'C': - cache_crls = TRUE; - continue; - case 'x': - crl_check_interval = atoi(optarg); - continue; - case 'e': - eapdir = optarg; - continue; case 0: /* option is in signal */ levels[signal] = atoi(optarg); @@ -554,14 +631,6 @@ int main(int argc, char *argv[]) exit(-1); } - /* initialize fetcher_t class */ - fetcher_initialize(); - /* load pluggable EAP modules */ - eap_method_load(eapdir); - - /* set strict_crl_policy, cache_crls and crl_check_interval options */ - ca_info_set_options(strict_crl_policy, cache_crls, crl_check_interval); - /* check/setup PID file */ if (stat(PID_FILE, &stb) == 0) { @@ -573,7 +642,7 @@ int main(int argc, char *argv[]) if (pid_file) { fprintf(pid_file, "%d\n", getpid()); - fchown(fileno(pid_file), IPSEC_UID, IPSEC_GID); + fchown(fileno(pid_file), charon->uid, charon->gid); fclose(pid_file); } @@ -581,17 +650,19 @@ int main(int argc, char *argv[]) drop_capabilities(private_charon, TRUE); /* start the engine, go multithreaded */ - charon->processor->set_threads(charon->processor, WORKER_THREADS); + charon->processor->set_threads(charon->processor, + lib->settings->get_int(lib->settings, "charon.threads", + DEFAULT_THREADS)); /* run daemon */ run(private_charon); - eap_method_unload(); - fetcher_finalize(); /* normal termination, cleanup and exit */ destroy(private_charon); unlink(PID_FILE); + library_deinit(); + return 0; } diff --git a/src/charon/daemon.h b/src/charon/daemon.h index 33c63091d..5893e7332 100644 --- a/src/charon/daemon.h +++ b/src/charon/daemon.h @@ -1,14 +1,7 @@ -/** - * @file daemon.h - * - * @brief Interface of daemon_t. - * - */ - /* * Copyright (C) 2006-2007 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -21,345 +14,189 @@ * 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. + * + * $Id: daemon.h 3964 2008-05-15 14:01:26Z martin $ */ -#ifndef DAEMON_H_ -#define DAEMON_H_ - -typedef struct daemon_t daemon_t; - -#include <credential_store.h> - -#include <network/sender.h> -#include <network/receiver.h> -#include <network/socket.h> -#include <processing/scheduler.h> -#include <processing/processor.h> -#include <kernel/kernel_interface.h> -#include <control/interface_manager.h> -#include <bus/bus.h> -#include <bus/listeners/file_logger.h> -#include <bus/listeners/sys_logger.h> -#include <sa/ike_sa_manager.h> -#include <config/backend_manager.h> - -#ifdef P2P -#include <sa/connect_manager.h> -#include <sa/mediation_manager.h> -#endif /* P2P */ - /** * @defgroup charon charon * - * @brief IKEv2 keying daemon. - * - * All IKEv2 stuff is handled in charon. It uses a newer and more flexible - * architecture than pluto. Charon uses a thread-pool (called processor), - * which allows parallel execution SA-management. All threads originate - * from the processor. Work is delegated to the processor by queueing jobs - * to it. - @verbatim - - +--------+ +-------+ +--------+ +-----------+ +-----------+ - | Stroke | | XML | | DBUS | | Local | | SQLite | - +--------+ +-------+ +--------+ +-----------+ +-----------+ - | | | | | - +---------------------------------+ +----------------------------+ - | Interfaces | | Backends | - +---------------------------------+ +----------------------------+ - - - +------------+ +-----------+ +------+ +----------+ - | receiver | | | | | +------+ | CHILD_SA | - +----+-------+ | Scheduler | | IKE- | | IKE- |--+----------+ - | | | | SA |--| SA | | CHILD_SA | - +-------+--+ +-----------+ | | +------+ +----------+ - <->| socket | | | Man- | - +-------+--+ +-----------+ | ager | +------+ +----------+ - | | | | | | IKE- |--| CHILD_SA | - +----+-------+ | Processor |--------| |--| SA | +----------+ - | sender | | | | | +------+ - +------------+ +-----------+ +------+ - - - +---------------------------------+ +----------------------------+ - | Bus | | Kernel Interface | - +---------------------------------+ +----------------------------+ - | | | - +-------------+ +-------------+ V - | File-Logger | | Sys-Logger | ////// - +-------------+ +-------------+ - - - @endverbatim - * The scheduler is responsible to execute timed events. Jobs may be queued to - * the scheduler to get executed at a defined time (e.g. rekeying). The scheduler - * does not execute the jobs itself, it queues them to the processor. - * - * The IKE_SA manager managers all IKE_SA. It further handles the synchronization: - * Each IKE_SA must be checked out strictly and checked in again after use. The - * manager guarantees that only one thread may check out a single IKE_SA. This allows - * us to write the (complex) IKE_SAs routines non-threadsave. - * The IKE_SA contain the state and the logic of each IKE_SA and handle the messages. - * - * The CHILD_SA contains state about a IPsec security association and manages them. - * An IKE_SA may have multiple CHILD_SAs. Communication to the kernel takes place - * here through the kernel interface. - * - * The kernel interface installs IPsec security associations, policies routes and - * virtual addresses. It further provides methods to enumerate interfaces and may notify - * the daemon about state changes at lower layers. - * - * The bus receives signals from the different threads and relais them to interested - * listeners. Debugging signals, but also important state changes or error messages are - * sent over the bus. - * It's listeners are not only for logging, but also to track the state of an IKE_SA. - * - * The interface manager loads pluggable controlling interfaces. These are written to control - * the daemon from external inputs (e.g. initiate IKE_SA, close IKE_SA, ...). The interface - * manager further provides a simple API to establish these tasks. - * Backends are pluggable modules which provide configuration. They have to implement an API - * which the daemon core uses to get configuration. - */ - -/** * @defgroup bus bus - * - * Signaling bus and its listeners. - * * @ingroup charon - */ - -/** - * @defgroup config config - * - * Classes implementing configuration related things. + * + * @defgroup listeners listeners + * @ingroup bus * + * @defgroup config config * @ingroup charon - */ - -/** - * @defgroup backends backends - * - * Classes implementing configuration backends. * + * @defgroup attributes attributes * @ingroup config - */ - -/** - * @defgroup credentials credentials * - * Trust chain verification and certificate store. - * - * @ingroup config - */ - -/** * @defgroup control control + * @ingroup charon * - * Handling of loadable control interface modules. - * + * @defgroup ccredentials credentials * @ingroup charon - */ - -/** - * @defgroup interfaces interfaces * - * Classes which control the daemon using IPC mechanisms. + * @defgroup sets sets + * @ingroup ccredentials * - * @ingroup control - */ - -/** * @defgroup encoding encoding - * - * Classes used to encode and decode IKEv2 messages. - * * @ingroup charon - */ - - /** - * @defgroup payloads payloads - * - * Classes representing specific IKEv2 payloads. * + * @defgroup payloads payloads * @ingroup encoding - */ - -/** - * @defgroup kernel kernel - * - * Classes to configure and query the kernel. * + * @defgroup kernel kernel * @ingroup charon - */ - -/** - * @defgroup network network - * - * Classes for sending and receiving UDP packets over the network. * + * @defgroup network network * @ingroup charon - */ - -/** - * @defgroup processing processing - * - * Queueing, scheduling and processing of jobs * + * @defgroup cplugins plugins * @ingroup charon - */ - -/** - * @defgroup jobs jobs * - * Jobs to queue, schedule and process. + * @defgroup processing processing + * @ingroup charon * + * @defgroup jobs jobs * @ingroup processing - */ - -/** - * @defgroup sa sa - * - * Security associations for IKE and IPSec, and its helper classes. * + * @defgroup sa sa * @ingroup charon - */ - -/** - * @defgroup authenticators authenticators - * - * Authenticator classes to prove identity of a peer. * + * @defgroup authenticators authenticators * @ingroup sa - */ - -/** - * @defgroup eap eap - * - * EAP module loader, interface and it's implementations. * + * @defgroup eap eap * @ingroup authenticators - */ - -/** + * * @defgroup tasks tasks + * @ingroup sa * - * Tasks process and build message payloads. They are used to create - * and process multiple exchanges. + * @addtogroup charon + * @{ * - * @ingroup sa - */ - -/** - * Name of the daemon. + * IKEv2 keying daemon. * - * @ingroup charon - */ -#define DAEMON_NAME "charon" + * All IKEv2 stuff is handled in charon. It uses a newer and more flexible + * architecture than pluto. Charon uses a thread-pool (called processor), + * which allows parallel execution SA-management. All threads originate + * from the processor. Work is delegated to the processor by queueing jobs + * to it. + @verbatim + + +---------------------------------+ +----------------------------+ + | controller | | config | + +---------------------------------+ +----------------------------+ + | | | ^ ^ ^ + V V V | | | + + +----------+ +-----------+ +------+ +----------+ +----+ + | receiver | | | | | +------+ | CHILD_SA | | K | + +---+------+ | Scheduler | | IKE- | | IKE- |--+----------+ | e | + | | | | SA |--| SA | | CHILD_SA | | r | + +------+---+ +-----------+ | | +------+ +----------+ | n | + <->| socket | | | Man- | | e | + +------+---+ +-----------+ | ager | +------+ +----------+ | l | + | | | | | | IKE- |--| CHILD_SA | | - | + +---+------+ | Processor |---| |--| SA | +----------+ | I | + | sender | | | | | +------+ | f | + +----------+ +-----------+ +------+ +----+ + + | | | | | | + V V V V V V + +---------------------------------+ +----------------------------+ + | Bus | | credentials | + +---------------------------------+ +----------------------------+ -/** - * @brief Number of threads in the thread pool. + @endverbatim + * The scheduler is responsible to execute timed events. Jobs may be queued to + * the scheduler to get executed at a defined time (e.g. rekeying). The + * scheduler does not execute the jobs itself, it queues them to the processor. * - * @ingroup charon - */ -#define WORKER_THREADS 16 - -/** - * UDP Port on which the daemon will listen for incoming traffic. + * The IKE_SA manager managers all IKE_SA. It further handles the + * synchronization: + * Each IKE_SA must be checked out strictly and checked in again after use. The + * manager guarantees that only one thread may check out a single IKE_SA. This + * allows us to write the (complex) IKE_SAs routines non-threadsave. + * The IKE_SA contain the state and the logic of each IKE_SA and handle the + * messages. * - * @ingroup charon - */ -#define IKEV2_UDP_PORT 500 - -/** - * UDP Port to which the daemon will float to if NAT is detected. - * - * @ingroup charon - */ -#define IKEV2_NATT_PORT 4500 - -/** - * PID file, in which charon stores its process id + * The CHILD_SA contains state about a IPsec security association and manages + * them. An IKE_SA may have multiple CHILD_SAs. Communication to the kernel + * takes place here through the kernel interface. * - * @ingroup charon - */ -#define PID_FILE IPSEC_PIDDIR "/charon.pid" - -/** - * Configuration directory + * The kernel interface installs IPsec security associations, policies, routes + * and virtual addresses. It further provides methods to enumerate interfaces + * and may notify the daemon about state changes at lower layers. * - * @ingroup charon + * The bus receives signals from the different threads and relais them to interested + * listeners. Debugging signals, but also important state changes or error + * messages are sent over the bus. + * It's listeners are not only for logging, but also to track the state of an + * IKE_SA. + * + * The controller, credential_manager, bus and backend_manager (config) are + * places where a plugin ca register itself to privide information or observe + * and control the daemon. */ -#define CONFIG_DIR IPSEC_CONFDIR -/** - * Directory of IPsec relevant files - * - * @ingroup charon - */ -#define IPSEC_D_DIR CONFIG_DIR "/ipsec.d" +#ifndef DAEMON_H_ +#define DAEMON_H_ -/** - * Default directory for private keys - * - * @ingroup charon - */ -#define PRIVATE_KEY_DIR IPSEC_D_DIR "/private" +typedef struct daemon_t daemon_t; -/** - * Default directory for end entity certificates - * - * @ingroup charon - */ -#define CERTIFICATE_DIR IPSEC_D_DIR "/certs" +#include <network/sender.h> +#include <network/receiver.h> +#include <network/socket.h> +#include <processing/scheduler.h> +#include <processing/processor.h> +#include <kernel/kernel_interface.h> +#include <control/controller.h> +#include <bus/bus.h> +#include <bus/listeners/file_logger.h> +#include <bus/listeners/sys_logger.h> +#include <sa/ike_sa_manager.h> +#include <config/backend_manager.h> +#include <config/attributes/attribute_manager.h> +#include <credentials/credential_manager.h> +#include <sa/authenticators/eap/eap_manager.h> -/** - * Default directory for trusted Certification Authority certificates - * - * @ingroup charon - */ -#define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts" +#ifdef ME +#include <sa/connect_manager.h> +#include <sa/mediation_manager.h> +#endif /* ME */ /** - * Default directory for Authorization Authority certificates - * - * @ingroup charon + * Name of the daemon. */ -#define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts" +#define DAEMON_NAME "charon" /** - * Default directory for Attribute certificates - * - * @ingroup charon + * Number of threads in the thread pool, if not specified in config. */ -#define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts" +#define DEFAULT_THREADS 16 /** - * Default directory for OCSP signing certificates - * - * @ingroup charon + * UDP Port on which the daemon will listen for incoming traffic. */ -#define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts" +#define IKEV2_UDP_PORT 500 /** - * Default directory for CRLs - * - * @ingroup charon + * UDP Port to which the daemon will float to if NAT is detected. */ -#define CRL_DIR IPSEC_D_DIR "/crls" +#define IKEV2_NATT_PORT 4500 /** - * Secrets files - * - * @ingroup charon + * PID file, in which charon stores its process id */ -#define SECRETS_FILE CONFIG_DIR "/ipsec.secrets" +#define PID_FILE IPSEC_PIDDIR "/charon.pid" + /** - * @brief Main class of daemon, contains some globals. - * - * @ingroup charon + * Main class of daemon, contains some globals. */ struct daemon_t { @@ -379,9 +216,14 @@ struct daemon_t { backend_manager_t *backends; /** - * A credential_store_t instance. + * Manager IKEv2 cfg payload attributes + */ + attribute_manager_t *attributes; + + /** + * Manager for the credential backends */ - credential_store_t *credentials; + credential_manager_t *credentials; /** * The Sender-Thread. @@ -429,11 +271,16 @@ struct daemon_t { kernel_interface_t *kernel_interface; /** - * Interfaces for IPC + * Controller to control the daemon */ - interface_manager_t *interfaces; + controller_t *controller; -#ifdef P2P + /** + * EAP manager to maintain registered EAP methods + */ + eap_manager_t *eap; + +#ifdef ME /** * Connect manager */ @@ -443,12 +290,21 @@ struct daemon_t { * Mediation manager */ mediation_manager_t *mediation_manager; -#endif /* P2P */ +#endif /* ME */ + + /** + * User ID the daemon will user after initialization + */ + uid_t uid; + + /** + * Group ID the daemon will use after initialization + */ + gid_t gid; /** - * @brief Shut down the daemon. + * Shut down the daemon. * - * @param this the daemon to kill * @param reason describtion why it will be killed */ void (*kill) (daemon_t *this, char *reason); @@ -459,4 +315,4 @@ struct daemon_t { */ extern daemon_t *charon; -#endif /*DAEMON_H_*/ +#endif /*DAEMON_H_ @} */ diff --git a/src/charon/encoding/generator.c b/src/charon/encoding/generator.c index efa845bb3..3b68af84e 100644 --- a/src/charon/encoding/generator.c +++ b/src/charon/encoding/generator.c @@ -1,10 +1,3 @@ -/** - * @file generator.c - * - * @brief Implementation of generator_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: generator.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stdlib.h> diff --git a/src/charon/encoding/generator.h b/src/charon/encoding/generator.h index 8eff957cc..b6f2af2cb 100644 --- a/src/charon/encoding/generator.h +++ b/src/charon/encoding/generator.h @@ -1,10 +1,3 @@ -/** - * @file generator.h - * - * @brief Interface of generator_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: generator.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup generator generator + * @{ @ingroup encoding */ #ifndef GENERATOR_H_ @@ -33,21 +33,17 @@ typedef struct generator_t generator_t; /** * Generating is done in a data buffer. * This is thehe start size of this buffer in bytes. - * - * @ingroup enconding */ #define GENERATOR_DATA_BUFFER_SIZE 500 /** * Number of bytes to increase the buffer, if it is to small. - * - * @ingroup enconding */ #define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500 /** - * @brief A generator_t class used to generate IKEv2 payloads. + * A generator_t class used to generate IKEv2 payloads. * * After creation, multiple payloads can be generated with the generate_payload * method. The generated bytes are appended. After all payloads are added, @@ -56,47 +52,36 @@ typedef struct generator_t generator_t; * The generater uses a set of encoding rules, which it can get from * the supplied payload. With this rules, the generater can generate * the payload and all substructures automatically. - * - * @b Constructor: - * - generator_create() - * - * @ingroup encoding */ struct generator_t { /** - * @brief Generates a specific payload from given payload object. + * Generates a specific payload from given payload object. * * Remember: Header and substructures are also handled as payloads. * - * @param this generator_t object - * @param[in] payload interface payload_t implementing object + * @param payload interface payload_t implementing object */ void (*generate_payload) (generator_t *this,payload_t *payload); /** - * @brief Writes all generated data of the generator to a chunk. + * Writes all generated data of the generator to a chunk. * - * @param this generator_t object - * @param[out] data chunk to write the data to + * @param data chunk to write the data to */ void (*write_to_chunk) (generator_t *this,chunk_t *data); /** - * @brief Destroys a generator_t object. - * - * @param this generator_t object + * Destroys a generator_t object. */ void (*destroy) (generator_t *this); }; /** - * @brief Constructor to create a generator. + * Constructor to create a generator. * * @return generator_t object. - * - * @ingroup encoding */ generator_t *generator_create(void); -#endif /*GENERATOR_H_*/ +#endif /*GENERATOR_H_ @} */ diff --git a/src/charon/encoding/message.c b/src/charon/encoding/message.c index 3dfa64fb9..af9483192 100644 --- a/src/charon/encoding/message.c +++ b/src/charon/encoding/message.c @@ -1,10 +1,3 @@ -/** - * @file message.c - * - * @brief Implementation of message_t. - * - */ - /* * Copyright (C) 2006-2007 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger @@ -21,6 +14,8 @@ * 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. + * + * $Id: message.c 3991 2008-05-21 17:56:21Z martin $ */ #include <stdlib.h> @@ -82,13 +77,31 @@ struct payload_rule_t { bool sufficient; }; +typedef struct payload_order_t payload_order_t; + +/** + * payload ordering structure allows us to reorder payloads according to RFC. + */ +struct payload_order_t { + + /** + * payload type + */ + payload_type_t type; + + /** + * notify type, if payload == NOTIFY + */ + notify_type_t notify; +}; + + typedef struct message_rule_t message_rule_t; /** * A message rule defines the kind of a message, * if it has encrypted contents and a list - * of payload rules. - * + * of payload ordering rules and payload parsing rules. */ struct message_rule_t { /** @@ -109,161 +122,398 @@ struct message_rule_t { /** * Number of payload rules which will follow */ - size_t payload_rule_count; + int payload_rule_count; /** * Pointer to first payload rule */ payload_rule_t *payload_rules; + + /** + * Number of payload order rules + */ + int payload_order_count; + + /** + * payload ordering rules + */ + payload_order_t *payload_order; }; /** * Message rule for IKE_SA_INIT from initiator. */ static payload_rule_t ike_sa_init_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,FALSE}, - {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, - {KEY_EXCHANGE,1,1,FALSE,FALSE}, - {NONCE,1,1,FALSE,FALSE}, - {VENDOR_ID,0,10,FALSE,FALSE}, +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE}, + {KEY_EXCHANGE, 1, 1, FALSE, FALSE}, + {NONCE, 1, 1, FALSE, FALSE}, + {VENDOR_ID, 0, 10, FALSE, FALSE}, +}; + +/** + * payload order for IKE_SA_INIT initiator + */ +static payload_order_t ike_sa_init_i_payload_order[] = { +/* payload type notify type */ + {NOTIFY, COOKIE}, + {SECURITY_ASSOCIATION, 0}, + {KEY_EXCHANGE, 0}, + {NONCE, 0}, + {NOTIFY, NAT_DETECTION_SOURCE_IP}, + {NOTIFY, NAT_DETECTION_DESTINATION_IP}, + {NOTIFY, 0}, + {VENDOR_ID, 0}, }; /** * Message rule for IKE_SA_INIT from responder. */ static payload_rule_t ike_sa_init_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,FALSE,TRUE}, - {SECURITY_ASSOCIATION,1,1,FALSE,FALSE}, - {KEY_EXCHANGE,1,1,FALSE,FALSE}, - {NONCE,1,1,FALSE,FALSE}, - {VENDOR_ID,0,10,FALSE,FALSE}, +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, FALSE, TRUE}, + {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE}, + {KEY_EXCHANGE, 1, 1, FALSE, FALSE}, + {NONCE, 1, 1, FALSE, FALSE}, + {VENDOR_ID, 0, 10, FALSE, FALSE}, +}; + +/** + * payload order for IKE_SA_INIT responder + */ +static payload_order_t ike_sa_init_r_payload_order[] = { +/* payload type notify type */ + {SECURITY_ASSOCIATION, 0}, + {KEY_EXCHANGE, 0}, + {NONCE, 0}, + {NOTIFY, NAT_DETECTION_SOURCE_IP}, + {NOTIFY, NAT_DETECTION_DESTINATION_IP}, + {NOTIFY, HTTP_CERT_LOOKUP_SUPPORTED}, + {CERTIFICATE_REQUEST, 0}, + {NOTIFY, 0}, + {VENDOR_ID, 0}, }; /** * Message rule for IKE_AUTH from initiator. */ static payload_rule_t ike_auth_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, - {EXTENSIBLE_AUTHENTICATION,0,1,TRUE,TRUE}, - {AUTHENTICATION,0,1,TRUE,TRUE}, - {ID_INITIATOR,1,1,TRUE,FALSE}, - {CERTIFICATE,0,1,TRUE,FALSE}, - {CERTIFICATE_REQUEST,0,1,TRUE,FALSE}, - {ID_RESPONDER,0,1,TRUE,FALSE}, -#ifdef P2P - {SECURITY_ASSOCIATION,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE}, +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {EXTENSIBLE_AUTHENTICATION, 0, 1, TRUE, TRUE}, + {AUTHENTICATION, 0, 1, TRUE, TRUE}, + {ID_INITIATOR, 1, 1, TRUE, FALSE}, + {CERTIFICATE, 0, 4, TRUE, FALSE}, + {CERTIFICATE_REQUEST, 0, 1, TRUE, FALSE}, + {ID_RESPONDER, 0, 1, TRUE, FALSE}, +#ifdef ME + {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, #else - {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE}, -#endif /* P2P */ - {CONFIGURATION,0,1,TRUE,FALSE}, - {VENDOR_ID,0,10,TRUE,FALSE}, + {SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_INITIATOR, 1, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_RESPONDER, 1, 1, TRUE, FALSE}, +#endif /* ME */ + {CONFIGURATION, 0, 1, TRUE, FALSE}, + {VENDOR_ID, 0, 10, TRUE, FALSE}, +}; + +/** + * payload order for IKE_AUTH initiator + */ +static payload_order_t ike_auth_i_payload_order[] = { +/* payload type notify type */ + {ID_INITIATOR, 0}, + {CERTIFICATE, 0}, + {NOTIFY, INITIAL_CONTACT}, + {NOTIFY, HTTP_CERT_LOOKUP_SUPPORTED}, + {CERTIFICATE_REQUEST, 0}, + {ID_RESPONDER, 0}, + {AUTHENTICATION, 0}, + {EXTENSIBLE_AUTHENTICATION, 0}, + {CONFIGURATION, 0}, + {NOTIFY, IPCOMP_SUPPORTED}, + {NOTIFY, USE_TRANSPORT_MODE}, + {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED}, + {NOTIFY, NON_FIRST_FRAGMENTS_ALSO}, + {SECURITY_ASSOCIATION, 0}, + {TRAFFIC_SELECTOR_INITIATOR, 0}, + {TRAFFIC_SELECTOR_RESPONDER, 0}, + {NOTIFY, MOBIKE_SUPPORTED}, + {NOTIFY, ADDITIONAL_IP4_ADDRESS}, + {NOTIFY, ADDITIONAL_IP6_ADDRESS}, + {NOTIFY, NO_ADDITIONAL_ADDRESSES}, + {NOTIFY, 0}, + {VENDOR_ID, 0}, }; /** * Message rule for IKE_AUTH from responder. */ static payload_rule_t ike_auth_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, - {EXTENSIBLE_AUTHENTICATION,0,1,TRUE,TRUE}, - {CERTIFICATE,0,1,TRUE,FALSE}, - {ID_RESPONDER,0,1,TRUE,FALSE}, - {AUTHENTICATION,0,1,TRUE,FALSE}, - {SECURITY_ASSOCIATION,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, - {VENDOR_ID,0,10,TRUE,FALSE}, +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, + {EXTENSIBLE_AUTHENTICATION, 0, 1, TRUE, TRUE}, + {CERTIFICATE, 0, 4, TRUE, FALSE}, + {ID_RESPONDER, 0, 1, TRUE, FALSE}, + {AUTHENTICATION, 0, 1, TRUE, FALSE}, + {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, + {CONFIGURATION, 0, 1, TRUE, FALSE}, + {VENDOR_ID, 0, 10, TRUE, FALSE}, }; +/** + * payload order for IKE_AUTH responder + */ +static payload_order_t ike_auth_r_payload_order[] = { +/* payload type notify type */ + {ID_RESPONDER, 0}, + {CERTIFICATE, 0}, + {AUTHENTICATION, 0}, + {EXTENSIBLE_AUTHENTICATION, 0}, + {CONFIGURATION, 0}, + {NOTIFY, IPCOMP_SUPPORTED}, + {NOTIFY, USE_TRANSPORT_MODE}, + {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED}, + {NOTIFY, NON_FIRST_FRAGMENTS_ALSO}, + {SECURITY_ASSOCIATION, 0}, + {TRAFFIC_SELECTOR_INITIATOR, 0}, + {TRAFFIC_SELECTOR_RESPONDER, 0}, + {NOTIFY, AUTH_LIFETIME}, + {NOTIFY, MOBIKE_SUPPORTED}, + {NOTIFY, ADDITIONAL_IP4_ADDRESS}, + {NOTIFY, ADDITIONAL_IP6_ADDRESS}, + {NOTIFY, NO_ADDITIONAL_ADDRESSES}, + {NOTIFY, 0}, + {VENDOR_ID, 0}, +}; /** * Message rule for INFORMATIONAL from initiator. */ static payload_rule_t informational_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, - {DELETE,0,1,TRUE,FALSE}, - {VENDOR_ID,0,10,TRUE,FALSE}, - +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {CONFIGURATION, 0, 1, TRUE, FALSE}, + {DELETE, 0, 1, TRUE, FALSE}, + {VENDOR_ID, 0, 10, TRUE, FALSE}, +}; + +/** + * payload order for INFORMATIONAL initiator + */ +static payload_order_t informational_i_payload_order[] = { +/* payload type notify type */ + {NOTIFY, UPDATE_SA_ADDRESSES}, + {NOTIFY, NAT_DETECTION_SOURCE_IP}, + {NOTIFY, NAT_DETECTION_DESTINATION_IP}, + {NOTIFY, COOKIE2}, + {NOTIFY, 0}, + {DELETE, 0}, + {CONFIGURATION, 0}, }; /** * Message rule for INFORMATIONAL from responder. */ static payload_rule_t informational_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, - {DELETE,0,1,TRUE,FALSE}, - {VENDOR_ID,0,10,TRUE,FALSE}, +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {CONFIGURATION, 0, 1, TRUE, FALSE}, + {DELETE, 0, 1, TRUE, FALSE}, + {VENDOR_ID, 0, 10, TRUE, FALSE}, +}; + +/** + * payload order for INFORMATIONAL responder + */ +static payload_order_t informational_r_payload_order[] = { +/* payload type notify type */ + {NOTIFY, UPDATE_SA_ADDRESSES}, + {NOTIFY, NAT_DETECTION_SOURCE_IP}, + {NOTIFY, NAT_DETECTION_DESTINATION_IP}, + {NOTIFY, COOKIE2}, + {NOTIFY, 0}, + {DELETE, 0}, + {CONFIGURATION, 0}, }; /** * Message rule for CREATE_CHILD_SA from initiator. */ static payload_rule_t create_child_sa_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, - {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, - {NONCE,1,1,TRUE,FALSE}, - {KEY_EXCHANGE,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, - {VENDOR_ID,0,10,TRUE,FALSE}, +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE}, + {NONCE, 1, 1, TRUE, FALSE}, + {KEY_EXCHANGE, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, + {CONFIGURATION, 0, 1, TRUE, FALSE}, + {VENDOR_ID, 0, 10, TRUE, FALSE}, +}; + +/** + * payload order for CREATE_CHILD_SA from initiator. + */ +static payload_order_t create_child_sa_i_payload_order[] = { +/* payload type notify type */ + {NOTIFY, REKEY_SA}, + {NOTIFY, IPCOMP_SUPPORTED}, + {NOTIFY, USE_TRANSPORT_MODE}, + {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED}, + {NOTIFY, NON_FIRST_FRAGMENTS_ALSO}, + {SECURITY_ASSOCIATION, 0}, + {NONCE, 0}, + {KEY_EXCHANGE, 0}, + {TRAFFIC_SELECTOR_INITIATOR, 0}, + {TRAFFIC_SELECTOR_RESPONDER, 0}, + {NOTIFY, 0}, }; /** * Message rule for CREATE_CHILD_SA from responder. */ static payload_rule_t create_child_sa_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, - {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, - {NONCE,1,1,TRUE,FALSE}, - {KEY_EXCHANGE,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE}, - {TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE}, - {CONFIGURATION,0,1,TRUE,FALSE}, - {VENDOR_ID,0,10,TRUE,FALSE}, +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, + {SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE}, + {NONCE, 1, 1, TRUE, FALSE}, + {KEY_EXCHANGE, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE}, + {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, + {CONFIGURATION, 0, 1, TRUE, FALSE}, + {VENDOR_ID, 0, 10, TRUE, FALSE}, }; -#ifdef P2P /** - * Message rule for P2P_CONNECT from initiator. + * payload order for CREATE_CHILD_SA from responder. */ -static payload_rule_t p2p_connect_i_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, - {ID_PEER,1,1,TRUE,FALSE}, - {VENDOR_ID,0,10,TRUE,FALSE} +static payload_order_t create_child_sa_r_payload_order[] = { +/* payload type notify type */ + {NOTIFY, IPCOMP_SUPPORTED}, + {NOTIFY, USE_TRANSPORT_MODE}, + {NOTIFY, ESP_TFC_PADDING_NOT_SUPPORTED}, + {NOTIFY, NON_FIRST_FRAGMENTS_ALSO}, + {SECURITY_ASSOCIATION, 0}, + {NONCE, 0}, + {KEY_EXCHANGE, 0}, + {TRAFFIC_SELECTOR_INITIATOR, 0}, + {TRAFFIC_SELECTOR_RESPONDER, 0}, + {NOTIFY, ADDITIONAL_TS_POSSIBLE}, + {NOTIFY, 0}, }; +#ifdef ME /** - * Message rule for P2P_CONNECT from responder. + * Message rule for ME_CONNECT from initiator. */ -static payload_rule_t p2p_connect_r_payload_rules[] = { - {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE}, - {VENDOR_ID,0,10,TRUE,FALSE} +static payload_rule_t me_connect_i_payload_rules[] = { +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, + {ID_PEER, 1, 1, TRUE, FALSE}, + {VENDOR_ID, 0, 10, TRUE, FALSE} }; -#endif /* P2P */ + +/** + * payload order for ME_CONNECT from initiator. + */ +static payload_order_t me_connect_i_payload_order[] = { +/* payload type notify type */ + {NOTIFY, 0}, + {ID_PEER, 0}, + {VENDOR_ID, 0}, +}; + +/** + * Message rule for ME_CONNECT from responder. + */ +static payload_rule_t me_connect_r_payload_rules[] = { +/* payload type min max encr suff */ + {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, + {VENDOR_ID, 0, 10, TRUE, FALSE} +}; + +/** + * payload order for ME_CONNECT from responder. + */ +static payload_order_t me_connect_r_payload_order[] = { +/* payload type notify type */ + {NOTIFY, 0}, + {VENDOR_ID, 0}, +}; +#endif /* ME */ /** * Message rules, defines allowed payloads. */ static message_rule_t message_rules[] = { - {IKE_SA_INIT,TRUE,FALSE,(sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_i_payload_rules}, - {IKE_SA_INIT,FALSE,FALSE,(sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)),ike_sa_init_r_payload_rules}, - {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules}, - {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules}, - {INFORMATIONAL,TRUE,TRUE,(sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),informational_i_payload_rules}, - {INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules}, - {CREATE_CHILD_SA,TRUE,TRUE,(sizeof(create_child_sa_i_payload_rules)/sizeof(payload_rule_t)),create_child_sa_i_payload_rules}, - {CREATE_CHILD_SA,FALSE,TRUE,(sizeof(create_child_sa_r_payload_rules)/sizeof(payload_rule_t)),create_child_sa_r_payload_rules}, -#ifdef P2P - {P2P_CONNECT,TRUE,TRUE,(sizeof(p2p_connect_i_payload_rules)/sizeof(payload_rule_t)),p2p_connect_i_payload_rules}, - {P2P_CONNECT,FALSE,TRUE,(sizeof(p2p_connect_r_payload_rules)/sizeof(payload_rule_t)),p2p_connect_r_payload_rules}, -#endif /* P2P */ + {IKE_SA_INIT, TRUE, FALSE, + (sizeof(ike_sa_init_i_payload_rules)/sizeof(payload_rule_t)), + ike_sa_init_i_payload_rules, + (sizeof(ike_sa_init_i_payload_order)/sizeof(payload_order_t)), + ike_sa_init_i_payload_order, + }, + {IKE_SA_INIT, FALSE, FALSE, + (sizeof(ike_sa_init_r_payload_rules)/sizeof(payload_rule_t)), + ike_sa_init_r_payload_rules, + (sizeof(ike_sa_init_r_payload_order)/sizeof(payload_order_t)), + ike_sa_init_r_payload_order, + }, + {IKE_AUTH, TRUE, TRUE, + (sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)), + ike_auth_i_payload_rules, + (sizeof(ike_auth_i_payload_order)/sizeof(payload_order_t)), + ike_auth_i_payload_order, + }, + {IKE_AUTH, FALSE, TRUE, + (sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)), + ike_auth_r_payload_rules, + (sizeof(ike_auth_r_payload_order)/sizeof(payload_order_t)), + ike_auth_r_payload_order, + }, + {INFORMATIONAL, TRUE, TRUE, + (sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)), + informational_i_payload_rules, + (sizeof(informational_i_payload_order)/sizeof(payload_order_t)), + informational_i_payload_order, + }, + {INFORMATIONAL, FALSE, TRUE, + (sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)), + informational_r_payload_rules, + (sizeof(informational_r_payload_order)/sizeof(payload_order_t)), + informational_r_payload_order, + }, + {CREATE_CHILD_SA, TRUE, TRUE, + (sizeof(create_child_sa_i_payload_rules)/sizeof(payload_rule_t)), + create_child_sa_i_payload_rules, + (sizeof(create_child_sa_i_payload_order)/sizeof(payload_order_t)), + create_child_sa_i_payload_order, + }, + {CREATE_CHILD_SA, FALSE, TRUE, + (sizeof(create_child_sa_r_payload_rules)/sizeof(payload_rule_t)), + create_child_sa_r_payload_rules, + (sizeof(create_child_sa_r_payload_order)/sizeof(payload_order_t)), + create_child_sa_r_payload_order, + }, +#ifdef ME + {ME_CONNECT, TRUE, TRUE, + (sizeof(me_connect_i_payload_rules)/sizeof(payload_rule_t)), + me_connect_i_payload_rules, + (sizeof(me_connect_i_payload_order)/sizeof(payload_order_t)), + me_connect_i_payload_order, + }, + {ME_CONNECT, FALSE, TRUE, + (sizeof(me_connect_r_payload_rules)/sizeof(payload_rule_t)), + me_connect_r_payload_rules, + (sizeof(me_connect_r_payload_order)/sizeof(payload_order_t)), + me_connect_r_payload_order, + }, +#endif /* ME */ }; @@ -517,38 +767,19 @@ static bool is_encoded(private_message_t *this) */ static void add_payload(private_message_t *this, payload_t *payload) { - payload_t *last_payload, *first_payload; - - if ((this->is_request && payload->get_type(payload) == ID_INITIATOR) || - (!this->is_request && payload->get_type(payload) == ID_RESPONDER)) + payload_t *last_payload; + + if (this->payloads->get_count(this->payloads) > 0) { - /* HOTD: insert ID payload in the beginning to respect RFC */ - if (this->payloads->get_first(this->payloads, - (void **)&first_payload) == SUCCESS) - { - payload->set_next_type(payload, first_payload->get_type(first_payload)); - } - else - { - payload->set_next_type(payload, NO_PAYLOAD); - } - this->first_payload = payload->get_type(payload); - this->payloads->insert_first(this->payloads, payload); + this->payloads->get_last(this->payloads, (void **)&last_payload); + last_payload->set_next_type(last_payload, payload->get_type(payload)); } else { - if (this->payloads->get_count(this->payloads) > 0) - { - this->payloads->get_last(this->payloads,(void **) &last_payload); - last_payload->set_next_type(last_payload, payload->get_type(payload)); - } - else - { - this->first_payload = payload->get_type(payload); - } - payload->set_next_type(payload, NO_PAYLOAD); - this->payloads->insert_last(this->payloads, payload); + this->first_payload = payload->get_type(payload); } + payload->set_next_type(payload, NO_PAYLOAD); + this->payloads->insert_last(this->payloads, payload); DBG2(DBG_ENC ,"added payload of type %N to message", payload_type_names, payload->get_type(payload)); @@ -694,9 +925,65 @@ static char* get_string(private_message_t *this, char *buf, int len) } /** + * reorder payloads depending on reordering rules + */ +static void order_payloads(private_message_t *this) +{ + linked_list_t *list; + payload_t *payload; + int i; + + /* move to temp list */ + list = linked_list_create(); + while (this->payloads->remove_last(this->payloads, + (void**)&payload) == SUCCESS) + { + list->insert_first(list, payload); + } + /* for each rule, ... */ + for (i = 0; i < this->message_rule->payload_order_count; i++) + { + enumerator_t *enumerator; + notify_payload_t *notify; + payload_order_t order = this->message_rule->payload_order[i]; + + /* ... find all payload ... */ + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &payload)) + { + /* ... with that type ... */ + if (payload->get_type(payload) == order.type) + { + notify = (notify_payload_t*)payload; + + /**... and check notify for type. */ + if (order.type != NOTIFY || order.notify == 0 || + order.notify == notify->get_notify_type(notify)) + { + list->remove_at(list, enumerator); + add_payload(this, payload); + } + } + } + enumerator->destroy(enumerator); + } + /* append all payloads without a rule to the end */ + while (list->remove_last(list, (void**)&payload) == SUCCESS) + { + DBG1(DBG_ENC, "payload %N has no ordering rule in %N %s", + payload_type_names, payload->get_type(payload), + exchange_type_names, this->message_rule->exchange_type, + this->message_rule->is_request ? "request" : "response"); + add_payload(this, payload); + } + list->destroy(list); +} + +/** * Implementation of private_message_t.encrypt_payloads. */ -static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, signer_t* signer) +static status_t encrypt_payloads(private_message_t *this, + crypter_t *crypter, signer_t* signer) { encryption_payload_t *encryption_payload = NULL; status_t status; @@ -778,7 +1065,8 @@ static status_t encrypt_payloads (private_message_t *this,crypter_t *crypter, si /** * Implementation of message_t.generate. */ -static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* signer, packet_t **packet) +static status_t generate(private_message_t *this, crypter_t *crypter, + signer_t* signer, packet_t **packet) { generator_t *generator; ike_header_t *ike_header; @@ -795,8 +1083,6 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* return SUCCESS; } - DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); - if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED) { DBG1(DBG_ENC, "exchange type is not defined"); @@ -819,6 +1105,10 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* return NOT_SUPPORTED; } + order_payloads(this); + + DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); + /* going to encrypt all content which have to be encrypted */ status = encrypt_payloads(this, crypter, signer); if (status != SUCCESS) @@ -842,7 +1132,7 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t* payload = (payload_t*)ike_header; - /* generate every payload expect last one, this is doen later*/ + /* generate every payload expect last one, this is done later*/ iterator = this->payloads->create_iterator(this->payloads, TRUE); while(iterator->iterate(iterator, (void**)&next_payload)) { @@ -1346,3 +1636,4 @@ message_t *message_create() { return message_create_from_packet(NULL); } + diff --git a/src/charon/encoding/message.h b/src/charon/encoding/message.h index 35b659f33..8cc604ea7 100644 --- a/src/charon/encoding/message.h +++ b/src/charon/encoding/message.h @@ -1,10 +1,3 @@ -/** - * @file message.h - * - * @brief Interface of message_t. - * - */ - /* * Copyright (C) 2006-2007 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger @@ -21,6 +14,13 @@ * 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. + * + * $Id: message.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup message message + * @{ @ingroup encoding */ #ifndef MESSAGE_H_ @@ -38,148 +38,126 @@ typedef struct message_t message_t; #include <crypto/signers/signer.h> /** - * @brief This class is used to represent an IKEv2-Message. + * This class is used to represent an IKEv2-Message. * * The message handles parsing and generation of payloads * via parser_t/generator_t. Encryption is done transparently * via the encryption_payload_t. A set of rules for messages * and payloads does check parsed messages. - * - * @b Constructors: - * - message_create() - * - message_create_from_packet() - * - message_create_notify_reply() - * - * @ingroup encoding */ struct message_t { /** - * @brief Sets the IKE major version of the message. + * Sets the IKE major version of the message. * - * @param this message_t object * @param major_version major version to set */ void (*set_major_version) (message_t *this,u_int8_t major_version); /** - * @brief Gets the IKE major version of the message. + * Gets the IKE major version of the message. * - * @param this message_t object * @return major version of the message */ u_int8_t (*get_major_version) (message_t *this); /** - * @brief Sets the IKE minor version of the message. + * Sets the IKE minor version of the message. * - * @param this message_t object * @param minor_version minor version to set */ void (*set_minor_version) (message_t *this,u_int8_t minor_version); /** - * @brief Gets the IKE minor version of the message. + * Gets the IKE minor version of the message. * - * @param this message_t object * @return minor version of the message */ u_int8_t (*get_minor_version) (message_t *this); /** - * @brief Sets the Message ID of the message. + * Sets the Message ID of the message. * - * @param this message_t object - * @param message_id message_id to set + * @param message_id message_id to set */ void (*set_message_id) (message_t *this,u_int32_t message_id); /** - * @brief Gets the Message ID of the message. + * Gets the Message ID of the message. * - * @param this message_t object * @return message_id type of the message */ u_int32_t (*get_message_id) (message_t *this); /** - * @brief Gets the initiator SPI of the message. + * Gets the initiator SPI of the message. * - * @param this message_t object * @return initiator spi of the message */ u_int64_t (*get_initiator_spi) (message_t *this); /** - * @brief Gets the responder SPI of the message. + * Gets the responder SPI of the message. * - * @param this message_t object * @return responder spi of the message */ u_int64_t (*get_responder_spi) (message_t *this); /** - * @brief Sets the IKE_SA ID of the message. + * Sets the IKE_SA ID of the message. * * ike_sa_id gets cloned. * - * @param this message_t object * @param ike_sa_id ike_sa_id to set */ void (*set_ike_sa_id) (message_t *this, ike_sa_id_t * ike_sa_id); /** - * @brief Gets the IKE_SA ID of the message. + * Gets the IKE_SA ID of the message. * * The ike_sa_id points to the message internal id, do not modify. * - * @param this message_t object * @return ike_sa_id of message */ ike_sa_id_t *(*get_ike_sa_id) (message_t *this); /** - * @brief Sets the exchange type of the message. + * Sets the exchange type of the message. * - * @param this message_t object * @param exchange_type exchange_type to set */ void (*set_exchange_type) (message_t *this,exchange_type_t exchange_type); /** - * @brief Gets the exchange type of the message. + * Gets the exchange type of the message. * - * @param this message_t object * @return exchange type of the message */ exchange_type_t (*get_exchange_type) (message_t *this); /** - * @brief Gets the payload type of the first payload. + * Gets the payload type of the first payload. * - * @param this message_t object * @return payload type of the first payload */ payload_type_t (*get_first_payload_type) (message_t *this); /** - * @brief Sets the request flag. + * Sets the request flag. * - * @param this message_t object - * @param original_initiator TRUE if message is a request, FALSE if it is a reply + * @param request TRUE if message is a request, FALSE if it is a reply */ - void (*set_request) (message_t *this,bool request); + void (*set_request) (message_t *this, bool request); /** - * @brief Gets request flag. + * Gets request flag. * - * @param this message_t object * @return TRUE if message is a request, FALSE if it is a reply */ bool (*get_request) (message_t *this); /** - * @brief Append a payload to the message. + * Append a payload to the message. * * If the payload must be encrypted is not specified here. Encryption * of payloads is evaluated via internal rules for the messages and @@ -187,19 +165,17 @@ struct message_t { * all payloads to encrypt are added to the encryption payload, which is * always the last one. * - * @param this message_t object * @param payload payload to append */ void (*add_payload) (message_t *this, payload_t *payload); /** - * @brief Build a notify payload and add it to the message. + * Build a notify payload and add it to the message. * * This is a helper method to create notify messages or add * notify payload to messages. The flush parameter specifies if existing * payloads should get removed before appending the notify. * - * @param this message_t object * @param flush TRUE to remove existing payloads * @param type type of the notify * @param data a chunk of data to add to the notify, gets cloned @@ -208,13 +184,12 @@ struct message_t { chunk_t data); /** - * @brief Parses header of message. + * Parses header of message. * * Begins parisng of a message created via message_create_from_packet(). * The parsing context is stored, so a subsequent call to parse_body() * will continue the parsing process. * - * @param this message_t object * @return * - SUCCESS if header could be parsed * - PARSE_ERROR if corrupted/invalid data found @@ -223,7 +198,7 @@ struct message_t { status_t (*parse_header) (message_t *this); /** - * @brief Parses body of message. + * Parses body of message. * * The body gets not only parsed, but rather it gets verified. * All payloads are verified if they are allowed to exist in the message @@ -234,7 +209,6 @@ struct message_t { * Crypter/signer can be omitted (by passing NULL) when no encryption * payload is expected. * - * @param this message_t object * @param crypter crypter to decrypt encryption payloads * @param signer signer to verifiy a message with an encryption payload * @return @@ -249,7 +223,7 @@ struct message_t { status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer); /** - * @brief Generates the UDP packet of specific message. + * Generates the UDP packet of specific message. * * Payloads which must be encrypted are generated first and added to * an encryption payload. This encryption payload will get encrypted via @@ -260,7 +234,6 @@ struct message_t { * payload is expected. * Generation is only done once, multiple calls will just return a packet copy. * - * @param this message_t object * @param crypter crypter to use when a payload must be encrypted * @param signer signer to build a mac * @param packet copy of generated packet @@ -273,103 +246,91 @@ struct message_t { status_t (*generate) (message_t *this, crypter_t *crypter, signer_t *signer, packet_t **packet); /** - * @brief Gets the source host informations. + * Gets the source host informations. * * @warning Returned host_t object is not getting cloned, * do not destroy nor modify. * - * @param this message_t object * @return host_t object representing source host */ host_t * (*get_source) (message_t *this); /** - * @brief Sets the source host informations. + * Sets the source host informations. * * @warning host_t object is not getting cloned and gets destroyed by * message_t.destroy or next call of message_t.set_source. * - * @param this message_t object * @param host host_t object representing source host */ void (*set_source) (message_t *this, host_t *host); /** - * @brief Gets the destination host informations. + * Gets the destination host informations. * * @warning Returned host_t object is not getting cloned, * do not destroy nor modify. * - * @param this message_t object * @return host_t object representing destination host */ host_t * (*get_destination) (message_t *this); /** - * @brief Sets the destination host informations. + * Sets the destination host informations. * * @warning host_t object is not getting cloned and gets destroyed by * message_t.destroy or next call of message_t.set_destination. * - * @param this message_t object * @param host host_t object representing destination host */ void (*set_destination) (message_t *this, host_t *host); /** - * @brief Returns an iterator on all stored payloads. + * Returns an iterator on all stored payloads. * * @warning Don't insert payloads over this iterator. * Use add_payload() instead. * - * @param this message_t object * @return iterator_t object which has to get destroyd by the caller */ iterator_t * (*get_payload_iterator) (message_t *this); /** - * @brief Find a payload of a specific type. + * Find a payload of a specific type. * * Returns the first occurance. * - * @param this message_t object * @param type type of the payload to find * @return payload, or NULL if no such payload found */ payload_t* (*get_payload) (message_t *this, payload_type_t type); /** - * @brief Returns a clone of the internal stored packet_t object. + * Returns a clone of the internal stored packet_t object. * - * @param this message_t object * @return packet_t object as clone of internal one */ packet_t * (*get_packet) (message_t *this); /** - * @brief Returns a clone of the internal stored packet_t data. + * Returns a clone of the internal stored packet_t data. * - * @param this message_t object * @return clone of the internal stored packet_t data. */ chunk_t (*get_packet_data) (message_t *this); /** - * @brief Destroys a message and all including objects. - * - * @param this message_t object + * Destroys a message and all including objects. */ void (*destroy) (message_t *this); }; /** - * @brief Creates an message_t object from a incoming UDP Packet. + * Creates an message_t object from a incoming UDP Packet. * * @warning the given packet_t object is not copied and gets * destroyed in message_t's destroy call. * - * @warning Packet is not parsed in here! - * * - exchange_type is set to NOT_SET * - original_initiator is set to TRUE * - is_request is set to TRUE @@ -377,23 +338,19 @@ struct message_t { * * @param packet packet_t object which is assigned to message * @return message_t object - * - * @ingroup encoding */ message_t * message_create_from_packet(packet_t *packet); /** - * @brief Creates an empty message_t object. + * Creates an empty message_t object. * * - exchange_type is set to NOT_SET * - original_initiator is set to TRUE * - is_request is set to TRUE * * @return message_t object - * - * @ingroup encoding */ message_t * message_create(void); -#endif /*MESSAGE_H_*/ +#endif /*MESSAGE_H_ @} */ diff --git a/src/charon/encoding/parser.c b/src/charon/encoding/parser.c index d7caf7099..1b03aacb2 100644 --- a/src/charon/encoding/parser.c +++ b/src/charon/encoding/parser.c @@ -1,10 +1,3 @@ -/** - * @file parser.c - * - * @brief Implementation of parser_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: parser.c 4010 2008-05-23 18:23:17Z martin $ */ #include <stdlib.h> @@ -67,7 +62,7 @@ struct private_parser_t { parser_t public; /** - * @brief Parse a 4-Bit unsigned integer from the current parsing position. + * Parse a 4-Bit unsigned integer from the current parsing position. * * @param this parser_t object * @param rule_number number of current rule @@ -79,7 +74,7 @@ struct private_parser_t { status_t (*parse_uint4) (private_parser_t *this, int rule_number, u_int8_t *output_pos); /** - * @brief Parse a 8-Bit unsigned integer from the current parsing position. + * Parse a 8-Bit unsigned integer from the current parsing position. * * @param this parser_t object * @param rule_number number of current rule @@ -91,7 +86,7 @@ struct private_parser_t { status_t (*parse_uint8) (private_parser_t *this, int rule_number, u_int8_t *output_pos); /** - * @brief Parse a 15-Bit unsigned integer from the current parsing position. + * Parse a 15-Bit unsigned integer from the current parsing position. * * This is a special case used for ATTRIBUTE_TYPE. * Big-/Little-endian conversion is done here. @@ -106,7 +101,7 @@ struct private_parser_t { status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos); /** - * @brief Parse a 16-Bit unsigned integer from the current parsing position. + * Parse a 16-Bit unsigned integer from the current parsing position. * * Big-/Little-endian conversion is done here. * @@ -120,7 +115,7 @@ struct private_parser_t { status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos); /** - * @brief Parse a 32-Bit unsigned integer from the current parsing position. + * Parse a 32-Bit unsigned integer from the current parsing position. * * Big-/Little-endian conversion is done here. * @@ -134,7 +129,7 @@ struct private_parser_t { status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos); /** - * @brief Parse a 64-Bit unsigned integer from the current parsing position. + * Parse a 64-Bit unsigned integer from the current parsing position. * * @todo add support for big-endian machines. * @@ -148,7 +143,7 @@ struct private_parser_t { status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos); /** - * @brief Parse a given amount of bytes and writes them to a specific location + * Parse a given amount of bytes and writes them to a specific location * * @param this parser_t object * @param rule_number number of current rule @@ -161,7 +156,7 @@ struct private_parser_t { status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes); /** - * @brief Parse a single Bit from the current parsing position + * Parse a single Bit from the current parsing position * * @param this parser_t object * @param rule_number number of current rule @@ -173,7 +168,7 @@ struct private_parser_t { status_t (*parse_bit) (private_parser_t *this, int rule_number, bool *output_pos); /** - * @brief Parse substructures in a list + * Parse substructures in a list * * This function calls the parser recursively to parse contained substructures * in a linked_list_t. The list must already be created. Payload defines @@ -192,7 +187,7 @@ struct private_parser_t { status_t (*parse_list) (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length); /** - * @brief Parse data from current parsing position in a chunk. + * Parse data from current parsing position in a chunk. * * This function clones length number of bytes to output_pos, without * modifiyng them. Space will be allocated and must be freed by caller. @@ -690,6 +685,11 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ return PARSE_ERROR; } payload_length = *(u_int16_t*)(output + rule->offset); + if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH) + { + pld->destroy(pld); + return PARSE_ERROR; + } break; } case HEADER_LENGTH: @@ -722,8 +722,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case PROPOSALS: { - size_t proposals_length = payload_length - SA_PAYLOAD_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS) + if (payload_length < SA_PAYLOAD_HEADER_LENGTH || + this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, + payload_length - SA_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -732,8 +733,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case TRANSFORMS: { - size_t transforms_length = payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS) + if (payload_length < spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH || + this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, + payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -742,8 +744,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case TRANSFORM_ATTRIBUTES: { - size_t transform_a_length = payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS) + if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH || + this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, + payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -752,8 +755,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case CONFIGURATION_ATTRIBUTES: { - size_t configuration_attributes_length = payload_length - CP_PAYLOAD_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, CONFIGURATION_ATTRIBUTE, configuration_attributes_length) != SUCCESS) + if (payload_length < CP_PAYLOAD_HEADER_LENGTH || + this->parse_list(this, rule_number, output + rule->offset, CONFIGURATION_ATTRIBUTE, + payload_length - CP_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -814,8 +818,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case NONCE_DATA: { - size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS) + if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - NONCE_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -824,8 +829,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case ID_DATA: { - size_t data_length = payload_length - ID_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < ID_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - ID_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -834,8 +840,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case AUTH_DATA: { - size_t data_length = payload_length - AUTH_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - AUTH_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -844,8 +851,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case CERT_DATA: { - size_t data_length = payload_length - CERT_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < CERT_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - CERT_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -854,8 +862,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case CERTREQ_DATA: { - size_t data_length = payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -864,8 +873,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case EAP_DATA: { - size_t data_length = payload_length - EAP_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < EAP_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - EAP_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -874,8 +884,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case SPIS: { - size_t data_length = payload_length - DELETE_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - DELETE_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -884,8 +895,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case VID_DATA: { - size_t data_length = payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -904,8 +916,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case KEY_EXCHANGE_DATA: { - size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS) + if (payload_length < KE_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - KE_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -914,8 +927,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case NOTIFICATION_DATA: { - size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size; - if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS) + if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -924,8 +938,9 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case ENCRYPTED_DATA: { - size_t data_length = payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS) + if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; @@ -954,18 +969,20 @@ static status_t parse_payload(private_parser_t *this, payload_type_t payload_typ } case TRAFFIC_SELECTORS: { - size_t traffic_selectors_length = payload_length - TS_PAYLOAD_HEADER_LENGTH; - if (this->parse_list(this, rule_number, output + rule->offset, TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic_selectors_length) != SUCCESS) + if (payload_length < TS_PAYLOAD_HEADER_LENGTH || + this->parse_list(this, rule_number, output + rule->offset, TRAFFIC_SELECTOR_SUBSTRUCTURE, + payload_length - TS_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; } break; } - case UNKNOWN_PAYLOAD: + case UNKNOWN_DATA: { - size_t unknown_payload_data_length = payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH; - if (this->parse_chunk(this, rule_number, output + rule->offset, unknown_payload_data_length) != SUCCESS) + if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH || + this->parse_chunk(this, rule_number, output + rule->offset, + payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH) != SUCCESS) { pld->destroy(pld); return PARSE_ERROR; diff --git a/src/charon/encoding/parser.h b/src/charon/encoding/parser.h index e9978524c..58778b57a 100644 --- a/src/charon/encoding/parser.h +++ b/src/charon/encoding/parser.h @@ -1,10 +1,3 @@ -/** - * @file parser.h - * - * @brief Interface of parser_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: parser.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup parser parser + * @{ @ingroup encoding */ #ifndef PARSER_H_ @@ -31,65 +31,51 @@ typedef struct parser_t parser_t; #include <encoding/payloads/payload.h> /** - * @brief A parser_t class to parse IKEv2 payloads. + * A parser_t class to parse IKEv2 payloads. * * A parser is used for parsing one chunk of data. Multiple * payloads can be parsed out of the chunk using parse_payload. * The parser remains the state until destroyed. - * - * @b Constructors: - * - parser_create() - * - * @ingroup encoding */ struct parser_t { /** - * @brief Parses the next payload. + * Parses the next payload. * * @warning Caller is responsible for freeing allocated payload. * * Rules for parsing are described in the payload definition. * - * @param this parser_t bject - * @param payload_type payload type to parse - * @param[out] payload pointer where parsed payload was allocated + * @param payload_type payload type to parse + * @param payload pointer where parsed payload was allocated * @return - * - SUCCESSFUL if succeeded, - * - PARSE_ERROR if corrupted/invalid data found + * - SUCCESSFUL if succeeded, + * - PARSE_ERROR if corrupted/invalid data found */ status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload); /** * Gets the remaining byte count which is not currently parsed. - * - * @param parser parser_t object */ int (*get_remaining_byte_count) (parser_t *this); /** - * @brief Resets the current parser context. - * - * @param parser parser_t object + * Resets the current parser context. */ void (*reset_context) (parser_t *this); /** - * @brief Destroys a parser_t object. - * - * @param parser parser_t object + * Destroys a parser_t object. */ void (*destroy) (parser_t *this); }; /** - * @brief Constructor to create a parser_t object. - * - * @param data chunk of data to parse with this parser_t object - * @return parser_t object + * Constructor to create a parser_t object. * - * @ingroup encoding + * @param data chunk of data to parse with this parser_t object + * @return parser_t object */ parser_t *parser_create(chunk_t data); -#endif /*PARSER_H_*/ +#endif /*PARSER_H_ @} */ diff --git a/src/charon/encoding/payloads/auth_payload.c b/src/charon/encoding/payloads/auth_payload.c index 256d6c8a4..f9ca23236 100644 --- a/src/charon/encoding/payloads/auth_payload.c +++ b/src/charon/encoding/payloads/auth_payload.c @@ -1,10 +1,3 @@ -/** - * @file auth_payload.h - * - * @brief Implementation of auth_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: auth_payload.c 4051 2008-06-10 09:08:27Z tobias $ */ #include "auth_payload.h" @@ -116,7 +111,8 @@ encoding_rule_t auth_payload_encodings[] = { static status_t verify(private_auth_payload_t *this) { if (this->auth_method == 0 || - (this->auth_method >= 4 && this->auth_method <= 200)) + (this->auth_method >= 4 && this->auth_method <= 8) || + (this->auth_method >= 12 && this->auth_method <= 200)) { /* reserved IDs */ return FAILED; diff --git a/src/charon/encoding/payloads/auth_payload.h b/src/charon/encoding/payloads/auth_payload.h index 2db82ec0b..bdbba9e35 100644 --- a/src/charon/encoding/payloads/auth_payload.h +++ b/src/charon/encoding/payloads/auth_payload.h @@ -1,10 +1,3 @@ -/** - * @file auth_payload.h - * - * @brief Interface of auth_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: auth_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup auth_payload auth_payload + * @{ @ingroup payloads */ #ifndef AUTH_PAYLOAD_H_ @@ -32,20 +32,13 @@ typedef struct auth_payload_t auth_payload_t; /** * Length of a auth payload without the auth data in bytes. - * - * @ingroup payloads */ #define AUTH_PAYLOAD_HEADER_LENGTH 8 /** - * @brief Class representing an IKEv2 AUTH payload. + * Class representing an IKEv2 AUTH payload. * * The AUTH payload format is described in RFC section 3.8. - * - * @b Constructors: - * - auth_payload_create() - * - * @ingroup payloads */ struct auth_payload_t { @@ -55,67 +48,57 @@ struct auth_payload_t { payload_t payload_interface; /** - * @brief Set the AUTH method. + * Set the AUTH method. * - * @param this calling auth_payload_t object * @param method auth_method_t to use */ void (*set_auth_method) (auth_payload_t *this, auth_method_t method); /** - * @brief Get the AUTH method. + * Get the AUTH method. * - * @param this calling auth_payload_t object * @return auth_method_t used */ auth_method_t (*get_auth_method) (auth_payload_t *this); /** - * @brief Set the AUTH data. + * Set the AUTH data. * - * Data are getting cloned. + * Data gets cloned. * - * @param this calling auth_payload_t object * @param data AUTH data as chunk_t */ void (*set_data) (auth_payload_t *this, chunk_t data); /** - * @brief Get the AUTH data. + * Get the AUTH data. * * Returned data are a copy of the internal one. * - * @param this calling auth_payload_t object * @return AUTH data as chunk_t */ chunk_t (*get_data_clone) (auth_payload_t *this); /** - * @brief Get the AUTH data. + * Get the AUTH data. * * Returned data are NOT copied * - * @param this calling auth_payload_t object * @return AUTH data as chunk_t */ chunk_t (*get_data) (auth_payload_t *this); /** - * @brief Destroys an auth_payload_t object. - * - * @param this auth_payload_t object to destroy + * Destroys an auth_payload_t object. */ void (*destroy) (auth_payload_t *this); }; /** - * @brief Creates an empty auth_payload_t object. + * Creates an empty auth_payload_t object. * * @return auth_payload_t object - * - * @ingroup payloads */ auth_payload_t *auth_payload_create(void); - -#endif /* AUTH_PAYLOAD_H_ */ +#endif /* AUTH_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/cert_payload.c b/src/charon/encoding/payloads/cert_payload.c index c456f4936..99f504c5e 100644 --- a/src/charon/encoding/payloads/cert_payload.c +++ b/src/charon/encoding/payloads/cert_payload.c @@ -1,12 +1,6 @@ -/** - * @file cert_payload.c - * - * @brief Implementation of cert_payload_t. - * - */ - /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -19,29 +13,32 @@ * 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. + * + * $Id: cert_payload.c 3852 2008-04-18 21:27:08Z andreas $ */ #include <stddef.h> +#include <ctype.h> -#include "cert_payload.h" +#include <daemon.h> +#include "cert_payload.h" -ENUM(cert_encoding_names, CERT_NONE, CERT_OCSP_CONTENT, - "CERT_NONE", - "CERT_PKCS7_WRAPPED_X509", - "CERT_PGP", - "CERT_DNS_SIGNED_KEY", - "CERT_X509_SIGNATURE", - "CERT_X509_KEY_EXCHANGE", - "CERT_KERBEROS_TOKENS", - "CERT_CRL", - "CERT_ARL", - "CERT_SPKI", - "CERT_X509_ATTRIBUTE", - "CERT_RAW_RSA_KEY", - "CERT_X509_HASH_AND_URL", - "CERT_X509_HASH_AND_URL_BUNDLE", - "CERT_OCSP_CONTENT", +ENUM(cert_encoding_names, ENC_PKCS7_WRAPPED_X509, ENC_OCSP_CONTENT, + "ENC_PKCS7_WRAPPED_X509", + "ENC_PGP", + "ENC_DNS_SIGNED_KEY", + "ENC_X509_SIGNATURE", + "ENC_X509_KEY_EXCHANGE", + "ENC_KERBEROS_TOKENS", + "ENC_CRL", + "ENC_ARL", + "ENC_SPKI", + "ENC_X509_ATTRIBUTE", + "ENC_RAW_RSA_KEY", + "ENC_X509_HASH_AND_URL", + "ENC_X509_HASH_AND_URL_BUNDLE", + "ENC_OCSP_CONTENT", ); typedef struct private_cert_payload_t private_cert_payload_t; @@ -74,12 +71,17 @@ struct private_cert_payload_t { /** * Encoding of the CERT Data. */ - u_int8_t cert_encoding; + u_int8_t encoding; /** * The contained cert data value. */ - chunk_t cert_data; + chunk_t data; + + /** + * TRUE if the "Hash and URL" data is invalid + */ + bool invalid_hash_and_url; }; /** @@ -105,9 +107,9 @@ encoding_rule_t cert_payload_encodings[] = { /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)}, /* 1 Byte CERT type*/ - { U_INT_8, offsetof(private_cert_payload_t, cert_encoding) }, + { U_INT_8, offsetof(private_cert_payload_t, encoding) }, /* some cert data bytes, length is defined in PAYLOAD_LENGTH */ - { CERT_DATA, offsetof(private_cert_payload_t, cert_data) } + { CERT_DATA, offsetof(private_cert_payload_t, data) } }; /* @@ -128,11 +130,41 @@ encoding_rule_t cert_payload_encodings[] = { */ static status_t verify(private_cert_payload_t *this) { - if ((this->cert_encoding == 0) || - ((this->cert_encoding >= CERT_ROOF) && (this->cert_encoding <= 200))) + if (this->encoding == ENC_X509_HASH_AND_URL || + this->encoding == ENC_X509_HASH_AND_URL_BUNDLE) { - /* reserved IDs */ - return FAILED; + /* coarse verification of "Hash and URL" encoded certificates */ + if (this->data.len <= 20) + { + DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore", + this->data.len); + this->invalid_hash_and_url = TRUE; + return SUCCESS; + } + + int i = 20; /* skipping the hash */ + for (; i < this->data.len; ++i) + { + if (this->data.ptr[i] == '\0') + { + /* null terminated, fine */ + return SUCCESS; + } + else if (!isprint(this->data.ptr[i])) + { + DBG1(DBG_ENC, "non printable characters in url of hash-and-url" + " encoded certificate payload, ignore"); + this->invalid_hash_and_url = TRUE; + return SUCCESS; + } + } + + /* URL is not null terminated, correct that */ + chunk_t data = chunk_alloc(this->data.len + 1); + memcpy(data.ptr, this->data.ptr, this->data.len); + data.ptr[this->data.len] = '\0'; + chunk_free(&this->data); + this->data = data; } return SUCCESS; } @@ -140,7 +172,8 @@ static status_t verify(private_cert_payload_t *this) /** * Implementation of cert_payload_t.get_encoding_rules. */ -static void get_encoding_rules(private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +static void get_encoding_rules(private_cert_payload_t *this, + encoding_rule_t **rules, size_t *rule_count) { *rules = cert_payload_encodings; *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t); @@ -159,7 +192,7 @@ static payload_type_t get_payload_type(private_cert_payload_t *this) */ static payload_type_t get_next_type(private_cert_payload_t *this) { - return (this->next_payload); + return this->next_payload; } /** @@ -179,56 +212,56 @@ static size_t get_length(private_cert_payload_t *this) } /** - * Implementation of cert_payload_t.set_cert_encoding. - */ -static void set_cert_encoding (private_cert_payload_t *this, cert_encoding_t encoding) -{ - this->cert_encoding = encoding; -} - -/** * Implementation of cert_payload_t.get_cert_encoding. */ -static cert_encoding_t get_cert_encoding (private_cert_payload_t *this) +static cert_encoding_t get_cert_encoding(private_cert_payload_t *this) { - return (this->cert_encoding); + return this->encoding; } /** - * Implementation of cert_payload_t.set_data. + * Implementation of cert_payload_t.get_cert. */ -static void set_data (private_cert_payload_t *this, chunk_t data) +static certificate_t *get_cert(private_cert_payload_t *this) { - if (this->cert_data.ptr != NULL) + if (this->encoding != ENC_X509_SIGNATURE) { - chunk_free(&(this->cert_data)); + return NULL; } - this->cert_data.ptr = clalloc(data.ptr,data.len); - this->cert_data.len = data.len; - this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->cert_data.len; + return lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, chunk_clone(this->data), + BUILD_END); } /** - * Implementation of cert_payload_t.get_data. + * Implementation of cert_payload_t.get_hash. */ -static chunk_t get_data (private_cert_payload_t *this) +static chunk_t get_hash(private_cert_payload_t *this) { - return (this->cert_data); + chunk_t hash = chunk_empty; + if ((this->encoding != ENC_X509_HASH_AND_URL && + this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || + this->invalid_hash_and_url) + { + return hash; + } + hash.ptr = this->data.ptr; + hash.len = 20; + return hash; } /** - * Implementation of cert_payload_t.get_data_clone. + * Implementation of cert_payload_t.get_url. */ -static chunk_t get_data_clone (private_cert_payload_t *this) +static char *get_url(private_cert_payload_t *this) { - chunk_t cloned_data; - if (this->cert_data.ptr == NULL) + if ((this->encoding != ENC_X509_HASH_AND_URL && + this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || + this->invalid_hash_and_url) { - return (this->cert_data); + return NULL; } - cloned_data.ptr = clalloc(this->cert_data.ptr,this->cert_data.len); - cloned_data.len = this->cert_data.len; - return cloned_data; + return (char*)this->data.ptr + 20; } /** @@ -236,11 +269,7 @@ static chunk_t get_data_clone (private_cert_payload_t *this) */ static void destroy(private_cert_payload_t *this) { - if (this->cert_data.ptr != NULL) - { - chunk_free(&(this->cert_data)); - } - + chunk_free(&this->data); free(this); } @@ -251,7 +280,6 @@ cert_payload_t *cert_payload_create() { private_cert_payload_t *this = malloc_thing(private_cert_payload_t); - /* interface functions */ this->public.payload_interface.verify = (status_t (*) (payload_t*))verify; this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**, size_t*))get_encoding_rules; this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length; @@ -260,31 +288,60 @@ cert_payload_t *cert_payload_create() this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type; this->public.payload_interface.destroy = (void (*) (payload_t*))destroy; - /* public functions */ this->public.destroy = (void (*) (cert_payload_t*))destroy; - this->public.set_cert_encoding = (void (*) (cert_payload_t*,cert_encoding_t))set_cert_encoding; + this->public.get_cert = (certificate_t* (*) (cert_payload_t*))get_cert; this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t*))get_cert_encoding; - this->public.set_data = (void (*) (cert_payload_t*,chunk_t))set_data; - this->public.get_data_clone = (chunk_t (*) (cert_payload_t*))get_data_clone; - this->public.get_data = (chunk_t (*) (cert_payload_t*))get_data; + this->public.get_hash = (chunk_t (*) (cert_payload_t*))get_hash; + this->public.get_url = (char* (*) (cert_payload_t*))get_url; - /* private variables */ this->critical = FALSE; this->next_payload = NO_PAYLOAD; this->payload_length = CERT_PAYLOAD_HEADER_LENGTH; - this->cert_data = chunk_empty; + this->data = chunk_empty; + this->encoding = 0; + this->invalid_hash_and_url = FALSE; - return (&(this->public)); + return &this->public; } /* * Described in header */ -cert_payload_t *cert_payload_create_from_x509(x509_t *cert) +cert_payload_t *cert_payload_create_from_cert(certificate_t *cert) { - cert_payload_t *this = cert_payload_create(); + private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create(); + + switch (cert->get_type(cert)) + { + case CERT_X509: + this->encoding = ENC_X509_SIGNATURE; + break; + default: + DBG1(DBG_ENC, "embedding %N certificate in payload failed", + certificate_type_names, cert->get_type(cert)); + free(this); + return NULL; + } + this->data = cert->get_encoding(cert); + this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len; + return &this->public; +} - this->set_cert_encoding(this, CERT_X509_SIGNATURE); - this->set_data(this, cert->get_certificate(cert)); - return this; +/* + * Described in header + */ +cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url) +{ + private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create(); + chunk_t url_chunk; + + this->encoding = ENC_X509_HASH_AND_URL; + + url_chunk.ptr = url; + url_chunk.len = strlen(url) + 1; + + this->data = chunk_cat("cc", hash, url_chunk); + this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len; + return &this->public; } + diff --git a/src/charon/encoding/payloads/cert_payload.h b/src/charon/encoding/payloads/cert_payload.h index bcb961398..aa16104a8 100644 --- a/src/charon/encoding/payloads/cert_payload.h +++ b/src/charon/encoding/payloads/cert_payload.h @@ -1,12 +1,6 @@ -/** - * @file cert_payload.h - * - * @brief Interface of cert_payload_t. - * - */ - /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -19,69 +13,58 @@ * 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. + * + * $Id: cert_payload.h 3838 2008-04-18 11:24:45Z tobias $ + */ + +/** + * @defgroup cert_payload cert_payload + * @{ @ingroup payloads */ #ifndef CERT_PAYLOAD_H_ #define CERT_PAYLOAD_H_ -typedef enum cert_encoding_t cert_encoding_t; typedef struct cert_payload_t cert_payload_t; +typedef enum cert_encoding_t cert_encoding_t; #include <library.h> -#include <crypto/x509.h> +#include <credentials/certificates/certificate.h> #include <encoding/payloads/payload.h> /** * Length of a cert payload without the cert data in bytes. - * - * @ingroup payloads */ #define CERT_PAYLOAD_HEADER_LENGTH 5 /** - * @brief Certificate encoding, as described in IKEv2 RFC section 3.6 - * - * @ingroup payloads + * Certifcate encodings, as in RFC4306 */ enum cert_encoding_t { - CERT_NONE = 0, - CERT_PKCS7_WRAPPED_X509 = 1, - CERT_PGP = 2, - CERT_DNS_SIGNED_KEY = 3, - CERT_X509_SIGNATURE = 4, - CERT_KERBEROS_TOKEN = 6, - CERT_CRL = 7, - CERT_ARL = 8, - CERT_SPKI = 9, - CERT_X509_ATTRIBUTE = 10, - CERT_RAW_RSA_KEY = 11, - CERT_X509_HASH_AND_URL = 12, - CERT_X509_HASH_AND_URL_BUNDLE = 13, - CERT_OCSP_CONTENT = 14, /* from RFC 4806 */ - CERT_ROOF = 15 + ENC_PKCS7_WRAPPED_X509 = 1, + ENC_PGP = 2, + ENC_DNS_SIGNED_KEY = 3, + ENC_X509_SIGNATURE = 4, + ENC_KERBEROS_TOKEN = 6, + ENC_CRL = 7, + ENC_ARL = 8, + ENC_SPKI = 9, + ENC_X509_ATTRIBUTE = 10, + ENC_RAW_RSA_KEY = 11, + ENC_X509_HASH_AND_URL = 12, + ENC_X509_HASH_AND_URL_BUNDLE = 13, + ENC_OCSP_CONTENT = 14, /* from RFC 4806 */ }; /** - * string mappings for cert_encoding_t. - * - * @ingroup payloads + * Enum names for cert_encoding_t */ extern enum_name_t *cert_encoding_names; /** - * @brief Class representing an IKEv2 CERT payload. + * Class representing an IKEv2 CERT payload. * * The CERT payload format is described in RFC section 3.6. - * This is just a dummy implementation to fullfill the standards - * requirements. A full implementation would offer setters/getters - * for the different encoding types. - * - * @b Constructors: - * - cert_payload_create() - * - * @todo Implement setters/getters for the different certificate encodings. - * - * @ingroup payloads */ struct cert_payload_t { @@ -89,78 +72,69 @@ struct cert_payload_t { * The payload_t interface. */ payload_t payload_interface; - - /** - * @brief Set the CERT encoding. - * - * @param this calling cert_payload_t object - * @param encoding CERT encoding - */ - void (*set_cert_encoding) (cert_payload_t *this, cert_encoding_t encoding); /** - * @brief Get the CERT encoding. + * Get the playoads encoded certifcate. * - * @param this calling cert_payload_t object - * @return Encoding of the CERT + * @return certifcate copy */ - cert_encoding_t (*get_cert_encoding) (cert_payload_t *this); + certificate_t *(*get_cert)(cert_payload_t *this); /** - * @brief Set the CERT data. + * Get the encoding of the certificate. * - * Data are getting cloned. - * - * @param this calling cert_payload_t object - * @param data CERT data as chunk_t + * @return encoding */ - void (*set_data) (cert_payload_t *this, chunk_t data); + cert_encoding_t (*get_cert_encoding)(cert_payload_t *this); /** - * @brief Get the CERT data. + * Get the hash if this is a hash and URL encoded certificate. * - * Returned data are a copy of the internal one. - * - * @param this calling cert_payload_t object - * @return CERT data as chunk_t + * This function returns internal data, do not free. + * + * @return hash */ - chunk_t (*get_data_clone) (cert_payload_t *this); + chunk_t (*get_hash)(cert_payload_t *this); /** - * @brief Get the CERT data. + * Get the URL if this is a hash and URL encoded certificate. * - * Returned data are NOT copied. - * - * @param this calling cert_payload_t object - * @return CERT data as chunk_t + * This function returns internal data, do not free. + * + * @return url */ - chunk_t (*get_data) (cert_payload_t *this); + char *(*get_url)(cert_payload_t *this); + /** - * @brief Destroys an cert_payload_t object. - * - * @param this cert_payload_t object to destroy + * Destroys the cert_payload object. */ void (*destroy) (cert_payload_t *this); }; /** - * @brief Creates an empty cert_payload_t object. + * Creates an empty certificate payload. * + * @param cert certificate to embed * @return cert_payload_t object - * - * @ingroup payloads */ cert_payload_t *cert_payload_create(void); /** - * @brief Creates a cert_payload_t object with an X.509 certificate. + * Creates a certificate payload with an embedded certificate. * - * @param cert X.509 certificate + * @param cert certificate to embed * @return cert_payload_t object + */ +cert_payload_t *cert_payload_create_from_cert(certificate_t *cert); + +/** + * Creates a certificate payload with hash and URL encoding of a certificate. * - * @ingroup payloads + * @param hash hash of the DER encoded certificate (get's cloned) + * @param url the URL to locate the certificate (get's cloned) + * @return cert_payload_t object */ -cert_payload_t *cert_payload_create_from_x509(x509_t *cert); +cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url); -#endif /* CERT_PAYLOAD_H_ */ +#endif /* CERT_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/certreq_payload.c b/src/charon/encoding/payloads/certreq_payload.c index 46663811a..1b499e9e8 100644 --- a/src/charon/encoding/payloads/certreq_payload.c +++ b/src/charon/encoding/payloads/certreq_payload.c @@ -1,10 +1,3 @@ -/** - * @file certreq_payload.c - * - * @brief Implementation of certreq_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,14 +12,15 @@ * 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. + * + * $Id: certreq_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> -#include <string.h> #include <daemon.h> #include <crypto/hashers/hasher.h> -#include <crypto/ca.h> +#include <encoding/payloads/cert_payload.h> #include "certreq_payload.h" @@ -61,12 +55,12 @@ struct private_certreq_payload_t { /** * Encoding of the CERT Data. */ - u_int8_t cert_encoding; + u_int8_t encoding; /** * The contained certreq data value. */ - chunk_t certreq_data; + chunk_t data; }; /** @@ -90,11 +84,11 @@ encoding_rule_t certreq_payload_encodings[] = { { RESERVED_BIT, 0 }, { RESERVED_BIT, 0 }, /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length)}, + { PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length) }, /* 1 Byte CERTREQ type*/ - { U_INT_8, offsetof(private_certreq_payload_t, cert_encoding)}, + { U_INT_8, offsetof(private_certreq_payload_t, encoding) }, /* some certreq data bytes, length is defined in PAYLOAD_LENGTH */ - { CERTREQ_DATA, offsetof(private_certreq_payload_t, certreq_data)} + { CERTREQ_DATA, offsetof(private_certreq_payload_t, data) } }; /* @@ -115,11 +109,15 @@ encoding_rule_t certreq_payload_encodings[] = { */ static status_t verify(private_certreq_payload_t *this) { - if ((this->cert_encoding == 0) || - ((this->cert_encoding >= CERT_ROOF) && (this->cert_encoding <= 200))) + if (this->encoding == ENC_X509_SIGNATURE) { - /* reserved IDs */ - return FAILED; + if (this->data.len < HASH_SIZE_SHA1 || + this->data.len % HASH_SIZE_SHA1) + { + DBG1(DBG_ENC, "invalid X509 hash length (%d) in certreq", + this->data.len); + return FAILED; + } } return SUCCESS; } @@ -164,58 +162,78 @@ static size_t get_length(private_certreq_payload_t *this) { return this->payload_length; } - + /** - * Implementation of certreq_payload_t.set_cert_encoding. + * Implementation of certreq_payload_t.add_keyid. */ -static void set_cert_encoding (private_certreq_payload_t *this, cert_encoding_t encoding) +static void add_keyid(private_certreq_payload_t *this, chunk_t keyid) { - this->cert_encoding = encoding; + this->data = chunk_cat("mc", this->data, keyid); + this->payload_length += keyid.len; } +typedef struct keyid_enumerator_t keyid_enumerator_t; + /** - * Implementation of certreq_payload_t.get_cert_encoding. + * enumerator to enumerate keyids */ -static cert_encoding_t get_cert_encoding (private_certreq_payload_t *this) -{ - return (this->cert_encoding); -} +struct keyid_enumerator_t { + enumerator_t public; + chunk_t full; + u_char *pos; +}; /** - * Implementation of certreq_payload_t.set_data. + * enumerate function for keyid_enumerator */ -static void set_data (private_certreq_payload_t *this, chunk_t data) +static bool keyid_enumerate(keyid_enumerator_t *this, chunk_t *chunk) { - if (this->certreq_data.ptr != NULL) + if (this->pos == NULL) + { + this->pos = this->full.ptr; + } + else { - chunk_free(&(this->certreq_data)); + this->pos += HASH_SIZE_SHA1; + if (this->pos > (this->full.ptr + this->full.len - HASH_SIZE_SHA1)) + { + this->pos = NULL; + } } - this->certreq_data.ptr = clalloc(data.ptr,data.len); - this->certreq_data.len = data.len; - this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH + this->certreq_data.len; + if (this->pos) + { + chunk->ptr = this->pos; + chunk->len = HASH_SIZE_SHA1; + return TRUE; + } + return FALSE; } /** - * Implementation of certreq_payload_t.get_data. + * Implementation of certreq_payload_t.create_keyid_enumerator. */ -static chunk_t get_data (private_certreq_payload_t *this) +static enumerator_t* create_keyid_enumerator(private_certreq_payload_t *this) { - return (this->certreq_data); + keyid_enumerator_t *enumerator = malloc_thing(keyid_enumerator_t); + enumerator->public.enumerate = (void*)keyid_enumerate; + enumerator->public.destroy = (void*)free; + enumerator->full = this->data; + enumerator->pos = NULL; + return &enumerator->public; } /** - * Implementation of certreq_payload_t.get_data_clone. + * Implementation of certreq_payload_t.get_cert_type. */ -static chunk_t get_data_clone (private_certreq_payload_t *this) +static certificate_type_t get_cert_type(private_certreq_payload_t *this) { - chunk_t cloned_data; - if (this->certreq_data.ptr == NULL) + switch (this->encoding) { - return (this->certreq_data); + case ENC_X509_SIGNATURE: + return CERT_X509; + default: + return CERT_ANY; } - cloned_data.ptr = clalloc(this->certreq_data.ptr,this->certreq_data.len); - cloned_data.len = this->certreq_data.len; - return cloned_data; } /** @@ -223,11 +241,7 @@ static chunk_t get_data_clone (private_certreq_payload_t *this) */ static void destroy(private_certreq_payload_t *this) { - if (this->certreq_data.ptr != NULL) - { - chunk_free(&(this->certreq_data)); - } - + chunk_free(&this->data); free(this); } @@ -249,87 +263,38 @@ certreq_payload_t *certreq_payload_create() /* public functions */ this->public.destroy = (void (*) (certreq_payload_t*)) destroy; - this->public.set_cert_encoding = (void (*) (certreq_payload_t*,cert_encoding_t))set_cert_encoding; - this->public.get_cert_encoding = (cert_encoding_t (*) (certreq_payload_t*))get_cert_encoding; - this->public.set_data = (void (*) (certreq_payload_t*,chunk_t))set_data; - this->public.get_data_clone = (chunk_t (*) (certreq_payload_t*))get_data_clone; - this->public.get_data = (chunk_t (*) (certreq_payload_t*))get_data; + this->public.create_keyid_enumerator = (enumerator_t*(*)(certreq_payload_t*))create_keyid_enumerator; + this->public.get_cert_type = (certificate_type_t(*)(certreq_payload_t*))get_cert_type; + this->public.add_keyid = (void(*)(certreq_payload_t*, chunk_t keyid))add_keyid; /* private variables */ this->critical = FALSE; this->next_payload = NO_PAYLOAD; - this->payload_length =CERTREQ_PAYLOAD_HEADER_LENGTH; - this->certreq_data = chunk_empty; + this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH; + this->data = chunk_empty; + this->encoding = 0; - return (&(this->public)); + return &this->public; } /* * Described in header */ -certreq_payload_t *certreq_payload_create_from_cacert(identification_t *id) +certreq_payload_t *certreq_payload_create_type(certificate_type_t type) { - x509_t *cacert; - rsa_public_key_t *pubkey; - chunk_t keyid; - certreq_payload_t *this; + private_certreq_payload_t *this = (private_certreq_payload_t*)certreq_payload_create(); - cacert = charon->credentials->get_auth_certificate(charon->credentials, AUTH_CA, id); - if (cacert == NULL) + switch (type) { - /* no such CA cert */ - return NULL; + case CERT_X509: + this->encoding = ENC_X509_SIGNATURE; + break; + default: + DBG1(DBG_ENC, "certificate type %N not supported in requests", + certificate_type_names, type); + free(this); + return NULL; } - - this = certreq_payload_create(); - pubkey = cacert->get_public_key(cacert); - keyid = pubkey->get_keyid(pubkey); - - DBG2(DBG_IKE, "requesting certificate issued by '%D'", id); - DBG2(DBG_IKE, " with keyid %#B", &keyid); - - this->set_cert_encoding(this, CERT_X509_SIGNATURE); - this->set_data(this, keyid); - return this; + return &this->public; } -/* - * Described in header - */ -certreq_payload_t *certreq_payload_create_from_cacerts(void) -{ - certreq_payload_t *this; - chunk_t keyids; - u_char *pos; - ca_info_t *cainfo; - - iterator_t *iterator = charon->credentials->create_cainfo_iterator(charon->credentials); - int count = iterator->get_count(iterator); - - if (count == 0) - { - iterator->destroy(iterator); - return NULL; - } - - this = certreq_payload_create(); - keyids = chunk_alloc(count * HASH_SIZE_SHA1); - pos = keyids.ptr; - - while (iterator->iterate(iterator, (void**)&cainfo)) - { - x509_t *cacert = cainfo->get_certificate(cainfo); - chunk_t keyid = cacert->get_keyid(cacert); - - DBG2(DBG_IKE, "requesting certificate issued by '%D'", cacert->get_subject(cacert)); - DBG2(DBG_IKE, " with keyid %#B", &keyid); - memcpy(pos, keyid.ptr, keyid.len); - pos += HASH_SIZE_SHA1; - } - iterator->destroy(iterator); - - this->set_cert_encoding(this, CERT_X509_SIGNATURE); - this->set_data(this, keyids); - free(keyids.ptr); - return this; -} diff --git a/src/charon/encoding/payloads/certreq_payload.h b/src/charon/encoding/payloads/certreq_payload.h index 2985fdae1..b835d7ad6 100644 --- a/src/charon/encoding/payloads/certreq_payload.h +++ b/src/charon/encoding/payloads/certreq_payload.h @@ -1,10 +1,3 @@ -/** - * @file certreq_payload.h - * - * @brief Interface of certreq_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: certreq_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup certreq_payload certreq_payload + * @{ @ingroup payloads */ #ifndef CERTREQ_PAYLOAD_H_ @@ -32,26 +32,13 @@ typedef struct certreq_payload_t certreq_payload_t; /** * Length of a CERTREQ payload without the CERTREQ data in bytes. - * - * @ingroup payloads */ #define CERTREQ_PAYLOAD_HEADER_LENGTH 5 - /** - * @brief Class representing an IKEv2 CERTREQ payload. + * Class representing an IKEv2 CERTREQ payload. * * The CERTREQ payload format is described in RFC section 3.7. - * This is just a dummy implementation to fullfill the standards - * requirements. A full implementation would offer setters/getters - * for the different encoding types. - * - * @b Constructors: - * - certreq_payload_create() - * - * @todo Implement payload functionality. - * - * @ingroup payloads */ struct certreq_payload_t { /** @@ -60,85 +47,46 @@ struct certreq_payload_t { payload_t payload_interface; /** - * @brief Set the CERT encoding. - * - * @param this calling certreq_payload_t object - * @param encoding CERT encoding - */ - void (*set_cert_encoding) (certreq_payload_t *this, cert_encoding_t encoding); - - /** - * @brief Get the CERT encoding. - * - * @param this calling certreq_payload_t object - * @return Encoding of the CERT - */ - cert_encoding_t (*get_cert_encoding) (certreq_payload_t *this); - - /** - * @brief Set the CERTREQ data. - * - * Data are getting cloned. + * Create an enumerator over contained keyids. * - * @param this calling certreq_payload_t object - * @param data CERTREQ data as chunk_t + * @return enumerator over chunk_t's. */ - void (*set_data) (certreq_payload_t *this, chunk_t data); + enumerator_t* (*create_keyid_enumerator)(certreq_payload_t *this); /** - * @brief Get the CERTREQ data. - * - * Returned data are a copy of the internal one. + * Get the type of contained certificate keyids. * - * @param this calling certreq_payload_t object - * @return CERTREQ data as chunk_t + * @return certificate keyid type */ - chunk_t (*get_data_clone) (certreq_payload_t *this); + certificate_type_t (*get_cert_type)(certreq_payload_t *this); /** - * @brief Get the CERTREQ data. - * - * Returned data are NOT copied. + * Add a certificates keyid to the payload. * - * @param this calling certreq_payload_t object - * @return CERTREQ data as chunk_t + * @param keyid keyid of the trusted certifcate + * @return */ - chunk_t (*get_data) (certreq_payload_t *this); + void (*add_keyid)(certreq_payload_t *this, chunk_t keyid); /** - * @brief Destroys an certreq_payload_t object. - * - * @param this certreq_payload_t object to destroy + * Destroys an certreq_payload_t object. */ void (*destroy) (certreq_payload_t *this); }; /** - * @brief Creates an empty certreq_payload_t object. + * Creates an empty certreq_payload_t object. * - * @return certreq_payload_t object - * - * @ingroup payloads + * @return certreq payload */ certreq_payload_t *certreq_payload_create(void); /** - * @brief Creates a certreq_payload_t object from a ca certificate - * - * @param id subject distinguished name of CA certificate - * @return certreq_payload_t object - * - * @ingroup payloads - */ -certreq_payload_t *certreq_payload_create_from_cacert(identification_t *id); - -/** - * @brief Creates a certreq_payload_t object from all ca certificates - * - * @return certreq_payload_t object + * Creates an empty certreq_payload_t for a kind of certificates. * - * @ingroup payloads + * @param type type of the added keyids + * @return certreq payload */ -certreq_payload_t *certreq_payload_create_from_cacerts(void); +certreq_payload_t *certreq_payload_create_type(certificate_type_t type); -#endif /* CERTREQ_PAYLOAD_H_ */ +#endif /* CERTREQ_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/configuration_attribute.c b/src/charon/encoding/payloads/configuration_attribute.c index afd08c6be..6b1cbffb4 100644 --- a/src/charon/encoding/payloads/configuration_attribute.c +++ b/src/charon/encoding/payloads/configuration_attribute.c @@ -1,10 +1,3 @@ -/** - * @file configuration_attribute.c - * - * @brief Implementation of configuration_attribute_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: configuration_attribute.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/configuration_attribute.h b/src/charon/encoding/payloads/configuration_attribute.h index 5c4f65b14..ade837107 100644 --- a/src/charon/encoding/payloads/configuration_attribute.h +++ b/src/charon/encoding/payloads/configuration_attribute.h @@ -1,10 +1,3 @@ -/** - * @file configuration_attribute.h - * - * @brief Interface of configuration_attribute_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: configuration_attribute.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup configuration_attribute configuration_attribute + * @{ @ingroup payloads */ #ifndef CONFIGURATION_ATTRIBUTE_H_ @@ -33,15 +33,11 @@ typedef struct configuration_attribute_t configuration_attribute_t; /** * Configuration attribute header length in bytes. - * - * @ingroup payloads */ #define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4 /** * Type of the attribute, as in IKEv2 RFC 3.15.1. - * - * @ingroup payloads */ enum configuration_attribute_type_t { INTERNAL_IP4_ADDRESS = 1, @@ -62,20 +58,13 @@ enum configuration_attribute_type_t { /** * enum names for configuration_attribute_type_t. - * - * @ingroup payloads */ extern enum_name_t *configuration_attribute_type_names; /** - * @brief Class representing an IKEv2-CONFIGURATION Attribute. + * Class representing an IKEv2-CONFIGURATION Attribute. * * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1. - * - * @b Constructors: - * - configuration_attribute_create() - * - * @ingroup payloads */ struct configuration_attribute_t { /** @@ -84,64 +73,55 @@ struct configuration_attribute_t { payload_t payload_interface; /** - * @brief Returns the currently set value of the attribute. + * Returns the currently set value of the attribute. * * @warning Returned data are not copied. * - * @param this calling configuration_attribute_t object * @return chunk_t pointing to the value */ chunk_t (*get_value) (configuration_attribute_t *this); /** - * @brief Sets the value of the attribute. + * Sets the value of the attribute. * - * @warning Value is getting copied. + * Value is getting copied. * - * @param this calling configuration_attribute_t object * @param value chunk_t pointing to the value to set */ void (*set_value) (configuration_attribute_t *this, chunk_t value); /** - * @brief Sets the type of the attribute. + * Sets the type of the attribute. * - * @param this calling configuration_attribute_t object * @param type type to set (most significant bit is set to zero) */ void (*set_type) (configuration_attribute_t *this, u_int16_t type); /** - * @brief get the type of the attribute. + * get the type of the attribute. * - * @param this calling configuration_attribute_t object * @return type of the value */ u_int16_t (*get_type) (configuration_attribute_t *this); /** - * @brief get the length of an attribute. + * get the length of an attribute. * - * @param this calling configuration_attribute_t object * @return type of the value */ u_int16_t (*get_length) (configuration_attribute_t *this); /** - * @brief Destroys an configuration_attribute_t object. - * - * @param this configuration_attribute_t object to destroy + * Destroys an configuration_attribute_t object. */ void (*destroy) (configuration_attribute_t *this); }; /** - * @brief Creates an empty configuration_attribute_t object. + * Creates an empty configuration_attribute_t object. * * @return created configuration_attribute_t object - * - * @ingroup payloads */ configuration_attribute_t *configuration_attribute_create(void); -#endif /* CONFIGURATION_ATTRIBUTE_H_*/ +#endif /* CONFIGURATION_ATTRIBUTE_H_ @} */ diff --git a/src/charon/encoding/payloads/cp_payload.c b/src/charon/encoding/payloads/cp_payload.c index 380ed9681..d39dc2a47 100644 --- a/src/charon/encoding/payloads/cp_payload.c +++ b/src/charon/encoding/payloads/cp_payload.c @@ -1,10 +1,3 @@ -/** - * @file cp_payload.c - * - * @brief Implementation of cp_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: cp_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/cp_payload.h b/src/charon/encoding/payloads/cp_payload.h index 27ff41005..0ca75e71d 100644 --- a/src/charon/encoding/payloads/cp_payload.h +++ b/src/charon/encoding/payloads/cp_payload.h @@ -1,10 +1,3 @@ -/** - * @file cp_payload.h - * - * @brief Interface of cp_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: cp_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup cp_payload cp_payload + * @{ @ingroup payloads */ #ifndef CP_PAYLOAD_H_ @@ -34,15 +34,11 @@ typedef struct cp_payload_t cp_payload_t; /** * CP_PAYLOAD length in bytes without any proposal substructure. - * - * @ingroup payloads */ #define CP_PAYLOAD_HEADER_LENGTH 8 /** * Config Type of an Configuration Payload. - * - * @ingroup payloads */ enum config_type_t { CFG_REQUEST = 1, @@ -53,20 +49,13 @@ enum config_type_t { /** * enum name for config_type_t. - * - * @ingroup payloads */ extern enum_name_t *config_type_names; /** - * @brief Class representing an IKEv2-CP Payload. + * Class representing an IKEv2-CP Payload. * * The CP Payload format is described in RFC section 3.15. - * - * @b Constructors: - * - cp_payload_create() - * - * @ingroup payloads */ struct cp_payload_t { /** @@ -75,58 +64,50 @@ struct cp_payload_t { payload_t payload_interface; /** - * @brief Creates an iterator of stored configuration_attribute_t objects. + * Creates an iterator of stored configuration_attribute_t objects. * * When deleting an attribute using this iterator, the length of this * configuration_attribute_t has to be refreshed by calling get_length()! * - * @param this calling cp_payload_t object * @return created iterator_t object */ iterator_t *(*create_attribute_iterator) (cp_payload_t *this); /** - * @brief Adds a configuration_attribute_t object to this object. + * Adds a configuration_attribute_t object to this object. * * The added configuration_attribute_t object is getting destroyed in * destroy function of cp_payload_t. * - * @param this calling cp_payload_t object * @param attribute configuration_attribute_t object to add */ void (*add_configuration_attribute) (cp_payload_t *this, configuration_attribute_t *attribute); /** - * @brief Set the config type. + * Set the config type. * - * @param this calling cp_payload_t object * @param config_type config_type_t to set */ void (*set_config_type) (cp_payload_t *this,config_type_t config_type); /** - * @brief Get the config type. + * Get the config type. * - * @param this calling cp_payload_t object * @return config_type_t */ config_type_t (*get_config_type) (cp_payload_t *this); /** - * @brief Destroys an cp_payload_t object. - * - * @param this cp_payload_t object to destroy + * Destroys an cp_payload_t object. */ void (*destroy) (cp_payload_t *this); }; /** - * @brief Creates an empty cp_payload_t object + * Creates an empty cp_payload_t object * * @return cp_payload_t object - * - * @ingroup payloads */ cp_payload_t *cp_payload_create(void); -#endif /*CP_PAYLOAD_H_*/ +#endif /*CP_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/delete_payload.c b/src/charon/encoding/payloads/delete_payload.c index 1d42a3af2..01ee7f027 100644 --- a/src/charon/encoding/payloads/delete_payload.c +++ b/src/charon/encoding/payloads/delete_payload.c @@ -1,10 +1,3 @@ -/** - * @file delete_payload.c - * - * @brief Implementation of delete_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: delete_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/delete_payload.h b/src/charon/encoding/payloads/delete_payload.h index 508f7fba2..2c1a596b9 100644 --- a/src/charon/encoding/payloads/delete_payload.h +++ b/src/charon/encoding/payloads/delete_payload.h @@ -1,10 +1,3 @@ -/** - * @file delete_payload.h - * - * @brief Interface of delete_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: delete_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup delete_payload delete_payload + * @{ @ingroup payloads */ #ifndef DELETE_PAYLOAD_H_ @@ -32,22 +32,13 @@ typedef struct delete_payload_t delete_payload_t; /** * Length of a delete payload without the SPI in bytes. - * - * @ingroup payloads */ #define DELETE_PAYLOAD_HEADER_LENGTH 8 /** - * @brief Class representing an IKEv2 DELETE payload. + * Class representing an IKEv2 DELETE payload. * * The DELETE payload format is described in RFC section 3.11. - * - * @b Constructors: - * - delete_payload_create() - * - * @todo Implement better setter/getters - * - * @ingroup payloads */ struct delete_payload_t { /** @@ -56,47 +47,40 @@ struct delete_payload_t { payload_t payload_interface; /** - * @brief Get the protocol ID. + * Get the protocol ID. * - * @param this calling delete_payload_t object * @return protocol ID */ protocol_id_t (*get_protocol_id) (delete_payload_t *this); /** - * @brief Add an SPI to the list of deleted SAs. + * Add an SPI to the list of deleted SAs. * - * @param this calling delete_payload_t object * @param spi spi to add */ void (*add_spi) (delete_payload_t *this, u_int32_t spi); /** - * @brief Get an iterator over the SPIs. + * Get an iterator over the SPIs. * * The iterate() function returns a pointer to a u_int32_t SPI. * - * @param this calling delete_payload_t object * @return iterator over SPIs */ iterator_t *(*create_spi_iterator) (delete_payload_t *this); /** - * @brief Destroys an delete_payload_t object. - * - * @param this delete_payload_t object to destroy + * Destroys an delete_payload_t object. */ void (*destroy) (delete_payload_t *this); }; /** - * @brief Creates an empty delete_payload_t object. + * Creates an empty delete_payload_t object. * * @param protocol_id protocol, such as AH|ESP * @return delete_payload_t object - * - * @ingroup payloads */ delete_payload_t *delete_payload_create(protocol_id_t protocol_id); -#endif /* DELETE_PAYLOAD_H_ */ +#endif /* DELETE_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/eap_payload.c b/src/charon/encoding/payloads/eap_payload.c index da2498c5e..d9a6fe6dd 100644 --- a/src/charon/encoding/payloads/eap_payload.c +++ b/src/charon/encoding/payloads/eap_payload.c @@ -1,10 +1,3 @@ -/** - * @file eap_payload.c - * - * @brief Implementation of eap_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: eap_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/eap_payload.h b/src/charon/encoding/payloads/eap_payload.h index e4f8663c2..23558053d 100644 --- a/src/charon/encoding/payloads/eap_payload.h +++ b/src/charon/encoding/payloads/eap_payload.h @@ -1,10 +1,3 @@ -/** - * @file eap_payload.h - * - * @brief Interface of eap_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: eap_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup eap_payload eap_payload + * @{ @ingroup payloads */ #ifndef EAP_PAYLOAD_H_ @@ -32,20 +32,13 @@ typedef struct eap_payload_t eap_payload_t; /** * Length of a EAP payload without the EAP Message in bytes. - * - * @ingroup payloads */ #define EAP_PAYLOAD_HEADER_LENGTH 4 /** - * @brief Class representing an IKEv2 EAP payload. + * Class representing an IKEv2 EAP payload. * * The EAP payload format is described in RFC section 3.16. - * - * @b Constructors: - * - eap_payload_create() - * - * @ingroup payloads */ struct eap_payload_t { @@ -55,79 +48,68 @@ struct eap_payload_t { payload_t payload_interface; /** - * @brief Set the contained EAP data. + * Set the contained EAP data. * * This contains the FULL EAP message starting with "code". * Chunk gets cloned. * - * @param this calling eap_payload_t object * @param message EAP data */ void (*set_data) (eap_payload_t *this, chunk_t data); /** - * @brief Get the contained EAP data. + * Get the contained EAP data. * * This contains the FULL EAP message starting with "code". * - * @param this calling eap_payload_t object * @return EAP data (pointer to internal data) */ chunk_t (*get_data) (eap_payload_t *this); /** - * @brief Get the EAP code. + * Get the EAP code. * - * @param this calling eap_payload_t object * @return EAP message as chunk_t */ eap_code_t (*get_code) (eap_payload_t *this); /** - * @brief Get the EAP identifier. + * Get the EAP identifier. * - * @param this calling eap_payload_t object * @return unique identifier */ u_int8_t (*get_identifier) (eap_payload_t *this); /** - * @brief Get the EAP method type. + * Get the EAP method type. * - * @param this calling eap_payload_t object * @param vendor pointer receiving vendor identifier * @return EAP method type, vendor specific if vendor != 0 */ eap_type_t (*get_type) (eap_payload_t *this, u_int32_t *vendor); /** - * @brief Destroys an eap_payload_t object. - * - * @param this eap_payload_t object to destroy + * Destroys an eap_payload_t object. */ void (*destroy) (eap_payload_t *this); }; /** - * @brief Creates an empty eap_payload_t object. + * Creates an empty eap_payload_t object. * * @return eap_payload_t object - * - * @ingroup payloads */ eap_payload_t *eap_payload_create(void); /** - * @brief Creates an eap_payload_t object with data. + * Creates an eap_payload_t object with data. * * @return eap_payload_t object - * - * @ingroup payloads */ eap_payload_t *eap_payload_create_data(chunk_t data); /** - * @brief Creates an eap_payload_t object with a code. + * Creates an eap_payload_t object with a code. * * Could should be either EAP_SUCCESS/EAP_FAILURE, use * constructor above otherwise. @@ -135,19 +117,15 @@ eap_payload_t *eap_payload_create_data(chunk_t data); * @param code EAP status code * @param identifier EAP identifier to use in payload * @return eap_payload_t object - * - * @ingroup payloads */ eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier); /** - * @brief Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK. + * Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK. * * @param identifier EAP identifier to use in payload * @return eap_payload_t object - * - * @ingroup payloads */ eap_payload_t *eap_payload_create_nak(u_int8_t identifier); -#endif /* EAP_PAYLOAD_H_ */ +#endif /* EAP_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/encodings.c b/src/charon/encoding/payloads/encodings.c index 55a7cf132..66c1fd999 100644 --- a/src/charon/encoding/payloads/encodings.c +++ b/src/charon/encoding/payloads/encodings.c @@ -1,10 +1,3 @@ -/** - * @file encodings.c - * - * @brief String mappings of encoding_type_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: encodings.c 3589 2008-03-13 14:14:44Z martin $ */ diff --git a/src/charon/encoding/payloads/encodings.h b/src/charon/encoding/payloads/encodings.h index 5e07fbfab..73c5f9c36 100644 --- a/src/charon/encoding/payloads/encodings.h +++ b/src/charon/encoding/payloads/encodings.h @@ -1,10 +1,3 @@ -/** - * @file encodings.h - * - * @brief Definition of encoding_type_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: encodings.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup encodings encodings + * @{ @ingroup payloads */ #ifndef ENCODINGS_H_ @@ -30,7 +30,7 @@ typedef struct encoding_rule_t encoding_rule_t; #include <library.h> /** - * @brief All different kinds of encoding types. + * All different kinds of encoding types. * * Each field of an IKEv2-Message (in header or payload) * which has to be parsed or generated differently has its own @@ -40,8 +40,6 @@ typedef struct encoding_rule_t encoding_rule_t; * from PRIVATE USE space. Also the substructures * of specific payload types get their own payload_id * from PRIVATE_USE space. See IKEv2-Draft for more informations. - * - * @ingroup payloads */ enum encoding_type_t { @@ -114,7 +112,7 @@ enum encoding_type_t { U_INT_64, /** - * @brief represents a RESERVED_BIT used in FLAG-Bytes. + * represents a RESERVED_BIT used in FLAG-Bytes. * * When generating, the next bit is set to zero and the current write * position is moved one bit forward. @@ -128,7 +126,7 @@ enum encoding_type_t { RESERVED_BIT, /** - * @brief represents a RESERVED_BYTE. + * represents a RESERVED_BYTE. * * When generating, the next byte is set to zero and the current write * position is moved one byte forward. @@ -499,21 +497,16 @@ enum encoding_type_t { /** * enum name for encoding_type_t - * - * @ingroup payloads */ extern enum_name_t *encoding_type_names; /** + * Rule how to en-/decode a payload field. + * * An encoding rule is a mapping of a specific encoding type to * a location in the data struct where the current field is stored to * or read from. - * - * For examples see files in this directory. - * * This rules are used by parser and generator. - * - * @ingroup payloads */ struct encoding_rule_t { @@ -534,4 +527,4 @@ struct encoding_rule_t { u_int32_t offset; }; -#endif /*ENCODINGS_H_*/ +#endif /*ENCODINGS_H_ @} */ diff --git a/src/charon/encoding/payloads/encryption_payload.c b/src/charon/encoding/payloads/encryption_payload.c index 23b6e8d9f..7237c69c5 100644 --- a/src/charon/encoding/payloads/encryption_payload.c +++ b/src/charon/encoding/payloads/encryption_payload.c @@ -1,10 +1,3 @@ -/** - * @file encryption_payload.c - * - * @brief Implementation of encryption_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: encryption_payload.c 3862 2008-04-22 07:14:24Z martin $ */ #include <stddef.h> @@ -32,7 +27,6 @@ #include <encoding/generator.h> #include <encoding/parser.h> #include <utils/iterator.h> -#include <utils/randomizer.h> #include <crypto/signers/signer.h> @@ -327,8 +321,7 @@ static void generate(private_encryption_payload_t *this) static status_t encrypt(private_encryption_payload_t *this) { chunk_t iv, padding, to_crypt, result; - randomizer_t *randomizer; - status_t status; + rng_t *rng; size_t block_size; if (this->signer == NULL || this->crypter == NULL) @@ -338,8 +331,12 @@ static status_t encrypt(private_encryption_payload_t *this) } /* for random data in iv and padding */ - randomizer = randomizer_create(); - + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) + { + DBG1(DBG_ENC, "could not encrypt, no RNG found"); + return FAILED; + } /* build payload chunk */ generate(this); @@ -349,12 +346,7 @@ static status_t encrypt(private_encryption_payload_t *this) /* build padding */ block_size = this->crypter->get_block_size(this->crypter); padding.len = block_size - ((this->decrypted.len + 1) % block_size); - status = randomizer->allocate_pseudo_random_bytes(randomizer, padding.len, &padding); - if (status != SUCCESS) - { - randomizer->destroy(randomizer); - return status; - } + rng->allocate_bytes(rng, padding.len, &padding); /* concatenate payload data, padding, padding len */ to_crypt.len = this->decrypted.len + padding.len + 1; @@ -366,28 +358,17 @@ static status_t encrypt(private_encryption_payload_t *this) /* build iv */ iv.len = block_size; - status = randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv); - randomizer->destroy(randomizer); - if (status != SUCCESS) - { - chunk_free(&to_crypt); - chunk_free(&padding); - return status; - } + rng->allocate_bytes(rng, iv.len, &iv); + rng->destroy(rng); DBG3(DBG_ENC, "data before encryption with padding %B", &to_crypt); /* encrypt to_crypt chunk */ free(this->encrypted.ptr); - status = this->crypter->encrypt(this->crypter, to_crypt, iv, &result); + this->crypter->encrypt(this->crypter, to_crypt, iv, &result); free(padding.ptr); free(to_crypt.ptr); - if (status != SUCCESS) - { - DBG2(DBG_ENC, "encryption failed"); - free(iv.ptr); - return status; - } + DBG3(DBG_ENC, "data after encryption %B", &result); /* build encrypted result with iv and signature */ @@ -459,7 +440,6 @@ static status_t decrypt(private_encryption_payload_t *this) { chunk_t iv, concatenated; u_int8_t padding_length; - status_t status; DBG2(DBG_ENC, "decrypting encryption payload"); DBG3(DBG_ENC, "data before decryption with IV and (invalid) signature %B", @@ -478,12 +458,11 @@ static status_t decrypt(private_encryption_payload_t *this) /* point concatenated to data + padding + padding_length*/ concatenated.ptr = this->encrypted.ptr + iv.len; - concatenated.len = this->encrypted.len - iv.len - this->signer->get_block_size(this->signer); + concatenated.len = this->encrypted.len - iv.len - + this->signer->get_block_size(this->signer); - /* check the size of input: - * concatenated must be at least on block_size of crypter - */ - if (concatenated.len < iv.len) + /* concatenated must be a multiple of block_size of crypter */ + if (concatenated.len < iv.len || concatenated.len % iv.len) { DBG1(DBG_ENC, "could not decrypt, invalid input"); return FAILED; @@ -494,18 +473,14 @@ static status_t decrypt(private_encryption_payload_t *this) DBG3(DBG_ENC, "data before decryption %B", &concatenated); - status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted)); - if (status != SUCCESS) - { - DBG1(DBG_ENC, "could not decrypt, decryption failed"); - return FAILED; - } + this->crypter->decrypt(this->crypter, concatenated, iv, &this->decrypted); + DBG3(DBG_ENC, "data after decryption with padding %B", &this->decrypted); - /* get padding length, sits just bevore signature */ padding_length = *(this->decrypted.ptr + this->decrypted.len - 1); - /* add one byte to the padding length, since the padding_length field is not included */ + /* add one byte to the padding length, since the padding_length field is + * not included */ padding_length++; this->decrypted.len -= padding_length; diff --git a/src/charon/encoding/payloads/encryption_payload.h b/src/charon/encoding/payloads/encryption_payload.h index 7cf53619f..e20ff6acc 100644 --- a/src/charon/encoding/payloads/encryption_payload.h +++ b/src/charon/encoding/payloads/encryption_payload.h @@ -1,9 +1,3 @@ -/** - * @file encryption_payload.h - * - * @brief Interface of encryption_payload_t. - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -18,6 +12,13 @@ * 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. + * + * $Id: encryption_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup encryption_payload encryption_payload + * @{ @ingroup payloads */ #ifndef ENCRYPTION_PAYLOAD_H_ @@ -33,14 +34,12 @@ typedef struct encryption_payload_t encryption_payload_t; /** * Encrpytion payload length in bytes without IV and following data. - * - * @ingroup payloads */ #define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4 /** - * @brief The encryption payload as described in RFC section 3.14. + * The encryption payload as described in RFC section 3.14. * * Before any crypt/decrypt/sign/verify operation can occur, * the transforms must be set. After that, a parsed encryption payload @@ -51,11 +50,6 @@ typedef struct encryption_payload_t encryption_payload_t; * must be builded after generation of all payloads and the encryption * of the encryption payload. * Signature verificatin is done before decryption. - * - * @b Constructors: - * - encryption_payload_create() - * - * @ingroup payloads */ struct encryption_payload_t { /** @@ -64,29 +58,26 @@ struct encryption_payload_t { payload_t payload_interface; /** - * @brief Creates an iterator for all contained payloads. + * Creates an iterator for all contained payloads. * - * @warning iterator_t object has to get destroyed by the caller. + * iterator_t object has to get destroyed by the caller. * - * @param this calling encryption_payload_t object - * @param[in] forward iterator direction (TRUE: front to end) + * @param forward iterator direction (TRUE: front to end) * return created iterator_t object */ iterator_t *(*create_payload_iterator) (encryption_payload_t *this, bool forward); /** - * @brief Adds a payload to this encryption payload. + * Adds a payload to this encryption payload. * - * @param this calling encryption_payload_t object * @param payload payload_t object to add */ void (*add_payload) (encryption_payload_t *this, payload_t *payload); /** - * @brief Reove the last payload in the contained payload list. + * Reove the last payload in the contained payload list. * - * @param this calling encryption_payload_t object - * @param[out] payload removed payload + * @param payload removed payload * @return * - SUCCESS, or * - NOT_FOUND if list empty @@ -94,15 +85,14 @@ struct encryption_payload_t { status_t (*remove_first_payload) (encryption_payload_t *this, payload_t **payload); /** - * @brief Get the number of payloads. + * Get the number of payloads. * - * @param this calling encryption_payload_t object * @return number of contained payloads */ size_t (*get_payload_count) (encryption_payload_t *this); /** - * @brief Set transforms to use. + * Set transforms to use. * * To decryption, encryption, signature building and verifying, * the payload needs a crypter and a signer object. @@ -110,34 +100,29 @@ struct encryption_payload_t { * @warning Do NOT call this function again after encryption, since * the signer must be the same while encrypting and signature building! * - * @param this calling encryption_payload_t * @param crypter crypter_t to use for data de-/encryption * @param signer signer_t to use for data signing/verifying */ void (*set_transforms) (encryption_payload_t *this, crypter_t *crypter, signer_t *signer); /** - * @brief Generate and encrypt contained payloads. + * Generate and encrypt contained payloads. * * This function generates the content for added payloads * and encrypts them. Signature is not built, since we need * additional data (the full message). * - * @param this calling encryption_payload_t - * @return - * - SUCCESS, or - * - INVALID_STATE if transforms not set + * @return SUCCESS, or INVALID_STATE if transforms not set */ status_t (*encrypt) (encryption_payload_t *this); /** - * @brief Decrypt and parse contained payloads. + * Decrypt and parse contained payloads. * * This function decrypts the contained data. After, * the payloads are parsed internally and are accessible * via the iterator. * - * @param this calling encryption_payload_t * @return * - SUCCESS, or * - INVALID_STATE if transforms not set, or @@ -146,13 +131,12 @@ struct encryption_payload_t { status_t (*decrypt) (encryption_payload_t *this); /** - * @brief Build the signature. + * Build the signature. * * The signature is built over the FULL message, so the header * and every payload (inclusive this one) must already be generated. * The generated message is supplied via the data paramater. * - * @param this calling encryption_payload_t * @param data chunk contains the already generated message * @return * - SUCCESS, or @@ -161,13 +145,12 @@ struct encryption_payload_t { status_t (*build_signature) (encryption_payload_t *this, chunk_t data); /** - * @brief Verify the signature. + * Verify the signature. * * Since the signature is built over the full message, we need * this data to do the verification. The message data * is supplied via the data argument. * - * @param this calling encryption_payload_t * @param data chunk contains the message * @return * - SUCCESS, or @@ -177,21 +160,16 @@ struct encryption_payload_t { status_t (*verify_signature) (encryption_payload_t *this, chunk_t data); /** - * @brief Destroys an encryption_payload_t object. - * - * @param this encryption_payload_t object to destroy + * Destroys an encryption_payload_t object. */ void (*destroy) (encryption_payload_t *this); }; /** - * @brief Creates an empty encryption_payload_t object. + * Creates an empty encryption_payload_t object. * * @return encryption_payload_t object - * - * @ingroup payloads */ encryption_payload_t *encryption_payload_create(void); - -#endif /*ENCRYPTION_PAYLOAD_H_*/ +#endif /*ENCRYPTION_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/endpoint_notify.c b/src/charon/encoding/payloads/endpoint_notify.c index 98bfb2ea0..c9ef47afb 100644 --- a/src/charon/encoding/payloads/endpoint_notify.c +++ b/src/charon/encoding/payloads/endpoint_notify.c @@ -1,10 +1,3 @@ -/** - * @file endpoint_notify.c - * - * @brief Implementation of endpoint_notify_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: endpoint_notify.c 3735 2008-04-02 18:21:03Z tobias $ */ #include "endpoint_notify.h" @@ -46,12 +41,12 @@ struct private_endpoint_notify_t { /** * Family */ - p2p_endpoint_family_t family; + me_endpoint_family_t family; /** * Endpoint type */ - p2p_endpoint_type_t type; + me_endpoint_type_t type; /** * Endpoint @@ -76,10 +71,10 @@ struct private_endpoint_notify_t { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -ENUM(p2p_endpoint_type_names, HOST, RELAYED, +ENUM(me_endpoint_type_names, HOST, RELAYED, "HOST", - "SERVER_REFLEXIVE", "PEER_REFLEXIVE", + "SERVER_REFLEXIVE", "RELAYED" ); @@ -120,7 +115,7 @@ static status_t parse_uint32(u_int8_t **cur, u_int8_t *top, u_int32_t *val) } /** - * Parses the notification data of a P2P_ENDPOINT notify + * Parses the notification data of a ME_ENDPOINT notify */ static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t data) { @@ -130,29 +125,29 @@ static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t u_int8_t *cur = data.ptr; u_int8_t *top = data.ptr + data.len; - DBG3(DBG_IKE, "p2p_endpoint_data %B", &data); + DBG3(DBG_IKE, "me_endpoint_data %B", &data); if (parse_uint32(&cur, top, &this->priority) != SUCCESS) { - DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid priority"); + DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid priority"); return FAILED; } if (parse_uint8(&cur, top, &family) != SUCCESS || family >= MAX_FAMILY) { - DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid family"); + DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid family"); return FAILED; } - this->family = (p2p_endpoint_family_t)family; + this->family = (me_endpoint_family_t)family; if (parse_uint8(&cur, top, &type) != SUCCESS || type >= MAX_TYPE) { - DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid type"); + DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid type"); return FAILED; } - this->type = (p2p_endpoint_type_t)type; + this->type = (me_endpoint_type_t)type; addr_family = AF_INET; addr.len = 4; @@ -166,13 +161,13 @@ static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t case IPv4: if (parse_uint16(&cur, top, &port) != SUCCESS) { - DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid port"); + DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid port"); return FAILED; } if (cur + addr.len > top) { - DBG1(DBG_IKE, "failed to parse P2P_ENDPOINT: invalid IP address"); + DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid IP address"); return FAILED; } @@ -190,7 +185,7 @@ static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t /** - * Generates the notification data of a P2P_ENDPOINT notify + * Generates the notification data of a ME_ENDPOINT notify */ static chunk_t build_notification_data(private_endpoint_notify_t *this) { @@ -222,7 +217,7 @@ static chunk_t build_notification_data(private_endpoint_notify_t *this) /* data = prio | family | type | port | addr */ data = chunk_cat("ccccc", prio_chunk, family_chunk, type_chunk, port_chunk, addr_chunk); - DBG3(DBG_IKE, "p2p_endpoint_data %B", &data); + DBG3(DBG_IKE, "me_endpoint_data %B", &data); return data; } @@ -236,7 +231,7 @@ static notify_payload_t *build_notify(private_endpoint_notify_t *this) notify_payload_t *notify; notify = notify_payload_create(); - notify->set_notify_type(notify, P2P_ENDPOINT); + notify->set_notify_type(notify, ME_ENDPOINT); data = build_notification_data(this); notify->set_notification_data(notify, data); chunk_free(&data); @@ -263,7 +258,7 @@ static void set_priority(private_endpoint_notify_t *this, u_int32_t priority) /** * Implementation of endpoint_notify_t.get_type. */ -static p2p_endpoint_type_t get_type(private_endpoint_notify_t *this) +static me_endpoint_type_t get_type(private_endpoint_notify_t *this) { return this->type; } @@ -271,7 +266,7 @@ static p2p_endpoint_type_t get_type(private_endpoint_notify_t *this) /** * Implementation of endpoint_notify_t.get_family. */ -static p2p_endpoint_family_t get_family(private_endpoint_notify_t *this) +static me_endpoint_family_t get_family(private_endpoint_notify_t *this) { return this->family; } @@ -321,6 +316,7 @@ static endpoint_notify_t *_clone(private_endpoint_notify_t *this) static status_t destroy(private_endpoint_notify_t *this) { DESTROY_IF(this->endpoint); + DESTROY_IF(this->base); free(this); return SUCCESS; } @@ -335,8 +331,8 @@ endpoint_notify_t *endpoint_notify_create() /* public functions */ this->public.get_priority = (u_int32_t (*) (endpoint_notify_t *)) get_priority; this->public.set_priority = (void (*) (endpoint_notify_t *, u_int32_t)) set_priority; - this->public.get_type = (p2p_endpoint_type_t (*) (endpoint_notify_t *)) get_type; - this->public.get_family = (p2p_endpoint_family_t (*) (endpoint_notify_t *)) get_family; + this->public.get_type = (me_endpoint_type_t (*) (endpoint_notify_t *)) get_type; + this->public.get_family = (me_endpoint_family_t (*) (endpoint_notify_t *)) get_family; this->public.get_host = (host_t *(*) (endpoint_notify_t *)) get_host; this->public.get_base = (host_t *(*) (endpoint_notify_t *)) get_base; this->public.build_notify = (notify_payload_t *(*) (endpoint_notify_t *)) build_notify; @@ -356,7 +352,7 @@ endpoint_notify_t *endpoint_notify_create() /** * Described in header */ -endpoint_notify_t *endpoint_notify_create_from_host(p2p_endpoint_type_t type, host_t *host, host_t *base) +endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type, host_t *host, host_t *base) { private_endpoint_notify_t *this = (private_endpoint_notify_t*)endpoint_notify_create(); @@ -365,20 +361,21 @@ endpoint_notify_t *endpoint_notify_create_from_host(p2p_endpoint_type_t type, ho switch(type) { case HOST: - this->priority = pow(2, 16) * P2P_PRIO_HOST; - break; - case SERVER_REFLEXIVE: - this->priority = pow(2, 16) * P2P_PRIO_SERVER; + this->priority = pow(2, 16) * ME_PRIO_HOST; break; case PEER_REFLEXIVE: - this->priority = pow(2, 16) * P2P_PRIO_PEER; + this->priority = pow(2, 16) * ME_PRIO_PEER; + break; + case SERVER_REFLEXIVE: + this->priority = pow(2, 16) * ME_PRIO_SERVER; break; case RELAYED: default: - this->priority = pow(2, 16) * P2P_PRIO_RELAY; + this->priority = pow(2, 16) * ME_PRIO_RELAY; break; } + /* FIXME: if there is more than one ip address we should vary this priority */ this->priority += 65535; if (!host) @@ -395,7 +392,7 @@ endpoint_notify_t *endpoint_notify_create_from_host(p2p_endpoint_type_t type, ho this->family = IPv6; break; default: - /* unsupported family type, we do not set the hsot + /* unsupported family type, we do not set the host * (family is set to NO_FAMILY) */ return &this->public; } @@ -415,7 +412,7 @@ endpoint_notify_t *endpoint_notify_create_from_host(p2p_endpoint_type_t type, ho */ endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify) { - if (notify->get_notify_type(notify) != P2P_ENDPOINT) + if (notify->get_notify_type(notify) != ME_ENDPOINT) { return NULL; } diff --git a/src/charon/encoding/payloads/endpoint_notify.h b/src/charon/encoding/payloads/endpoint_notify.h index 4a3a68f95..9a4a4d7a1 100644 --- a/src/charon/encoding/payloads/endpoint_notify.h +++ b/src/charon/encoding/payloads/endpoint_notify.h @@ -1,10 +1,3 @@ -/** - * @file endpoint_notify.h - * - * @brief Interface of endpoint_notify_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Hochschule fuer Technik Rapperswil @@ -18,29 +11,33 @@ * 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. + * + * $Id: endpoint_notify.h 3701 2008-03-31 10:56:49Z tobias $ */ +/** + * @defgroup endpoint_notify endpoint_notify + * @{ @ingroup payloads + */ #ifndef ENDPOINT_NOTIFY_H_ #define ENDPOINT_NOTIFY_H_ -#define P2P_PRIO_HOST 255 -#define P2P_PRIO_SERVER 100 -#define P2P_PRIO_PEER 120 -#define P2P_PRIO_RELAY 0 +#define ME_PRIO_HOST 255 +#define ME_PRIO_PEER 128 +#define ME_PRIO_SERVER 64 +#define ME_PRIO_RELAY 0 -typedef enum p2p_endpoint_family_t p2p_endpoint_family_t; -typedef enum p2p_endpoint_type_t p2p_endpoint_type_t; +typedef enum me_endpoint_family_t me_endpoint_family_t; +typedef enum me_endpoint_type_t me_endpoint_type_t; typedef struct endpoint_notify_t endpoint_notify_t; #include <encoding/payloads/notify_payload.h> /** - * @brief P2P endpoint families. - * - * @ingroup payloads + * ME endpoint families. */ -enum p2p_endpoint_family_t { +enum me_endpoint_family_t { NO_FAMILY = 0, @@ -53,19 +50,17 @@ enum p2p_endpoint_family_t { }; /** - * @brief P2P endpoint types. - * - * @ingroup payloads + * ME endpoint types. */ -enum p2p_endpoint_type_t { +enum me_endpoint_type_t { NO_TYPE = 0, HOST = 1, - SERVER_REFLEXIVE = 2, + PEER_REFLEXIVE = 2, - PEER_REFLEXIVE = 3, + SERVER_REFLEXIVE = 3, RELAYED = 4, @@ -74,129 +69,107 @@ enum p2p_endpoint_type_t { }; /** - * enum name for p2p_endpoint_type_t. - * - * @ingroup payloads + * enum name for me_endpoint_type_t. */ -extern enum_name_t *p2p_endpoint_type_names; +extern enum_name_t *me_endpoint_type_names; /** - * @brief Class representing a P2P_ENDPOINT notify. In fact it's not + * Class representing a ME_ENDPOINT Notify payload. In fact it's not * the notify per se, but the notification data of that notify that is * handled with this class. - * - * @b Constructors: - * - endpoint_notify_create() - * - endpoint_notify_create_from_host() - * - * @ingroup payloads */ struct endpoint_notify_t { /** - * @brief Returns the priority of this endpoint. + * Returns the priority of this endpoint. * - * @param this object * @return priority */ u_int32_t (*get_priority) (endpoint_notify_t *this); /** - * @brief Sets the priority of this endpoint. + * Sets the priority of this endpoint. * - * @param this object * @param priority priority */ void (*set_priority) (endpoint_notify_t *this, u_int32_t priority); /** - * @brief Returns the endpoint type of this endpoint. + * Returns the endpoint type of this endpoint. * - * @param this object * @return endpoint type */ - p2p_endpoint_type_t (*get_type) (endpoint_notify_t *this); + me_endpoint_type_t (*get_type) (endpoint_notify_t *this); /** - * @brief Returns the endpoint family of this endpoint. + * Returns the endpoint family of this endpoint. * - * @param this object * @return endpoint family */ - p2p_endpoint_family_t (*get_family) (endpoint_notify_t *this); + me_endpoint_family_t (*get_family) (endpoint_notify_t *this); /** - * @brief Returns the host of this endpoint. + * Returns the host of this endpoint. * - * @param this object * @return host */ host_t *(*get_host) (endpoint_notify_t *this); /** - * @brief Returns the base of this endpoint. + * Returns the base of this endpoint. * * If this is not a SERVER_REFLEXIVE endpoint, the returned host is the same * as the one returned by get_host. * - * @param this object * @return host */ host_t *(*get_base) (endpoint_notify_t *this); /** - * @brief Generates a notification payload from this endpoint. + * Generates a notification payload from this endpoint. * - * @param this object * @return built notify_payload_t */ notify_payload_t *(*build_notify) (endpoint_notify_t *this); /** - * @brief Clones an endpoint_notify_t object. + * Clones an endpoint_notify_t object. * - * @param this endpoint_notify_t object to clone - * @return cloned object + * @return cloned object */ endpoint_notify_t *(*clone) (endpoint_notify_t *this); /** - * @brief Destroys an endpoint_notify_t object. - * - * @param this endpoint_notify_t object to destroy + * Destroys an endpoint_notify_t object. */ void (*destroy) (endpoint_notify_t *this); }; /** - * @brief Creates an empty endpoint_notify_t object. + * Creates an empty endpoint_notify_t object. * * @return created endpoint_notify_t object - * - * @ingroup payloads */ endpoint_notify_t *endpoint_notify_create(void); /** - * @brief Creates an endpoint_notify_t object from a host. + * Creates an endpoint_notify_t object from a host. * * @param type the endpoint type * @param host host to base the notify on (gets cloned) * @param base base of the endpoint, applies only to reflexive endpoints (gets cloned) * @return created endpoint_notify_t object - * - * @ingroup payloads */ -endpoint_notify_t *endpoint_notify_create_from_host(p2p_endpoint_type_t type, host_t *host, host_t *base); +endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type, + host_t *host, host_t *base); /** - * @brief Creates an endpoint_notify_t object from a notify payload. + * Creates an endpoint_notify_t object from a notify payload. * * @param notify the notify payload * @return - created endpoint_notify_t object * - NULL if invalid payload - * @ingroup payloads */ endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify); -#endif /*ENDPOINT_NOTIFY_H_*/ +#endif /*ENDPOINT_NOTIFY_H_ @} */ diff --git a/src/charon/encoding/payloads/id_payload.c b/src/charon/encoding/payloads/id_payload.c index aef8f6b7e..347ad7563 100644 --- a/src/charon/encoding/payloads/id_payload.c +++ b/src/charon/encoding/payloads/id_payload.c @@ -1,10 +1,3 @@ -/** - * @file id_payload.h - * - * @brief Interface of id_payload_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -21,6 +14,8 @@ * 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. + * + * $Id: id_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/id_payload.h b/src/charon/encoding/payloads/id_payload.h index 8e9322b4a..49e6c214b 100644 --- a/src/charon/encoding/payloads/id_payload.h +++ b/src/charon/encoding/payloads/id_payload.h @@ -1,10 +1,3 @@ -/** - * @file id_payload.h - * - * @brief Interface of id_payload_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -20,8 +13,14 @@ * 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. + * + * $Id: id_payload.h 3589 2008-03-13 14:14:44Z martin $ */ +/** + * @defgroup id_payload id_payload + * @{ @ingroup payloads + */ #ifndef ID_PAYLOAD_H_ #define ID_PAYLOAD_H_ @@ -34,8 +33,6 @@ typedef struct id_payload_t id_payload_t; /** * Length of a id payload without the data in bytes. - * - * @ingroup payloads */ #define ID_PAYLOAD_HEADER_LENGTH 8 @@ -43,12 +40,6 @@ typedef struct id_payload_t id_payload_t; * Object representing an IKEv2 ID payload. * * The ID payload format is described in RFC section 3.5. - * - * @b Constructors: - * - id_payload_create_from_identification() - * - id_payload_create() - * - * @ingroup payloads */ struct id_payload_t { /** @@ -57,90 +48,77 @@ struct id_payload_t { payload_t payload_interface; /** - * @brief Set the ID type. + * Set the ID type. * - * @param this calling id_payload_t object * @param type Type of ID */ void (*set_id_type) (id_payload_t *this, id_type_t type); /** - * @brief Get the ID type. + * Get the ID type. * - * @param this calling id_payload_t object * @return type of the ID */ id_type_t (*get_id_type) (id_payload_t *this); /** - * @brief Set the ID data. + * Set the ID data. * * Data are getting cloned. * - * @param this calling id_payload_t object * @param data ID data as chunk_t */ void (*set_data) (id_payload_t *this, chunk_t data); /** - * @brief Get the ID data. + * Get the ID data. * * Returned data are a copy of the internal one * - * @param this calling id_payload_t object * @return ID data as chunk_t */ chunk_t (*get_data_clone) (id_payload_t *this); /** - * @brief Get the ID data. + * Get the ID data. * * Returned data are NOT copied. * - * @param this calling id_payload_t object * @return ID data as chunk_t */ chunk_t (*get_data) (id_payload_t *this); /** - * @brief Creates an identification object of this id payload. + * Creates an identification object of this id payload. * * Returned object has to get destroyed by the caller. * - * @param this calling id_payload_t object * @return identification_t object */ identification_t *(*get_identification) (id_payload_t *this); /** - * @brief Destroys an id_payload_t object. - * - * @param this id_payload_t object to destroy + * Destroys an id_payload_t object. */ void (*destroy) (id_payload_t *this); }; /** - * @brief Creates an empty id_payload_t object. + * Creates an empty id_payload_t object. * * @param payload_type one of ID_INITIATOR, ID_RESPONDER * @return id_payload_t object - * - * @ingroup payloads */ id_payload_t *id_payload_create(payload_type_t payload_type); /** - * @brief Creates an id_payload_t from an existing identification_t object. + * Creates an id_payload_t from an existing identification_t object. * * @param payload_type one of ID_INITIATOR, ID_RESPONDER * @param identification identification_t object * @return id_payload_t object - * - * @ingroup payloads */ -id_payload_t *id_payload_create_from_identification(payload_type_t payload_type, identification_t *identification); - - +id_payload_t *id_payload_create_from_identification(payload_type_t payload_type, + identification_t *identification); -#endif /* ID_PAYLOAD_H_ */ +#endif /* ID_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/ike_header.c b/src/charon/encoding/payloads/ike_header.c index 3a171b095..1db64f0e3 100644 --- a/src/charon/encoding/payloads/ike_header.c +++ b/src/charon/encoding/payloads/ike_header.c @@ -1,10 +1,3 @@ -/** - * @file ike_header.c - * - * @brief Implementation of ike_header_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -20,6 +13,8 @@ * 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. + * + * $Id: ike_header.c 3666 2008-03-26 18:40:19Z tobias $ */ /* offsetof macro */ @@ -110,13 +105,13 @@ ENUM_NEXT(exchange_type_names, IKE_SA_INIT, INFORMATIONAL, EXCHANGE_TYPE_UNDEFIN "IKE_AUTH", "CREATE_CHILD_SA", "INFORMATIONAL"); -#ifdef P2P -ENUM_NEXT(exchange_type_names, P2P_CONNECT, P2P_CONNECT, INFORMATIONAL, - "P2P_CONNECT"); -ENUM_END(exchange_type_names, P2P_CONNECT); +#ifdef ME +ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, INFORMATIONAL, + "ME_CONNECT"); +ENUM_END(exchange_type_names, ME_CONNECT); #else ENUM_END(exchange_type_names, INFORMATIONAL); -#endif /* P2P */ +#endif /* ME */ /** * Encoding rules to parse or generate a IKEv2-Header. @@ -181,9 +176,9 @@ static status_t verify(private_ike_header_t *this) { if ((this->exchange_type < IKE_SA_INIT) || ((this->exchange_type > INFORMATIONAL) -#ifdef P2P - && (this->exchange_type != P2P_CONNECT) -#endif /* P2P */ +#ifdef ME + && (this->exchange_type != ME_CONNECT) +#endif /* ME */ )) { /* unsupported exchange type */ @@ -191,11 +186,11 @@ static status_t verify(private_ike_header_t *this) } if (this->initiator_spi == 0 -#ifdef P2P +#ifdef ME /* we allow zero spi for INFORMATIONAL exchanges, - * to allow P2P connectivity checks */ + * to allow connectivity checks */ && this->exchange_type != INFORMATIONAL -#endif /* P2P */ +#endif /* ME */ ) { /* initiator spi not set */ diff --git a/src/charon/encoding/payloads/ike_header.h b/src/charon/encoding/payloads/ike_header.h index e80964482..5568f081b 100644 --- a/src/charon/encoding/payloads/ike_header.h +++ b/src/charon/encoding/payloads/ike_header.h @@ -1,10 +1,3 @@ -/** - * @file ike_header.h - * - * @brief Interface of ike_header_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -20,6 +13,13 @@ * 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. + * + * $Id: ike_header.h 3666 2008-03-26 18:40:19Z tobias $ + */ + +/** + * @defgroup ike_header ike_header + * @{ @ingroup payloads */ #ifndef IKE_HEADER_H_ @@ -33,38 +33,28 @@ typedef struct ike_header_t ike_header_t; /** * Major Version of IKEv2. - * - * @ingroup payloads */ #define IKE_MAJOR_VERSION 2 /** * Minor Version of IKEv2. - * - * @ingroup payloads */ #define IKE_MINOR_VERSION 0 /** * Flag in IKEv2-Header. Always 0. - * - * @ingroup payloads */ #define HIGHER_VERSION_SUPPORTED_FLAG 0 /** * Length of IKE Header in Bytes. - * - * @ingroup payloads */ #define IKE_HEADER_LENGTH 28 /** - * @brief Different types of IKE-Exchanges. + * Different types of IKE-Exchanges. * - * See Draft for different types. - * - * @ingroup payloads + * See RFC for different types. */ enum exchange_type_t{ @@ -92,33 +82,26 @@ enum exchange_type_t{ * INFORMATIONAL. */ INFORMATIONAL = 37, -#ifdef P2P +#ifdef ME /** - * P2P_CONNECT + * ME_CONNECT */ - P2P_CONNECT = 240 -#endif /* P2P */ + ME_CONNECT = 240 +#endif /* ME */ }; /** * enum name for exchange_type_t - * - * @ingroup payloads */ extern enum_name_t *exchange_type_names; /** - * @brief An object of this type represents an IKEv2 header and is used to + * An object of this type represents an IKEv2 header and is used to * generate and parse IKEv2 headers. * * The header format of an IKEv2-Message is compatible to the * ISAKMP-Header format to allow implementations supporting * both versions of the IKE-protocol. - * - * @b Constructors: - * - ike_header_create() - * - * @ingroup payloads */ struct ike_header_t { /** @@ -127,141 +110,121 @@ struct ike_header_t { payload_t payload_interface; /** - * @brief Get the initiator spi. + * Get the initiator spi. * - * @param this ike_header_t object * @return initiator_spi */ u_int64_t (*get_initiator_spi) (ike_header_t *this); /** - * @brief Set the initiator spi. + * Set the initiator spi. * - * @param this ike_header_t object * @param initiator_spi initiator_spi */ void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi); /** - * @brief Get the responder spi. + * Get the responder spi. * - * @param this ike_header_t object * @return responder_spi */ u_int64_t (*get_responder_spi) (ike_header_t *this); /** - * @brief Set the responder spi. + * Set the responder spi. * - * @param this ike_header_t object * @param responder_spi responder_spi */ void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi); /** - * @brief Get the major version. + * Get the major version. * - * @param this ike_header_t object * @return major version */ u_int8_t (*get_maj_version) (ike_header_t *this); /** - * @brief Get the minor version. + * Get the minor version. * - * @param this ike_header_t object * @return minor version */ u_int8_t (*get_min_version) (ike_header_t *this); /** - * @brief Get the response flag. + * Get the response flag. * - * @param this ike_header_t object * @return response flag */ bool (*get_response_flag) (ike_header_t *this); /** - * @brief Set the response flag- + * Set the response flag- * - * @param this ike_header_t object * @param response response flag * */ void (*set_response_flag) (ike_header_t *this, bool response); /** - * @brief Get "higher version supported"-flag. + * Get "higher version supported"-flag. * - * @param this ike_header_t object * @return version flag */ bool (*get_version_flag) (ike_header_t *this); /** - * @brief Get the initiator flag. + * Get the initiator flag. * - * @param this ike_header_t object * @return initiator flag */ bool (*get_initiator_flag) (ike_header_t *this); /** - * @brief Set the initiator flag. + * Set the initiator flag. * - * @param this ike_header_t object * @param initiator initiator flag - * */ void (*set_initiator_flag) (ike_header_t *this, bool initiator); /** - * @brief Get the exchange type. + * Get the exchange type. * - * @param this ike_header_t object - * @return exchange type + * @return exchange type */ u_int8_t (*get_exchange_type) (ike_header_t *this); /** - * @brief Set the exchange type. + * Set the exchange type. * - * @param this ike_header_t object * @param exchange_type exchange type */ void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type); /** - * @brief Get the message id. + * Get the message id. * - * @param this ike_header_t object * @return message id */ u_int32_t (*get_message_id) (ike_header_t *this); /** - * @brief Set the message id. + * Set the message id. * - * @param this ike_header_t object * @param initiator_spi message id */ void (*set_message_id) (ike_header_t *this, u_int32_t message_id); /** - * @brief Destroys a ike_header_t object. - * - * @param this ike_header_t object to destroy + * Destroys a ike_header_t object. */ void (*destroy) (ike_header_t *this); }; /** - * @brief Create an ike_header_t object + * Create an ike_header_t object * * @return ike_header_t object - * - * @ingroup payloads */ ike_header_t *ike_header_create(void); -#endif /*IKE_HEADER_H_*/ +#endif /*IKE_HEADER_H_ @} */ diff --git a/src/charon/encoding/payloads/ke_payload.c b/src/charon/encoding/payloads/ke_payload.c index 8926b15f9..2f718e49c 100644 --- a/src/charon/encoding/payloads/ke_payload.c +++ b/src/charon/encoding/payloads/ke_payload.c @@ -1,10 +1,3 @@ -/** - * @file ke_payload.c - * - * @brief Implementation of ke_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: ke_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/ke_payload.h b/src/charon/encoding/payloads/ke_payload.h index 52be8ffe3..222d2ec7c 100644 --- a/src/charon/encoding/payloads/ke_payload.h +++ b/src/charon/encoding/payloads/ke_payload.h @@ -1,10 +1,3 @@ -/** - * @file ke_payload.h - * - * @brief Interface of ke_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: ke_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ke_payload ke_payload + * @{ @ingroup payloads */ #ifndef KE_PAYLOAD_H_ @@ -34,20 +34,13 @@ typedef struct ke_payload_t ke_payload_t; /** * KE payload length in bytes without any key exchange data. - * - * @ingroup payloads */ #define KE_PAYLOAD_HEADER_LENGTH 8 /** - * @brief Class representing an IKEv2-KE Payload. + * Class representing an IKEv2-KE Payload. * * The KE Payload format is described in RFC section 3.4. - * - * @b Constructors: - * - ke_payload_create() - * - * @ingroup payloads */ struct ke_payload_t { /** @@ -56,66 +49,58 @@ struct ke_payload_t { payload_t payload_interface; /** - * @brief Returns the currently set key exchange data of this KE payload. + * Returns the currently set key exchange data of this KE payload. * * @warning Returned data are not copied. * - * @param this calling ke_payload_t object * @return chunk_t pointing to the value */ chunk_t (*get_key_exchange_data) (ke_payload_t *this); /** - * @brief Sets the key exchange data of this KE payload. + * Sets the key exchange data of this KE payload. * - * @warning Value is getting copied. + * Value is getting copied. * - * @param this calling ke_payload_t object - * @param key_exchange_data chunk_t pointing to the value to set + * @param key_exchange_data chunk_t pointing to the value to set */ void (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data); /** - * @brief Gets the Diffie-Hellman Group Number of this KE payload. + * Gets the Diffie-Hellman Group Number of this KE payload. * - * @param this calling ke_payload_t object - * @return DH Group Number of this payload + * @return DH Group Number of this payload */ diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this); /** - * @brief Sets the Diffie-Hellman Group Number of this KE payload. + * Sets the Diffie-Hellman Group Number of this KE payload. * - * @param this calling ke_payload_t object * @param dh_group_number DH Group to set */ - void (*set_dh_group_number) (ke_payload_t *this, diffie_hellman_group_t dh_group_number); + void (*set_dh_group_number) (ke_payload_t *this, + diffie_hellman_group_t dh_group_number); /** - * @brief Destroys an ke_payload_t object. - * - * @param this ke_payload_t object to destroy + * Destroys an ke_payload_t object. */ void (*destroy) (ke_payload_t *this); }; /** - * @brief Creates an empty ke_payload_t object + * Creates an empty ke_payload_t object * * @return ke_payload_t object - * - * @ingroup payloads */ ke_payload_t *ke_payload_create(void); /** - * @brief Creates a ke_payload_t from a diffie_hellman_t + * Creates a ke_payload_t from a diffie_hellman_t * * @param diffie_hellman diffie hellman object containing group and key * @return ke_payload_t object - * - * @ingroup payloads */ -ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *diffie_hellman); +ke_payload_t *ke_payload_create_from_diffie_hellman( + diffie_hellman_t *diffie_hellman); -#endif /* KE_PAYLOAD_H_ */ +#endif /* KE_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/nonce_payload.c b/src/charon/encoding/payloads/nonce_payload.c index 8e1fc505e..da68ce4ab 100644 --- a/src/charon/encoding/payloads/nonce_payload.c +++ b/src/charon/encoding/payloads/nonce_payload.c @@ -1,10 +1,3 @@ -/** - * @file nonce_payload.h - * - * @brief Implementation of nonce_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: nonce_payload.c 3589 2008-03-13 14:14:44Z martin $ */ /* offsetof macro */ diff --git a/src/charon/encoding/payloads/nonce_payload.h b/src/charon/encoding/payloads/nonce_payload.h index 96d83b028..f1679834e 100644 --- a/src/charon/encoding/payloads/nonce_payload.h +++ b/src/charon/encoding/payloads/nonce_payload.h @@ -1,10 +1,3 @@ -/** - * @file nonce_payload.h - * - * @brief Interface of nonce_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: nonce_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup nonce_payload nonce_payload + * @{ @ingroup payloads */ #ifndef NONCE_PAYLOAD_H_ @@ -31,17 +31,11 @@ typedef struct nonce_payload_t nonce_payload_t; /** * Nonce size in bytes for nonces sending to other peer. - * - * @warning Nonce size MUST be between 16 and 256 bytes. - * - * @ingroup payloads */ #define NONCE_SIZE 16 /** * Length of a nonce payload without a nonce in bytes. - * - * @ingroup payloads */ #define NONCE_PAYLOAD_HEADER_LENGTH 4 @@ -49,11 +43,6 @@ typedef struct nonce_payload_t nonce_payload_t; * Object representing an IKEv2 Nonce payload. * * The Nonce payload format is described in RFC section 3.3. - * - * @b Constructors: - * - nonce_payload_create() - * - * @ingroup payloads */ struct nonce_payload_t { /** @@ -62,38 +51,30 @@ struct nonce_payload_t { payload_t payload_interface; /** - * @brief Set the nonce value. + * Set the nonce value. * - * @param this calling nonce_payload_t object * @param nonce chunk containing the nonce, will be cloned */ void (*set_nonce) (nonce_payload_t *this, chunk_t nonce); /** - * @brief Get the nonce value. + * Get the nonce value. * - * @param this calling nonce_payload_t object * @return a chunk containing the cloned nonce */ chunk_t (*get_nonce) (nonce_payload_t *this); /** - * @brief Destroys an nonce_payload_t object. - * - * @param this nonce_payload_t object to destroy + * Destroys an nonce_payload_t object. */ void (*destroy) (nonce_payload_t *this); }; /** - * @brief Creates an empty nonce_payload_t object + * Creates an empty nonce_payload_t object * * @return nonce_payload_t object - * - * @ingroup payloads */ - nonce_payload_t *nonce_payload_create(void); - -#endif /*NONCE_PAYLOAD_H_*/ +#endif /*NONCE_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/notify_payload.c b/src/charon/encoding/payloads/notify_payload.c index d32257af6..defb0b98a 100644 --- a/src/charon/encoding/payloads/notify_payload.c +++ b/src/charon/encoding/payloads/notify_payload.c @@ -1,12 +1,5 @@ -/** - * @file notify_payload.c - * - * @brief Implementation of notify_payload_t. - * - */ - /* - * Copyright (C) 2006-2007 Tobias Brunner + * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -21,6 +14,8 @@ * 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. + * + * $Id: notify_payload.c 3920 2008-05-08 16:19:11Z tobias $ */ #include <stddef.h> @@ -57,9 +52,9 @@ ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, UNEXPECTED_NAT_DETECTED, AUTH "INVALID_SELECTORS", "UNACCEPTABLE_ADDRESSES", "UNEXPECTED_NAT_DETECTED"); -ENUM_NEXT(notify_type_names, P2P_CONNECT_FAILED, P2P_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED, - "P2P_CONNECT_FAILED"); -ENUM_NEXT(notify_type_names, INITIAL_CONTACT, AUTH_LIFETIME, P2P_CONNECT_FAILED, +ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED, + "ME_CONNECT_FAILED"); +ENUM_NEXT(notify_type_names, INITIAL_CONTACT, AUTH_LIFETIME, ME_CONNECT_FAILED, "INITIAL_CONTACT", "SET_WINDOW_SIZE", "ADDITIONAL_TS_POSSIBLE", @@ -84,14 +79,15 @@ ENUM_NEXT(notify_type_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, A "EAP_ONLY_AUTHENTICATION"); ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION, "USE_BEET_MODE"); -ENUM_NEXT(notify_type_names, P2P_MEDIATION, P2P_RESPONSE, USE_BEET_MODE, - "P2P_MEDIATION", - "P2P_ENDPOINT", - "P2P_CALLBACK", - "P2P_SESSIONID", - "P2P_SESSIONKEY", - "P2P_RESPONSE"); -ENUM_END(notify_type_names, P2P_RESPONSE); +ENUM_NEXT(notify_type_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE, + "ME_MEDIATION", + "ME_ENDPOINT", + "ME_CALLBACK", + "ME_CONNECTID", + "ME_CONNECTKEY", + "ME_CONNECTAUTH", + "ME_RESPONSE"); +ENUM_END(notify_type_names, ME_RESPONSE); ENUM_BEGIN(notify_type_short_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD, @@ -120,9 +116,9 @@ ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, UNEXPECTED_NAT_DETECTED "INVAL_SEL", "UNACCEPT_ADDR", "UNEXPECT_NAT"); -ENUM_NEXT(notify_type_short_names, P2P_CONNECT_FAILED, P2P_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED, - "P2P_CONN_FAIL"); -ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, AUTH_LIFETIME, P2P_CONNECT_FAILED, +ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED, + "ME_CONN_FAIL"); +ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, AUTH_LIFETIME, ME_CONNECT_FAILED, "INIT_CONTACT", "SET_WINSIZE", "ADD_TS_POSS", @@ -147,14 +143,15 @@ ENUM_NEXT(notify_type_short_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICAT "EAP_ONLY"); ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION, "BEET_MODE"); -ENUM_NEXT(notify_type_short_names, P2P_MEDIATION, P2P_RESPONSE, USE_BEET_MODE, - "P2P_MED", - "P2P_EP", - "P2P_CB", - "P2P_SID", - "P2P_SKEY", - "P2P_R"); -ENUM_END(notify_type_short_names, P2P_RESPONSE); +ENUM_NEXT(notify_type_short_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE, + "ME_MED", + "ME_EP", + "ME_CB", + "ME_CID", + "ME_CKEY", + "ME_CAUTH", + "ME_R"); +ENUM_END(notify_type_short_names, ME_RESPONSE); typedef struct private_notify_payload_t private_notify_payload_t; @@ -293,6 +290,7 @@ static status_t verify(private_notify_payload_t *this) } case NAT_DETECTION_SOURCE_IP: case NAT_DETECTION_DESTINATION_IP: + case ME_CONNECTAUTH: { if (this->notification_data.len != HASH_SIZE_SHA1) { @@ -334,7 +332,36 @@ static status_t verify(private_notify_payload_t *this) } break; } - /* FIXME: check size of P2P-NAT-T payloads */ + case IPCOMP_SUPPORTED: + { + if (this->notification_data.len != 3) + { + bad_length = TRUE; + } + break; + } + case ME_ENDPOINT: + if (this->notification_data.len != 8 && + this->notification_data.len != 12 && + this->notification_data.len != 24) + { + bad_length = TRUE; + } + break; + case ME_CONNECTID: + if (this->notification_data.len < 4 || + this->notification_data.len > 16) + { + bad_length = TRUE; + } + break; + case ME_CONNECTKEY: + if (this->notification_data.len < 16 || + this->notification_data.len > 32) + { + bad_length = TRUE; + } + break; default: /* TODO: verify */ break; diff --git a/src/charon/encoding/payloads/notify_payload.h b/src/charon/encoding/payloads/notify_payload.h index 03f61d473..f4a3bf27c 100644 --- a/src/charon/encoding/payloads/notify_payload.h +++ b/src/charon/encoding/payloads/notify_payload.h @@ -1,12 +1,5 @@ -/** - * @file notify_payload.h - * - * @brief Interface of notify_payload_t. - * - */ - /* - * Copyright (C) 2006-2007 Tobias Brunner + * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -21,8 +14,14 @@ * 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. + * + * $Id: notify_payload.h 3670 2008-03-27 09:54:09Z tobias $ */ +/** + * @defgroup notify_payload notify_payload + * @{ @ingroup payloads + */ #ifndef NOTIFY_PAYLOAD_H_ #define NOTIFY_PAYLOAD_H_ @@ -37,17 +36,13 @@ typedef struct notify_payload_t notify_payload_t; /** * Notify payload length in bytes without any spi and notification data. - * - * @ingroup payloads */ #define NOTIFY_PAYLOAD_HEADER_LENGTH 8 /** - * @brief Notify message types. + * Notify message types. * * See IKEv2 RFC 3.10.1. - * - * @ingroup payloads */ enum notify_type_t { /* notify error messages */ @@ -68,8 +63,8 @@ enum notify_type_t { INVALID_SELECTORS = 39, UNACCEPTABLE_ADDRESSES = 40, UNEXPECTED_NAT_DETECTED = 41, - /* P2P-NAT-T, private use */ - P2P_CONNECT_FAILED = 8192, + /* IKE-ME, private use */ + ME_CONNECT_FAILED = 8192, /* notify status messages */ INITIAL_CONTACT = 16384, @@ -98,41 +93,30 @@ enum notify_type_t { EAP_ONLY_AUTHENTICATION = 40960, /* BEET mode, not even a draft yet. private use */ USE_BEET_MODE = 40961, - /* P2P-NAT-T, private use */ - P2P_MEDIATION = 40962, - P2P_ENDPOINT = 40963, - P2P_CALLBACK = 40964, - P2P_SESSIONID = 40965, - P2P_SESSIONKEY = 40966, - P2P_RESPONSE = 40967 + /* IKE-ME, private use */ + ME_MEDIATION = 40962, + ME_ENDPOINT = 40963, + ME_CALLBACK = 40964, + ME_CONNECTID = 40965, + ME_CONNECTKEY = 40966, + ME_CONNECTAUTH = 40967, + ME_RESPONSE = 40968 }; /** * enum name for notify_type_t. - * - * @ingroup payloads */ extern enum_name_t *notify_type_names; /** * enum name for notify_type_t (shorter strings). - * - * @ingroup payloads */ extern enum_name_t *notify_type_short_names; /** - * @brief Class representing an IKEv2-Notify Payload. + * Class representing an IKEv2-Notify Payload. * * The Notify Payload format is described in Draft section 3.10. - * - * @b Constructors: - * - notify_payload_create() - * - notify_payload_create_from_protocol_and_type() - * - * @todo Build specified constructor/getter for notify's - * - * @ingroup payloads */ struct notify_payload_t { /** @@ -141,104 +125,91 @@ struct notify_payload_t { payload_t payload_interface; /** - * @brief Gets the protocol id of this payload. + * Gets the protocol id of this payload. * - * @param this calling notify_payload_t object * @return protocol id of this payload */ u_int8_t (*get_protocol_id) (notify_payload_t *this); /** - * @brief Sets the protocol id of this payload. + * Sets the protocol id of this payload. * - * @param this calling notify_payload_t object * @param protocol_id protocol id to set */ void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id); /** - * @brief Gets the notify message type of this payload. + * Gets the notify message type of this payload. * - * @param this calling notify_payload_t object * @return notify message type of this payload */ notify_type_t (*get_notify_type) (notify_payload_t *this); /** - * @brief Sets notify message type of this payload. + * Sets notify message type of this payload. * - * @param this calling notify_payload_t object * @param type notify message type to set */ void (*set_notify_type) (notify_payload_t *this, notify_type_t type); /** - * @brief Returns the currently set spi of this payload. + * Returns the currently set spi of this payload. * * This is only valid for notifys with protocol AH|ESP * - * @param this calling notify_payload_t object * @return SPI value */ u_int32_t (*get_spi) (notify_payload_t *this); /** - * @brief Sets the spi of this payload. + * Sets the spi of this payload. * * This is only valid for notifys with protocol AH|ESP * - * @param this calling notify_payload_t object * @param spi SPI value */ void (*set_spi) (notify_payload_t *this, u_int32_t spi); /** - * @brief Returns the currently set notification data of payload. + * Returns the currently set notification data of payload. * - * @warning Returned data are not copied. + * Returned data are not copied. * - * @param this calling notify_payload_t object * @return chunk_t pointing to the value */ chunk_t (*get_notification_data) (notify_payload_t *this); /** - * @brief Sets the notification data of this payload. + * Sets the notification data of this payload. * * @warning Value is getting copied. * - * @param this calling notify_payload_t object * @param notification_data chunk_t pointing to the value to set */ - void (*set_notification_data) (notify_payload_t *this, chunk_t notification_data); + void (*set_notification_data) (notify_payload_t *this, + chunk_t notification_data); /** - * @brief Destroys an notify_payload_t object. - * - * @param this notify_payload_t object to destroy + * Destroys an notify_payload_t object. */ void (*destroy) (notify_payload_t *this); }; /** - * @brief Creates an empty notify_payload_t object + * Creates an empty notify_payload_t object * * @return created notify_payload_t object - * - * @ingroup payloads */ notify_payload_t *notify_payload_create(void); /** - * @brief Creates an notify_payload_t object of specific type for specific protocol id. + * Creates an notify_payload_t object of specific type for specific protocol id. * * @param protocol_id protocol id (IKE, AH or ESP) * @param type notify type (see notify_type_t) * @return notify_payload_t object - * - * @ingroup payloads */ -notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t type); - +notify_payload_t *notify_payload_create_from_protocol_and_type( + protocol_id_t protocol_id, notify_type_t type); -#endif /*NOTIFY_PAYLOAD_H_*/ +#endif /*NOTIFY_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/payload.c b/src/charon/encoding/payloads/payload.c index 2c51c60de..17986dd58 100644 --- a/src/charon/encoding/payloads/payload.c +++ b/src/charon/encoding/payloads/payload.c @@ -1,11 +1,3 @@ -/** - * @file payload.c - * - * @brief Generic constructor to the payload_t interface. - * - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -21,6 +13,8 @@ * 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. + * + * $Id: payload.c 3666 2008-03-26 18:40:19Z tobias $ */ @@ -64,13 +58,13 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N "ENCRYPTED", "CONFIGURATION", "EXTENSIBLE_AUTHENTICATION"); -#ifdef P2P +#ifdef ME ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION, "ID_PEER"); ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER, #else ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION, -#endif /* P2P */ +#endif /* ME */ "HEADER", "PROPOSAL_SUBSTRUCTURE", "TRANSFORM_SUBSTRUCTURE", @@ -100,13 +94,13 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT "E", "CP", "EAP"); -#ifdef P2P +#ifdef ME ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION, "IDp"); ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER, #else ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION, -#endif /* P2P */ +#endif /* ME */ "HDR", "PROP", "TRANS", @@ -139,10 +133,10 @@ payload_t *payload_create(payload_type_t type) return (payload_t*)id_payload_create(ID_INITIATOR); case ID_RESPONDER: return (payload_t*)id_payload_create(ID_RESPONDER); -#ifdef P2P +#ifdef ME case ID_PEER: return (payload_t*)id_payload_create(ID_PEER); -#endif /* P2P */ +#endif /* ME */ case AUTHENTICATION: return (payload_t*)auth_payload_create(); case CERTIFICATE: diff --git a/src/charon/encoding/payloads/payload.h b/src/charon/encoding/payloads/payload.h index ab902d755..abc79259a 100644 --- a/src/charon/encoding/payloads/payload.h +++ b/src/charon/encoding/payloads/payload.h @@ -1,10 +1,3 @@ -/** - * @file payload.h - * - * @brief Interface payload_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -20,6 +13,13 @@ * 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. + * + * $Id: payload.h 3666 2008-03-26 18:40:19Z tobias $ + */ + +/** + * @defgroup payload payload + * @{ @ingroup payloads */ #ifndef PAYLOAD_H_ @@ -33,12 +33,10 @@ typedef struct payload_t payload_t; /** - * @brief Payload-Types of a IKEv2-Message. + * Payload-Types of a IKEv2-Message. * * Header and substructures are also defined as * payload types with values from PRIVATE USE space. - * - * @ingroup payloads */ enum payload_type_t{ @@ -127,13 +125,13 @@ enum payload_type_t{ */ EXTENSIBLE_AUTHENTICATION = 48, -#ifdef P2P +#ifdef ME /** - * Identification payload for peers in P2P-NAT-T has a value from + * Identification payload for peers has a value from * the PRIVATE USE space. */ ID_PEER = 128, -#endif /* P2P */ +#endif /* ME */ /** * Header has a value of PRIVATE USE space. @@ -204,80 +202,65 @@ extern enum_name_t *payload_type_names; extern enum_name_t *payload_type_short_names; /** - * @brief Generic interface for all payload types (incl.header and substructures). + * Generic interface for all payload types (incl.header and substructures). * * To handle all kinds of payloads on a generic way, this interface must * be implemented by every payload. This allows parser_t/generator_t a simple * handling of all payloads. - * - * @b Constructors: - * - payload_create() with the payload to instantiate. - * - * @ingroup payloads */ struct payload_t { /** - * @brief Get encoding rules for this payload. + * Get encoding rules for this payload. * - * @param this calling object - * @param[out] rules location to store pointer of first rule - * @param[out] rule_count location to store number of rules + * @param rules location to store pointer of first rule + * @param rule_count location to store number of rules */ void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count); /** - * @brief Get type of payload. + * Get type of payload. * - * @param this calling object - * @return type of this payload + * @return type of this payload */ payload_type_t (*get_type) (payload_t *this); /** - * @brief Get type of next payload or NO_PAYLOAD (0) if this is the last one. + * Get type of next payload or NO_PAYLOAD (0) if this is the last one. * - * @param this calling object - * @return type of next payload + * @return type of next payload */ payload_type_t (*get_next_type) (payload_t *this); /** - * @brief Set type of next payload. + * Set type of next payload. * - * @param this calling object - * @param type type of next payload + * @param type type of next payload */ void (*set_next_type) (payload_t *this,payload_type_t type); /** - * @brief Get length of payload. + * Get length of payload. * - * @param this calling object - * @return length of this payload + * @return length of this payload */ size_t (*get_length) (payload_t *this); /** - * @brief Verifies payload structure and makes consistence check. + * Verifies payload structure and makes consistence check. * - * @param this calling object - * @return - * - SUCCESS - * - FAILED if consistence not given + * @return SUCCESS, FAILED if consistence not given */ status_t (*verify) (payload_t *this); /** - * @brief Destroys a payload and all included substructures. - * - * @param this payload to destroy + * Destroys a payload and all included substructures. */ void (*destroy) (payload_t *this); }; /** - * @brief Create an empty payload. + * Create an empty payload. * * Useful for the parser, who wants a generic constructor for all payloads. * It supports all payload_t methods. If a payload type is not known, @@ -288,4 +271,4 @@ struct payload_t { */ payload_t *payload_create(payload_type_t type); -#endif /*PAYLOAD_H_*/ +#endif /*PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/proposal_substructure.c b/src/charon/encoding/payloads/proposal_substructure.c index 182d2b6e8..daa015d3e 100644 --- a/src/charon/encoding/payloads/proposal_substructure.c +++ b/src/charon/encoding/payloads/proposal_substructure.c @@ -1,10 +1,3 @@ -/** - * @file proposal_substructure.h - * - * @brief Implementation of proposal_substructure_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: proposal_substructure.c 3658 2008-03-26 10:06:45Z martin $ */ #include <stddef.h> @@ -521,60 +516,62 @@ proposal_substructure_t *proposal_substructure_create() */ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal) { - private_proposal_substructure_t *this = (private_proposal_substructure_t*) - proposal_substructure_create(); - iterator_t *iterator; - algorithm_t *algo; transform_substructure_t *transform; + private_proposal_substructure_t *this; + u_int16_t alg, key_size; + enumerator_t *enumerator; + + this = (private_proposal_substructure_t*)proposal_substructure_create(); /* encryption algorithm is only availble in ESP */ - iterator = proposal->create_algorithm_iterator(proposal, ENCRYPTION_ALGORITHM); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM); + while (enumerator->enumerate(enumerator, &alg, &key_size)) { transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM, - algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); + alg, key_size); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* integrity algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, INTEGRITY_ALGORITHM); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM); + while (enumerator->enumerate(enumerator, &alg, &key_size)) { transform = transform_substructure_create_type(INTEGRITY_ALGORITHM, - algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); + alg, key_size); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* prf algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, PSEUDO_RANDOM_FUNCTION); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION); + while (enumerator->enumerate(enumerator, &alg, &key_size)) { transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION, - algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); + alg, key_size); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* dh groups */ - iterator = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP); + while (enumerator->enumerate(enumerator, &alg, NULL)) { - transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, algo->algorithm, 0); - this->public.add_transform_substructure(&(this->public), transform); + transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, + alg, 0); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* extended sequence numbers */ - iterator = proposal->create_algorithm_iterator(proposal, EXTENDED_SEQUENCE_NUMBERS); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS); + while (enumerator->enumerate(enumerator, &alg, NULL)) { transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS, - algo->algorithm, 0); - this->public.add_transform_substructure(&(this->public), transform); + alg, 0); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* add SPI, if necessary */ switch (proposal->get_protocol(proposal)) diff --git a/src/charon/encoding/payloads/proposal_substructure.h b/src/charon/encoding/payloads/proposal_substructure.h index 93a8d7b2f..85daadddc 100644 --- a/src/charon/encoding/payloads/proposal_substructure.h +++ b/src/charon/encoding/payloads/proposal_substructure.h @@ -1,10 +1,3 @@ -/** - * @file proposal_substructure.h - * - * @brief Interface of proposal_substructure_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: proposal_substructure.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup proposal_substructure proposal_substructure + * @{ @ingroup payloads */ #ifndef PROPOSAL_SUBSTRUCTURE_H_ @@ -35,20 +35,13 @@ typedef struct proposal_substructure_t proposal_substructure_t; /** * Length of the proposal substructure header (without spi). - * - * @ingroup payloads */ #define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8 /** - * @brief Class representing an IKEv2-PROPOSAL SUBSTRUCTURE. + * Class representing an IKEv2-PROPOSAL SUBSTRUCTURE. * * The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1. - * - * @b Constructors: - * - proposal_substructure_create() - * - * @ingroup payloads */ struct proposal_substructure_t { /** @@ -57,150 +50,126 @@ struct proposal_substructure_t { payload_t payload_interface; /** - * @brief Creates an iterator of stored transform_substructure_t objects. - * - * @warning The created iterator has to get destroyed by the caller! - * When deleting any transform over this iterator, call - * get_size to make sure the length and number values are ok. + * Creates an iterator of stored transform_substructure_t objects. * - * @param this calling proposal_substructure_t object * @param forward iterator direction (TRUE: front to end) * @return created iterator_t object */ - iterator_t *(*create_transform_substructure_iterator) (proposal_substructure_t *this, bool forward); + iterator_t *(*create_transform_substructure_iterator) ( + proposal_substructure_t *this, bool forward); /** - * @brief Adds a transform_substructure_t object to this object. - * - * @warning The added transform_substructure_t object is - * getting destroyed in destroy function of proposal_substructure_t. + * Adds a transform_substructure_t object to this object. * - * @param this calling proposal_substructure_t object - * @param transform transform_substructure_t object to add + * @param transform transform_substructure_t object to add */ - void (*add_transform_substructure) (proposal_substructure_t *this,transform_substructure_t *transform); + void (*add_transform_substructure) (proposal_substructure_t *this, + transform_substructure_t *transform); /** - * @brief Sets the proposal number of current proposal. + * Sets the proposal number of current proposal. * - * @param this calling proposal_substructure_t object - * @param id proposal number to set + * @param id proposal number to set */ - void (*set_proposal_number) (proposal_substructure_t *this,u_int8_t proposal_number); + void (*set_proposal_number) (proposal_substructure_t *this, + u_int8_t proposal_number); /** - * @brief get proposal number of current proposal. + * get proposal number of current proposal. * - * @param this calling proposal_substructure_t object * @return proposal number of current proposal substructure. */ u_int8_t (*get_proposal_number) (proposal_substructure_t *this); /** - * @brief get the number of transforms in current proposal. + * get the number of transforms in current proposal. * - * @param this calling proposal_substructure_t object * @return transform count in current proposal */ size_t (*get_transform_count) (proposal_substructure_t *this); /** - * @brief get size of the set spi in bytes. + * get size of the set spi in bytes. * - * @param this calling proposal_substructure_t object * @return size of the spi in bytes */ size_t (*get_spi_size) (proposal_substructure_t *this); /** - * @brief Sets the protocol id of current proposal. + * Sets the protocol id of current proposal. * - * @param this calling proposal_substructure_t object - * @param id protocol id to set + * @param id protocol id to set */ - void (*set_protocol_id) (proposal_substructure_t *this,u_int8_t protocol_id); + void (*set_protocol_id) (proposal_substructure_t *this, + u_int8_t protocol_id); /** - * @brief get protocol id of current proposal. + * get protocol id of current proposal. * - * @param this calling proposal_substructure_t object * @return protocol id of current proposal substructure. */ u_int8_t (*get_protocol_id) (proposal_substructure_t *this); /** - * @brief Sets the next_payload field of this substructure + * Sets the next_payload field of this substructure * * If this is the last proposal, next payload field is set to 0, * otherwise to 2 * - * @param this calling proposal_substructure_t object * @param is_last When TRUE, next payload field is set to 0, otherwise to 2 */ void (*set_is_last_proposal) (proposal_substructure_t *this, bool is_last); /** - * @brief Returns the currently set SPI of this proposal. - * - * @warning Returned data are not copied - * - * @param this calling proposal_substructure_t object - * @return chunk_t pointing to the value + * Returns the currently set SPI of this proposal. + * + * @return chunk_t pointing to the value */ chunk_t (*get_spi) (proposal_substructure_t *this); /** - * @brief Sets the SPI of the current proposal. + * Sets the SPI of the current proposal. * * @warning SPI is getting copied * - * @param this calling proposal_substructure_t object - * @param spi chunk_t pointing to the value to set + * @param spi chunk_t pointing to the value to set */ void (*set_spi) (proposal_substructure_t *this, chunk_t spi); /** - * @brief Get a proposal_t from the propsal_substructure_t. + * Get a proposal_t from the propsal_substructure_t. * - * @param this calling proposal_substructure_t object * @return proposal_t */ proposal_t * (*get_proposal) (proposal_substructure_t *this); /** - * @brief Clones an proposal_substructure_t object. + * Clones an proposal_substructure_t object. * - * @param this proposal_substructure_t object to clone * @return cloned object */ proposal_substructure_t* (*clone) (proposal_substructure_t *this); /** - * @brief Destroys an proposal_substructure_t object. - * - * @param this proposal_substructure_t object to destroy + * Destroys an proposal_substructure_t object. */ void (*destroy) (proposal_substructure_t *this); }; /** - * @brief Creates an empty proposal_substructure_t object + * Creates an empty proposal_substructure_t object * * @return proposal_substructure_t object - * - * @ingroup payloads */ proposal_substructure_t *proposal_substructure_create(void); /** - * @brief Creates a proposal_substructure_t from a proposal_t. + * Creates a proposal_substructure_t from a proposal_t. * * @param proposal proposal to build a substruct out of it * @return proposal_substructure_t object - * - * @ingroup payloads */ -proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal); - +proposal_substructure_t *proposal_substructure_create_from_proposal( + proposal_t *proposal); -#endif /*PROPOSAL_SUBSTRUCTURE_H_*/ +#endif /*PROPOSAL_SUBSTRUCTURE_H_ @} */ diff --git a/src/charon/encoding/payloads/sa_payload.c b/src/charon/encoding/payloads/sa_payload.c index 304f1b64c..ecc3b0f60 100644 --- a/src/charon/encoding/payloads/sa_payload.c +++ b/src/charon/encoding/payloads/sa_payload.c @@ -1,10 +1,3 @@ -/** - * @file sa_payload.c - * - * @brief Implementation of sa_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: sa_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/sa_payload.h b/src/charon/encoding/payloads/sa_payload.h index 67d687857..34906c889 100644 --- a/src/charon/encoding/payloads/sa_payload.h +++ b/src/charon/encoding/payloads/sa_payload.h @@ -1,10 +1,3 @@ -/** - * @file sa_payload.h - * - * @brief Interface of sa_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: sa_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup sa_payload sa_payload + * @{ @ingroup payloads */ #ifndef SA_PAYLOAD_H_ @@ -33,24 +33,13 @@ typedef struct sa_payload_t sa_payload_t; /** * SA_PAYLOAD length in bytes without any proposal substructure. - * - * @ingroup payloads */ #define SA_PAYLOAD_HEADER_LENGTH 4 /** - * @brief Class representing an IKEv2-SA Payload. + * Class representing an IKEv2-SA Payload. * * The SA Payload format is described in RFC section 3.3. - * - * @b Constructors: - * - sa_payload_create() - * - sa_payload_create_from_ike_proposals() - * - sa_payload_create_from_proposal() - * - * @todo Add support of algorithms without specified keylength in get_proposals and get_ike_proposals. - * - * @ingroup payloads */ struct sa_payload_t { /** @@ -59,83 +48,70 @@ struct sa_payload_t { payload_t payload_interface; /** - * @brief Creates an iterator of stored proposal_substructure_t objects. + * Creates an iterator of stored proposal_substructure_t objects. * - * @warning The created iterator has to get destroyed by the caller! - * - * @warning When deleting an proposal using this iterator, - * the length of this transform substructure has to be refreshed - * by calling get_length()! + * When deleting an proposal using this iterator, + * the length of this transform substructure has to be refreshed + * by calling get_length()! * - * @param this calling sa_payload_t object - * @param[in] forward iterator direction (TRUE: front to end) - * @return created iterator_t object + * @param forward iterator direction (TRUE: front to end) + * @return created iterator_t object */ - iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this, bool forward); + iterator_t *(*create_proposal_substructure_iterator) (sa_payload_t *this, + bool forward); /** - * @brief Adds a proposal_substructure_t object to this object. - * - * @warning The added proposal_substructure_t object is - * getting destroyed in destroy function of sa_payload_t. + * Adds a proposal_substructure_t object to this object. * - * @param this calling sa_payload_t object * @param proposal proposal_substructure_t object to add */ - void (*add_proposal_substructure) (sa_payload_t *this,proposal_substructure_t *proposal); + void (*add_proposal_substructure) (sa_payload_t *this, + proposal_substructure_t *proposal); /** - * @brief Gets the proposals in this payload as a list. + * Gets the proposals in this payload as a list. * * @return a list containing proposal_t s */ linked_list_t *(*get_proposals) (sa_payload_t *this); /** - * @brief Add a child proposal (AH/ESP) to the payload. + * Add a child proposal (AH/ESP) to the payload. * * @param proposal child proposal to add to the payload */ void (*add_proposal) (sa_payload_t *this, proposal_t *proposal); /** - * @brief Destroys an sa_payload_t object. - * - * @param this sa_payload_t object to destroy + * Destroys an sa_payload_t object. */ void (*destroy) (sa_payload_t *this); }; /** - * @brief Creates an empty sa_payload_t object + * Creates an empty sa_payload_t object * * @return created sa_payload_t object - * - * @ingroup payloads */ sa_payload_t *sa_payload_create(void); /** - * @brief Creates a sa_payload_t object from a list of proposals. + * Creates a sa_payload_t object from a list of proposals. * * @param proposals list of proposals to build the payload from * @return sa_payload_t object - * - * @ingroup payloads */ sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals); /** - * @brief Creates a sa_payload_t object from a single proposal. + * Creates a sa_payload_t object from a single proposal. * * This is only for convenience. Use sa_payload_create_from_proposal_list * if you want to add more than one proposal. * * @param proposal proposal from which the payload should be built. * @return sa_payload_t object - * - * @ingroup payloads */ sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal); -#endif /*SA_PAYLOAD_H_*/ +#endif /*SA_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/traffic_selector_substructure.c b/src/charon/encoding/payloads/traffic_selector_substructure.c index 573139bf3..f6042b4b6 100644 --- a/src/charon/encoding/payloads/traffic_selector_substructure.c +++ b/src/charon/encoding/payloads/traffic_selector_substructure.c @@ -1,10 +1,3 @@ -/** - * @file traffic_selector_substructure.c - * - * @brief Interface of traffic_selector_substructure_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: traffic_selector_substructure.c 3589 2008-03-13 14:14:44Z martin $ */ #include "traffic_selector_substructure.h" diff --git a/src/charon/encoding/payloads/traffic_selector_substructure.h b/src/charon/encoding/payloads/traffic_selector_substructure.h index 14efccc89..2a2769fb6 100644 --- a/src/charon/encoding/payloads/traffic_selector_substructure.h +++ b/src/charon/encoding/payloads/traffic_selector_substructure.h @@ -1,10 +1,3 @@ -/** - * @file traffic_selector_substructure.h - * - * @brief Interface of traffic_selector_substructure_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,8 +12,14 @@ * 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. + * + * $Id: traffic_selector_substructure.h 3589 2008-03-13 14:14:44Z martin $ */ +/** + * @defgroup traffic_selector_substructure traffic_selector_substructure + * @{ @ingroup payloads + */ #ifndef TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ #define TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ @@ -34,21 +33,13 @@ typedef struct traffic_selector_substructure_t traffic_selector_substructure_t; /** * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address. - * - * @ingroup payloads */ #define TRAFFIC_SELECTOR_HEADER_LENGTH 8 /** - * @brief Class representing an IKEv2 TRAFFIC SELECTOR. + * Class representing an IKEv2 TRAFFIC SELECTOR. * * The TRAFFIC SELECTOR format is described in RFC section 3.13.1. - * - * @b Constructors: - * - traffic_selector_substructure_create() - * - traffic_selector_substructure_create_from_traffic_selector() - * - * @ingroup payloads */ struct traffic_selector_substructure_t { /** @@ -57,116 +48,106 @@ struct traffic_selector_substructure_t { payload_t payload_interface; /** - * @brief Get the type of Traffic selector. + * Get the type of Traffic selector. * - * @param this calling traffic_selector_substructure_t object * @return type of traffic selector * */ ts_type_t (*get_ts_type) (traffic_selector_substructure_t *this); /** - * @brief Set the type of Traffic selector. + * Set the type of Traffic selector. * - * @param this calling traffic_selector_substructure_t object * @param ts_type type of traffic selector */ - void (*set_ts_type) (traffic_selector_substructure_t *this,ts_type_t ts_type); + void (*set_ts_type) (traffic_selector_substructure_t *this, + ts_type_t ts_type); /** - * @brief Get the IP protocol ID of Traffic selector. + * Get the IP protocol ID of Traffic selector. * - * @param this calling traffic_selector_substructure_t object * @return type of traffic selector * */ u_int8_t (*get_protocol_id) (traffic_selector_substructure_t *this); /** - * @brief Set the IP protocol ID of Traffic selector + * Set the IP protocol ID of Traffic selector * - * @param this calling traffic_selector_substructure_t object * @param protocol_id protocol ID of traffic selector */ - void (*set_protocol_id) (traffic_selector_substructure_t *this,u_int8_t protocol_id); + void (*set_protocol_id) (traffic_selector_substructure_t *this, + u_int8_t protocol_id); /** - * @brief Get the start port and address as host_t object. + * Get the start port and address as host_t object. * * Returned host_t object has to get destroyed by the caller. * - * @param this calling traffic_selector_substructure_t object * @return start host as host_t object * */ host_t *(*get_start_host) (traffic_selector_substructure_t *this); /** - * @brief Set the start port and address as host_t object. + * Set the start port and address as host_t object. * - * @param this calling traffic_selector_substructure_t object * @param start_host start host as host_t object */ - void (*set_start_host) (traffic_selector_substructure_t *this,host_t *start_host); + void (*set_start_host) (traffic_selector_substructure_t *this, + host_t *start_host); /** - * @brief Get the end port and address as host_t object. + * Get the end port and address as host_t object. * * Returned host_t object has to get destroyed by the caller. * - * @param this calling traffic_selector_substructure_t object * @return end host as host_t object * */ host_t *(*get_end_host) (traffic_selector_substructure_t *this); /** - * @brief Set the end port and address as host_t object. + * Set the end port and address as host_t object. * - * @param this calling traffic_selector_substructure_t object * @param end_host end host as host_t object */ - void (*set_end_host) (traffic_selector_substructure_t *this,host_t *end_host); + void (*set_end_host) (traffic_selector_substructure_t *this, + host_t *end_host); /** - * @brief Get a traffic_selector_t from this substructure. + * Get a traffic_selector_t from this substructure. * * @warning traffic_selector_t must be destroyed after usage. * - * @param this calling traffic_selector_substructure_t object * @return contained traffic_selector_t */ - traffic_selector_t *(*get_traffic_selector) (traffic_selector_substructure_t *this); + traffic_selector_t *(*get_traffic_selector) ( + traffic_selector_substructure_t *this); /** - * @brief Destroys an traffic_selector_substructure_t object. - * - * @param this traffic_selector_substructure_t object to destroy + * Destroys an traffic_selector_substructure_t object. */ void (*destroy) (traffic_selector_substructure_t *this); }; /** - * @brief Creates an empty traffic_selector_substructure_t object. + * Creates an empty traffic_selector_substructure_t object. * * TS type is set to default TS_IPV4_ADDR_RANGE! * * @return traffic_selector_substructure_t object - * - * @ingroup payloads */ traffic_selector_substructure_t *traffic_selector_substructure_create(void); /** - * @brief Creates an initialized traffif selector substructure using + * Creates an initialized traffif selector substructure using * the values from a traffic_selector_t. * * @param traffic_selector traffic_selector_t to use for initialization * @return traffic_selector_substructure_t object - * - * @ingroup payloads */ -traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector); - +traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector( + traffic_selector_t *traffic_selector); -#endif /* /TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ */ +#endif /* /TRAFFIC_SELECTOR_SUBSTRUCTURE_H_ @} */ diff --git a/src/charon/encoding/payloads/transform_attribute.c b/src/charon/encoding/payloads/transform_attribute.c index 066885c55..b9b5ff879 100644 --- a/src/charon/encoding/payloads/transform_attribute.c +++ b/src/charon/encoding/payloads/transform_attribute.c @@ -1,10 +1,3 @@ -/** - * @file transform_attribute.c - * - * @brief Implementation of transform_attribute_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: transform_attribute.c 3589 2008-03-13 14:14:44Z martin $ */ #include <string.h> diff --git a/src/charon/encoding/payloads/transform_attribute.h b/src/charon/encoding/payloads/transform_attribute.h index 30583b23f..891155913 100644 --- a/src/charon/encoding/payloads/transform_attribute.h +++ b/src/charon/encoding/payloads/transform_attribute.h @@ -1,10 +1,3 @@ -/** - * @file transform_attribute.h - * - * @brief Interface of transform_attribute_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: transform_attribute.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup transform_attribute transform_attribute + * @{ @ingroup payloads */ #ifndef TRANSFORM_ATTRIBUTE_H_ @@ -33,8 +33,6 @@ typedef struct transform_attribute_t transform_attribute_t; /** * Type of the attribute, as in IKEv2 RFC 3.3.5. - * - * @ingroup payloads */ enum transform_attribute_type_t { ATTRIBUTE_UNDEFINED = 16384, @@ -43,17 +41,13 @@ enum transform_attribute_type_t { /** * enum name for transform_attribute_type_t. - * - * @ingroup payloads */ extern enum_name_t *transform_attribute_type_names; /** - * @brief Class representing an IKEv2- TRANSFORM Attribute. + * Class representing an IKEv2- TRANSFORM Attribute. * * The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5. - * - * @ingroup payloads */ struct transform_attribute_t { /** @@ -62,93 +56,79 @@ struct transform_attribute_t { payload_t payload_interface; /** - * @brief Returns the currently set value of the attribute. + * Returns the currently set value of the attribute. * - * @warning Returned data are not copied. + * Returned data are not copied. * - * @param this calling transform_attribute_t object * @return chunk_t pointing to the value */ chunk_t (*get_value_chunk) (transform_attribute_t *this); /** - * @brief Returns the currently set value of the attribute. + * Returns the currently set value of the attribute. * - * @warning Returned data are not copied. + * Returned data are not copied. * - * @param this calling transform_attribute_t object * @return value */ u_int16_t (*get_value) (transform_attribute_t *this); /** - * @brief Sets the value of the attribute. + * Sets the value of the attribute. * - * @warning Value is getting copied. + * Value is getting copied. * - * @param this calling transform_attribute_t object * @param value chunk_t pointing to the value to set */ void (*set_value_chunk) (transform_attribute_t *this, chunk_t value); /** - * @brief Sets the value of the attribute. + * Sets the value of the attribute. * - * @param this calling transform_attribute_t object * @param value value to set */ void (*set_value) (transform_attribute_t *this, u_int16_t value); /** - * @brief Sets the type of the attribute. + * Sets the type of the attribute. * - * @param this calling transform_attribute_t object * @param type type to set (most significant bit is set to zero) */ void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type); /** - * @brief get the type of the attribute. + * get the type of the attribute. * - * @param this calling transform_attribute_t object * @return type of the value */ u_int16_t (*get_attribute_type) (transform_attribute_t *this); /** - * @brief Clones an transform_attribute_t object. + * Clones an transform_attribute_t object. * - * @param this transform_attribute_t object to clone * @return cloned transform_attribute_t object */ transform_attribute_t * (*clone) (transform_attribute_t *this); /** - * @brief Destroys an transform_attribute_t object. - * - * @param this transform_attribute_t object to destroy + * Destroys an transform_attribute_t object. */ void (*destroy) (transform_attribute_t *this); }; /** - * @brief Creates an empty transform_attribute_t object. + * Creates an empty transform_attribute_t object. * * @return transform_attribute_t object - * - * @ingroup payloads */ transform_attribute_t *transform_attribute_create(void); /** - * @brief Creates an transform_attribute_t of type KEY_LENGTH. + * Creates an transform_attribute_t of type KEY_LENGTH. * * @param key_length key length in bytes * @return transform_attribute_t object - * - * @ingroup payloads */ transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length); - -#endif /*TRANSFORM_ATTRIBUTE_H_*/ +#endif /*TRANSFORM_ATTRIBUTE_H_ @} */ diff --git a/src/charon/encoding/payloads/transform_substructure.c b/src/charon/encoding/payloads/transform_substructure.c index d64d6c754..7c3d6421a 100644 --- a/src/charon/encoding/payloads/transform_substructure.c +++ b/src/charon/encoding/payloads/transform_substructure.c @@ -1,10 +1,3 @@ -/** - * @file transform_substructure.h - * - * @brief Implementation of transform_substructure_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: transform_substructure.c 3971 2008-05-16 13:27:21Z tobias $ */ #include <stddef.h> @@ -395,14 +390,28 @@ transform_substructure_t *transform_substructure_create_type(transform_type_t tr transform->set_transform_id(transform,transform_id); /* a keylength attribute is only created for variable length algos */ - if (transform_type == ENCRYPTION_ALGORITHM && - (transform_id == ENCR_AES_CBC || - transform_id == ENCR_IDEA || - transform_id == ENCR_CAST || - transform_id == ENCR_BLOWFISH)) + if (transform_type == ENCRYPTION_ALGORITHM) { - transform_attribute_t *attribute = transform_attribute_create_key_length(key_length); - transform->add_transform_attribute(transform,attribute); + switch(transform_id) + { + case ENCR_AES_CBC: + case ENCR_IDEA: + case ENCR_CAST: + case ENCR_BLOWFISH: + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + { + transform_attribute_t *attribute = transform_attribute_create_key_length(key_length); + transform->add_transform_attribute(transform,attribute); + break; + } + default: + break; + } } return transform; diff --git a/src/charon/encoding/payloads/transform_substructure.h b/src/charon/encoding/payloads/transform_substructure.h index 97f587d5d..6be4b6d1e 100644 --- a/src/charon/encoding/payloads/transform_substructure.h +++ b/src/charon/encoding/payloads/transform_substructure.h @@ -1,10 +1,3 @@ -/** - * @file transform_substructure.h - * - * @brief Interface of transform_substructure_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: transform_substructure.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup transform_substructure transform_substructure + * @{ @ingroup payloads */ #ifndef TRANSFORM_SUBSTRUCTURE_H_ @@ -39,25 +39,19 @@ typedef struct transform_substructure_t transform_substructure_t; /** * IKEv1 Value for a transform payload. - * - * @ingroup payloads */ #define TRANSFORM_TYPE_VALUE 3 /** * Length of the transform substructure header in bytes. - * - * @ingroup payloads */ #define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8 /** - * @brief Class representing an IKEv2- TRANSFORM SUBSTRUCTURE. + * Class representing an IKEv2- TRANSFORM SUBSTRUCTURE. * * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2. - * - * @ingroup payloads */ struct transform_substructure_t { /** @@ -66,121 +60,105 @@ struct transform_substructure_t { payload_t payload_interface; /** - * @brief Creates an iterator of stored transform_attribute_t objects. - * - * @warning The created iterator has to get destroyed by the caller! + * Creates an iterator of stored transform_attribute_t objects. * - * @warning When deleting an transform attribute using this iterator, - * the length of this transform substructure has to be refreshed - * by calling get_length()! + * When deleting an transform attribute using this iterator, + * the length of this transform substructure has to be refreshed + * by calling get_length(). * - * @param this calling transform_substructure_t object - * @param[in] forward iterator direction (TRUE: front to end) + * @param forward iterator direction (TRUE: front to end) * @return created iterator_t object. */ - iterator_t * (*create_transform_attribute_iterator) (transform_substructure_t *this, bool forward); + iterator_t * (*create_transform_attribute_iterator) ( + transform_substructure_t *this, bool forward); /** - * @brief Adds a transform_attribute_t object to this object. - * - * @warning The added proposal_substructure_t object is - * getting destroyed in destroy function of transform_substructure_t. + * Adds a transform_attribute_t object to this object. * - * @param this calling transform_substructure_t object * @param proposal transform_attribute_t object to add */ - void (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute); + void (*add_transform_attribute) (transform_substructure_t *this, + transform_attribute_t *attribute); /** - * @brief Sets the next_payload field of this substructure + * Sets the next_payload field of this substructure * * If this is the last transform, next payload field is set to 0, * otherwise to 3 * - * @param this calling transform_substructure_t object * @param is_last When TRUE, next payload field is set to 0, otherwise to 3 */ void (*set_is_last_transform) (transform_substructure_t *this, bool is_last); /** - * @brief Checks if this is the last transform. + * Checks if this is the last transform. * - * @param this calling transform_substructure_t object * @return TRUE if this is the last Transform, FALSE otherwise */ bool (*get_is_last_transform) (transform_substructure_t *this); /** - * @brief Sets transform type of the current transform substructure. + * Sets transform type of the current transform substructure. * - * @param this calling transform_substructure_t object * @param type type value to set */ - void (*set_transform_type) (transform_substructure_t *this,u_int8_t type); + void (*set_transform_type) (transform_substructure_t *this, u_int8_t type); /** - * @brief get transform type of the current transform. + * get transform type of the current transform. * - * @param this calling transform_substructure_t object * @return Transform type of current transform substructure. */ u_int8_t (*get_transform_type) (transform_substructure_t *this); /** - * @brief Sets transform id of the current transform substructure. + * Sets transform id of the current transform substructure. * - * @param this calling transform_substructure_t object - * @param id transform id to set + * @param id transform id to set */ - void (*set_transform_id) (transform_substructure_t *this,u_int16_t id); + void (*set_transform_id) (transform_substructure_t *this, u_int16_t id); /** - * @brief get transform id of the current transform. + * get transform id of the current transform. * - * @param this calling transform_substructure_t object * @return Transform id of current transform substructure. */ u_int16_t (*get_transform_id) (transform_substructure_t *this); /** - * @brief get transform id of the current transform. + * get transform id of the current transform. * - * @param this calling transform_substructure_t object - * @param key_length The key length is written to this location + * @param key_length The key length is written to this location * @return * - SUCCESS if a key length attribute is contained * - FAILED if no key length attribute is part of this * transform or key length uses more then 16 bit! */ - status_t (*get_key_length) (transform_substructure_t *this,u_int16_t *key_length); + status_t (*get_key_length) (transform_substructure_t *this, + u_int16_t *key_length); /** - * @brief Clones an transform_substructure_t object. + * Clones an transform_substructure_t object. * - * @param this transform_substructure_t object to clone * @return cloned transform_substructure_t object */ transform_substructure_t* (*clone) (transform_substructure_t *this); /** - * @brief Destroys an transform_substructure_t object. - * - * @param this transform_substructure_t object to destroy + * Destroys an transform_substructure_t object. */ void (*destroy) (transform_substructure_t *this); }; /** - * @brief Creates an empty transform_substructure_t object. + * Creates an empty transform_substructure_t object. * * @return created transform_substructure_t object - * - * @ingroup payloads */ transform_substructure_t *transform_substructure_create(void); /** - * @brief Creates an empty transform_substructure_t object. + * Creates an empty transform_substructure_t object. * * The key length is used for the transport types ENCRYPTION_ALGORITHM, * PSEUDO_RANDOM_FUNCTION, INTEGRITY_ALGORITHM. For all @@ -190,9 +168,9 @@ transform_substructure_t *transform_substructure_create(void); * @param transform_id transform id specifying the specific algorithm of a transform type * @param key_length Key length for key lenght attribute * @return transform_substructure_t object - * - * @ingroup payloads */ -transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length); +transform_substructure_t *transform_substructure_create_type( + transform_type_t transform_type, u_int16_t transform_id, + u_int16_t key_length); -#endif /*TRANSFORM_SUBSTRUCTURE_H_*/ +#endif /*TRANSFORM_SUBSTRUCTURE_H_ @} */ diff --git a/src/charon/encoding/payloads/ts_payload.c b/src/charon/encoding/payloads/ts_payload.c index ae89919f6..5d53793b1 100644 --- a/src/charon/encoding/payloads/ts_payload.c +++ b/src/charon/encoding/payloads/ts_payload.c @@ -1,10 +1,3 @@ -/** - * @file ts_payload.c - * - * @brief Implementation of ts_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: ts_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/ts_payload.h b/src/charon/encoding/payloads/ts_payload.h index 1addee22c..d8a108ddd 100644 --- a/src/charon/encoding/payloads/ts_payload.h +++ b/src/charon/encoding/payloads/ts_payload.h @@ -1,10 +1,3 @@ -/** - * @file ts_payload.h - * - * @brief Interface of ts_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: ts_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ts_payload ts_payload + * @{ @ingroup payloads */ @@ -35,22 +35,14 @@ typedef struct ts_payload_t ts_payload_t; /** * Length of a TS payload without the Traffic selectors. - * - * @ingroup payloads */ #define TS_PAYLOAD_HEADER_LENGTH 8 /** - * @brief Class representing an IKEv2 TS payload. + * Class representing an IKEv2 TS payload. * * The TS payload format is described in RFC section 3.13. - * - * @b Constructors: - * - ts_payload_create() - * - ts_payload_create_from_traffic_selectors() - * - * @ingroup payloads */ struct ts_payload_t { /** @@ -59,9 +51,8 @@ struct ts_payload_t { payload_t payload_interface; /** - * @brief Get the type of TSpayload (TSi or TSr). + * Get the type of TSpayload (TSi or TSr). * - * @param this calling id_payload_t object * @return * - TRUE if this payload is of type TSi * - FALSE if this payload is of type TSr @@ -69,9 +60,8 @@ struct ts_payload_t { bool (*get_initiator) (ts_payload_t *this); /** - * @brief Set the type of TS payload (TSi or TSr). + * Set the type of TS payload (TSi or TSr). * - * @param this calling id_payload_t object * @param is_initiator * - TRUE if this payload is of type TSi * - FALSE if this payload is of type TSr @@ -79,75 +69,61 @@ struct ts_payload_t { void (*set_initiator) (ts_payload_t *this,bool is_initiator); /** - * @brief Adds a traffic_selector_substructure_t object to this object. - * - * @warning The added traffic_selector_substructure_t object is - * getting destroyed in destroy function of ts_payload_t. + * Adds a traffic_selector_substructure_t object to this object. * - * @param this calling ts_payload_t object * @param traffic_selector traffic_selector_substructure_t object to add */ - void (*add_traffic_selector_substructure) (ts_payload_t *this,traffic_selector_substructure_t *traffic_selector); + void (*add_traffic_selector_substructure) (ts_payload_t *this, + traffic_selector_substructure_t *traffic_selector); /** - * @brief Creates an iterator of stored traffic_selector_substructure_t objects. + * Creates an iterator of stored traffic_selector_substructure_t objects. * - * @warning The created iterator has to get destroyed by the caller! - * - * @warning When removing an traffic_selector_substructure_t object - * using this iterator, the length of this payload - * has to get refreshed by calling payload_t.get_length! + * When removing an traffic_selector_substructure_t object + * using this iterator, the length of this payload + * has to get refreshed by calling payload_t.get_length! * - * @param this calling ts_payload_t object - * @param[in] forward iterator direction (TRUE: front to end) + * @param forward iterator direction (TRUE: front to end) * @return created iterator_t object */ - iterator_t *(*create_traffic_selector_substructure_iterator) (ts_payload_t *this, bool forward); + iterator_t *(*create_traffic_selector_substructure_iterator) ( + ts_payload_t *this, bool forward); /** - * @brief Get a list of nested traffic selectors as traffic_selector_t. + * Get a list of nested traffic selectors as traffic_selector_t. * * Resulting list and its traffic selectors must be destroyed after usage * - * @param this calling ts_payload_t object * @return list of traffic selectors */ linked_list_t *(*get_traffic_selectors) (ts_payload_t *this); /** - * @brief Destroys an ts_payload_t object. - * - * @param this ts_payload_t object to destroy + * Destroys an ts_payload_t object. */ void (*destroy) (ts_payload_t *this); }; /** - * @brief Creates an empty ts_payload_t object. - * + * Creates an empty ts_payload_t object. * * @param is_initiator * - TRUE if this payload is of type TSi * - FALSE if this payload is of type TSr * @return ts_payload_t object - * - * @ingroup payloads */ ts_payload_t *ts_payload_create(bool is_initiator); /** - * @brief Creates ts_payload with a list of traffic_selector_t - * + * Creates ts_payload with a list of traffic_selector_t * * @param is_initiator * - TRUE if this payload is of type TSi * - FALSE if this payload is of type TSr * @param traffic_selectors list of traffic selectors to include * @return ts_payload_t object - * - * @ingroup payloads */ -ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors); - +ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, + linked_list_t *traffic_selectors); -#endif /* TS_PAYLOAD_H_ */ +#endif /* TS_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/unknown_payload.c b/src/charon/encoding/payloads/unknown_payload.c index bbe736085..8a8db308d 100644 --- a/src/charon/encoding/payloads/unknown_payload.c +++ b/src/charon/encoding/payloads/unknown_payload.c @@ -1,10 +1,3 @@ -/** - * @file unknown_payload.c - * - * @brief Implementation of unknown_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: unknown_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/unknown_payload.h b/src/charon/encoding/payloads/unknown_payload.h index 8d13a03a3..045448f06 100644 --- a/src/charon/encoding/payloads/unknown_payload.h +++ b/src/charon/encoding/payloads/unknown_payload.h @@ -1,10 +1,3 @@ -/** - * @file unknown_payload.h - * - * @brief Interface of unknown_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: unknown_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup unknown_payload unknown_payload + * @{ @ingroup payloads */ #ifndef UNKNOWN_PAYLOAD_H_ @@ -31,22 +31,15 @@ typedef struct unknown_payload_t unknown_payload_t; /** * Header length of the unknown payload. - * - * @ingroup payloads */ #define UNKNOWN_PAYLOAD_HEADER_LENGTH 4 /** - * @brief Payload which can't be processed further. + * Payload which can't be processed further. * * When the parser finds an unknown payload, he builds an instance of * this class. This allows further processing of this payload, such as * a check for the critical bit in the header. - * - * @b Constructors: - * - unknown_payload_create() - * - * @ingroup payloads */ struct unknown_payload_t { @@ -56,40 +49,33 @@ struct unknown_payload_t { payload_t payload_interface; /** - * @brief Get the raw data of this payload, without + * Get the raw data of this payload, without * the generic payload header. * * Returned data are NOT copied and must not be freed. * - * @param this calling unknown_payload_t object * @return data as chunk_t */ chunk_t (*get_data) (unknown_payload_t *this); /** - * @brief Get the critical flag. + * Get the critical flag. * - * @param this calling unknown_payload_t object * @return TRUE if payload is critical, FALSE if not */ bool (*is_critical) (unknown_payload_t *this); /** - * @brief Destroys an unknown_payload_t object. - * - * @param this unknown_payload_t object to destroy + * Destroys an unknown_payload_t object. */ void (*destroy) (unknown_payload_t *this); }; /** - * @brief Creates an empty unknown_payload_t object. + * Creates an empty unknown_payload_t object. * * @return unknown_payload_t object - * - * @ingroup payloads */ unknown_payload_t *unknown_payload_create(void); - -#endif /* UNKNOWN_PAYLOAD_H_ */ +#endif /* UNKNOWN_PAYLOAD_H_ @} */ diff --git a/src/charon/encoding/payloads/vendor_id_payload.c b/src/charon/encoding/payloads/vendor_id_payload.c index e3a4d2e1f..3eacc1a72 100644 --- a/src/charon/encoding/payloads/vendor_id_payload.c +++ b/src/charon/encoding/payloads/vendor_id_payload.c @@ -1,10 +1,3 @@ -/** - * @file vendor_id_payload.c - * - * @brief Implementation of vendor_id_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: vendor_id_payload.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stddef.h> diff --git a/src/charon/encoding/payloads/vendor_id_payload.h b/src/charon/encoding/payloads/vendor_id_payload.h index c7eebc155..e489bfd5a 100644 --- a/src/charon/encoding/payloads/vendor_id_payload.h +++ b/src/charon/encoding/payloads/vendor_id_payload.h @@ -1,10 +1,3 @@ -/** - * @file vendor_id_payload.h - * - * @brief Interface of vendor_id_payload_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: vendor_id_payload.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup vendor_id_payload vendor_id_payload + * @{ @ingroup payloads */ #ifndef VENDOR_ID_PAYLOAD_H_ @@ -31,21 +31,14 @@ typedef struct vendor_id_payload_t vendor_id_payload_t; /** * Length of a VENDOR ID payload without the VID data in bytes. - * - * @ingroup payloads */ #define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4 /** - * @brief Class representing an IKEv2 VENDOR ID payload. + * Class representing an IKEv2 VENDOR ID payload. * * The VENDOR ID payload format is described in RFC section 3.12. - * - * @b Constructors: - * - vendor_id_payload_create() - * - * @ingroup payloads */ struct vendor_id_payload_t { /** @@ -54,51 +47,43 @@ struct vendor_id_payload_t { payload_t payload_interface; /** - * @brief Set the VID data. + * Set the VID data. * * Data are getting cloned. * - * @param this calling vendor_id_payload_t object * @param data VID data as chunk_t */ void (*set_data) (vendor_id_payload_t *this, chunk_t data); /** - * @brief Get the VID data. + * Get the VID data. * * Returned data are a copy of the internal one. * - * @param this calling vendor_id_payload_t object * @return VID data as chunk_t */ chunk_t (*get_data_clone) (vendor_id_payload_t *this); /** - * @brief Get the VID data. + * Get the VID data. * * Returned data are NOT copied. * - * @param this calling vendor_id_payload_t object * @return VID data as chunk_t */ chunk_t (*get_data) (vendor_id_payload_t *this); /** - * @brief Destroys an vendor_id_payload_t object. - * - * @param this vendor_id_payload_t object to destroy + * Destroys an vendor_id_payload_t object. */ void (*destroy) (vendor_id_payload_t *this); }; /** - * @brief Creates an empty vendor_id_payload_t object. + * Creates an empty vendor_id_payload_t object. * * @return vendor_id_payload_t object - * - * @ingroup payloads */ vendor_id_payload_t *vendor_id_payload_create(void); - -#endif /* VENDOR_ID_PAYLOAD_H_ */ +#endif /* VENDOR_ID_PAYLOAD_H_ @} */ diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index b7f6a1def..f5cb40977 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -1,13 +1,6 @@ -/** - * @file kernel_interface.c - * - * @brief Implementation of kernel_interface_t. - * - */ - /* + * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi - * Copyright (C) 2006-2007 Tobias Brunner * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005 Jan Hutter @@ -25,6 +18,8 @@ * 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. + * + * $Id: kernel_interface.c 4104 2008-06-24 15:35:09Z tobias $ */ #include <sys/types.h> @@ -116,26 +111,32 @@ struct kernel_algorithm_t { /** * Algorithms for encryption */ -kernel_algorithm_t encryption_algs[] = { -/* {ENCR_DES_IV64, "***", 0}, */ - {ENCR_DES, "des", 64}, - {ENCR_3DES, "des3_ede", 192}, -/* {ENCR_RC5, "***", 0}, */ -/* {ENCR_IDEA, "***", 0}, */ - {ENCR_CAST, "cast128", 0}, - {ENCR_BLOWFISH, "blowfish", 0}, -/* {ENCR_3IDEA, "***", 0}, */ -/* {ENCR_DES_IV32, "***", 0}, */ - {ENCR_NULL, "cipher_null", 0}, - {ENCR_AES_CBC, "aes", 0}, -/* {ENCR_AES_CTR, "***", 0}, */ +static kernel_algorithm_t encryption_algs[] = { +/* {ENCR_DES_IV64, "***", 0}, */ + {ENCR_DES, "des", 64}, + {ENCR_3DES, "des3_ede", 192}, +/* {ENCR_RC5, "***", 0}, */ +/* {ENCR_IDEA, "***", 0}, */ + {ENCR_CAST, "cast128", 0}, + {ENCR_BLOWFISH, "blowfish", 0}, +/* {ENCR_3IDEA, "***", 0}, */ +/* {ENCR_DES_IV32, "***", 0}, */ + {ENCR_NULL, "cipher_null", 0}, + {ENCR_AES_CBC, "aes", 0}, +/* {ENCR_AES_CTR, "***", 0}, */ + {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))", 64}, /* key_size = ICV size */ + {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))", 96}, /* key_size = ICV size */ + {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))", 128}, /* key_size = ICV size */ + {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))", 64}, /* key_size = ICV size */ + {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))", 96}, /* key_size = ICV size */ + {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))", 128}, /* key_size = ICV size */ {END_OF_LIST, NULL, 0}, }; /** * Algorithms for integrity protection */ -kernel_algorithm_t integrity_algs[] = { +static kernel_algorithm_t integrity_algs[] = { {AUTH_HMAC_MD5_96, "md5", 128}, {AUTH_HMAC_SHA1_96, "sha1", 160}, {AUTH_HMAC_SHA2_256_128, "sha256", 256}, @@ -148,22 +149,29 @@ kernel_algorithm_t integrity_algs[] = { }; /** + * Algorithms for IPComp + */ +static kernel_algorithm_t compression_algs[] = { +/* {IPCOMP_OUI, "***", 0}, */ + {IPCOMP_DEFLATE, "deflate", 0}, + {IPCOMP_LZS, "lzs", 0}, + {IPCOMP_LZJH, "lzjh", 0}, + {END_OF_LIST, NULL, 0}, +}; + +/** * Look up a kernel algorithm name and its key size */ -char* lookup_algorithm(kernel_algorithm_t *kernel_algo, - algorithm_t *ikev2_algo, u_int *key_size) +static char* lookup_algorithm(kernel_algorithm_t *kernel_algo, + u_int16_t ikev2_algo, u_int16_t *key_size) { while (kernel_algo->ikev2_id != END_OF_LIST) { - if (ikev2_algo->algorithm == kernel_algo->ikev2_id) + if (ikev2_algo == kernel_algo->ikev2_id) { /* match, evaluate key length */ - if (ikev2_algo->key_size) - { /* variable length */ - *key_size = ikev2_algo->key_size; - } - else - { /* fixed length */ + if (key_size && *key_size == 0) + { /* update key size if not set */ *key_size = kernel_algo->key_size; } return kernel_algo->name; @@ -363,6 +371,21 @@ struct private_kernel_interface_t { * time of the last roam_job */ struct timeval last_roam; + + /** + * whether to install routes along policies + */ + bool install_routes; + + /** + * routing table to install routes + */ + int routing_table; + + /** + * priority of used routing table + */ + int routing_table_prio; }; /** @@ -527,11 +550,20 @@ static void process_expire(private_kernel_interface_t *this, struct nlmsghdr *hd struct xfrm_user_expire *expire; expire = (struct xfrm_user_expire*)NLMSG_DATA(hdr); - protocol = expire->state.id.proto == KERNEL_ESP ? PROTO_ESP : PROTO_AH; + protocol = expire->state.id.proto; + protocol = (protocol == KERNEL_ESP) ? PROTO_ESP : (protocol == KERNEL_AH) ? PROTO_AH : protocol; spi = expire->state.id.spi; reqid = expire->state.reqid; DBG2(DBG_KNL, "received a XFRM_MSG_EXPIRE"); + + if (protocol != PROTO_ESP && protocol != PROTO_AH) + { + DBG2(DBG_KNL, "ignoring XFRM_MSG_EXPIRE for SA 0x%x (reqid %d) which is " + "not a CHILD_SA", ntohl(spi), reqid); + return; + } + DBG1(DBG_KNL, "creating %s job for %N CHILD_SA 0x%x (reqid %d)", expire->hard ? "delete" : "rekey", protocol_id_names, protocol, ntohl(spi), reqid); @@ -1425,11 +1457,10 @@ static status_t manage_srcroute(private_kernel_interface_t *this, int nlmsg_type struct rtmsg *msg; chunk_t chunk; -#if IPSEC_ROUTING_TABLE == 0 /* if route is 0.0.0.0/0, we can't install it, as it would * overwrite the default route. Instead, we add two routes: * 0.0.0.0/1 and 128.0.0.0/1 */ - if (route->prefixlen == 0) + if (this->routing_table == 0 && route->prefixlen == 0) { route_entry_t half; status_t status; @@ -1446,7 +1477,6 @@ static status_t manage_srcroute(private_kernel_interface_t *this, int nlmsg_type status = manage_srcroute(this, nlmsg_type, flags, &half); return status; } -#endif memset(&request, 0, sizeof(request)); @@ -1458,7 +1488,7 @@ static status_t manage_srcroute(private_kernel_interface_t *this, int nlmsg_type msg = (struct rtmsg*)NLMSG_DATA(hdr); msg->rtm_family = route->src_ip->get_family(route->src_ip); msg->rtm_dst_len = route->prefixlen; - msg->rtm_table = IPSEC_ROUTING_TABLE; + msg->rtm_table = this->routing_table; msg->rtm_protocol = RTPROT_STATIC; msg->rtm_type = RTN_UNICAST; msg->rtm_scope = RT_SCOPE_UNIVERSE; @@ -1620,7 +1650,7 @@ static host_t *get_route(private_kernel_interface_t *this, host_t *dest, * - is the default route or * - its destination net contains our destination */ - if (msg->rtm_table != IPSEC_ROUTING_TABLE + if ((this->routing_table == 0 ||msg->rtm_table != this->routing_table) && msg->rtm_dst_len > best && (msg->rtm_dst_len == 0 || /* default route */ (rta_dst.ptr && addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len)))) @@ -1639,6 +1669,13 @@ static host_t *get_route(private_kernel_interface_t *this, host_t *dest, { DESTROY_IF(src); src = host_create_from_chunk(msg->rtm_family, rta_src, 0); + if (get_vip_refcount(this, src)) + { /* skip source address if it is installed by us */ + DESTROY_IF(src); + src = NULL; + current = NLMSG_NEXT(current, len); + continue; + } } else { @@ -1823,12 +1860,11 @@ static status_t del_ip(private_kernel_interface_t *this, host_t *virtual_ip) } /** - * Implementation of kernel_interface_t.get_spi. + * Get an SPI for a specific protocol from the kernel. */ -static status_t get_spi(private_kernel_interface_t *this, - host_t *src, host_t *dst, - protocol_id_t protocol, u_int32_t reqid, - u_int32_t *spi) +static status_t get_spi_internal(private_kernel_interface_t *this, + host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max, + u_int32_t reqid, u_int32_t *spi) { unsigned char request[BUFFER_SIZE]; struct nlmsghdr *hdr, *out; @@ -1838,8 +1874,6 @@ static status_t get_spi(private_kernel_interface_t *this, memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "getting SPI for reqid %d", reqid); - hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST; hdr->nlmsg_type = XFRM_MSG_ALLOCSPI; @@ -1848,12 +1882,12 @@ static status_t get_spi(private_kernel_interface_t *this, userspi = (struct xfrm_userspi_info*)NLMSG_DATA(hdr); host2xfrm(src, &userspi->info.saddr); host2xfrm(dst, &userspi->info.id.daddr); - userspi->info.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + userspi->info.id.proto = proto; userspi->info.mode = TRUE; /* tunnel mode */ userspi->info.reqid = reqid; userspi->info.family = src->get_family(src); - userspi->min = 0xc0000000; - userspi->max = 0xcFFFFFFF; + userspi->min = min; + userspi->max = max; if (netlink_send(this, this->socket_xfrm, hdr, &out, &len) == SUCCESS) { @@ -1889,13 +1923,57 @@ static status_t get_spi(private_kernel_interface_t *this, if (received_spi == 0) { + return FAILED; + } + + *spi = received_spi; + return SUCCESS; +} + +/** + * Implementation of kernel_interface_t.get_spi. + */ +static status_t get_spi(private_kernel_interface_t *this, + host_t *src, host_t *dst, + protocol_id_t protocol, u_int32_t reqid, + u_int32_t *spi) +{ + DBG2(DBG_KNL, "getting SPI for reqid %d", reqid); + + if (get_spi_internal(this, src, dst, + (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH, + 0xc0000000, 0xcFFFFFFF, reqid, spi) != SUCCESS) + { DBG1(DBG_KNL, "unable to get SPI for reqid %d", reqid); return FAILED; } - DBG2(DBG_KNL, "got SPI 0x%x for reqid %d", received_spi, reqid); + DBG2(DBG_KNL, "got SPI 0x%x for reqid %d", *spi, reqid); + + return SUCCESS; +} + +/** + * Implementation of kernel_interface_t.get_cpi. + */ +static status_t get_cpi(private_kernel_interface_t *this, + host_t *src, host_t *dst, + u_int32_t reqid, u_int16_t *cpi) +{ + u_int32_t received_spi = 0; + DBG2(DBG_KNL, "getting CPI for reqid %d", reqid); + + if (get_spi_internal(this, src, dst, + IPPROTO_COMP, 0x100, 0xEFFF, reqid, &received_spi) != SUCCESS) + { + DBG1(DBG_KNL, "unable to get CPI for reqid %d", reqid); + return FAILED; + } + + *cpi = htons((u_int16_t)ntohl(received_spi)); + + DBG2(DBG_KNL, "got CPI 0x%x for reqid %d", *cpi, reqid); - *spi = received_spi; return SUCCESS; } @@ -1906,19 +1984,21 @@ static status_t add_sa(private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, u_int64_t expire_soft, u_int64_t expire_hard, - algorithm_t *enc_alg, algorithm_t *int_alg, - prf_plus_t *prf_plus, mode_t mode, bool encap, + u_int16_t enc_alg, u_int16_t enc_size, + u_int16_t int_alg, u_int16_t int_size, + prf_plus_t *prf_plus, mode_t mode, + u_int16_t ipcomp, bool encap, bool replace) { unsigned char request[BUFFER_SIZE]; char *alg_name; - u_int key_size; + u_int16_t add_keymat = 32; /* additional 4 octets KEYMAT required for AES-GCM as of RFC4106 8.1. */ struct nlmsghdr *hdr; struct xfrm_usersa_info *sa; memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "adding SAD entry with SPI 0x%x", spi); + DBG2(DBG_KNL, "adding SAD entry with SPI 0x%x and reqid %d", spi, reqid); hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; @@ -1929,10 +2009,10 @@ static status_t add_sa(private_kernel_interface_t *this, host2xfrm(src, &sa->saddr); host2xfrm(dst, &sa->id.daddr); sa->id.spi = spi; - sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol; sa->family = src->get_family(src); sa->mode = mode; - sa->replay_window = 32; + sa->replay_window = (protocol == IPPROTO_COMP) ? 0 : 32; sa->reqid = reqid; /* we currently do not expire SAs by volume/packet count */ sa->lft.soft_byte_limit = XFRM_INF; @@ -1947,20 +2027,96 @@ static status_t add_sa(private_kernel_interface_t *this, struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_info); - if (enc_alg->algorithm != ENCR_UNDEFINED) + switch (enc_alg) + { + case ENCR_UNDEFINED: + /* no encryption */ + break; + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + /* AES-CCM needs only 3 additional octets KEYMAT as of RFC 4309 7.1. */ + add_keymat = 24; + /* fall-through */ + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + { + u_int16_t icv_size = 0; + rthdr->rta_type = XFRMA_ALG_AEAD; + alg_name = lookup_algorithm(encryption_algs, enc_alg, &icv_size); + if (alg_name == NULL) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + encryption_algorithm_names, enc_alg); + return FAILED; + } + DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", + encryption_algorithm_names, enc_alg, enc_size); + + /* additional KEYMAT required */ + enc_size += add_keymat; + + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_size / 8); + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + struct xfrm_algo_aead* algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr); + algo->alg_key_len = enc_size; + algo->alg_icv_len = icv_size; + strcpy(algo->alg_name, alg_name); + prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key); + + rthdr = XFRM_RTA_NEXT(rthdr); + break; + } + default: + { + rthdr->rta_type = XFRMA_ALG_CRYPT; + alg_name = lookup_algorithm(encryption_algs, enc_alg, &enc_size); + if (alg_name == NULL) + { + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + encryption_algorithm_names, enc_alg); + return FAILED; + } + DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", + encryption_algorithm_names, enc_alg, enc_size); + + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_size / 8); + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); + algo->alg_key_len = enc_size; + strcpy(algo->alg_name, alg_name); + prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key); + + rthdr = XFRM_RTA_NEXT(rthdr); + break; + } + } + + if (int_alg != AUTH_UNDEFINED) { - rthdr->rta_type = XFRMA_ALG_CRYPT; - alg_name = lookup_algorithm(encryption_algs, enc_alg, &key_size); + rthdr->rta_type = XFRMA_ALG_AUTH; + alg_name = lookup_algorithm(integrity_algs, int_alg, &int_size); if (alg_name == NULL) { - DBG1(DBG_KNL, "algorithm %N not supported by kernel!", - encryption_algorithm_names, enc_alg->algorithm); + DBG1(DBG_KNL, "algorithm %N not supported by kernel!", + integrity_algorithm_names, int_alg); return FAILED; } - DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", - encryption_algorithm_names, enc_alg->algorithm, key_size); + DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", + integrity_algorithm_names, int_alg, int_size); - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + key_size); + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_size / 8); hdr->nlmsg_len += rthdr->rta_len; if (hdr->nlmsg_len > sizeof(request)) { @@ -1968,27 +2124,27 @@ static status_t add_sa(private_kernel_interface_t *this, } struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); - algo->alg_key_len = key_size; + algo->alg_key_len = int_size; strcpy(algo->alg_name, alg_name); - prf_plus->get_bytes(prf_plus, key_size / 8, algo->alg_key); + prf_plus->get_bytes(prf_plus, int_size / 8, algo->alg_key); rthdr = XFRM_RTA_NEXT(rthdr); } - if (int_alg->algorithm != AUTH_UNDEFINED) + if (ipcomp != IPCOMP_NONE) { - rthdr->rta_type = XFRMA_ALG_AUTH; - alg_name = lookup_algorithm(integrity_algs, int_alg, &key_size); + rthdr->rta_type = XFRMA_ALG_COMP; + alg_name = lookup_algorithm(compression_algs, ipcomp, NULL); if (alg_name == NULL) { DBG1(DBG_KNL, "algorithm %N not supported by kernel!", - integrity_algorithm_names, int_alg->algorithm); + ipcomp_transform_names, ipcomp); return FAILED; } - DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", - integrity_algorithm_names, int_alg->algorithm, key_size); + DBG2(DBG_KNL, " using compression algorithm %N", + ipcomp_transform_names, ipcomp); - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + key_size); + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo)); hdr->nlmsg_len += rthdr->rta_len; if (hdr->nlmsg_len > sizeof(request)) { @@ -1996,15 +2152,12 @@ static status_t add_sa(private_kernel_interface_t *this, } struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); - algo->alg_key_len = key_size; + algo->alg_key_len = 0; strcpy(algo->alg_name, alg_name); - prf_plus->get_bytes(prf_plus, key_size / 8, algo->alg_key); rthdr = XFRM_RTA_NEXT(rthdr); } - /* TODO: add IPComp here */ - if (encap) { rthdr->rta_type = XFRMA_ENCAP; @@ -2042,6 +2195,91 @@ static status_t add_sa(private_kernel_interface_t *this, } /** + * Get the replay state (i.e. sequence numbers) of an SA. + */ +static status_t get_replay_state(private_kernel_interface_t *this, + u_int32_t spi, protocol_id_t protocol, host_t *dst, + struct xfrm_replay_state *replay) +{ + unsigned char request[BUFFER_SIZE]; + struct nlmsghdr *hdr, *out = NULL; + struct xfrm_aevent_id *out_aevent = NULL, *aevent_id; + size_t len; + struct rtattr *rta; + size_t rtasize; + + memset(&request, 0, sizeof(request)); + + DBG2(DBG_KNL, "querying replay state from SAD entry with SPI 0x%x", spi); + + hdr = (struct nlmsghdr*)request; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = XFRM_MSG_GETAE; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id)); + + aevent_id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr); + aevent_id->flags = XFRM_AE_RVAL; + + host2xfrm(dst, &aevent_id->sa_id.daddr); + aevent_id->sa_id.spi = spi; + aevent_id->sa_id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol; + aevent_id->sa_id.family = dst->get_family(dst); + + if (netlink_send(this, this->socket_xfrm, hdr, &out, &len) == SUCCESS) + { + hdr = out; + while (NLMSG_OK(hdr, len)) + { + switch (hdr->nlmsg_type) + { + case XFRM_MSG_NEWAE: + { + out_aevent = NLMSG_DATA(hdr); + break; + } + case NLMSG_ERROR: + { + struct nlmsgerr *err = NLMSG_DATA(hdr); + DBG1(DBG_KNL, "querying replay state from SAD entry failed: %s (%d)", + strerror(-err->error), -err->error); + break; + } + default: + hdr = NLMSG_NEXT(hdr, len); + continue; + case NLMSG_DONE: + break; + } + break; + } + } + + if (out_aevent == NULL) + { + DBG1(DBG_KNL, "unable to query replay state from SAD entry with SPI 0x%x", spi); + free(out); + return FAILED; + } + + rta = XFRM_RTA(out, struct xfrm_aevent_id); + rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id); + while(RTA_OK(rta, rtasize)) + { + if (rta->rta_type == XFRMA_REPLAY_VAL) + { + memcpy(replay, RTA_DATA(rta), rta->rta_len); + free(out); + return SUCCESS; + } + rta = RTA_NEXT(rta, rtasize); + } + + DBG1(DBG_KNL, "unable to query replay state from SAD entry with SPI 0x%x", spi); + free(out); + return FAILED; +} + +/** * Implementation of kernel_interface_t.update_sa. */ static status_t update_sa(private_kernel_interface_t *this, @@ -2057,6 +2295,8 @@ static status_t update_sa(private_kernel_interface_t *this, struct rtattr *rta; size_t rtasize; struct xfrm_encap_tmpl* tmpl = NULL; + bool got_replay_state; + struct xfrm_replay_state replay; memset(&request, 0, sizeof(request)); @@ -2071,7 +2311,7 @@ static status_t update_sa(private_kernel_interface_t *this, sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr); host2xfrm(dst, &sa_id->daddr); sa_id->spi = spi; - sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol; sa_id->family = dst->get_family(dst); if (netlink_send(this, this->socket_xfrm, hdr, &out, &len) == SUCCESS) @@ -2102,14 +2342,25 @@ static status_t update_sa(private_kernel_interface_t *this, break; } } - if (out_sa == NULL || - this->public.del_sa(&this->public, dst, spi, protocol) != SUCCESS) + if (out_sa == NULL) { DBG1(DBG_KNL, "unable to update SAD entry with SPI 0x%x", spi); free(out); return FAILED; } + /* try to get the replay state */ + got_replay_state = (get_replay_state( + this, spi, protocol, dst, &replay) == SUCCESS); + + /* delete the old SA */ + if (this->public.del_sa(&this->public, dst, spi, protocol) != SUCCESS) + { + DBG1(DBG_KNL, "unable to delete old SAD entry with SPI 0x%x", spi); + free(out); + return FAILED; + } + DBG2(DBG_KNL, "updating SAD entry with SPI 0x%x from %#H..%#H to %#H..%#H", spi, src, dst, new_src, new_dst); @@ -2146,22 +2397,46 @@ static status_t update_sa(private_kernel_interface_t *this, tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); } memcpy(pos, rta, rta->rta_len); - pos += rta->rta_len; - hdr->nlmsg_len += rta->rta_len; + pos += RTA_ALIGN(rta->rta_len); + hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); } rta = RTA_NEXT(rta, rtasize); } + + rta = (struct rtattr*)pos; if (tmpl == NULL && encap) { /* add tmpl if we are enabling it */ - rta = (struct rtattr*)pos; rta->rta_type = XFRMA_ENCAP; rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); + hdr->nlmsg_len += rta->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta); tmpl->encap_type = UDP_ENCAP_ESPINUDP; tmpl->encap_sport = ntohs(new_src->get_port(new_src)); tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t)); + + rta = XFRM_RTA_NEXT(rta); + } + + if (got_replay_state) + { /* copy the replay data if available */ + rta->rta_type = XFRMA_REPLAY_VAL; + rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state)); + + hdr->nlmsg_len += rta->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + memcpy(RTA_DATA(rta), &replay, sizeof(replay)); + + rta = XFRM_RTA_NEXT(rta); } if (netlink_send_ack(this, this->socket_xfrm, hdr) != SUCCESS) @@ -2199,7 +2474,7 @@ static status_t query_sa(private_kernel_interface_t *this, host_t *dst, sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr); host2xfrm(dst, &sa_id->daddr); sa_id->spi = spi; - sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol; sa_id->family = dst->get_family(dst); if (netlink_send(this, this->socket_xfrm, hdr, &out, &len) == SUCCESS) @@ -2265,7 +2540,7 @@ static status_t del_sa(private_kernel_interface_t *this, host_t *dst, sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr); host2xfrm(dst, &sa_id->daddr); sa_id->spi = spi; - sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH; + sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol; sa_id->family = dst->get_family(dst); if (netlink_send_ack(this, this->socket_xfrm, hdr) != SUCCESS) @@ -2285,7 +2560,8 @@ static status_t add_policy(private_kernel_interface_t *this, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, policy_dir_t direction, protocol_id_t protocol, - u_int32_t reqid, bool high_prio, mode_t mode) + u_int32_t reqid, bool high_prio, mode_t mode, + u_int16_t ipcomp) { iterator_t *iterator; policy_entry_t *current, *policy; @@ -2310,7 +2586,7 @@ static status_t add_policy(private_kernel_interface_t *this, { /* use existing policy */ current->refcount++; - DBG2(DBG_KNL, "policy %R===%R already exists, increasing ", + DBG2(DBG_KNL, "policy %R===%R already exists, increasing " "refcount", src_ts, dst_ts); free(policy); policy = current; @@ -2357,10 +2633,8 @@ static status_t add_policy(private_kernel_interface_t *this, struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info); rthdr->rta_type = XFRMA_TMPL; - - rthdr->rta_len = sizeof(struct xfrm_user_tmpl); - rthdr->rta_len = RTA_LENGTH(rthdr->rta_len); - + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); + hdr->nlmsg_len += rthdr->rta_len; if (hdr->nlmsg_len > sizeof(request)) { @@ -2368,6 +2642,30 @@ static status_t add_policy(private_kernel_interface_t *this, } struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr); + + if (ipcomp != IPCOMP_NONE) + { + tmpl->reqid = reqid; + tmpl->id.proto = IPPROTO_COMP; + tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; + tmpl->mode = mode; + tmpl->optional = direction != POLICY_OUT; + tmpl->family = src->get_family(src); + + host2xfrm(src, &tmpl->saddr); + host2xfrm(dst, &tmpl->id.daddr); + + /* add an additional xfrm_user_tmpl */ + rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); + hdr->nlmsg_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + tmpl++; + } + tmpl->reqid = reqid; tmpl->id.proto = (protocol == PROTO_AH) ? KERNEL_AH : KERNEL_ESP; tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; @@ -2388,9 +2686,11 @@ static status_t add_policy(private_kernel_interface_t *this, * - this is a forward policy (to just get one for each child) * - we are in tunnel mode * - we are not using IPv6 (does not work correctly yet!) + * - routing is not disabled via strongswan.conf */ if (policy->route == NULL && direction == POLICY_FWD && - mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6) + mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6 && + this->install_routes) { policy->route = malloc_thing(route_entry_t); if (get_address_by_ts(this, dst_ts, &policy->route->src_ip) == SUCCESS) @@ -2575,7 +2875,11 @@ static status_t del_policy(private_kernel_interface_t *this, */ static void destroy(private_kernel_interface_t *this) { - manage_rule(this, RTM_DELRULE, IPSEC_ROUTING_TABLE, IPSEC_ROUTING_TABLE_PRIO); + if (this->routing_table) + { + manage_rule(this, RTM_DELRULE, this->routing_table, + this->routing_table_prio); + } this->job->cancel(this->job); close(this->socket_xfrm_events); @@ -2597,11 +2901,12 @@ kernel_interface_t *kernel_interface_create() /* public functions */ this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; - this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,mode_t,bool,bool))add_sa; + this->public.get_cpi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi; + this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,mode_t,u_int16_t,bool,bool))add_sa; this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa; this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa; this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa; - this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,mode_t))add_policy; + this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,mode_t,u_int16_t))add_policy; this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy; this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy; this->public.get_interface = (char*(*)(kernel_interface_t*,host_t*))get_interface_name; @@ -2620,7 +2925,12 @@ kernel_interface_t *kernel_interface_create() pthread_mutex_init(&this->nl_mutex, NULL); pthread_cond_init(&this->cond, NULL); timerclear(&this->last_roam); - + this->install_routes = lib->settings->get_bool(lib->settings, + "charon.install_routes", TRUE); + this->routing_table = lib->settings->get_int(lib->settings, + "charon.routing_table", IPSEC_ROUTING_TABLE); + this->routing_table_prio = lib->settings->get_int(lib->settings, + "charon.routing_table_prio", IPSEC_ROUTING_TABLE_PRIO); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; @@ -2682,10 +2992,13 @@ kernel_interface_t *kernel_interface_create() charon->kill(charon, "unable to get interface list"); } - if (manage_rule(this, RTM_NEWRULE, IPSEC_ROUTING_TABLE, - IPSEC_ROUTING_TABLE_PRIO) != SUCCESS) + if (this->routing_table) { - DBG1(DBG_KNL, "unable to create routing table rule"); + if (manage_rule(this, RTM_NEWRULE, this->routing_table, + this->routing_table_prio) != SUCCESS) + { + DBG1(DBG_KNL, "unable to create routing table rule"); + } } return &this->public; diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h index 256c20797..49928c74b 100644 --- a/src/charon/kernel/kernel_interface.h +++ b/src/charon/kernel/kernel_interface.h @@ -1,12 +1,6 @@ -/** - * @file kernel_interface.h - * - * @brief Interface of kernel_interface_t. - * - */ - /* - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Copyright (C) 2006-2008 Tobias Brunner + * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +14,13 @@ * 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. + * + * $Id: kernel_interface.h 3920 2008-05-08 16:19:11Z tobias $ + */ + +/** + * @defgroup kernel_interface kernel_interface + * @{ @ingroup kernel */ #ifndef KERNEL_INTERFACE_H_ @@ -37,8 +38,6 @@ typedef struct kernel_interface_t kernel_interface_t; * Direction of a policy. These are equal to those * defined in xfrm.h, but we want to stay implementation * neutral here. - * - * @ingroup kernel */ enum policy_dir_t { /** Policy for inbound traffic */ @@ -50,7 +49,7 @@ enum policy_dir_t { }; /** - * @brief Interface to the kernel. + * Interface to the kernel. * * The kernel interface handles the communication with the kernel * for SA and policy management. It allows setup of these, and provides @@ -59,36 +58,40 @@ enum policy_dir_t { * reference counting. The Linux kernel does not allow the same policy * installed twice, but we need this as CHILD_SA exist multiple times * when rekeying. Thats why we do reference counting of policies. - * - * @b Constructors: - * - kernel_interface_create() - * - * @ingroup kernel */ struct kernel_interface_t { /** - * @brief Get a SPI from the kernel. + * Get a SPI from the kernel. * * @warning get_spi() implicitely creates an SA with * the allocated SPI, therefore the replace flag * in add_sa() must be set when installing this SA. * - * @param this calling object * @param src source address of SA * @param dst destination address of SA * @param protocol protocol for SA (ESP/AH) * @param reqid unique ID for this SA - * @param[out] spi allocated spi - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @param spi allocated spi + * @return SUCCESS if operation completed */ status_t (*get_spi)(kernel_interface_t *this, host_t *src, host_t *dst, protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi); /** - * @brief Add an SA to the SAD. + * Get a Compression Parameter Index (CPI) from the kernel. + * + * @param src source address of SA + * @param dst destination address of SA + * @param reqid unique ID for the corresponding SA + * @param cpi allocated cpi + * @return SUCCESS if operation completed + */ + status_t (*get_cpi)(kernel_interface_t *this, host_t *src, host_t *dst, + u_int32_t reqid, u_int16_t *cpi); + + /** + * Add an SA to the SAD. * * add_sa() may update an already allocated * SPI (via get_spi). In this case, the replace @@ -98,7 +101,6 @@ struct kernel_interface_t { * gets the keys itself from the PRF, as we don't know * his algorithms and key sizes. * - * @param this calling object * @param src source address for this SA * @param dst destination address for this SA * @param spi SPI allocated by us or remote peer @@ -107,32 +109,34 @@ struct kernel_interface_t { * @param expire_soft lifetime in seconds before rekeying * @param expire_hard lieftime in seconds before delete * @param enc_alg Algorithm to use for encryption (ESP only) + * @param enc_size key length of encryption algorithm, if dynamic * @param int_alg Algorithm to use for integrity protection + * @param int_size key length of integrity algorithm, if dynamic * @param prf_plus PRF to derive keys from * @param mode mode of the SA (tunnel, transport) + * @param ipcomp IPComp transform to use * @param encap enable UDP encapsulation for NAT traversal * @param replace Should an already installed SA be updated? - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @return SUCCESS if operation completed */ status_t (*add_sa) (kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, u_int64_t expire_soft, u_int64_t expire_hard, - algorithm_t *enc_alg, algorithm_t *int_alg, - prf_plus_t *prf_plus, mode_t mode, bool encap, + u_int16_t enc_alg, u_int16_t enc_size, + u_int16_t int_alg, u_int16_t int_size, + prf_plus_t *prf_plus, mode_t mode, + u_int16_t ipcomp, bool encap, bool update); /** - * @brief Update the hosts on an installed SA. + * Update the hosts on an installed SA. * * We cannot directly update the destination address as the kernel * requires the spi, the protocol AND the destination address (and family) * to identify SAs. Therefore if the destination address changed we * create a new SA and delete the old one. * - * @param this calling object * @param spi SPI of the SA * @param protocol protocol for this SA (ESP/AH) * @param src current source address @@ -140,9 +144,7 @@ struct kernel_interface_t { * @param new_src new source address * @param new_dst new destination address * @param encap use UDP encapsulation - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @return SUCCESS if operation completed */ status_t (*update_sa)(kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol, @@ -150,44 +152,37 @@ struct kernel_interface_t { host_t *new_src, host_t *new_dst, bool encap); /** - * @brief Query the use time of an SA. + * Query the use time of an SA. * * The use time of an SA is not the time of the last usage, but * the time of the first usage of the SA. * - * @param this calling object * @param dst destination address for this SA * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) - * @param[out] use_time the time of this SA's last use - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @param use_time pointer receives the time of this SA's last use + * @return SUCCESS if operation completed */ status_t (*query_sa) (kernel_interface_t *this, host_t *dst, u_int32_t spi, protocol_id_t protocol, u_int32_t *use_time); /** - * @brief Delete a previusly installed SA from the SAD. + * Delete a previusly installed SA from the SAD. * - * @param this calling object * @param dst destination address for this SA * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @return SUCCESS if operation completed */ status_t (*del_sa) (kernel_interface_t *this, host_t *dst, u_int32_t spi, protocol_id_t protocol); /** - * @brief Add a policy to the SPD. + * Add a policy to the SPD. * * A policy is always associated to an SA. Traffic which matches a * policy is handled by the SA with the same reqid. * - * @param this calling object * @param src source address of SA * @param dst dest address of SA * @param src_ts traffic selector to match traffic source @@ -197,31 +192,28 @@ struct kernel_interface_t { * @param reqid uniqe ID of an SA to use to enforce policy * @param high_prio if TRUE, uses a higher priority than any with FALSE * @param mode mode of SA (tunnel, transport) - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @param ipcomp the IPComp transform used + * @return SUCCESS if operation completed */ status_t (*add_policy) (kernel_interface_t *this, host_t *src, host_t *dst, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, policy_dir_t direction, protocol_id_t protocol, - u_int32_t reqid, bool high_prio, mode_t mode); + u_int32_t reqid, bool high_prio, mode_t mode, + u_int16_t ipcomp); /** - * @brief Query the use time of a policy. + * Query the use time of a policy. * * The use time of a policy is the time the policy was used * for the last time. * - * @param this calling object * @param src_ts traffic selector to match traffic source * @param dst_ts traffic selector to match traffic dest * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD * @param[out] use_time the time of this SA's last use - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @return SUCCESS if operation completed */ status_t (*query_policy) (kernel_interface_t *this, traffic_selector_t *src_ts, @@ -229,20 +221,17 @@ struct kernel_interface_t { policy_dir_t direction, u_int32_t *use_time); /** - * @brief Remove a policy from the SPD. + * Remove a policy from the SPD. * * The kernel interface implements reference counting for policies. * If the same policy is installed multiple times (in the case of rekeying), * the reference counter is increased. del_policy() decreases the ref counter * and removes the policy only when no more references are available. * - * @param this calling object * @param src_ts traffic selector to match traffic source * @param dst_ts traffic selector to match traffic dest * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @return SUCCESS if operation completed */ status_t (*del_policy) (kernel_interface_t *this, traffic_selector_t *src_ts, @@ -250,82 +239,69 @@ struct kernel_interface_t { policy_dir_t direction); /** - * @brief Get our outgoing source address for a destination. + * Get our outgoing source address for a destination. * * Does a route lookup to get the source address used to reach dest. * The returned host is allocated and must be destroyed. * - * @param this calling object * @param dest target destination address * @return outgoing source address, NULL if unreachable */ host_t* (*get_source_addr)(kernel_interface_t *this, host_t *dest); /** - * @brief Get the interface name of a local address. + * Get the interface name of a local address. * - * @param this calling object * @param host address to get interface name from * @return allocated interface name, or NULL if not found */ char* (*get_interface) (kernel_interface_t *this, host_t *host); /** - * @brief Creates an iterator over all local addresses. + * Creates an iterator over all local addresses. * * This function blocks an internal cached address list until the * iterator gets destroyed. * These hosts are read-only, do not modify or free. * - * @param this calling object * @return iterator over host_t's */ iterator_t *(*create_address_iterator) (kernel_interface_t *this); /** - * @brief Add a virtual IP to an interface. + * Add a virtual IP to an interface. * * Virtual IPs are attached to an interface. If an IP is added multiple * times, the IP is refcounted and not removed until del_ip() was called * as many times as add_ip(). * The virtual IP is attached to the interface where the iface_ip is found. * - * @param this calling object * @param virtual_ip virtual ip address to assign * @param iface_ip IP of an interface to attach virtual IP - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @return SUCCESS if operation completed */ status_t (*add_ip) (kernel_interface_t *this, host_t *virtual_ip, host_t *iface_ip); /** - * @brief Remove a virtual IP from an interface. + * Remove a virtual IP from an interface. * * The kernel interface uses refcounting, see add_ip(). * - * @param this calling object * @param virtual_ip virtual ip address to assign - * @return - * - SUCCESS - * - FAILED if kernel comm failed + * @return SUCCESS if operation completed */ status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip); /** - * @brief Destroys a kernel_interface object. - * - * @param kernel_interface_t calling object + * Destroys a kernel_interface object. */ void (*destroy) (kernel_interface_t *kernel_interface); }; /** - * @brief Creates an object of type kernel_interface_t. - * - * @ingroup kernel + * Creates an object of type kernel_interface_t. */ kernel_interface_t *kernel_interface_create(void); -#endif /*KERNEL_INTERFACE_H_*/ +#endif /*KERNEL_INTERFACE_H_ @} */ diff --git a/src/charon/network/packet.c b/src/charon/network/packet.c index f2fa91569..b47e6322f 100644 --- a/src/charon/network/packet.c +++ b/src/charon/network/packet.c @@ -1,10 +1,3 @@ -/** - * @file packet.c - * - * @brief Implementation of packet_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,12 +12,12 @@ * 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. + * + * $Id: packet.c 3589 2008-03-13 14:14:44Z martin $ */ - #include "packet.h" - typedef struct private_packet_t private_packet_t; /** diff --git a/src/charon/network/packet.h b/src/charon/network/packet.h index acf953032..2f126d465 100644 --- a/src/charon/network/packet.h +++ b/src/charon/network/packet.h @@ -1,10 +1,3 @@ -/** - * @file packet.h - * - * @brief Interface of packet_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: packet.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup packet packet + * @{ @ingroup network */ #ifndef PACKET_H_ @@ -30,105 +30,88 @@ typedef struct packet_t packet_t; #include <utils/host.h> /** - * @brief Abstraction of an UDP-Packet, contains data, sender and receiver. - * - * @b Constructors: - * - packet_create() - * - * @ingroup network + * Abstraction of an UDP-Packet, contains data, sender and receiver. */ struct packet_t { /** - * @brief Set the source address. + * Set the source address. * * Set host_t is now owned by packet_t, it will destroy * it if necessary. * - * @param this calling object * @param source address to set as source */ void (*set_source) (packet_t *packet, host_t *source); /** - * @brief Set the destination address. + * Set the destination address. * * Set host_t is now owned by packet_t, it will destroy * it if necessary. * - * @param this calling object * @param source address to set as destination */ void (*set_destination) (packet_t *packet, host_t *destination); /** - * @brief Get the source address. + * Get the source address. * * Set host_t is still owned by packet_t, clone it * if needed. * - * @param this calling object * @return source address */ host_t *(*get_source) (packet_t *packet); /** - * @brief Get the destination address. + * Get the destination address. * * Set host_t is still owned by packet_t, clone it * if needed. * - * @param this calling object * @return destination address */ host_t *(*get_destination) (packet_t *packet); /** - * @brief Get the data from the packet. + * Get the data from the packet. * * The data pointed by the chunk is still owned * by the packet. Clone it if needed. * - * @param this calling object * @return chunk containing the data */ chunk_t (*get_data) (packet_t *packet); /** - * @brief Set the data in the packet. + * Set the data in the packet. * * Supplied chunk data is now owned by the * packet. It will free it. * - * @param this calling object * @param data chunk with data to set */ void (*set_data) (packet_t *packet, chunk_t data); /** - * @brief Clones a packet_t object. + * Clones a packet_t object. * - * @param packet calling object - * @param clone pointer to a packet_t object pointer where the new object is stored + * @param clone clone of the packet */ packet_t* (*clone) (packet_t *packet); /** - * @brief Destroy the packet, freeing contained data. - * - * @param packet packet to destroy + * Destroy the packet, freeing contained data. */ void (*destroy) (packet_t *packet); }; /** - * @brief create an empty packet + * create an empty packet * * @return packet_t object - * - * @ingroup network */ packet_t *packet_create(void); - -#endif /*PACKET_H_*/ +#endif /*PACKET_H_ @} */ diff --git a/src/charon/network/receiver.c b/src/charon/network/receiver.c index 1de1dd3d2..885280a62 100644 --- a/src/charon/network/receiver.c +++ b/src/charon/network/receiver.c @@ -1,10 +1,3 @@ -/** - * @file receiver.c - * - * @brief Implementation of receiver_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: receiver.c 3994 2008-05-21 21:52:59Z andreas $ */ #include <stdlib.h> @@ -33,9 +28,8 @@ #include <processing/jobs/job.h> #include <processing/jobs/process_message_job.h> #include <processing/jobs/callback_job.h> +#include <crypto/hashers/hasher.h> -/** length of the full cookie, including time (u_int32_t + SHA1()) */ -#define COOKIE_LENGTH 24 /** lifetime of a cookie, in seconds */ #define COOKIE_LIFETIME 10 /** how many times to reuse the secret */ @@ -94,9 +88,9 @@ struct private_receiver_t { u_int32_t secret_offset; /** - * the randomizer to use for secret generation + * the RNG to use for secret generation */ - randomizer_t *randomizer; + rng_t *rng; /** * hasher to use for cookie calculation @@ -145,11 +139,12 @@ static chunk_t cookie_build(private_receiver_t *this, message_t *message, { u_int64_t spi = message->get_initiator_spi(message); host_t *ip = message->get_source(message); - chunk_t input, hash = chunk_alloca(this->hasher->get_hash_size(this->hasher)); + chunk_t input, hash; /* COOKIE = t | sha1( IPi | SPIi | t | secret ) */ input = chunk_cata("cccc", ip->get_address(ip), chunk_from_thing(spi), chunk_from_thing(t), secret); + hash = chunk_alloca(this->hasher->get_hash_size(this->hasher)); this->hasher->get_hash(this->hasher, input, hash.ptr); return chunk_cat("cc", chunk_from_thing(t), hash); } @@ -167,7 +162,8 @@ static bool cookie_verify(private_receiver_t *this, message_t *message, now = time(NULL); t = *(u_int32_t*)cookie.ptr; - if (cookie.len != COOKIE_LENGTH || + if (cookie.len != sizeof(u_int32_t) + + this->hasher->get_hash_size(this->hasher) || t < now - this->secret_offset - COOKIE_LIFETIME) { DBG2(DBG_NET, "received cookie lifetime expired, rejecting"); @@ -212,7 +208,8 @@ static bool cookie_required(private_receiver_t *this, message_t *message) packet_t *packet = message->get_packet(message); chunk_t data = packet->get_data(packet); if (data.len < - IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH + COOKIE_LENGTH || + IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH + + sizeof(u_int32_t) + this->hasher->get_hash_size(this->hasher) || *(data.ptr + 16) != NOTIFY || *(u_int16_t*)(data.ptr + IKE_HEADER_LENGTH + 6) != htons(COOKIE)) { @@ -222,7 +219,7 @@ static bool cookie_required(private_receiver_t *this, message_t *message) else { data.ptr += IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH; - data.len = COOKIE_LENGTH; + data.len = sizeof(u_int32_t) + this->hasher->get_hash_size(this->hasher); if (!cookie_verify(this, message, data)) { DBG2(DBG_NET, "found cookie, but content invalid"); @@ -307,8 +304,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) DBG1(DBG_NET, "generating new cookie secret after %d uses", this->secret_used); memcpy(this->secret_old, this->secret, SECRET_LENGTH); - this->randomizer->get_pseudo_random_bytes(this->randomizer, - SECRET_LENGTH, this->secret); + this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret); this->secret_switch = now; this->secret_used = 0; } @@ -320,7 +316,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) if (peer_to_aggressive(this, message)) { DBG1(DBG_NET, "ignoring IKE_SA setup from %H, " - "peer to aggressive", message->get_source(message)); + "peer too aggressive", message->get_source(message)); message->destroy(message); return JOB_REQUEUE_DIRECT; } @@ -336,7 +332,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) static void destroy(private_receiver_t *this) { this->job->cancel(this->job); - this->randomizer->destroy(this->randomizer); + this->rng->destroy(this->rng); this->hasher->destroy(this->hasher); free(this); } @@ -351,13 +347,25 @@ receiver_t *receiver_create() this->public.destroy = (void(*)(receiver_t*)) destroy; - this->randomizer = randomizer_create(); - this->hasher = hasher_create(HASH_SHA1); + this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED); + if (this->hasher == NULL) + { + DBG1(DBG_NET, "creating cookie hasher failed, no hashers supported"); + free(this); + return NULL; + } + this->rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (this->rng == NULL) + { + DBG1(DBG_NET, "creating cookie RNG failed, no RNG supported"); + this->hasher->destroy(this->hasher); + free(this); + return NULL; + } this->secret_switch = now; this->secret_offset = random() % now; this->secret_used = 0; - this->randomizer->get_pseudo_random_bytes(this->randomizer, SECRET_LENGTH, - this->secret); + this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret); memcpy(this->secret_old, this->secret, SECRET_LENGTH); this->job = callback_job_create((callback_job_cb_t)receive_packets, diff --git a/src/charon/network/receiver.h b/src/charon/network/receiver.h index 1bfa7b764..810a51849 100644 --- a/src/charon/network/receiver.h +++ b/src/charon/network/receiver.h @@ -1,10 +1,3 @@ -/** - * @file receiver.h - * - * @brief Interface of receiver_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: receiver.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup receiver receiver + * @{ @ingroup network */ #ifndef RECEIVER_H_ @@ -30,7 +30,7 @@ typedef struct receiver_t receiver_t; #include <utils/host.h> /** - * @brief Receives packets from the socket and adds them to the job queue. + * Receives packets from the socket and adds them to the job queue. * * The receiver starts a thread, wich reads on the blocking socket. A received * packet is preparsed and a process_message_job is queued in the job queue. @@ -50,32 +50,23 @@ typedef struct receiver_t receiver_t; * * Further, the number of half-initiated IKE_SAs is limited per peer. This * mades it impossible for a peer to flood the server with its real IP address. - * - * @b Constructors: - * - receiver_create() - * - * @ingroup network */ struct receiver_t { /** - * @brief Destroys a receiver_t object. - * - * @param receiver receiver object + * Destroys a receiver_t object. */ void (*destroy) (receiver_t *receiver); }; /** - * @brief Create a receiver_t object. + * Create a receiver_t object. * * The receiver thread will start working, get data * from the socket and add those packets to the job queue. * - * @return receiver_t object - * - * @ingroup network + * @return receiver_t object, NULL if initialization fails */ receiver_t * receiver_create(void); -#endif /*RECEIVER_H_*/ +#endif /*RECEIVER_H_ @} */ diff --git a/src/charon/network/sender.c b/src/charon/network/sender.c index f934dc509..60a08d0c3 100644 --- a/src/charon/network/sender.c +++ b/src/charon/network/sender.c @@ -1,10 +1,3 @@ -/** - * @file sender.c - * - * @brief Implementation of sender_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: sender.c 3742 2008-04-03 09:19:12Z tobias $ */ #include <stdlib.h> @@ -58,9 +53,14 @@ struct private_sender_t { pthread_mutex_t mutex; /** - * condvar to signal for packets in list + * condvar to signal for packets added to list */ - pthread_cond_t condvar; + pthread_cond_t gotone; + + /** + * condvar to signal for packets sent + */ + pthread_cond_t sentone; }; /** @@ -76,8 +76,8 @@ static void send_(private_sender_t *this, packet_t *packet) pthread_mutex_lock(&this->mutex); this->list->insert_last(this->list, packet); + pthread_cond_signal(&this->gotone); pthread_mutex_unlock(&this->mutex); - pthread_cond_signal(&this->condvar); } /** @@ -95,12 +95,13 @@ static job_requeue_t send_packets(private_sender_t * this) pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&this->mutex); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - pthread_cond_wait(&this->condvar, &this->mutex); + pthread_cond_wait(&this->gotone, &this->mutex); pthread_setcancelstate(oldstate, NULL); pthread_cleanup_pop(0); } this->list->remove_first(this->list, (void**)&packet); + pthread_cond_signal(&this->sentone); pthread_mutex_unlock(&this->mutex); charon->socket->send(charon->socket, packet); @@ -114,10 +115,13 @@ static job_requeue_t send_packets(private_sender_t * this) static void destroy(private_sender_t *this) { /* send all packets in the queue */ + pthread_mutex_lock(&this->mutex); while (this->list->get_count(this->list)) { - sched_yield(); + pthread_cond_wait(&this->sentone, &this->mutex); } + pthread_mutex_unlock(&this->mutex); + pthread_mutex_destroy(&this->mutex); this->job->cancel(this->job); this->list->destroy(this->list); free(this); @@ -135,7 +139,8 @@ sender_t * sender_create() this->list = linked_list_create(); pthread_mutex_init(&this->mutex, NULL); - pthread_cond_init(&this->condvar, NULL); + pthread_cond_init(&this->gotone, NULL); + pthread_cond_init(&this->sentone, NULL); this->job = callback_job_create((callback_job_cb_t)send_packets, this, NULL, NULL); diff --git a/src/charon/network/sender.h b/src/charon/network/sender.h index 8d611cc90..4a67c7e72 100644 --- a/src/charon/network/sender.h +++ b/src/charon/network/sender.h @@ -1,10 +1,3 @@ -/** - * @file sender.h - * - * @brief Interface of sender_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: sender.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup sender sender + * @{ @ingroup network */ #ifndef SENDER_H_ @@ -30,45 +30,35 @@ typedef struct sender_t sender_t; #include <network/packet.h> /** - * @brief Thread responsible for sending packets over the socket. - * - * @b Constructors: - * - sender_create() - * - * @ingroup network + * Thread responsible for sending packets over the socket. */ struct sender_t { /** - * @brief Send a packet over the network. + * Send a packet over the network. * * This function is non blocking and adds the packet to a queue. * Whenever the sender thread thinks it's good to send the packet, * it'll do so. * - * @param this calling object * @param packet packet to send */ void (*send) (sender_t *this, packet_t *packet); /** - * @brief Destroys a sender object. - * - * @param this calling object + * Destroys a sender object. */ void (*destroy) (sender_t *this); }; /** - * @brief Create the sender thread. + * Create the sender thread. * * The thread will start to work, getting packets * from its queue and sends them out. * * @return created sender object - * - * @ingroup network */ sender_t * sender_create(void); -#endif /*SENDER_H_*/ +#endif /*SENDER_H_ @} */ diff --git a/src/charon/network/socket-raw.c b/src/charon/network/socket-raw.c index 3b76ae570..5d1623ffd 100644 --- a/src/charon/network/socket-raw.c +++ b/src/charon/network/socket-raw.c @@ -1,10 +1,3 @@ -/** - * @file socket.c - * - * @brief Implementation of socket_t. - * - */ - /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi @@ -20,8 +13,13 @@ * 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. + * + * $Id: socket-raw.c 3870 2008-04-24 13:49:20Z martin $ */ +/* for struct in6_pktinfo */ +#define _GNU_SOURCE + #include <pthread.h> #include <sys/types.h> #include <sys/socket.h> diff --git a/src/charon/network/socket.c b/src/charon/network/socket.c index a4c407579..60ea5f7c8 100644 --- a/src/charon/network/socket.c +++ b/src/charon/network/socket.c @@ -1,10 +1,3 @@ -/** - * @file socket.c - * - * @brief Implementation of socket_t. - * - */ - /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger * Copyright (C) 2005-2007 Martin Willi @@ -20,8 +13,13 @@ * 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. + * + * $Id: socket.c 3870 2008-04-24 13:49:20Z martin $ */ +/* for struct in6_pktinfo */ +#define _GNU_SOURCE + #include <pthread.h> #include <sys/types.h> #include <sys/socket.h> diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h index 4d8251325..077da4bba 100644 --- a/src/charon/network/socket.h +++ b/src/charon/network/socket.h @@ -1,10 +1,3 @@ -/** - * @file socket.h - * - * @brief Interface for socket_t. - * - */ - /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi @@ -20,6 +13,13 @@ * 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. + * + * $Id: socket.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup socket socket + * @{ @ingroup network */ #ifndef SOCKET_H_ @@ -33,38 +33,36 @@ typedef struct socket_t socket_t; #include <utils/linked_list.h> /** - * @brief Maximum size of a packet. - * - * 3000 Bytes should be sufficient, see IKEv2 RFC. + * Maximum size of a packet. * - * @ingroup network + * 3000 Bytes should be sufficient, see IKEv2 RFC. However, we currently + * do not support HASH_AND_URL certificates, so we require to transmit + * the full certificates. To run our multi-CA test with 2 intermediate CAs, + * 5000 bytes is sufficient. */ -#define MAX_PACKET 3000 +#define MAX_PACKET 5000 /** - * @brief Abstraction of all sockets (IPv6/IPv6 send/receive). + * Abstraction of all sockets (IPv4/IPv6 send/receive). * * All available sockets are bound and the receive function - * reads from them. To allow binding of other daemons (pluto) to - * UDP/500, this implementation uses RAW sockets. An installed - * "Linux socket filter" filters out all non-IKEv2 traffic and handles - * just IKEv2 messages. An other daemon (pluto) must handle all traffic - * seperatly, e.g. ignore IKEv2 traffic, since charon handles that. - * - * @b Constructors: - * - socket_create() - * - * @ingroup network + * reads from them. There are actually two implementations: + * The first uses raw sockets to allow binding of other daemons (pluto) to + * UDP/500. An installed "Linux socket filter" filters out all non-IKEv2 + * traffic and handles just IKEv2 messages. An other daemon (pluto) must + * handle all traffic seperatly, e.g. ignore IKEv2 traffic, since charon + * handles that. + * The other implementation uses normal sockets and is built if + * --disable-pluto is given to the configure script. */ struct socket_t { /** - * @brief Receive a packet. + * Receive a packet. * * Reads a packet from the socket and sets source/dest * appropriately. * - * @param this socket_t object to work on * @param packet pinter gets address from allocated packet_t * @return * - SUCCESS when packet successfully received @@ -73,14 +71,13 @@ struct socket_t { status_t (*receive) (socket_t *this, packet_t **packet); /** - * @brief Send a packet. + * Send a packet. * * Sends a packet to the net using destination from the packet. * Packet is sent using default routing mechanisms, thus the * source address in packet is ignored. * - * @param this socket_t object to work on - * @param packet[out] packet_t to send + * @param packet packet_t to send * @return * - SUCCESS when packet successfully sent * - FAILED when unable to send @@ -88,23 +85,16 @@ struct socket_t { status_t (*send) (socket_t *this, packet_t *packet); /** - * @brief Destroy sockets. - * - * close sockets and destroy socket_t object - * - * @param this socket_t to destroy + * Destroy socket. */ void (*destroy) (socket_t *this); }; /** - * @brief Create a socket_t, wich binds multiple sockets. + * Create a socket_t, wich binds multiple sockets. * * @return socket_t object - * - * @ingroup network */ socket_t *socket_create(); - -#endif /*SOCKET_H_*/ +#endif /*SOCKET_H_ @} */ diff --git a/src/charon/plugins/eap_aka/Makefile.am b/src/charon/plugins/eap_aka/Makefile.am new file mode 100644 index 000000000..e1ad1eaf9 --- /dev/null +++ b/src/charon/plugins/eap_aka/Makefile.am @@ -0,0 +1,11 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-eapaka.la + +libstrongswan_eapaka_la_SOURCES = eap_aka_plugin.h eap_aka_plugin.c eap_aka.h eap_aka.c +libstrongswan_eapaka_la_LDFLAGS = -module +libstrongswan_eapaka_la_LIBADD = -lgmp + diff --git a/src/charon/plugins/eap_aka/Makefile.in b/src/charon/plugins/eap_aka/Makefile.in new file mode 100644 index 000000000..ad28b0247 --- /dev/null +++ b/src/charon/plugins/eap_aka/Makefile.in @@ -0,0 +1,496 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/eap_aka +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_eapaka_la_DEPENDENCIES = +am_libstrongswan_eapaka_la_OBJECTS = eap_aka_plugin.lo eap_aka.lo +libstrongswan_eapaka_la_OBJECTS = \ + $(am_libstrongswan_eapaka_la_OBJECTS) +libstrongswan_eapaka_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_eapaka_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_eapaka_la_SOURCES) +DIST_SOURCES = $(libstrongswan_eapaka_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-eapaka.la +libstrongswan_eapaka_la_SOURCES = eap_aka_plugin.h eap_aka_plugin.c eap_aka.h eap_aka.c +libstrongswan_eapaka_la_LDFLAGS = -module +libstrongswan_eapaka_la_LIBADD = -lgmp +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/eap_aka/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/eap_aka/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-eapaka.la: $(libstrongswan_eapaka_la_OBJECTS) $(libstrongswan_eapaka_la_DEPENDENCIES) + $(libstrongswan_eapaka_la_LINK) -rpath $(plugindir) $(libstrongswan_eapaka_la_OBJECTS) $(libstrongswan_eapaka_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_aka_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/sa/authenticators/eap/eap_aka.c b/src/charon/plugins/eap_aka/eap_aka.c index 8fb1f85cd..9e35de9e1 100644 --- a/src/charon/sa/authenticators/eap/eap_aka.c +++ b/src/charon/plugins/eap_aka/eap_aka.c @@ -1,10 +1,3 @@ -/** - * @file eap_aka.c - * - * @brief Implementation of eap_aka_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: eap_aka.c 4008 2008-05-23 15:49:43Z martin $ */ @@ -44,14 +39,13 @@ #include <unistd.h> #include <sys/time.h> #include <time.h> +#include <gmp.h> #include "eap_aka.h" #include <daemon.h> #include <library.h> -#include <utils/randomizer.h> #include <crypto/hashers/hasher.h> -#include <crypto/prfs/fips_prf.h> /* Use test vectors specified in S.S0055 #define TEST_VECTORS */ @@ -84,6 +78,54 @@ #define F5 0x47 #define F5STAR 0x48 +typedef enum aka_subtype_t aka_subtype_t; +typedef enum aka_attribute_t aka_attribute_t; + +/** + * Subtypes of AKA messages + */ +enum aka_subtype_t { + AKA_CHALLENGE = 1, + AKA_AUTHENTICATION_REJECT = 2, + AKA_SYNCHRONIZATION_FAILURE = 4, + AKA_IDENTITY = 5, + AKA_NOTIFICATION = 12, + AKA_REAUTHENTICATION = 13, + AKA_CLIENT_ERROR = 14, +}; + +/** + * Attribute types in AKA messages + */ +enum aka_attribute_t { + /** defines the end of attribute list */ + AT_END = -1, + AT_RAND = 1, + AT_AUTN = 2, + AT_RES = 3, + AT_AUTS = 4, + AT_PADDING = 6, + AT_NONCE_MT = 7, + AT_PERMANENT_ID_REQ = 10, + AT_MAC = 11, + AT_NOTIFICATION = 12, + AT_ANY_ID_REQ = 13, + AT_IDENTITY = 14, + AT_VERSION_LIST = 15, + AT_SELECTED_VERSION = 16, + AT_FULLAUTH_ID_REQ = 17, + AT_COUNTER = 19, + AT_COUNTER_TOO_SMALL = 20, + AT_NONCE_S = 21, + AT_CLIENT_ERROR_CODE = 22, + AT_IV = 129, + AT_ENCR_DATA = 130, + AT_NEXT_PSEUDONYM = 132, + AT_NEXT_REAUTH_ID = 133, + AT_CHECKCODE = 134, + AT_RESULT_IND = 135, +}; + ENUM_BEGIN(aka_subtype_names, AKA_CHALLENGE, AKA_IDENTITY, "AKA_CHALLENGE", "AKA_AUTHENTICATION_REJECT", @@ -156,6 +198,26 @@ struct private_eap_aka_t { identification_t *peer; /** + * SHA11 hasher + */ + hasher_t *sha1; + + /** + * MAC function used in EAP-AKA + */ + signer_t *signer; + + /** + * pseudo random function used in EAP-aka + */ + prf_t *prf; + + /** + * Special keyed SHA1 hasher used in EAP-AKA, implemented as PRF + */ + prf_t *keyed_prf; + + /** * Key for EAP MAC */ chunk_t k_auth; @@ -347,7 +409,7 @@ static void mpz_mod_poly(mpz_t r, mpz_t a, mpz_t b) * Step 4 of the various fx() functions: * Polynomial whiten calculations */ -static void step4(u_int8_t x[]) +static void step4(private_eap_aka_t *this, u_int8_t x[]) { mpz_t xm, am, bm, gm; @@ -377,24 +439,35 @@ static void step4(u_int8_t x[]) * Step 3 of the various fx() functions: * XOR the key into the SHA1 IV */ -static void step3(chunk_t k, chunk_t payload, u_int8_t h[]) +static void step3(private_eap_aka_t *this, + chunk_t k, chunk_t payload, u_int8_t h[]) { - u_int8_t iv[] = { - 0x67,0x45,0x23,0x01,0xEF,0xCD,0xAB,0x89,0x98,0xBA, - 0xDC,0xFE,0x10,0x32,0x54,0x76,0xC3,0xD2,0xE1,0xF0, - }; + u_int8_t buf[64]; - /* XOR key into IV */ - memxor(iv, k.ptr, k.len); + if (payload.len < sizeof(buf)) + { + /* pad c with zeros */ + memset(buf, 0, sizeof(buf)); + memcpy(buf, payload.ptr, payload.len); + payload.ptr = buf; + payload.len = sizeof(buf); + } + else + { + /* not more than 512 bits can be G()-ed */ + payload.len = sizeof(buf); + } - /* hash it with the G() function defined in FIPS 186-2 from fips_prf.h */ - g_sha1(iv, payload, h); + /* use the keyed hasher to build the hash */ + this->keyed_prf->set_key(this->keyed_prf, k); + this->keyed_prf->get_bytes(this->keyed_prf, payload, h); } /** * Calculation function for f2(), f3(), f4() */ -static void fx(u_int8_t f, chunk_t k, chunk_t rand, u_int8_t out[]) +static void fx(private_eap_aka_t *this, + u_int8_t f, chunk_t k, chunk_t rand, u_int8_t out[]) { chunk_t payload = chunk_alloca(PAYLOAD_LENGTH); u_int8_t h[HASH_SIZE_SHA1]; @@ -412,8 +485,8 @@ static void fx(u_int8_t f, chunk_t k, chunk_t rand, u_int8_t out[]) payload.ptr[35] ^= i; payload.ptr[51] ^= i; - step3(k, payload, h); - step4(h); + step3(this, k, payload, h); + step4(this, h); memcpy(out + i * 8, h, 8); } } @@ -421,7 +494,8 @@ static void fx(u_int8_t f, chunk_t k, chunk_t rand, u_int8_t out[]) /** * Calculation function of f1() and f1star() */ -static void f1x(u_int8_t f, chunk_t k, chunk_t rand, chunk_t sqn, +static void f1x(private_eap_aka_t *this, + u_int8_t f, chunk_t k, chunk_t rand, chunk_t sqn, chunk_t amf, u_int8_t mac[]) { /* generate MAC = f1(FMK, SQN, RAND, AMF) @@ -438,15 +512,16 @@ static void f1x(u_int8_t f, chunk_t k, chunk_t rand, chunk_t sqn, memxor(payload.ptr + 34, sqn.ptr, sqn.len); memxor(payload.ptr + 42, amf.ptr, amf.len); - step3(k, payload, h); - step4(h); + step3(this, k, payload, h); + step4(this, h); memcpy(mac, h, MAC_LENGTH); } /** * Calculation function of f5() and f5star() */ -static void f5x(u_int8_t f, chunk_t k, chunk_t rand, u_int8_t ak[]) +static void f5x(private_eap_aka_t *this, + u_int8_t f, chunk_t k, chunk_t rand, u_int8_t ak[]) { chunk_t payload = chunk_alloca(PAYLOAD_LENGTH); u_int8_t h[HASH_SIZE_SHA1]; @@ -456,81 +531,81 @@ static void f5x(u_int8_t f, chunk_t k, chunk_t rand, u_int8_t ak[]) memxor(payload.ptr + 12, fmk.ptr, fmk.len); memxor(payload.ptr + 16, rand.ptr, rand.len); - step3(k, payload, h); - step4(h); + step3(this, k, payload, h); + step4(this, h); memcpy(ak, h, AK_LENGTH); } /** * Calculate the MAC from a RAND, SQN, AMF value using K */ -static void f1(chunk_t k, chunk_t rand, chunk_t sqn, chunk_t amf, u_int8_t mac[]) +static void f1(private_eap_aka_t *this, chunk_t k, chunk_t rand, chunk_t sqn, + chunk_t amf, u_int8_t mac[]) { - f1x(F1, k, rand, sqn, amf, mac); + f1x(this, F1, k, rand, sqn, amf, mac); DBG3(DBG_IKE, "MAC %b", mac, MAC_LENGTH); } /** * Calculate the MACS from a RAND, SQN, AMF value using K */ -static void f1star(chunk_t k, chunk_t rand, chunk_t sqn, chunk_t amf, u_int8_t macs[]) +static void f1star(private_eap_aka_t *this, chunk_t k, chunk_t rand, + chunk_t sqn, chunk_t amf, u_int8_t macs[]) { - f1x(F1STAR, k, rand, sqn, amf, macs); + f1x(this, F1STAR, k, rand, sqn, amf, macs); DBG3(DBG_IKE, "MACS %b", macs, MAC_LENGTH); } /** * Calculate RES from RAND using K */ -static void f2(chunk_t k, chunk_t rand, u_int8_t res[]) +static void f2(private_eap_aka_t *this, chunk_t k, chunk_t rand, u_int8_t res[]) { - fx(F2, k, rand, res); + fx(this, F2, k, rand, res); DBG3(DBG_IKE, "RES %b", res, RES_LENGTH); } /** * Calculate CK from RAND using K */ -static void f3(chunk_t k, chunk_t rand, u_int8_t ck[]) +static void f3(private_eap_aka_t *this, chunk_t k, chunk_t rand, u_int8_t ck[]) { - fx(F3, k, rand, ck); + fx(this, F3, k, rand, ck); DBG3(DBG_IKE, "CK %b", ck, CK_LENGTH); } /** * Calculate IK from RAND using K */ -static void f4(chunk_t k, chunk_t rand, u_int8_t ik[]) +static void f4(private_eap_aka_t *this, chunk_t k, chunk_t rand, u_int8_t ik[]) { - fx(F4, k, rand, ik); + fx(this, F4, k, rand, ik); DBG3(DBG_IKE, "IK %b", ik, IK_LENGTH); } /** * Calculate AK from a RAND using K */ -static void f5(chunk_t k, chunk_t rand, u_int8_t ak[]) +static void f5(private_eap_aka_t *this, chunk_t k, chunk_t rand, u_int8_t ak[]) { - f5x(F5, k, rand, ak); + f5x(this, F5, k, rand, ak); DBG3(DBG_IKE, "AK %b", ak, AK_LENGTH); } /** * Calculate AKS from a RAND using K */ -static void f5star(chunk_t k, chunk_t rand, u_int8_t aks[]) +static void f5star(private_eap_aka_t *this, chunk_t k, chunk_t rand, u_int8_t aks[]) { - f5x(F5STAR, k, rand, aks); + f5x(this, F5STAR, k, rand, aks); DBG3(DBG_IKE, "AKS %b", aks, AK_LENGTH); } /** * derive the keys needed for EAP_AKA */ -static void derive_keys(private_eap_aka_t *this, identification_t *id) +static bool derive_keys(private_eap_aka_t *this, identification_t *id) { - hasher_t *hasher; - prf_t *prf; chunk_t ck, ik, mk, identity, tmp; ck = chunk_alloca(CK_LENGTH); @@ -539,26 +614,22 @@ static void derive_keys(private_eap_aka_t *this, identification_t *id) identity = id->get_encoding(id); /* MK = SHA1( Identity | IK | CK ) */ - f3(this->k, this->rand, ck.ptr); - f4(this->k, this->rand, ik.ptr); + f3(this, this->k, this->rand, ck.ptr); + f4(this, this->k, this->rand, ik.ptr); DBG3(DBG_IKE, "Identity %B", &identity); tmp = chunk_cata("ccc", identity, ik, ck); DBG3(DBG_IKE, "Identity|IK|CK %B", &tmp); - hasher = hasher_create(HASH_SHA1); - hasher->get_hash(hasher, tmp, mk.ptr); - hasher->destroy(hasher); + this->sha1->get_hash(this->sha1, tmp, mk.ptr); /* K_encr | K_auth | MSK | EMSK = prf(0) | prf(0) * FIPS PRF has 320 bit block size, we need 160 byte for keys * => run prf four times */ - prf = prf_create(PRF_FIPS_SHA1_160); - prf->set_key(prf, mk); - tmp = chunk_alloca(prf->get_block_size(prf) * 4); - prf->get_bytes(prf, chunk_empty, tmp.ptr); - prf->get_bytes(prf, chunk_empty, tmp.ptr + tmp.len / 4 * 1); - prf->get_bytes(prf, chunk_empty, tmp.ptr + tmp.len / 4 * 2); - prf->get_bytes(prf, chunk_empty, tmp.ptr + tmp.len / 4 * 3); - prf->destroy(prf); + this->prf->set_key(this->prf, mk); + tmp = chunk_alloca(this->prf->get_block_size(this->prf) * 4); + this->prf->get_bytes(this->prf, chunk_empty, tmp.ptr); + this->prf->get_bytes(this->prf, chunk_empty, tmp.ptr + tmp.len / 4 * 1); + this->prf->get_bytes(this->prf, chunk_empty, tmp.ptr + tmp.len / 4 * 2); + this->prf->get_bytes(this->prf, chunk_empty, tmp.ptr + tmp.len / 4 * 3); chunk_free(&this->k_encr); chunk_free(&this->k_auth); chunk_free(&this->msk); @@ -571,6 +642,7 @@ static void derive_keys(private_eap_aka_t *this, identification_t *id) DBG3(DBG_IKE, "K_auth %B", &this->k_auth); DBG3(DBG_IKE, "MSK %B", &this->msk); DBG3(DBG_IKE, "EMSK %B", &this->emsk); + return TRUE; } /* @@ -582,18 +654,21 @@ static void derive_keys(private_eap_aka_t *this, identification_t *id) */ static status_t load_key(identification_t *me, identification_t *other, chunk_t *k) { - chunk_t shared_key; + shared_key_t *shared; + chunk_t key; - if (charon->credentials->get_eap_key(charon->credentials, me, - other, &shared_key) != SUCCESS) + shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP, + me, other); + if (shared == NULL) { return NOT_FOUND; } + key = shared->get_key(shared); chunk_free(k); *k = chunk_alloc(K_LENGTH); memset(k->ptr, '\0', k->len); - memcpy(k->ptr, shared_key.ptr, min(shared_key.len, k->len)); - chunk_free(&shared_key); + memcpy(k->ptr, key.ptr, min(key.len, k->len)); + shared->destroy(shared); return SUCCESS; } @@ -739,13 +814,11 @@ static eap_payload_t *build_aka_payload(private_eap_aka_t *this, eap_code_t code /* create MAC if AT_MAC attribte was included */ if (mac_pos) { - signer_t *signer = signer_create(AUTH_HMAC_SHA1_128); - signer->set_key(signer, this->k_auth); + this->signer->set_key(this->signer, this->k_auth); DBG3(DBG_IKE, "AT_MAC signature of %B", &message); DBG3(DBG_IKE, "using key %B", &this->k_auth); - signer->get_signature(signer, message, mac_pos); + this->signer->get_signature(this->signer, message, mac_pos); DBG3(DBG_IKE, "is %b", mac_pos, AT_MAC_LENGTH); - signer->destroy(signer); } /* payload constructor takes data with some bytes skipped */ @@ -758,10 +831,10 @@ static eap_payload_t *build_aka_payload(private_eap_aka_t *this, eap_code_t code /** * Initiate a AKA-Challenge using SQN */ -static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn, eap_payload_t **out) +static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn, + eap_payload_t **out) { - randomizer_t *randomizer; - status_t status; + rng_t *rng; chunk_t mac, ak, autn; mac = chunk_alloca(MAC_LENGTH); @@ -770,16 +843,16 @@ static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn, chunk_free(&this->xres); /* generate RAND: - * we use our standard randomizer, not f0() proposed in S.S0055 + * we use a registered RNG, not f0() proposed in S.S0055 */ - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes(randomizer, RAND_LENGTH, &this->rand); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { DBG1(DBG_IKE, "generating RAND for EAP-AKA authentication failed"); return FAILED; } + rng->allocate_bytes(rng, RAND_LENGTH, &this->rand); + rng->destroy(rng); # ifdef TEST_VECTORS /* Test vector for RAND */ @@ -808,14 +881,14 @@ static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn, # endif /* TEST_VECTORS */ /* generate MAC */ - f1(this->k, this->rand, sqn, amf, mac.ptr); + f1(this, this->k, this->rand, sqn, amf, mac.ptr); /* generate AK */ - f5(this->k, this->rand, ak.ptr); + f5(this, this->k, this->rand, ak.ptr); /* precalculate XRES as expected from client */ this->xres = chunk_alloc(RES_LENGTH); - f2(this->k, this->rand, this->xres.ptr); + f2(this, this->k, this->rand, this->xres.ptr); /* calculate AUTN = (SQN xor AK) || AMF || MAC */ autn = chunk_cata("ccc", sqn, amf, mac); @@ -896,7 +969,7 @@ static status_t server_process_synchronize(private_eap_aka_t *this, chunk_split(auts, "mm", SQN_LENGTH, &sqn, MAC_LENGTH, &macs); aks = chunk_alloca(AK_LENGTH); - f5star(this->k, this->rand, aks.ptr); + f5star(this, this->k, this->rand, aks.ptr); /* decrypt serial number by XORing AKS */ memxor(sqn.ptr, aks.ptr, aks.len); @@ -905,7 +978,7 @@ static status_t server_process_synchronize(private_eap_aka_t *this, amf = chunk_alloca(AMF_LENGTH); /* an AMF of zero is used for MACS calculation */ memset(amf.ptr, 0, amf.len); - f1star(this->k, this->rand, sqn, amf, xmacs.ptr); + f1star(this, this->k, this->rand, sqn, amf, xmacs.ptr); if (!chunk_equals(macs, xmacs)) { DBG1(DBG_IKE, "received MACS does not match XMACS"); @@ -974,14 +1047,10 @@ static status_t server_process_challenge(private_eap_aka_t *this, eap_payload_t /* verify EAP message MAC AT_MAC */ { - bool valid; - signer_t *signer = signer_create(AUTH_HMAC_SHA1_128); - signer->set_key(signer, this->k_auth); + this->signer->set_key(this->signer, this->k_auth); DBG3(DBG_IKE, "verifying AT_MAC signature of %B", &message); DBG3(DBG_IKE, "using key %B", &this->k_auth); - valid = signer->verify_signature(signer, message, at_mac); - signer->destroy(signer); - if (!valid) + if (!this->signer->verify_signature(this->signer, message, at_mac)) { DBG1(DBG_IKE, "MAC in AT_MAC attribute verification failed"); return FAILED; @@ -1135,7 +1204,7 @@ static status_t peer_process_challenge(private_eap_aka_t *this, # endif /* TEST_VECTORS */ /* calculate anonymity key AK */ - f5(this->k, this->rand, ak.ptr); + f5(this, this->k, this->rand, ak.ptr); DBG3(DBG_IKE, "using rand %B", &this->rand); DBG3(DBG_IKE, "using ak %B", &ak); /* XOR AK into SQN to decrypt it */ @@ -1147,7 +1216,7 @@ static status_t peer_process_challenge(private_eap_aka_t *this, DBG3(DBG_IKE, "using sqn %B", &sqn); /* calculate expected MAC and compare against received one */ - f1(this->k, this->rand, sqn, amf, xmac.ptr); + f1(this, this->k, this->rand, sqn, amf, xmac.ptr); if (!chunk_equals(mac, xmac)) { *out = build_aka_payload(this, EAP_RESPONSE, identifier, @@ -1171,9 +1240,9 @@ static status_t peer_process_challenge(private_eap_aka_t *this, /* AMF is set to zero in AKA_SYNCHRONIZATION_FAILURE */ memset(amf.ptr, 0, amf.len); /* AKS = f5*(RAND) */ - f5star(this->k, this->rand, aks.ptr); + f5star(this, this->k, this->rand, aks.ptr); /* MACS = f1*(RAND) */ - f1star(this->k, this->rand, peer_sqn, amf, macs.ptr); + f1star(this, this->k, this->rand, peer_sqn, amf, macs.ptr); /* AUTS = SQN xor AKS | MACS */ memxor(aks.ptr, peer_sqn.ptr, aks.len); auts = chunk_cata("cc", aks, macs); @@ -1190,33 +1259,26 @@ static status_t peer_process_challenge(private_eap_aka_t *this, /* derive K_encr, K_auth, MSK, EMSK */ derive_keys(this, this->peer); - + /* verify EAP message MAC AT_MAC */ + DBG3(DBG_IKE, "verifying AT_MAC signature of %B", &message); + DBG3(DBG_IKE, "using key %B", &this->k_auth); + this->signer->set_key(this->signer, this->k_auth); + if (!this->signer->verify_signature(this->signer, message, at_mac)) { - bool valid; - signer_t *signer = signer_create(AUTH_HMAC_SHA1_128); - signer->set_key(signer, this->k_auth); - - DBG3(DBG_IKE, "verifying AT_MAC signature of %B", &message); - DBG3(DBG_IKE, "using key %B", &this->k_auth); - valid = signer->verify_signature(signer, message, at_mac); - signer->destroy(signer); - if (!valid) - { - *out = build_aka_payload(this, EAP_RESPONSE, identifier, AKA_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_code, AT_END); - DBG1(DBG_IKE, "MAC in AT_MAC attribute verification " - "failed, sending %N %d", aka_attribute_names, - AT_CLIENT_ERROR_CODE, 0); - return NEED_MORE; - } + *out = build_aka_payload(this, EAP_RESPONSE, identifier, AKA_CLIENT_ERROR, + AT_CLIENT_ERROR_CODE, client_error_code, AT_END); + DBG1(DBG_IKE, "MAC in AT_MAC attribute verification " + "failed, sending %N %d", aka_attribute_names, + AT_CLIENT_ERROR_CODE, 0); + return NEED_MORE; } /* update stored SQN to the received one */ memcpy(peer_sqn.ptr, sqn.ptr, sqn.len); /* calculate RES */ - f2(this->k, this->rand, res.ptr); + f2(this, this->k, this->rand, res.ptr); /* build response */ *out = build_aka_payload(this, EAP_RESPONSE, identifier, AKA_CHALLENGE, @@ -1387,6 +1449,10 @@ static bool is_mutual(private_eap_aka_t *this) */ static void destroy(private_eap_aka_t *this) { + DESTROY_IF(this->sha1); + DESTROY_IF(this->signer); + DESTROY_IF(this->prf); + DESTROY_IF(this->keyed_prf); chunk_free(&this->k_encr); chunk_free(&this->k_auth); chunk_free(&this->msk); @@ -1397,29 +1463,16 @@ static void destroy(private_eap_aka_t *this) free(this); } -/* - * Described in header. +/** + * generic constructor used by client & server */ -eap_aka_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer) +static private_eap_aka_t *eap_aka_create_generic(identification_t *server, + identification_t *peer) { private_eap_aka_t *this = malloc_thing(private_eap_aka_t); - /* public functions */ - switch (role) - { - case EAP_SERVER: - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))server_initiate; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))server_process; - break; - case EAP_PEER: - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))peer_initiate; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))peer_process; - break; - default: - free(this); - return NULL; - } + this->public.eap_method_interface.initiate = NULL; + this->public.eap_method_interface.process = NULL; this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; @@ -1436,5 +1489,51 @@ eap_aka_t *eap_create(eap_role_t role, this->k = chunk_empty; this->rand = chunk_empty; - return &this->public; + this->sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_SHA1_128); + this->prf = lib->crypto->create_prf(lib->crypto, PRF_FIPS_SHA1_160); + this->keyed_prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1); + + if (!this->sha1 || !this->signer || !this->prf || !this->keyed_prf) + { + DBG1(DBG_IKE, "unable to initiate EAP-AKA, FIPS-PRF/SHA1 not supported"); + DESTROY_IF(this->sha1); + DESTROY_IF(this->signer); + DESTROY_IF(this->prf); + DESTROY_IF(this->keyed_prf); + destroy(this); + return NULL; + } + return this; +} + +/* + * Described in header. + */ +eap_aka_t *eap_aka_create_server(identification_t *server, identification_t *peer) +{ + private_eap_aka_t *this = eap_aka_create_generic(server, peer); + + if (this) + { + this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))server_initiate; + this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))server_process; + } + return (eap_aka_t*)this; } + +/* + * Described in header. + */ +eap_aka_t *eap_aka_create_peer(identification_t *server, identification_t *peer) +{ + private_eap_aka_t *this = eap_aka_create_generic(server, peer); + + if (this) + { + this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))peer_initiate; + this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))peer_process; + } + return (eap_aka_t*)this; +} + diff --git a/src/charon/sa/authenticators/eap/eap_aka.h b/src/charon/plugins/eap_aka/eap_aka.h index a886863be..118f2c44f 100644 --- a/src/charon/sa/authenticators/eap/eap_aka.h +++ b/src/charon/plugins/eap_aka/eap_aka.h @@ -1,12 +1,5 @@ -/** - * @file eap_aka.h - * - * @brief Interface of eap_aka_t. - * - */ - /* - * Copyright (C) 2006 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,80 +11,29 @@ * 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. + * + * $Id: eap_aka.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup eap_aka_i eap_aka + * @{ @ingroup eap_aka */ #ifndef EAP_AKA_H_ #define EAP_AKA_H_ typedef struct eap_aka_t eap_aka_t; -typedef enum aka_subtype_t aka_subtype_t; -typedef enum aka_attribute_t aka_attribute_t; #include <sa/authenticators/eap/eap_method.h> - -/** - * Subtypes of AKA messages - */ -enum aka_subtype_t { - AKA_CHALLENGE = 1, - AKA_AUTHENTICATION_REJECT = 2, - AKA_SYNCHRONIZATION_FAILURE = 4, - AKA_IDENTITY = 5, - AKA_NOTIFICATION = 12, - AKA_REAUTHENTICATION = 13, - AKA_CLIENT_ERROR = 14, -}; - -/** - * enum names for aka_subtype_t - */ -extern enum_name_t *aka_subtype_names; - -/** - * Attribute types in AKA messages - */ -enum aka_attribute_t { - /** defines the end of attribute list */ - AT_END = -1, - AT_RAND = 1, - AT_AUTN = 2, - AT_RES = 3, - AT_AUTS = 4, - AT_PADDING = 6, - AT_NONCE_MT = 7, - AT_PERMANENT_ID_REQ = 10, - AT_MAC = 11, - AT_NOTIFICATION = 12, - AT_ANY_ID_REQ = 13, - AT_IDENTITY = 14, - AT_VERSION_LIST = 15, - AT_SELECTED_VERSION = 16, - AT_FULLAUTH_ID_REQ = 17, - AT_COUNTER = 19, - AT_COUNTER_TOO_SMALL = 20, - AT_NONCE_S = 21, - AT_CLIENT_ERROR_CODE = 22, - AT_IV = 129, - AT_ENCR_DATA = 130, - AT_NEXT_PSEUDONYM = 132, - AT_NEXT_REAUTH_ID = 133, - AT_CHECKCODE = 134, - AT_RESULT_IND = 135, -}; - -/** - * enum names for aka_attribute_t - */ -extern enum_name_t *aka_attribute_names; - /** check SEQ values as client for validity, disabled by default */ #ifndef SEQ_CHECK # define SEQ_CHECK 0 #endif /** - * @brief Implementation of the eap_method_t interface using EAP-AKA. + * Implementation of the eap_method_t interface using EAP-AKA. * * EAP-AKA uses 3rd generation mobile phone standard authentication * mechanism for authentication. It is a mutual authentication @@ -111,12 +53,6 @@ extern enum_name_t *aka_attribute_names; * any SEQ numbers. This allows an attacker to do replay attacks. But since * the server has proven his identity via IKE, such an attack is only * possible between server and AAA (if any). - * - * @b Constructors: - * - eap_aka_create() - * - eap_client_create() using eap_method EAP_AKA - * - * @ingroup eap */ struct eap_aka_t { @@ -127,15 +63,21 @@ struct eap_aka_t { }; /** - * @brief Creates the EAP method EAP-AKA. + * Creates the server implementation of the EAP method EAP-AKA. * * @param server ID of the EAP server * @param peer ID of the EAP client * @return eap_aka_t object + */ +eap_aka_t *eap_aka_create_server(identification_t *server, identification_t *peer); + +/** + * Creates the peer implementation of the EAP method EAP-AKA. * - * @ingroup eap + * @param server ID of the EAP server + * @param peer ID of the EAP client + * @return eap_aka_t object */ -eap_aka_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer); +eap_aka_t *eap_aka_create_peer(identification_t *server, identification_t *peer); -#endif /* EAP_AKA_H_ */ +#endif /* EAP_AKA_H_ @}*/ diff --git a/src/charon/plugins/eap_aka/eap_aka_plugin.c b/src/charon/plugins/eap_aka/eap_aka_plugin.c new file mode 100644 index 000000000..5c15b6d7e --- /dev/null +++ b/src/charon/plugins/eap_aka/eap_aka_plugin.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_aka_plugin.c 3491 2008-02-22 14:04:00Z martin $ + */ + +#include "eap_aka_plugin.h" + +#include "eap_aka.h" + +#include <daemon.h> + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(eap_aka_plugin_t *this) +{ + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_aka_create_server); + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_aka_create_peer); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + eap_aka_plugin_t *this = malloc_thing(eap_aka_plugin_t); + + this->plugin.destroy = (void(*)(plugin_t*))destroy; + + charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_SERVER, + (eap_constructor_t)eap_aka_create_server); + charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_PEER, + (eap_constructor_t)eap_aka_create_peer); + + return &this->plugin; +} + diff --git a/src/charon/plugins/eap_aka/eap_aka_plugin.h b/src/charon/plugins/eap_aka/eap_aka_plugin.h new file mode 100644 index 000000000..506d47f98 --- /dev/null +++ b/src/charon/plugins/eap_aka/eap_aka_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_aka_plugin.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup eap_aka eap_aka + * @ingroup cplugins + * + * @defgroup eap_aka_plugin eap_aka_plugin + * @{ @ingroup eap_aka + */ + +#ifndef EAP_AKA_PLUGIN_H_ +#define EAP_AKA_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct eap_aka_plugin_t eap_aka_plugin_t; + +/** + * EAP-AKA plugin + */ +struct eap_aka_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a eap_aka_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* EAP_AKA_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/eap_identity/Makefile.am b/src/charon/plugins/eap_identity/Makefile.am new file mode 100644 index 000000000..dbf66e74b --- /dev/null +++ b/src/charon/plugins/eap_identity/Makefile.am @@ -0,0 +1,10 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-eapidentity.la +libstrongswan_eapidentity_la_SOURCES = \ + eap_identity_plugin.h eap_identity_plugin.c eap_identity.h eap_identity.c +libstrongswan_eapidentity_la_LDFLAGS = -module + diff --git a/src/charon/plugins/eap_identity/Makefile.in b/src/charon/plugins/eap_identity/Makefile.in new file mode 100644 index 000000000..37f3505f2 --- /dev/null +++ b/src/charon/plugins/eap_identity/Makefile.in @@ -0,0 +1,499 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/eap_identity +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_eapidentity_la_LIBADD = +am_libstrongswan_eapidentity_la_OBJECTS = eap_identity_plugin.lo \ + eap_identity.lo +libstrongswan_eapidentity_la_OBJECTS = \ + $(am_libstrongswan_eapidentity_la_OBJECTS) +libstrongswan_eapidentity_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_eapidentity_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_eapidentity_la_SOURCES) +DIST_SOURCES = $(libstrongswan_eapidentity_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-eapidentity.la +libstrongswan_eapidentity_la_SOURCES = \ + eap_identity_plugin.h eap_identity_plugin.c eap_identity.h eap_identity.c + +libstrongswan_eapidentity_la_LDFLAGS = -module +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/eap_identity/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/eap_identity/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-eapidentity.la: $(libstrongswan_eapidentity_la_OBJECTS) $(libstrongswan_eapidentity_la_DEPENDENCIES) + $(libstrongswan_eapidentity_la_LINK) -rpath $(plugindir) $(libstrongswan_eapidentity_la_OBJECTS) $(libstrongswan_eapidentity_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_identity.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_identity_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/sa/authenticators/eap/eap_identity.c b/src/charon/plugins/eap_identity/eap_identity.c index 12a8bf7cc..0c90e8a04 100644 --- a/src/charon/sa/authenticators/eap/eap_identity.c +++ b/src/charon/plugins/eap_identity/eap_identity.c @@ -1,10 +1,3 @@ -/** - * @file eap_identity.c - * - * @brief Implementation of eap_identity_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: eap_identity.c 3491 2008-02-22 14:04:00Z martin $ */ #include "eap_identity.h" @@ -76,8 +71,9 @@ static status_t initiate(private_eap_identity_t *this, eap_payload_t **out) /** * Implementation of eap_method_t.get_type. */ -static eap_type_t get_type(private_eap_identity_t *this) +static eap_type_t get_type(private_eap_identity_t *this, u_int32_t *vendor) { + *vendor = 0; return EAP_IDENTITY; } @@ -108,22 +104,15 @@ static void destroy(private_eap_identity_t *this) /* * Described in header. */ -eap_identity_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer) +eap_identity_t *eap_identity_create_peer(identification_t *server, + identification_t *peer) { - private_eap_identity_t *this; - - if (role != EAP_PEER) - { - return NULL; - } - - this = malloc_thing(private_eap_identity_t); + private_eap_identity_t *this = malloc_thing(private_eap_identity_t); /* public functions */ this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; - this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*))get_type; + this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; @@ -133,3 +122,4 @@ eap_identity_t *eap_create(eap_role_t role, return &this->public; } + diff --git a/src/charon/sa/authenticators/eap/eap_identity.h b/src/charon/plugins/eap_identity/eap_identity.h index 20f0f0b67..9de89e6e3 100644 --- a/src/charon/sa/authenticators/eap/eap_identity.h +++ b/src/charon/plugins/eap_identity/eap_identity.h @@ -1,12 +1,5 @@ -/** - * @file eap_identity.h - * - * @brief Interface of eap_identity_t. - * - */ - /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,6 +11,13 @@ * 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. + * + * $Id: eap_identity.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup eap_identity_i eap_identity + * @{ @ingroup eap_identity */ #ifndef EAP_IDENTITY_H_ @@ -28,13 +28,7 @@ typedef struct eap_identity_t eap_identity_t; #include <sa/authenticators/eap/eap_method.h> /** - * @brief Implementation of the eap_method_t interface using EAP Identity. - * - * @b Constructors: - * - eap_identity_create() - * - eap_client_create() using eap_method EAP_IDENTITY - * - * @ingroup eap + * Implementation of the eap_method_t interface using EAP Identity. */ struct eap_identity_t { @@ -45,15 +39,13 @@ struct eap_identity_t { }; /** - * @brief Creates the EAP method EAP Identity. + * Creates the EAP method EAP Identity, acting as peer. * * @param server ID of the EAP server * @param peer ID of the EAP client * @return eap_identity_t object - * - * @ingroup eap */ -eap_identity_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer); +eap_identity_t *eap_identity_create_peer(identification_t *server, + identification_t *peer); -#endif /* EAP_IDENTITY_H_ */ +#endif /* EAP_IDENTITY_H_ @}*/ diff --git a/src/charon/plugins/eap_identity/eap_identity_plugin.c b/src/charon/plugins/eap_identity/eap_identity_plugin.c new file mode 100644 index 000000000..38a19d784 --- /dev/null +++ b/src/charon/plugins/eap_identity/eap_identity_plugin.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_identity_plugin.c 3491 2008-02-22 14:04:00Z martin $ + */ + +#include "eap_identity_plugin.h" + +#include "eap_identity.h" + +#include <daemon.h> + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(eap_identity_plugin_t *this) +{ + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_identity_create_peer); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + eap_identity_plugin_t *this = malloc_thing(eap_identity_plugin_t); + + this->plugin.destroy = (void(*)(plugin_t*))destroy; + + charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_PEER, + (eap_constructor_t)eap_identity_create_peer); + + return &this->plugin; +} + diff --git a/src/charon/control/interfaces/dbus_interface.h b/src/charon/plugins/eap_identity/eap_identity_plugin.h index 0ce57bbbc..d7fa525ce 100644 --- a/src/charon/control/interfaces/dbus_interface.h +++ b/src/charon/plugins/eap_identity/eap_identity_plugin.h @@ -1,12 +1,5 @@ -/** - * @file dbus_interface.h - * - * @brief Interface of dbus_interface_t. - * - */ - /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,40 +11,39 @@ * 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. + * + * $Id: eap_identity_plugin.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup eap_identity eap_identity + * @ingroup cplugins + * + * @defgroup eap_identity_plugin eap_identity_plugin + * @{ @ingroup eap_identity */ -#ifndef DBUS_INTERFACE_H_ -#define DBUS_INTERFACE_H_ +#ifndef EAP_IDENTITY_PLUGIN_H_ +#define EAP_IDENTITY_PLUGIN_H_ -typedef struct dbus_interface_t dbus_interface_t; +#include <plugins/plugin.h> -#include <control/interfaces/interface.h> +typedef struct eap_identity_plugin_t eap_identity_plugin_t; /** - * @brief The DBUS interface uses the DBUS system bus to communicate. - * - * @b Constructors: - * - dbus_interface_create() - * - * @ingroup interfaces + * EAP-IDENTITY plugin. */ -struct dbus_interface_t { - +struct eap_identity_plugin_t { + /** - * implements interface_t. + * implements plugin interface */ - interface_t interface; + plugin_t plugin; }; - /** - * @brief Create the DBUS interface. - * - * @return stroke_t object - * - * @ingroup interfaces + * Create a eap_identity_plugin instance. */ -interface_t *interface_create(); - -#endif /* DBUS_INTERFACE_H_ */ +plugin_t *plugin_create(); +#endif /* EAP_IDENTITY_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/eap_md5/Makefile.am b/src/charon/plugins/eap_md5/Makefile.am new file mode 100644 index 000000000..d7964fee9 --- /dev/null +++ b/src/charon/plugins/eap_md5/Makefile.am @@ -0,0 +1,10 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-eapmd5.la + +libstrongswan_eapmd5_la_SOURCES = eap_md5_plugin.h eap_md5_plugin.c eap_md5.h eap_md5.c +libstrongswan_eapmd5_la_LDFLAGS = -module + diff --git a/src/charon/plugins/eap_md5/Makefile.in b/src/charon/plugins/eap_md5/Makefile.in new file mode 100644 index 000000000..d48fb2c44 --- /dev/null +++ b/src/charon/plugins/eap_md5/Makefile.in @@ -0,0 +1,495 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/eap_md5 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_eapmd5_la_LIBADD = +am_libstrongswan_eapmd5_la_OBJECTS = eap_md5_plugin.lo eap_md5.lo +libstrongswan_eapmd5_la_OBJECTS = \ + $(am_libstrongswan_eapmd5_la_OBJECTS) +libstrongswan_eapmd5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_eapmd5_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_eapmd5_la_SOURCES) +DIST_SOURCES = $(libstrongswan_eapmd5_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-eapmd5.la +libstrongswan_eapmd5_la_SOURCES = eap_md5_plugin.h eap_md5_plugin.c eap_md5.h eap_md5.c +libstrongswan_eapmd5_la_LDFLAGS = -module +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/eap_md5/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/eap_md5/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-eapmd5.la: $(libstrongswan_eapmd5_la_OBJECTS) $(libstrongswan_eapmd5_la_DEPENDENCIES) + $(libstrongswan_eapmd5_la_LINK) -rpath $(plugindir) $(libstrongswan_eapmd5_la_OBJECTS) $(libstrongswan_eapmd5_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_md5.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_md5_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/sa/authenticators/eap/eap_md5.c b/src/charon/plugins/eap_md5/eap_md5.c index 0ca9fc566..990d64011 100644 --- a/src/charon/sa/authenticators/eap/eap_md5.c +++ b/src/charon/plugins/eap_md5/eap_md5.c @@ -1,10 +1,3 @@ -/** - * @file eap_md5.c - * - * @brief Implementation of eap_md5_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,12 +11,15 @@ * 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. + * + * $Id: eap_md5.c 3806 2008-04-15 05:56:35Z martin $ */ - + #include "eap_md5.h" #include <daemon.h> #include <library.h> +#include <crypto/hashers/hasher.h> typedef struct private_eap_md5_t private_eap_md5_t; @@ -85,20 +81,28 @@ struct eap_md5_header_t { * Hash the challenge string, create response */ static status_t hash_challenge(private_eap_md5_t *this, chunk_t *response) -{ - chunk_t concat, secret; +{ + shared_key_t *shared; + chunk_t concat; hasher_t *hasher; - - if (charon->credentials->get_eap_key(charon->credentials, this->server, - this->peer, &secret) != SUCCESS) + + shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP, + this->server, this->peer); + if (shared == NULL) { DBG1(DBG_IKE, "no EAP key found for hosts '%D' - '%D'", this->server, this->peer); return NOT_FOUND; } - concat = chunk_cata("cmc", chunk_from_thing(this->identifier), - secret, this->challenge); - hasher = hasher_create(HASH_MD5); + concat = chunk_cata("ccc", chunk_from_thing(this->identifier), + shared->get_key(shared), this->challenge); + shared->destroy(shared); + hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); + if (hasher == NULL) + { + DBG1(DBG_IKE, "EAP-MD5 failed, MD5 not supported"); + return FAILED; + } hasher->allocate_hash(hasher, concat, response); hasher->destroy(hasher); return SUCCESS; @@ -118,18 +122,16 @@ static status_t initiate_peer(private_eap_md5_t *this, eap_payload_t **out) */ static status_t initiate_server(private_eap_md5_t *this, eap_payload_t **out) { - randomizer_t *randomizer; - status_t status; + rng_t *rng; eap_md5_header_t *req; - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes(randomizer, CHALLENGE_LEN, - &this->challenge); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { return FAILED; } + rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge); + rng->destroy(rng); req = alloca(PAYLOAD_LEN); req->length = htons(PAYLOAD_LEN); @@ -244,29 +246,16 @@ static void destroy(private_eap_md5_t *this) free(this); } -/* - * Described in header. +/** + * Generic constructor */ -eap_md5_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer) +static private_eap_md5_t *eap_md5_create_generic(identification_t *server, + identification_t *peer) { private_eap_md5_t *this = malloc_thing(private_eap_md5_t); - /* public functions */ - switch (role) - { - case EAP_SERVER: - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server; - break; - case EAP_PEER: - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer; - break; - default: - free(this); - return NULL; - } + this->public.eap_method_interface.initiate = NULL; + this->public.eap_method_interface.process = NULL; this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; @@ -278,5 +267,32 @@ eap_md5_t *eap_create(eap_role_t role, this->challenge = chunk_empty; this->identifier = random(); + return this; +} + +/* + * see header + */ +eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *peer) +{ + private_eap_md5_t *this = eap_md5_create_generic(server, peer); + + this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server; + this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server; + + return &this->public; +} + +/* + * see header + */ +eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer) +{ + private_eap_md5_t *this = eap_md5_create_generic(server, peer); + + this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer; + this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer; + return &this->public; } + diff --git a/src/charon/sa/authenticators/eap/eap_md5.h b/src/charon/plugins/eap_md5/eap_md5.h index 260210b59..421e1e602 100644 --- a/src/charon/sa/authenticators/eap/eap_md5.h +++ b/src/charon/plugins/eap_md5/eap_md5.h @@ -1,12 +1,5 @@ -/** - * @file eap_md5.h - * - * @brief Interface of eap_md5_t. - * - */ - /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,6 +11,13 @@ * 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. + * + * $Id: eap_md5.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup eap_md5_i eap_md5 + * @{ @ingroup eap_md5 */ #ifndef EAP_MD5_H_ @@ -28,13 +28,7 @@ typedef struct eap_md5_t eap_md5_t; #include <sa/authenticators/eap/eap_method.h> /** - * @brief Implementation of the eap_method_t interface using EAP-MD5 (CHAP). - * - * @b Constructors: - * - eap_md5_create() - * - eap_client_create() using eap_method EAP_MD5 - * - * @ingroup eap + * Implementation of the eap_method_t interface using EAP-MD5 (CHAP). */ struct eap_md5_t { @@ -45,15 +39,21 @@ struct eap_md5_t { }; /** - * @brief Creates the EAP method EAP-MD5. + * Creates the EAP method EAP-MD5 acting as server. * * @param server ID of the EAP server * @param peer ID of the EAP client * @return eap_md5_t object + */ +eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *peer); + +/** + * Creates the EAP method EAP-MD5 acting as peer. * - * @ingroup eap + * @param server ID of the EAP server + * @param peer ID of the EAP client + * @return eap_md5_t object */ -eap_md5_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer); +eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer); -#endif /* EAP_MD5_H_ */ +#endif /* EAP_MD5_H_ @}*/ diff --git a/src/charon/plugins/eap_md5/eap_md5_plugin.c b/src/charon/plugins/eap_md5/eap_md5_plugin.c new file mode 100644 index 000000000..cb6a9bd7c --- /dev/null +++ b/src/charon/plugins/eap_md5/eap_md5_plugin.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_md5_plugin.c 3491 2008-02-22 14:04:00Z martin $ + */ + +#include "eap_md5_plugin.h" + +#include "eap_md5.h" + +#include <daemon.h> + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(eap_md5_plugin_t *this) +{ + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_md5_create_server); + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_md5_create_peer); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + eap_md5_plugin_t *this = malloc_thing(eap_md5_plugin_t); + + this->plugin.destroy = (void(*)(plugin_t*))destroy; + + charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_SERVER, + (eap_constructor_t)eap_md5_create_server); + charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_PEER, + (eap_constructor_t)eap_md5_create_peer); + + return &this->plugin; +} + diff --git a/src/charon/plugins/eap_md5/eap_md5_plugin.h b/src/charon/plugins/eap_md5/eap_md5_plugin.h new file mode 100644 index 000000000..d13794f2e --- /dev/null +++ b/src/charon/plugins/eap_md5/eap_md5_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_md5_plugin.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup eap_md5 eap_md5 + * @ingroup cplugins + * + * @defgroup eap_md5_plugin eap_md5_plugin + * @{ @ingroup eap_md5 + */ + +#ifndef EAP_MD5_PLUGIN_H_ +#define EAP_MD5_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct eap_md5_plugin_t eap_md5_plugin_t; + +/** + * EAP-MD5 plugin + */ +struct eap_md5_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a eap_md5_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* EAP_MD5_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/eap_sim/Makefile.am b/src/charon/plugins/eap_sim/Makefile.am new file mode 100644 index 000000000..63267b9d3 --- /dev/null +++ b/src/charon/plugins/eap_sim/Makefile.am @@ -0,0 +1,13 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DSIM_READER_LIB=\"${simreader}\" + +plugin_LTLIBRARIES = libstrongswan-eapsim.la libeapsim-file.la + +libstrongswan_eapsim_la_SOURCES = eap_sim_plugin.h eap_sim_plugin.c eap_sim.h eap_sim.c +libstrongswan_eapsim_la_LDFLAGS = -module + +libeapsim_file_la_SOURCES = eap_sim_file.c +libeapsim_file_la_LDFLAGS = -module + diff --git a/src/charon/plugins/eap_sim/Makefile.in b/src/charon/plugins/eap_sim/Makefile.in new file mode 100644 index 000000000..e70f8457c --- /dev/null +++ b/src/charon/plugins/eap_sim/Makefile.in @@ -0,0 +1,508 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/eap_sim +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libeapsim_file_la_LIBADD = +am_libeapsim_file_la_OBJECTS = eap_sim_file.lo +libeapsim_file_la_OBJECTS = $(am_libeapsim_file_la_OBJECTS) +libeapsim_file_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libeapsim_file_la_LDFLAGS) $(LDFLAGS) -o $@ +libstrongswan_eapsim_la_LIBADD = +am_libstrongswan_eapsim_la_OBJECTS = eap_sim_plugin.lo eap_sim.lo +libstrongswan_eapsim_la_OBJECTS = \ + $(am_libstrongswan_eapsim_la_OBJECTS) +libstrongswan_eapsim_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_eapsim_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libeapsim_file_la_SOURCES) \ + $(libstrongswan_eapsim_la_SOURCES) +DIST_SOURCES = $(libeapsim_file_la_SOURCES) \ + $(libstrongswan_eapsim_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DSIM_READER_LIB=\"${simreader}\" +plugin_LTLIBRARIES = libstrongswan-eapsim.la libeapsim-file.la +libstrongswan_eapsim_la_SOURCES = eap_sim_plugin.h eap_sim_plugin.c eap_sim.h eap_sim.c +libstrongswan_eapsim_la_LDFLAGS = -module +libeapsim_file_la_SOURCES = eap_sim_file.c +libeapsim_file_la_LDFLAGS = -module +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/eap_sim/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/eap_sim/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libeapsim-file.la: $(libeapsim_file_la_OBJECTS) $(libeapsim_file_la_DEPENDENCIES) + $(libeapsim_file_la_LINK) -rpath $(plugindir) $(libeapsim_file_la_OBJECTS) $(libeapsim_file_la_LIBADD) $(LIBS) +libstrongswan-eapsim.la: $(libstrongswan_eapsim_la_OBJECTS) $(libstrongswan_eapsim_la_DEPENDENCIES) + $(libstrongswan_eapsim_la_LINK) -rpath $(plugindir) $(libstrongswan_eapsim_la_OBJECTS) $(libstrongswan_eapsim_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/sa/authenticators/eap/eap_sim.c b/src/charon/plugins/eap_sim/eap_sim.c index 90898fb46..b14076f34 100644 --- a/src/charon/sa/authenticators/eap/eap_sim.c +++ b/src/charon/plugins/eap_sim/eap_sim.c @@ -1,10 +1,3 @@ -/** - * @file eap_sim.c - * - * @brief Implementation of eap_sim_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: eap_sim.c 3806 2008-04-15 05:56:35Z martin $ */ #include "eap_sim.h" @@ -140,6 +135,21 @@ struct private_eap_sim_t { identification_t *peer; /** + * hashing function + */ + hasher_t *hasher; + + /** + * prf + */ + prf_t *prf; + + /** + * MAC function + */ + signer_t *signer; + + /** * SIM cardreader function loaded from library */ sim_algo_t alg; @@ -403,13 +413,11 @@ static eap_payload_t *build_payload(private_eap_sim_t *this, u_int8_t identifier * chunk mac_data to "to-sign" chunk */ if (mac_pos) { - signer_t *signer = signer_create(AUTH_HMAC_SHA1_128); - signer->set_key(signer, this->k_auth); + this->signer->set_key(this->signer, this->k_auth); mac_data = chunk_cata("cc", message, mac_data); - signer->get_signature(signer, mac_data, mac_pos); + this->signer->get_signature(this->signer, mac_data, mac_pos); DBG3(DBG_IKE, "AT_MAC signature of %B\n is %b", &mac_data, mac_pos, MAC_LEN); - signer->destroy(signer); } payload = eap_payload_create_data(message); @@ -520,30 +528,24 @@ static status_t peer_process_start(private_eap_sim_t *this, eap_payload_t *in, static void derive_keys(private_eap_sim_t *this, chunk_t kcs) { chunk_t tmp, mk; - hasher_t *hasher; - prf_t *prf; int i; /* build MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ tmp = chunk_cata("ccccc", this->peer->get_encoding(this->peer), kcs, this->nonce, this->version_list, this->version); - hasher = hasher_create(HASH_SHA1); - mk = chunk_alloca(hasher->get_hash_size(hasher)); - hasher->get_hash(hasher, tmp, mk.ptr); - hasher->destroy(hasher); + mk = chunk_alloca(this->hasher->get_hash_size(this->hasher)); + this->hasher->get_hash(this->hasher, tmp, mk.ptr); DBG3(DBG_IKE, "MK = SHA1(%B\n) = %B", &tmp, &mk); /* K_encr | K_auth | MSK | EMSK = prf() | prf() | prf() | prf() * FIPS PRF has 320 bit block size, we need 160 byte for keys * => run prf four times */ - prf = prf_create(PRF_FIPS_SHA1_160); - prf->set_key(prf, mk); - tmp = chunk_alloca(prf->get_block_size(prf) * 4); + this->prf->set_key(this->prf, mk); + tmp = chunk_alloca(this->prf->get_block_size(this->prf) * 4); for (i = 0; i < 4; i++) { - prf->get_bytes(prf, chunk_empty, tmp.ptr + tmp.len / 4 * i); + this->prf->get_bytes(this->prf, chunk_empty, tmp.ptr + tmp.len / 4 * i); } - prf->destroy(prf); chunk_free(&this->k_encr); chunk_free(&this->k_auth); chunk_free(&this->msk); @@ -564,7 +566,6 @@ static status_t peer_process_challenge(private_eap_sim_t *this, sim_attribute_t attribute; u_int8_t identifier; chunk_t mac = chunk_empty, rands = chunk_empty; - signer_t *signer; if (this->tries-- <= 0) { @@ -670,19 +671,16 @@ static status_t peer_process_challenge(private_eap_sim_t *this, derive_keys(this, kcs); /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT" */ - signer = signer_create(AUTH_HMAC_SHA1_128); - signer->set_key(signer, this->k_auth); + this->signer->set_key(this->signer, this->k_auth); tmp = chunk_cata("cc", in->get_data(in), this->nonce); - if (!signer->verify_signature(signer, tmp, mac)) + if (!this->signer->verify_signature(this->signer, tmp, mac)) { DBG1(DBG_IKE, "AT_MAC verification failed"); - signer->destroy(signer); *out = build_payload(this, identifier, SIM_CLIENT_ERROR, AT_CLIENT_ERROR_CODE, client_error_general, AT_END); return NEED_MORE; } - signer->destroy(signer); /* build response, AT_MAC is built over "EAP packet | n*SRES" */ *out = build_payload(this, identifier, SIM_CHALLENGE, @@ -700,7 +698,6 @@ static status_t server_process_challenge(private_eap_sim_t *this, chunk_t message, data; sim_attribute_t attribute; chunk_t mac = chunk_empty, tmp; - signer_t *signer; message = in->get_data(in); read_header(&message); @@ -729,16 +726,13 @@ static status_t server_process_challenge(private_eap_sim_t *this, return FAILED; } /* verify AT_MAC attribute, signature is over "EAP packet | n*SRES" */ - signer = signer_create(AUTH_HMAC_SHA1_128); - signer->set_key(signer, this->k_auth); + this->signer->set_key(this->signer, this->k_auth); tmp = chunk_cata("cc", in->get_data(in), this->sreses); - if (!signer->verify_signature(signer, tmp, mac)) + if (!this->signer->verify_signature(this->signer, tmp, mac)) { DBG1(DBG_IKE, "AT_MAC verification failed"); - signer->destroy(signer); return FAILED; } - signer->destroy(signer); return SUCCESS; } @@ -942,7 +936,7 @@ static status_t peer_process(private_eap_sim_t *this, * Implementation of eap_method_t.process for the server */ static status_t server_process(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) + eap_payload_t *in, eap_payload_t **out) { sim_subtype_t type; chunk_t message; @@ -1023,6 +1017,9 @@ static bool is_mutual(private_eap_sim_t *this) static void destroy(private_eap_sim_t *this) { dlclose(this->handle); + DESTROY_IF(this->hasher); + DESTROY_IF(this->prf); + DESTROY_IF(this->signer); chunk_free(&this->nonce); chunk_free(&this->sreses); chunk_free(&this->version_list); @@ -1033,14 +1030,14 @@ static void destroy(private_eap_sim_t *this) free(this); } -/* - * Described in header. +/** + * Generic constructor for both roles */ -eap_sim_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer) +eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server, + identification_t *peer) { private_eap_sim_t *this; - randomizer_t *randomizer; + rng_t *rng; void *symbol; char *name; @@ -1101,16 +1098,15 @@ eap_sim_t *eap_create(eap_role_t role, this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))peer_process; this->alg = symbol; this->type = EAP_RESPONSE; - randomizer = randomizer_create(); - if (randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LEN, - &this->nonce)) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { - DBG1(DBG_IKE, "unable to generate NONCE for EAP_SIM"); - randomizer->destroy(randomizer); + DBG1(DBG_IKE, "unable to generate NONCE for EAP_SIM"); free(this); return NULL; } - randomizer->destroy(randomizer); + rng->allocate_bytes(rng, NONCE_LEN, &this->nonce); + rng->destroy(rng); break; default: free(this); @@ -1121,5 +1117,33 @@ eap_sim_t *eap_create(eap_role_t role, this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; + this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + this->prf = lib->crypto->create_prf(lib->crypto, PRF_FIPS_SHA1_160); + this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_SHA1_128); + if (!this->hasher || !this->prf || !this->signer) + { + DBG1(DBG_IKE, "initiating EAP-SIM failed, FIPS-PRF/SHA1 not supported"); + destroy(this); + return NULL; + } return &this->public; } + +/* + * Described in header. + */ +eap_sim_t *eap_sim_create_server(identification_t *server, + identification_t *peer) +{ + return eap_sim_create_generic(EAP_SERVER, server, peer); +} + +/* + * Described in header. + */ +eap_sim_t *eap_sim_create_peer(identification_t *server, + identification_t *peer) +{ + return eap_sim_create_generic(EAP_PEER, server, peer); +} + diff --git a/src/charon/sa/authenticators/eap/eap_sim.h b/src/charon/plugins/eap_sim/eap_sim.h index d50cf7397..65020aa64 100644 --- a/src/charon/sa/authenticators/eap/eap_sim.h +++ b/src/charon/plugins/eap_sim/eap_sim.h @@ -1,12 +1,5 @@ -/** - * @file eap_sim.h - * - * @brief Interface of eap_sim_t. - * - */ - /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2007-2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,6 +13,11 @@ * for more details. */ +/** + * @defgroup eap_sim_i eap_sim + * @{ @ingroup eap_sim + */ + #ifndef EAP_SIM_H_ #define EAP_SIM_H_ @@ -33,7 +31,7 @@ typedef struct eap_sim_t eap_sim_t; #endif /* SIM_READER_LIB */ /** - * @brief Cardreaders SIM function. + * Cardreaders SIM function. * * @param rand RAND to run algo with * @param rand_length length of value in rand @@ -53,7 +51,7 @@ typedef int (*sim_algo_t)(const unsigned char *rand, int rand_length, #endif /* SIM_READER_ALG */ /** - * @brief Function to get a SIM triplet. + * Function to get a SIM triplet. * * @param identity identity (imsi) to get a triplet for * @param rand buffer to get RAND @@ -75,7 +73,7 @@ typedef int (*sim_get_triplet_t)(char *identity, #endif /* SIM_READER_GET_TRIPLET */ /** - * @brief Implementation of the eap_method_t interface using EAP-SIM. + * Implementation of the eap_method_t interface using EAP-SIM. * * This EAP-SIM client implementation uses another pluggable library to * access the SIM card/triplet provider. This module is specified using the @@ -83,12 +81,6 @@ typedef int (*sim_get_triplet_t)(char *identity, * calculate a triplet (client), and/or a sim_get_triplet() function to get * a triplet (server). These functions are named to the SIM_READER_ALG and * the SIM_READER_GET_TRIPLET definitions. - * - * @b Constructors: - * - eap_create() of this module - * - eap_client_create() using eap_method EAP_SIM - * - * @ingroup eap */ struct eap_sim_t { @@ -99,16 +91,21 @@ struct eap_sim_t { }; /** - * @brief Creates the EAP method EAP-SIM. + * Creates the EAP method EAP-SIM acting as server. * - * @param role role of the module, client/server * @param server ID of the EAP server * @param peer ID of the EAP client * @return eap_sim_t object + */ +eap_sim_t *eap_sim_create_server(identification_t *server, identification_t *peer); + +/** + * Creates the EAP method EAP-SIM acting as peer. * - * @ingroup eap + * @param server ID of the EAP server + * @param peer ID of the EAP client + * @return eap_sim_t object */ -eap_sim_t *eap_create(eap_role_t role, - identification_t *server, identification_t *peer); +eap_sim_t *eap_sim_create_peer(identification_t *server, identification_t *peer); -#endif /* EAP_SIM_H_ */ +#endif /* EAP_SIM_H_ @}*/ diff --git a/src/charon/sa/authenticators/eap/sim/eap_sim_file.c b/src/charon/plugins/eap_sim/eap_sim_file.c index 2ab45a578..fc4c1af26 100644 --- a/src/charon/sa/authenticators/eap/sim/eap_sim_file.c +++ b/src/charon/plugins/eap_sim/eap_sim_file.c @@ -1,10 +1,3 @@ -/**
- * @file eap_sim.h
- *
- * @brief Interface of eap_sim_t.
- *
- */
-
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
@@ -17,7 +10,9 @@ * 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.
+ * for more details. + * + * $Id: eap_sim_file.c 3491 2008-02-22 14:04:00Z martin $ */
#include <string.h>
diff --git a/src/charon/plugins/eap_sim/eap_sim_plugin.c b/src/charon/plugins/eap_sim/eap_sim_plugin.c new file mode 100644 index 000000000..d937c57b4 --- /dev/null +++ b/src/charon/plugins/eap_sim/eap_sim_plugin.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_sim_plugin.c 3491 2008-02-22 14:04:00Z martin $ + */ + +#include "eap_sim_plugin.h" + +#include "eap_sim.h" + +#include <daemon.h> + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(eap_sim_plugin_t *this) +{ + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_sim_create_server); + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_sim_create_peer); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + eap_sim_plugin_t *this = malloc_thing(eap_sim_plugin_t); + + this->plugin.destroy = (void(*)(plugin_t*))destroy; + + charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_SERVER, + (eap_constructor_t)eap_sim_create_server); + charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_PEER, + (eap_constructor_t)eap_sim_create_peer); + + return &this->plugin; +} + diff --git a/src/charon/plugins/eap_sim/eap_sim_plugin.h b/src/charon/plugins/eap_sim/eap_sim_plugin.h new file mode 100644 index 000000000..938807884 --- /dev/null +++ b/src/charon/plugins/eap_sim/eap_sim_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_sim_plugin.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup eap_sim eap_sim + * @ingroup cplugins + * + * @defgroup eap_sim_plugin eap_sim_plugin + * @{ @ingroup eap_sim + */ + +#ifndef EAP_SIM_PLUGIN_H_ +#define EAP_SIM_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct eap_sim_plugin_t eap_sim_plugin_t; + +/** + * EAP-sim plugin + */ +struct eap_sim_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a eap_sim_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* EAP_SIM_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/medcli/Makefile.am b/src/charon/plugins/medcli/Makefile.am new file mode 100644 index 000000000..f15950af9 --- /dev/null +++ b/src/charon/plugins/medcli/Makefile.am @@ -0,0 +1,12 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-medcli.la +libstrongswan_medcli_la_SOURCES = medcli_plugin.h medcli_plugin.c \ + medcli_creds.h medcli_creds.c \ + medcli_config.h medcli_config.c \ + medcli_listener.h medcli_listener.c +libstrongswan_medcli_la_LDFLAGS = -module + diff --git a/src/charon/plugins/medcli/Makefile.in b/src/charon/plugins/medcli/Makefile.in new file mode 100644 index 000000000..85be6bae7 --- /dev/null +++ b/src/charon/plugins/medcli/Makefile.in @@ -0,0 +1,502 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/medcli +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_medcli_la_LIBADD = +am_libstrongswan_medcli_la_OBJECTS = medcli_plugin.lo medcli_creds.lo \ + medcli_config.lo medcli_listener.lo +libstrongswan_medcli_la_OBJECTS = \ + $(am_libstrongswan_medcli_la_OBJECTS) +libstrongswan_medcli_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_medcli_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_medcli_la_SOURCES) +DIST_SOURCES = $(libstrongswan_medcli_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-medcli.la +libstrongswan_medcli_la_SOURCES = medcli_plugin.h medcli_plugin.c \ + medcli_creds.h medcli_creds.c \ + medcli_config.h medcli_config.c \ + medcli_listener.h medcli_listener.c + +libstrongswan_medcli_la_LDFLAGS = -module +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/medcli/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/medcli/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-medcli.la: $(libstrongswan_medcli_la_OBJECTS) $(libstrongswan_medcli_la_DEPENDENCIES) + $(libstrongswan_medcli_la_LINK) -rpath $(plugindir) $(libstrongswan_medcli_la_OBJECTS) $(libstrongswan_medcli_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_creds.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medcli_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/plugins/medcli/medcli_config.c b/src/charon/plugins/medcli/medcli_config.c new file mode 100644 index 000000000..96dfa7c94 --- /dev/null +++ b/src/charon/plugins/medcli/medcli_config.c @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#define _GNU_SOURCE +#include <string.h> + +#include "medcli_config.h" + +#include <daemon.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_medcli_config_t private_medcli_config_t; + +/** + * Private data of an medcli_config_t object + */ +struct private_medcli_config_t { + + /** + * Public part + */ + medcli_config_t public; + + /** + * database connection + */ + database_t *db; + + /** + * rekey time + */ + int rekey; + + /** + * dpd delay + */ + int dpd; + + /** + * default ike config + */ + ike_cfg_t *ike; +}; + +/** + * create a traffic selector from a CIDR notation string + */ +static traffic_selector_t *ts_from_string(char *str) +{ + if (str) + { + int netbits = 32; + host_t *net; + char *pos; + + str = strdupa(str); + pos = strchr(str, '/'); + if (pos) + { + *pos++ = '\0'; + netbits = atoi(pos); + } + else + { + if (strchr(str, ':')) + { + netbits = 128; + } + } + net = host_create_from_string(str, 0); + if (net) + { + return traffic_selector_create_from_subnet(net, netbits, 0, 0); + } + } + return traffic_selector_create_dynamic(0, 0, 65535); +} + +/** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *name) +{ + enumerator_t *e; + peer_cfg_t *peer_cfg, *med_cfg; + ike_cfg_t *ike_cfg; + child_cfg_t *child_cfg; + chunk_t me, other; + char *address, *local_net, *remote_net; + + /* query mediation server config: + * - build ike_cfg/peer_cfg for mediation connection on-the-fly + */ + e = this->db->query(this->db, + "SELECT Address, ClientConfig.KeyId, MediationServerConfig.KeyId " + "FROM MediationServerConfig JOIN ClientConfig", + DB_TEXT, DB_BLOB, DB_BLOB); + if (!e || !e->enumerate(e, &address, &me, &other)) + { + DESTROY_IF(e); + return NULL; + } + ike_cfg = ike_cfg_create(FALSE, FALSE, "0.0.0.0", address); + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + med_cfg = peer_cfg_create( + "mediation", 2, ike_cfg, + identification_create_from_encoding(ID_KEY_ID, me), + identification_create_from_encoding(ID_KEY_ID, other), + CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY, + 0, 0, /* EAP method, vendor */ + 1, this->rekey*60, 0, /* keytries, rekey, reauth */ + this->rekey*5, this->rekey*3, /* jitter, overtime */ + TRUE, this->dpd, /* mobike, dpddelay */ + NULL, NULL, /* vip, pool */ + TRUE, NULL, NULL); /* mediation, med by, peer id */ + e->destroy(e); + + /* query mediated config: + * - use any-any ike_cfg + * - build peer_cfg on-the-fly using med_cfg + * - add a child_cfg + */ + e = this->db->query(this->db, + "SELECT ClientConfig.KeyId, Connection.KeyId, " + "Connection.LocalSubnet, Connection.RemoteSubnet " + "FROM ClientConfig JOIN Connection " + "WHERE Active AND Alias = ?", DB_TEXT, name, + DB_BLOB, DB_BLOB, DB_TEXT, DB_TEXT); + if (!e || !e->enumerate(e, &me, &other, &local_net, &remote_net)) + { + DESTROY_IF(e); + return NULL; + } + peer_cfg = peer_cfg_create( + name, 2, this->ike->get_ref(this->ike), + identification_create_from_encoding(ID_KEY_ID, me), + identification_create_from_encoding(ID_KEY_ID, other), + CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY, + 0, 0, /* EAP method, vendor */ + 1, this->rekey*60, 0, /* keytries, rekey, reauth */ + this->rekey*5, this->rekey*3, /* jitter, overtime */ + TRUE, this->dpd, /* mobike, dpddelay */ + NULL, NULL, /* vip, pool */ + FALSE, med_cfg, /* mediation, med by */ + identification_create_from_encoding(ID_KEY_ID, other)); + + child_cfg = child_cfg_create(name, this->rekey*60 + this->rekey, + this->rekey*60, this->rekey, NULL, TRUE, + MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE); + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net)); + child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net)); + peer_cfg->add_child_cfg(peer_cfg, child_cfg); + e->destroy(e); + return peer_cfg; +} + +/** + * Implementation of backend_t.create_ike_cfg_enumerator. + */ +static enumerator_t* create_ike_cfg_enumerator(private_medcli_config_t *this, + host_t *me, host_t *other) +{ + return enumerator_create_single(this->ike, NULL); +} + +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated peer config */ + peer_cfg_t *current; + /** ike cfg to use in peer cfg */ + ike_cfg_t *ike; + /** rekey time */ + int rekey; + /** dpd time */ + int dpd; +} peer_enumerator_t; + +/** + * Implementation of peer_enumerator_t.public.enumerate + */ +static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) +{ + char *name, *local_net, *remote_net; + chunk_t me, other; + child_cfg_t *child_cfg; + + DESTROY_IF(this->current); + if (!this->inner->enumerate(this->inner, &name, &me, &other, + &local_net, &remote_net)) + { + this->current = NULL; + return FALSE; + } + this->current = peer_cfg_create( + name, 2, this->ike->get_ref(this->ike), + identification_create_from_encoding(ID_KEY_ID, me), + identification_create_from_encoding(ID_KEY_ID, other), + CERT_NEVER_SEND, UNIQUE_REPLACE, AUTH_RSA, + 0, 0, /* EAP method, vendor */ + 1, this->rekey*60, 0, /* keytries, rekey, reauth */ + this->rekey*5, this->rekey*3, /* jitter, overtime */ + TRUE, this->dpd, /* mobike, dpddelay */ + NULL, NULL, /* vip, pool */ + FALSE, NULL, NULL); /* mediation, med by, peer id */ + child_cfg = child_cfg_create( + name, this->rekey*60 + this->rekey, + this->rekey*60, this->rekey, NULL, TRUE, + MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE); + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net)); + child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net)); + this->current->add_child_cfg(this->current, child_cfg); + *cfg = this->current; + return TRUE; +} + +/** + * Implementation of peer_enumerator_t.public.destroy + */ +static void peer_enumerator_destroy(peer_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of backend_t.create_peer_cfg_enumerator. + */ +static enumerator_t* create_peer_cfg_enumerator(private_medcli_config_t *this, + identification_t *me, + identification_t *other) +{ + peer_enumerator_t *e = malloc_thing(peer_enumerator_t); + + e->current = NULL; + e->ike = this->ike; + e->rekey = this->rekey; + e->dpd = this->dpd; + e->public.enumerate = (void*)peer_enumerator_enumerate; + e->public.destroy = (void*)peer_enumerator_destroy; + + /* filter on IDs: NULL or ANY or matching KEY_ID */ + e->inner = this->db->query(this->db, + "SELECT Alias, ClientConfig.KeyId, Connection.KeyId, " + "Connection.LocalSubnet, Connection.RemoteSubnet " + "FROM ClientConfig JOIN Connection " + "WHERE Active AND " + "(? OR ClientConfig.KeyId = ?) AND (? OR Connection.KeyId = ?)", + DB_INT, me == NULL || me->get_type(me) == ID_ANY, + DB_BLOB, me && me->get_type(me) == ID_KEY_ID ? + me->get_encoding(me) : chunk_empty, + DB_INT, other == NULL || other->get_type(other) == ID_ANY, + DB_BLOB, other && other->get_type(other) == ID_KEY_ID ? + other->get_encoding(other) : chunk_empty, + DB_TEXT, DB_BLOB, DB_BLOB, DB_TEXT, DB_TEXT); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * initiate a peer config + */ +static job_requeue_t initiate_config(peer_cfg_t *peer_cfg) +{ + enumerator_t *enumerator; + child_cfg_t *child_cfg = NULL;; + + enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + enumerator->enumerate(enumerator, &child_cfg); + if (child_cfg) + { + child_cfg->get_ref(child_cfg); + peer_cfg->get_ref(peer_cfg); + enumerator->destroy(enumerator); + charon->controller->initiate(charon->controller, + peer_cfg, child_cfg, NULL, NULL); + } + else + { + enumerator->destroy(enumerator); + } + return JOB_REQUEUE_NONE; +} + +/** + * schedule initation of all "active" connections + */ +static void schedule_autoinit(private_medcli_config_t *this) +{ + enumerator_t *e; + char *name; + + e = this->db->query(this->db, "SELECT Alias FROM Connection WHERE Active", + DB_TEXT); + if (e) + { + while (e->enumerate(e, &name)) + { + peer_cfg_t *peer_cfg; + + peer_cfg = get_peer_cfg_by_name(this, name); + if (peer_cfg) + { + /* schedule asynchronous initiation job */ + charon->processor->queue_job(charon->processor, + (job_t*)callback_job_create( + (callback_job_cb_t)initiate_config, + peer_cfg, (void*)peer_cfg->destroy, NULL)); + } + } + e->destroy(e); + } +} + +/** + * Implementation of medcli_config_t.destroy. + */ +static void destroy(private_medcli_config_t *this) +{ + this->ike->destroy(this->ike); + free(this); +} + +/** + * Described in header. + */ +medcli_config_t *medcli_config_create(database_t *db) +{ + private_medcli_config_t *this = malloc_thing(private_medcli_config_t); + + this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; + this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; + this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; + this->public.destroy = (void(*)(medcli_config_t*))destroy; + + this->db = db; + this->rekey = lib->settings->get_int(lib->settings, + "medclient.rekey", 20) * 60; + this->dpd = lib->settings->get_int(lib->settings, "medclient.dpd", 300); + this->ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", "0.0.0.0"); + this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); + + schedule_autoinit(this); + + return &this->public; +} + diff --git a/src/charon/config/backends/sqlite_backend.h b/src/charon/plugins/medcli/medcli_config.h index 4bc146583..789a73243 100644 --- a/src/charon/config/backends/sqlite_backend.h +++ b/src/charon/plugins/medcli/medcli_config.h @@ -1,12 +1,5 @@ -/** - * @file sqlite_backend.h - * - * @brief Interface of sqlite_backend_t. - * - */ - /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,41 +11,45 @@ * 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. + * + * $Id$ + */ + +/** + * @defgroup medcli_config_i medcli_config + * @{ @ingroup medcli */ - -#ifndef SQLITE_BACKEND_H_ -#define SQLITE_BACKEND_H_ -typedef struct sqlite_backend_t sqlite_backend_t; +#ifndef MEDCLI_CONFIG_H_ +#define MEDCLI_CONFIG_H_ -#include <library.h> +#include <config/backend.h> +#include <database/database.h> -#include "backend.h" +typedef struct medcli_config_t medcli_config_t; /** - * @brief An SQLite based configuration backend. - * - * @b Constructors: - * - sqlite_backend_create() - * - * @ingroup backends + * Mediation client configuration backend. */ -struct sqlite_backend_t { - +struct medcli_config_t { + /** * Implements backend_t interface */ backend_t backend; + + /** + * Destroy the backend. + */ + void (*destroy)(medcli_config_t *this); }; /** - * @brief Create a backend_t instance implemented as sqlite backend. + * Create a medcli_config backend instance. * - * @return backend instance - * - * @ingroup backends + * @param db underlying database + * @return backend instance */ -backend_t *backend_create(void); - -#endif /* SQLITE_BACKEND_H_ */ +medcli_config_t *medcli_config_create(database_t *db); +#endif /* MEDCLI_CONFIG_H_ @}*/ diff --git a/src/charon/plugins/medcli/medcli_creds.c b/src/charon/plugins/medcli/medcli_creds.c new file mode 100644 index 000000000..685f34271 --- /dev/null +++ b/src/charon/plugins/medcli/medcli_creds.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "medcli_creds.h" + +#include <daemon.h> +#include <library.h> +#include <utils/enumerator.h> + +typedef struct private_medcli_creds_t private_medcli_creds_t; + +/** + * Private data of an medcli_creds_t object + */ +struct private_medcli_creds_t { + + /** + * Public part + */ + medcli_creds_t public; + + /** + * underlying database handle + */ + database_t *db; +}; + +/** + * enumerator over private keys + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated private key */ + private_key_t *current; +} private_enumerator_t; + +/** + * Implementation of private_enumerator_t.public.enumerate + */ +static bool private_enumerator_enumerate(private_enumerator_t *this, + private_key_t **key) +{ + chunk_t chunk; + + DESTROY_IF(this->current); + while (this->inner->enumerate(this->inner, &chunk)) + { + this->current = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + BUILD_BLOB_ASN1_DER, chunk_clone(chunk), + BUILD_END); + if (this->current) + { + *key = this->current; + return TRUE; + } + } + this->current = NULL; + return FALSE; +} + +/** + * Implementation of private_enumerator_t.public.destroy + */ +static void private_enumerator_destroy(private_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of credential_set_t.create_private_enumerator. + */ +static enumerator_t* create_private_enumerator(private_medcli_creds_t *this, + key_type_t type, identification_t *id) +{ + private_enumerator_t *e; + + if ((type != KEY_RSA && type != KEY_ANY) || + id == NULL || id->get_type(id) != ID_KEY_ID) + { + DBG1(DBG_CFG, "%N - %D", key_type_names, type, id); + return NULL; + } + + e = malloc_thing(private_enumerator_t); + e->current = NULL; + e->public.enumerate = (void*)private_enumerator_enumerate; + e->public.destroy = (void*)private_enumerator_destroy; + e->inner = this->db->query(this->db, + "SELECT PrivateKey FROM ClientConfig WHERE KeyId = ?", + DB_BLOB, id->get_encoding(id), + DB_BLOB); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * enumerator over certificates + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated cert */ + certificate_t *current; + /** type of requested key */ + key_type_t type; +} cert_enumerator_t; + +/** + * Implementation of cert_enumerator_t.public.enumerate + */ +static bool cert_enumerator_enumerate(cert_enumerator_t *this, + certificate_t **cert) +{ + public_key_t *public; + chunk_t chunk; + + DESTROY_IF(this->current); + while (this->inner->enumerate(this->inner, &chunk)) + { + public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + BUILD_BLOB_ASN1_DER, chunk_clone(chunk), + BUILD_END); + if (public) + { + if (this->type == KEY_ANY || this->type == public->get_type(public)) + { + this->current = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, + BUILD_PUBLIC_KEY, public, BUILD_END); + if (this->current) + { + *cert = this->current; + return TRUE; + } + continue; + } + public->destroy(public); + } + } + this->current = NULL; + return FALSE; +} + +/** + * Implementation of cert_enumerator_t.public.destroy + */ +static void cert_enumerator_destroy(cert_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of credential_set_t.create_cert_enumerator. + */ +static enumerator_t* create_cert_enumerator(private_medcli_creds_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + cert_enumerator_t *e; + + if ((cert != CERT_TRUSTED_PUBKEY && cert != CERT_ANY) || + id == NULL || id->get_type(id) != ID_KEY_ID) + { + return NULL; + } + + e = malloc_thing(cert_enumerator_t); + e->current = NULL; + e->type = key; + e->public.enumerate = (void*)cert_enumerator_enumerate; + e->public.destroy = (void*)cert_enumerator_destroy; + e->inner = this->db->query(this->db, + "SELECT PublicKey FROM ClientConfig WHERE KeyId = ? UNION " + "SELECT PublicKey FROM MediationServerConfig WHERE KeyId = ? UNION " + "SELECT PublicKey FROM Connection WHERE KeyId = ?", + DB_BLOB, id->get_encoding(id), + DB_BLOB, id->get_encoding(id), + DB_BLOB, id->get_encoding(id), + DB_BLOB); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * Implementation of backend_t.destroy. + */ +static void destroy(private_medcli_creds_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +medcli_creds_t *medcli_creds_create(database_t *db) +{ + private_medcli_creds_t *this = malloc_thing(private_medcli_creds_t); + + this->public.set.create_private_enumerator = (void*)create_private_enumerator; + this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; + this->public.set.create_shared_enumerator = (void*)return_null; + this->public.set.create_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)nop; + + this->public.destroy = (void (*)(medcli_creds_t*))destroy; + + this->db = db; + + return &this->public; +} + diff --git a/src/charon/plugins/medcli/medcli_creds.h b/src/charon/plugins/medcli/medcli_creds.h new file mode 100644 index 000000000..5a81edaf2 --- /dev/null +++ b/src/charon/plugins/medcli/medcli_creds.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup medcli_creds_i medcli_creds + * @{ @ingroup medcli + */ + +#ifndef MEDCLI_CREDS_H_ +#define MEDCLI_CREDS_H_ + +#include <credentials/credential_set.h> +#include <database/database.h> + +typedef struct medcli_creds_t medcli_creds_t; + +/** + * Mediation client credentials database. + */ +struct medcli_creds_t { + + /** + * Implements credential_set_t interface + */ + credential_set_t set; + + /** + * Destroy the credentials databse. + */ + void (*destroy)(medcli_creds_t *this); +}; + +/** + * Create the medcli credential set. + * + * @param database underlying database + * @return credential set implementation on that database + */ +medcli_creds_t *medcli_creds_create(database_t *database); + +#endif /* MEDCLI_CREDS_H_ @}*/ diff --git a/src/charon/plugins/medcli/medcli_listener.c b/src/charon/plugins/medcli/medcli_listener.c new file mode 100644 index 000000000..cb370ba2a --- /dev/null +++ b/src/charon/plugins/medcli/medcli_listener.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "medcli_listener.h" + +#include <daemon.h> +#include <library.h> + +typedef struct private_medcli_listener_t private_medcli_listener_t; +typedef enum mediated_state_t mediated_state_t; + +/** + * state of a mediated connection + */ +enum mediated_state_t { + STATE_DOWN = 1, + STATE_CONNECTING = 2, + STATE_UP = 3, +}; + +/** + * Private data of an medcli_listener_t object + */ +struct private_medcli_listener_t { + + /** + * Public part + */ + medcli_listener_t public; + + /** + * underlying database handle + */ + database_t *db; +}; + +/** + * Implementation of bus_listener_t.signal. + */ +static bool signal_(private_medcli_listener_t *this, signal_t signal, level_t level, + int thread, ike_sa_t* ike_sa, char *format, va_list args) +{ + mediated_state_t state; + + if (!ike_sa) + { + return TRUE; + } + + switch (signal) + { + case IKE_UP_START: + state = STATE_CONNECTING; + break; + case IKE_UP_FAILED: + case IKE_DOWN_SUCCESS: + case IKE_DOWN_FAILED: + state = STATE_DOWN; + break; + case IKE_UP_SUCCESS: + state = STATE_UP; + break; + default: + return TRUE; + } + this->db->execute(this->db, NULL, + "UPDATE Connection SET Status = ? WHERE Alias = ?", + DB_UINT, state, DB_TEXT, ike_sa->get_name(ike_sa)); + return TRUE; +} + +/** + * Implementation of backend_t.destroy. + */ +static void destroy(private_medcli_listener_t *this) +{ + this->db->execute(this->db, NULL, "UPDATE Connection SET Status = ?", + DB_UINT, STATE_DOWN); + free(this); +} + +/** + * Described in header. + */ +medcli_listener_t *medcli_listener_create(database_t *db) +{ + private_medcli_listener_t *this = malloc_thing(private_medcli_listener_t); + + this->public.listener.signal = (bool(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,char*,va_list))signal_; + this->public.destroy = (void (*)(medcli_listener_t*))destroy; + + this->db = db; + db->execute(db, NULL, "UPDATE Connection SET Status = ?", + DB_UINT, STATE_DOWN); + + return &this->public; +} + diff --git a/src/charon/plugins/medcli/medcli_listener.h b/src/charon/plugins/medcli/medcli_listener.h new file mode 100644 index 000000000..f07218d78 --- /dev/null +++ b/src/charon/plugins/medcli/medcli_listener.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup medcli_listener_i medcli_listener + * @{ @ingroup medcli + */ + +#ifndef MEDCLI_LISTENER_H_ +#define MEDCLI_LISTENER_H_ + +#include <bus/bus.h> +#include <database/database.h> + +typedef struct medcli_listener_t medcli_listener_t; + +/** + * Mediation client listener, writes connection status to database + */ +struct medcli_listener_t { + + /** + * Implements bus_listener_t interface + */ + bus_listener_t listener; + + /** + * Destroy the credentials databse. + */ + void (*destroy)(medcli_listener_t *this); +}; + +/** + * Create the medcli credential set. + * + * @param database underlying database + * @return listener + */ +medcli_listener_t *medcli_listener_create(database_t *database); + +#endif /* MEDCLI_LISTENER_H_ @}*/ diff --git a/src/charon/plugins/medcli/medcli_plugin.c b/src/charon/plugins/medcli/medcli_plugin.c new file mode 100644 index 000000000..1642ed2fe --- /dev/null +++ b/src/charon/plugins/medcli/medcli_plugin.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "medcli_plugin.h" + +#include "medcli_creds.h" +#include "medcli_config.h" +#include "medcli_listener.h" + +#include <daemon.h> + +typedef struct private_medcli_plugin_t private_medcli_plugin_t; + +/** + * private data of medcli plugin + */ +struct private_medcli_plugin_t { + + /** + * implements plugin interface + */ + medcli_plugin_t public; + + /** + * database connection instance + */ + database_t *db; + + /** + * medcli credential set instance + */ + medcli_creds_t *creds; + + /** + * medcli config database + */ + medcli_config_t *config; + + /** + * Listener to update database connection state + */ + medcli_listener_t *listener; +}; + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_medcli_plugin_t *this) +{ + charon->bus->remove_listener(charon->bus, &this->listener->listener); + charon->backends->remove_backend(charon->backends, &this->config->backend); + charon->credentials->remove_set(charon->credentials, &this->creds->set); + this->listener->destroy(this->listener); + this->config->destroy(this->config); + this->creds->destroy(this->creds); + this->db->destroy(this->db); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + char *uri; + private_medcli_plugin_t *this = malloc_thing(private_medcli_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + uri = lib->settings->get_str(lib->settings, + "medcli.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "mediation client database URI not defined, skipped"); + free(this); + return NULL; + } + + this->db = lib->db->create(lib->db, uri); + if (this->db == NULL) + { + DBG1(DBG_CFG, "opening mediation client database failed"); + free(this); + return NULL; + } + + this->creds = medcli_creds_create(this->db); + this->config = medcli_config_create(this->db); + this->listener = medcli_listener_create(this->db); + + charon->credentials->add_set(charon->credentials, &this->creds->set); + charon->backends->add_backend(charon->backends, &this->config->backend); + charon->bus->add_listener(charon->bus, &this->listener->listener); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/medcli/medcli_plugin.h b/src/charon/plugins/medcli/medcli_plugin.h new file mode 100644 index 000000000..1a8c5b5e7 --- /dev/null +++ b/src/charon/plugins/medcli/medcli_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup medcli medcli + * @ingroup cplugins + * + * @defgroup medcli_plugin medcli_plugin + * @{ @ingroup medcli + */ + +#ifndef MEDCLI_PLUGIN_H_ +#define MEDCLI_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct medcli_plugin_t medcli_plugin_t; + +/** + * Mediation client database plugin. + */ +struct medcli_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a medcli_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* MEDCLI_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/medsrv/Makefile.am b/src/charon/plugins/medsrv/Makefile.am new file mode 100644 index 000000000..476da1878 --- /dev/null +++ b/src/charon/plugins/medsrv/Makefile.am @@ -0,0 +1,11 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-medsrv.la +libstrongswan_medsrv_la_SOURCES = medsrv_plugin.h medsrv_plugin.c \ + medsrv_creds.h medsrv_creds.c \ + medsrv_config.h medsrv_config.c +libstrongswan_medsrv_la_LDFLAGS = -module + diff --git a/src/charon/plugins/medsrv/Makefile.in b/src/charon/plugins/medsrv/Makefile.in new file mode 100644 index 000000000..b6561e15e --- /dev/null +++ b/src/charon/plugins/medsrv/Makefile.in @@ -0,0 +1,500 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/medsrv +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_medsrv_la_LIBADD = +am_libstrongswan_medsrv_la_OBJECTS = medsrv_plugin.lo medsrv_creds.lo \ + medsrv_config.lo +libstrongswan_medsrv_la_OBJECTS = \ + $(am_libstrongswan_medsrv_la_OBJECTS) +libstrongswan_medsrv_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_medsrv_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_medsrv_la_SOURCES) +DIST_SOURCES = $(libstrongswan_medsrv_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-medsrv.la +libstrongswan_medsrv_la_SOURCES = medsrv_plugin.h medsrv_plugin.c \ + medsrv_creds.h medsrv_creds.c \ + medsrv_config.h medsrv_config.c + +libstrongswan_medsrv_la_LDFLAGS = -module +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/medsrv/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/medsrv/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-medsrv.la: $(libstrongswan_medsrv_la_OBJECTS) $(libstrongswan_medsrv_la_DEPENDENCIES) + $(libstrongswan_medsrv_la_LINK) -rpath $(plugindir) $(libstrongswan_medsrv_la_OBJECTS) $(libstrongswan_medsrv_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medsrv_config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medsrv_creds.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medsrv_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/plugins/medsrv/medsrv_config.c b/src/charon/plugins/medsrv/medsrv_config.c new file mode 100644 index 000000000..1017b9de0 --- /dev/null +++ b/src/charon/plugins/medsrv/medsrv_config.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include <string.h> + +#include "medsrv_config.h" + +#include <daemon.h> + +typedef struct private_medsrv_config_t private_medsrv_config_t; + +/** + * Private data of an medsrv_config_t object + */ +struct private_medsrv_config_t { + + /** + * Public part + */ + medsrv_config_t public; + + /** + * database connection + */ + database_t *db; + + /** + * rekey time + */ + int rekey; + + /** + * dpd delay + */ + int dpd; + + /** + * default ike config + */ + ike_cfg_t *ike; +}; + +/** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_medsrv_config_t *this, char *name) +{ + return NULL; +} + +/** + * Implementation of backend_t.create_ike_cfg_enumerator. + */ +static enumerator_t* create_ike_cfg_enumerator(private_medsrv_config_t *this, + host_t *me, host_t *other) +{ + return enumerator_create_single(this->ike, NULL); +} + +/** + * Implementation of backend_t.create_peer_cfg_enumerator. + */ +static enumerator_t* create_peer_cfg_enumerator(private_medsrv_config_t *this, + identification_t *me, + identification_t *other) +{ + enumerator_t *e; + + if (!me || !other || other->get_type(other) != ID_KEY_ID) + { + return NULL; + } + e = this->db->query(this->db, + "SELECT CONCAT(peer.alias, CONCAT('@', user.login)) FROM " + "peer JOIN user ON peer.user = user.id " + "WHERE peer.keyid = ?", DB_BLOB, other->get_encoding(other), + DB_TEXT); + if (e) + { + peer_cfg_t *peer_cfg; + char *name; + + if (e->enumerate(e, &name)) + { + peer_cfg = peer_cfg_create( + name, 2, this->ike->get_ref(this->ike), + me->clone(me), other->clone(other), + CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY, + 0, 0, /* EAP method, vendor */ + 1, this->rekey*60, 0, /* keytries, rekey, reauth */ + this->rekey*5, this->rekey*3, /* jitter, overtime */ + TRUE, this->dpd, /* mobike, dpddelay */ + NULL, NULL, /* vip, pool */ + TRUE, NULL, NULL); /* mediation, med by, peer id */ + e->destroy(e); + return enumerator_create_single(peer_cfg, (void*)peer_cfg->destroy); + } + e->destroy(e); + } + return NULL; +} + +/** + * Implementation of medsrv_config_t.destroy. + */ +static void destroy(private_medsrv_config_t *this) +{ + this->ike->destroy(this->ike); + free(this); +} + +/** + * Described in header. + */ +medsrv_config_t *medsrv_config_create(database_t *db) +{ + private_medsrv_config_t *this = malloc_thing(private_medsrv_config_t); + + this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; + this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; + this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; + this->public.destroy = (void(*)(medsrv_config_t*))destroy; + + this->db = db; + this->rekey = lib->settings->get_int(lib->settings, + "medsrv.rekey", 20) * 60; + this->dpd = lib->settings->get_int(lib->settings, "medsrv.dpd", 300); + this->ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", "0.0.0.0"); + this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); + + return &this->public; +} + diff --git a/src/charon/plugins/medsrv/medsrv_config.h b/src/charon/plugins/medsrv/medsrv_config.h new file mode 100644 index 000000000..ebb62037e --- /dev/null +++ b/src/charon/plugins/medsrv/medsrv_config.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup medsrv_config_i medsrv_config + * @{ @ingroup medsrv + */ + +#ifndef MEDSRV_CONFIG_H_ +#define MEDSRV_CONFIG_H_ + +#include <config/backend.h> +#include <database/database.h> + +typedef struct medsrv_config_t medsrv_config_t; + +/** + * Mediation server configuration backend. + */ +struct medsrv_config_t { + + /** + * Implements backend_t interface + */ + backend_t backend; + + /** + * Destroy the backend. + */ + void (*destroy)(medsrv_config_t *this); +}; + +/** + * Create a medsrv_config backend instance. + * + * @param db underlying database + * @return backend instance + */ +medsrv_config_t *medsrv_config_create(database_t *db); + +#endif /* MEDSRV_CONFIG_H_ @}*/ diff --git a/src/charon/plugins/medsrv/medsrv_creds.c b/src/charon/plugins/medsrv/medsrv_creds.c new file mode 100644 index 000000000..48e05c38e --- /dev/null +++ b/src/charon/plugins/medsrv/medsrv_creds.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: medsrv_creds.c 4061 2008-06-11 14:13:24Z martin $ + */ + +#include "medsrv_creds.h" + +#include <daemon.h> +#include <library.h> +#include <utils/enumerator.h> + +typedef struct private_medsrv_creds_t private_medsrv_creds_t; + +/** + * Private data of an medsrv_creds_t object + */ +struct private_medsrv_creds_t { + + /** + * Public part + */ + medsrv_creds_t public; + + /** + * underlying database handle + */ + database_t *db; +}; + +/** + * enumerator over certificates + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated cert */ + certificate_t *current; + /** type of requested key */ + key_type_t type; +} cert_enumerator_t; + +/** + * Implementation of cert_enumerator_t.public.enumerate + */ +static bool cert_enumerator_enumerate(cert_enumerator_t *this, + certificate_t **cert) +{ + certificate_t *trusted; + public_key_t *public; + chunk_t chunk; + + DESTROY_IF(this->current); + while (this->inner->enumerate(this->inner, &chunk)) + { + public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + BUILD_BLOB_ASN1_DER, chunk_clone(chunk), + BUILD_END); + if (public) + { + if (this->type == KEY_ANY || this->type == public->get_type(public)) + { + trusted = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, + BUILD_PUBLIC_KEY, public, BUILD_END); + if (trusted) + { + *cert = this->current = trusted; + return TRUE; + } + continue; + } + public->destroy(public); + } + } + this->current = NULL; + return FALSE; +} + +/** + * Implementation of cert_enumerator_t.public.destroy + */ +static void cert_enumerator_destroy(cert_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of credential_set_t.create_cert_enumerator. + */ +static enumerator_t* create_cert_enumerator(private_medsrv_creds_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + cert_enumerator_t *e; + + if ((cert != CERT_TRUSTED_PUBKEY && cert != CERT_ANY) || + id == NULL || id->get_type(id) != ID_KEY_ID) + { + return NULL; + } + + e = malloc_thing(cert_enumerator_t); + e->current = NULL; + e->type = key; + e->public.enumerate = (void*)cert_enumerator_enumerate; + e->public.destroy = (void*)cert_enumerator_destroy; + e->inner = this->db->query(this->db, + "SELECT public_key FROM peer WHERE keyid = ?", + DB_BLOB, id->get_encoding(id), + DB_BLOB); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * Implementation of backend_t.destroy. + */ +static void destroy(private_medsrv_creds_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +medsrv_creds_t *medsrv_creds_create(database_t *db) +{ + private_medsrv_creds_t *this = malloc_thing(private_medsrv_creds_t); + + this->public.set.create_private_enumerator = (void*)return_null; + this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; + this->public.set.create_shared_enumerator = (void*)return_null; + this->public.set.create_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)nop; + + this->public.destroy = (void (*)(medsrv_creds_t*))destroy; + + this->db = db; + + return &this->public; +} + diff --git a/src/charon/plugins/medsrv/medsrv_creds.h b/src/charon/plugins/medsrv/medsrv_creds.h new file mode 100644 index 000000000..f65e98411 --- /dev/null +++ b/src/charon/plugins/medsrv/medsrv_creds.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2008 Martin Willi + * 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. + * + * $Id: medsrv_creds.h 3915 2008-05-08 12:11:30Z martin $ + */ + +/** + * @defgroup medsrv_creds_i medsrv_creds + * @{ @ingroup medsrv + */ + +#ifndef MEDSRV_CREDS_H_ +#define MEDSRV_CREDS_H_ + +#include <credentials/credential_set.h> +#include <database/database.h> + +typedef struct medsrv_creds_t medsrv_creds_t; + +/** + * Mediation credentials database. + */ +struct medsrv_creds_t { + + /** + * Implements credential_set_t interface + */ + credential_set_t set; + + /** + * Destroy the credentials databse. + */ + void (*destroy)(medsrv_creds_t *this); +}; + +/** + * Create the medsrv credentials db. + * + * @param database underlying database + * @return credential set implementation on that database + */ +medsrv_creds_t *medsrv_creds_create(database_t *database); + +#endif /* MEDSRV_CREDS_H_ @}*/ diff --git a/src/charon/plugins/medsrv/medsrv_plugin.c b/src/charon/plugins/medsrv/medsrv_plugin.c new file mode 100644 index 000000000..f29120337 --- /dev/null +++ b/src/charon/plugins/medsrv/medsrv_plugin.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: medsrv_plugin.c 3915 2008-05-08 12:11:30Z martin $ + */ + +#include "medsrv_plugin.h" + +#include "medsrv_creds.h" +#include "medsrv_config.h" + +#include <daemon.h> + +typedef struct private_medsrv_plugin_t private_medsrv_plugin_t; + +/** + * private data of medsrv plugin + */ +struct private_medsrv_plugin_t { + + /** + * implements plugin interface + */ + medsrv_plugin_t public; + + /** + * database connection instance + */ + database_t *db; + + /** + * medsrv credential set instance + */ + medsrv_creds_t *creds; + + /** + * medsrv config database + */ + medsrv_config_t *config; +}; + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_medsrv_plugin_t *this) +{ + charon->backends->remove_backend(charon->backends, &this->config->backend); + charon->credentials->remove_set(charon->credentials, &this->creds->set); + this->config->destroy(this->config); + this->creds->destroy(this->creds); + this->db->destroy(this->db); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + char *uri; + private_medsrv_plugin_t *this = malloc_thing(private_medsrv_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + uri = lib->settings->get_str(lib->settings, + "medmanager.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "mediation database URI not defined, skipped"); + free(this); + return NULL; + } + + this->db = lib->db->create(lib->db, uri); + if (this->db == NULL) + { + DBG1(DBG_CFG, "opening mediation server database failed"); + free(this); + return NULL; + } + + this->creds = medsrv_creds_create(this->db); + this->config = medsrv_config_create(this->db); + + charon->credentials->add_set(charon->credentials, &this->creds->set); + charon->backends->add_backend(charon->backends, &this->config->backend); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/medsrv/medsrv_plugin.h b/src/charon/plugins/medsrv/medsrv_plugin.h new file mode 100644 index 000000000..8aa56d607 --- /dev/null +++ b/src/charon/plugins/medsrv/medsrv_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: medsrv_plugin.h 3915 2008-05-08 12:11:30Z martin $ + */ + +/** + * @defgroup medsrv medsrv + * @ingroup cplugins + * + * @defgroup medsrv_plugin medsrv_plugin + * @{ @ingroup medsrv + */ + +#ifndef MEDSRV_PLUGIN_H_ +#define MEDSRV_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct medsrv_plugin_t medsrv_plugin_t; + +/** + * Mediation server database plugin. + */ +struct medsrv_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a medsrv_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* MEDSRV_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/smp/Makefile.am b/src/charon/plugins/smp/Makefile.am new file mode 100644 index 000000000..1679f1c68 --- /dev/null +++ b/src/charon/plugins/smp/Makefile.am @@ -0,0 +1,10 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${xml_CFLAGS} + +AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\" + +plugin_LTLIBRARIES = libstrongswan-smp.la +libstrongswan_smp_la_SOURCES = smp.h smp.c +libstrongswan_smp_la_LDFLAGS = -module +libstrongswan_smp_la_LIBADD = ${xml_LIBS} + diff --git a/src/charon/plugins/smp/Makefile.in b/src/charon/plugins/smp/Makefile.in new file mode 100644 index 000000000..198526abb --- /dev/null +++ b/src/charon/plugins/smp/Makefile.in @@ -0,0 +1,495 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/smp +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libstrongswan_smp_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_smp_la_OBJECTS = smp.lo +libstrongswan_smp_la_OBJECTS = $(am_libstrongswan_smp_la_OBJECTS) +libstrongswan_smp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_smp_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_smp_la_SOURCES) +DIST_SOURCES = $(libstrongswan_smp_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${xml_CFLAGS} +AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\" +plugin_LTLIBRARIES = libstrongswan-smp.la +libstrongswan_smp_la_SOURCES = smp.h smp.c +libstrongswan_smp_la_LDFLAGS = -module +libstrongswan_smp_la_LIBADD = ${xml_LIBS} +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/smp/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/smp/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-smp.la: $(libstrongswan_smp_la_OBJECTS) $(libstrongswan_smp_la_DEPENDENCIES) + $(libstrongswan_smp_la_LINK) -rpath $(plugindir) $(libstrongswan_smp_la_OBJECTS) $(libstrongswan_smp_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smp.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/control/interfaces/xml_interface.c b/src/charon/plugins/smp/smp.c index aa2a554a0..3b7fa0070 100644 --- a/src/charon/control/interfaces/xml_interface.c +++ b/src/charon/plugins/smp/smp.c @@ -1,10 +1,3 @@ -/** - * @file xml_interface.c - * - * @brief Implementation of xml_interface_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,11 +11,13 @@ * 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. + * + * $Id: smp.c 4073 2008-06-20 07:14:35Z martin $ */ #include <stdlib.h> -#include "xml_interface.h" +#include "smp.h" #include <sys/types.h> #include <sys/stat.h> @@ -40,17 +35,17 @@ #include <processing/jobs/callback_job.h> -typedef struct private_xml_interface_t private_xml_interface_t; +typedef struct private_smp_t private_smp_t; /** - * Private data of an xml_interface_t object. + * Private data of an smp_t object. */ -struct private_xml_interface_t { +struct private_smp_t { /** - * Public part of xml_t object. + * Public part of smp_t object. */ - xml_interface_t public; + smp_t public; /** * XML unix socket fd @@ -151,12 +146,12 @@ static void write_address(xmlTextWriterPtr writer, char *element, host_t *host) static void write_networks(xmlTextWriterPtr writer, char *element, linked_list_t *list) { - iterator_t *iterator; + enumerator_t *enumerator; traffic_selector_t *ts; xmlTextWriterStartElement(writer, element); - iterator = list->create_iterator(list, TRUE); - while (iterator->iterate(iterator, (void**)&ts)) + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, (void**)&ts)) { xmlTextWriterStartElement(writer, "network"); xmlTextWriterWriteAttribute(writer, "type", @@ -164,7 +159,7 @@ static void write_networks(xmlTextWriterPtr writer, char *element, xmlTextWriterWriteFormatString(writer, "%R", ts); xmlTextWriterEndElement(writer); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); xmlTextWriterEndElement(writer); } @@ -215,14 +210,14 @@ static void write_child(xmlTextWriterPtr writer, child_sa_t *child) */ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer) { - iterator_t *iterator; + enumerator_t *enumerator; ike_sa_t *ike_sa; /* <ikesalist> */ xmlTextWriterStartElement(writer, "ikesalist"); - iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager); - while (iterator->iterate(iterator, (void**)&ike_sa)) + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) { ike_sa_id_t *id; host_t *local, *remote; @@ -288,7 +283,7 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer /* </ikesa> */ xmlTextWriterEndElement(writer); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* </ikesalist> */ xmlTextWriterEndElement(writer); @@ -299,16 +294,16 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer */ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr writer) { - iterator_t *iterator; + enumerator_t *enumerator; peer_cfg_t *peer_cfg; /* <configlist> */ xmlTextWriterStartElement(writer, "configlist"); - iterator = charon->backends->create_iterator(charon->backends); - while (iterator->iterate(iterator, (void**)&peer_cfg)) + enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends); + while (enumerator->enumerate(enumerator, (void**)&peer_cfg)) { - iterator_t *children; + enumerator_t *children; child_cfg_t *child_cfg; ike_cfg_t *ike_cfg; linked_list_t *list; @@ -327,15 +322,15 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write /* <ikeconfig> */ ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); xmlTextWriterStartElement(writer, "ikeconfig"); - write_address(writer, "local", ike_cfg->get_my_host(ike_cfg)); - write_address(writer, "remote", ike_cfg->get_other_host(ike_cfg)); + xmlTextWriterWriteElement(writer, "local", ike_cfg->get_my_addr(ike_cfg)); + xmlTextWriterWriteElement(writer, "remote", ike_cfg->get_other_addr(ike_cfg)); xmlTextWriterEndElement(writer); /* </ikeconfig> */ /* <childconfiglist> */ xmlTextWriterStartElement(writer, "childconfiglist"); - children = peer_cfg->create_child_cfg_iterator(peer_cfg); - while (children->iterate(children, (void**)&child_cfg)) + children = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (children->enumerate(children, &child_cfg)) { /* <childconfig> */ xmlTextWriterStartElement(writer, "childconfig"); @@ -356,7 +351,7 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write /* </peerconfig> */ xmlTextWriterEndElement(writer); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* </configlist> */ xmlTextWriterEndElement(writer); } @@ -395,26 +390,50 @@ static void request_control_terminate(xmlTextReaderPtr reader, status_t status; str = xmlTextReaderConstValue(reader); - if (str == NULL || !(id = atoi(str))) + if (str == NULL) { DBG1(DBG_CFG, "error parsing XML id string"); return; } + id = atoi(str); + if (!id) + { + enumerator_t *enumerator; + ike_sa_t *ike_sa; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (streq(str, ike_sa->get_name(ike_sa))) + { + ike = TRUE; + id = ike_sa->get_unique_id(ike_sa); + break; + } + } + enumerator->destroy(enumerator); + } + if (!id) + { + DBG1(DBG_CFG, "error parsing XML id string"); + return; + } + DBG1(DBG_CFG, "terminating %s_SA %d", ike ? "IKE" : "CHILD", id); /* <log> */ xmlTextWriterStartElement(writer, "log"); if (ike) { - status = charon->interfaces->terminate_ike( - charon->interfaces, id, - (interface_manager_cb_t)xml_callback, writer); + status = charon->controller->terminate_ike( + charon->controller, id, + (controller_cb_t)xml_callback, writer); } else { - status = charon->interfaces->terminate_child( - charon->interfaces, id, - (interface_manager_cb_t)xml_callback, writer); + status = charon->controller->terminate_child( + charon->controller, id, + (controller_cb_t)xml_callback, writer); } /* </log> */ xmlTextWriterEndElement(writer); @@ -435,7 +454,7 @@ static void request_control_initiate(xmlTextReaderPtr reader, status_t status = FAILED; peer_cfg_t *peer; child_cfg_t *child = NULL; - iterator_t *iterator; + enumerator_t *enumerator; str = xmlTextReaderConstValue(reader); if (str == NULL) @@ -450,10 +469,10 @@ static void request_control_initiate(xmlTextReaderPtr reader, peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str); if (peer) { - iterator = peer->create_child_cfg_iterator(peer); + enumerator = peer->create_child_cfg_enumerator(peer); if (ike) { - if (!iterator->iterate(iterator, (void**)&child)) + if (!enumerator->enumerate(enumerator, &child)) { child = NULL; } @@ -461,7 +480,7 @@ static void request_control_initiate(xmlTextReaderPtr reader, } else { - while (iterator->iterate(iterator, (void**)&child)) + while (enumerator->enumerate(enumerator, &child)) { if (streq(child->get_name(child), str)) { @@ -471,11 +490,11 @@ static void request_control_initiate(xmlTextReaderPtr reader, child = NULL; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); if (child) { - status = charon->interfaces->initiate(charon->interfaces, - peer, child, (interface_manager_cb_t)xml_callback, + status = charon->controller->initiate(charon->controller, + peer, child, (controller_cb_t)xml_callback, writer); } else @@ -667,7 +686,7 @@ static job_requeue_t process(int *fdp) /** * accept from XML socket and create jobs to process connections */ -static job_requeue_t dispatch(private_xml_interface_t *this) +static job_requeue_t dispatch(private_smp_t *this) { struct sockaddr_un strokeaddr; int oldstate, fd, *fdp, strokeaddrlen = sizeof(strokeaddr); @@ -696,7 +715,7 @@ static job_requeue_t dispatch(private_xml_interface_t *this) /** * Implementation of itnerface_t.destroy. */ -static void destroy(private_xml_interface_t *this) +static void destroy(private_smp_t *this) { this->job->cancel(this->job); close(this->socket); @@ -706,13 +725,13 @@ static void destroy(private_xml_interface_t *this) /* * Described in header file */ -interface_t *interface_create() +plugin_t *plugin_create() { struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"}; - private_xml_interface_t *this = malloc_thing(private_xml_interface_t); + private_smp_t *this = malloc_thing(private_smp_t); mode_t old; - this->public.interface.destroy = (void (*)(interface_t*))destroy; + this->public.plugin.destroy = (void (*)(plugin_t*))destroy; /* set up unix socket */ this->socket = socket(AF_UNIX, SOCK_STREAM, 0); @@ -733,7 +752,7 @@ interface_t *interface_create() return NULL; } umask(old); - if (chown(unix_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0) + if (chown(unix_addr.sun_path, charon->uid, charon->gid) != 0) { DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno)); } @@ -749,6 +768,6 @@ interface_t *interface_create() this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL); charon->processor->queue_job(charon->processor, (job_t*)this->job); - return &this->public.interface; + return &this->public.plugin; } diff --git a/src/charon/control/interfaces/xml_interface.h b/src/charon/plugins/smp/smp.h index 6d88c3842..e65d5ea2c 100644 --- a/src/charon/control/interfaces/xml_interface.h +++ b/src/charon/plugins/smp/smp.h @@ -1,12 +1,5 @@ -/** - * @file xml_interface.h - * - * @brief Interface of xml_interface_t. - * - */ - /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2007-2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,40 +11,42 @@ * 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. + * + * $Id: smp.h 3689 2008-03-28 12:44:01Z martin $ */ -#ifndef XML_INTERFACE_H_ -#define XML_INTERFACE_H_ +/** + * @defgroup smp smp + * @ingroup cplugins + * + * @defgroup smp_i smp + * @{ @ingroup smp + */ + +#ifndef SMP_H_ +#define SMP_H_ -typedef struct xml_interface_t xml_interface_t; +#include <plugins/plugin.h> -#include <control/interfaces/interface.h> +typedef struct smp_t smp_t; /** - * @brief The XML interface uses a socket to communicate using XML. - * - * @b Constructors: - * - xml_interface_create() - * - * @ingroup interfaces + * SMP configuration and control interface. + * + * The SMP interface uses a socket and a to communicate. The syntax is strict + * XML, defined in the schema.xml specification. */ -struct xml_interface_t { - +struct smp_t { + /** - * implements interface_t. + * implements the plugin interface. */ - interface_t interface; + plugin_t plugin; }; - /** - * @brief Create the XML interface. - * - * @return stroke_t object - * - * @ingroup interfaces + * Create a smp plugin instance. */ -interface_t *interface_create(void); - -#endif /* XML_INTERFACE_H_ */ +plugin_t *plugin_create(); +#endif /* XML_H_ @}*/ diff --git a/src/charon/plugins/sql/Makefile.am b/src/charon/plugins/sql/Makefile.am new file mode 100644 index 000000000..ea39ce0d5 --- /dev/null +++ b/src/charon/plugins/sql/Makefile.am @@ -0,0 +1,17 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic \ + -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ + -DIPSEC_PLUGINDIR=\"${plugindir}\" \ + -DPLUGINS=\""${libstrongswan_plugins}\"" + +plugin_LTLIBRARIES = libstrongswan-sql.la +libstrongswan_sql_la_SOURCES = sql_plugin.h sql_plugin.c \ + sql_config.h sql_config.c sql_cred.h sql_cred.c \ + sql_attribute.h sql_attribute.c sql_logger.h sql_logger.c +libstrongswan_sql_la_LDFLAGS = -module + +ipsec_PROGRAMS = pool +pool_SOURCES = pool.c +pool_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la diff --git a/src/charon/plugins/sql/Makefile.in b/src/charon/plugins/sql/Makefile.in new file mode 100644 index 000000000..babc11ecb --- /dev/null +++ b/src/charon/plugins/sql/Makefile.in @@ -0,0 +1,549 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +ipsec_PROGRAMS = pool$(EXEEXT) +subdir = src/charon/plugins/sql +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_sql_la_LIBADD = +am_libstrongswan_sql_la_OBJECTS = sql_plugin.lo sql_config.lo \ + sql_cred.lo sql_attribute.lo sql_logger.lo +libstrongswan_sql_la_OBJECTS = $(am_libstrongswan_sql_la_OBJECTS) +libstrongswan_sql_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_sql_la_LDFLAGS) $(LDFLAGS) -o $@ +ipsecPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(ipsec_PROGRAMS) +am_pool_OBJECTS = pool.$(OBJEXT) +pool_OBJECTS = $(am_pool_OBJECTS) +pool_DEPENDENCIES = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_sql_la_SOURCES) $(pool_SOURCES) +DIST_SOURCES = $(libstrongswan_sql_la_SOURCES) $(pool_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic \ + -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ + -DIPSEC_PLUGINDIR=\"${plugindir}\" \ + -DPLUGINS=\""${libstrongswan_plugins}\"" + +plugin_LTLIBRARIES = libstrongswan-sql.la +libstrongswan_sql_la_SOURCES = sql_plugin.h sql_plugin.c \ + sql_config.h sql_config.c sql_cred.h sql_cred.c \ + sql_attribute.h sql_attribute.c sql_logger.h sql_logger.c + +libstrongswan_sql_la_LDFLAGS = -module +pool_SOURCES = pool.c +pool_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/sql/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/sql/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-sql.la: $(libstrongswan_sql_la_OBJECTS) $(libstrongswan_sql_la_DEPENDENCIES) + $(libstrongswan_sql_la_LINK) -rpath $(plugindir) $(libstrongswan_sql_la_OBJECTS) $(libstrongswan_sql_la_LIBADD) $(LIBS) +install-ipsecPROGRAMS: $(ipsec_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" + @list='$(ipsec_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(ipsecPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(ipsecdir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(ipsecPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(ipsecdir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-ipsecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(ipsec_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(ipsecdir)/$$f'"; \ + rm -f "$(DESTDIR)$(ipsecdir)/$$f"; \ + done + +clean-ipsecPROGRAMS: + @list='$(ipsec_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +pool$(EXEEXT): $(pool_OBJECTS) $(pool_DEPENDENCIES) + @rm -f pool$(EXEEXT) + $(LINK) $(pool_OBJECTS) $(pool_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_attribute.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_cred.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_logger.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-ipsecPROGRAMS install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-ipsecPROGRAMS uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-ipsecPROGRAMS clean-libtool clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-ipsecPROGRAMS install-man install-pdf \ + install-pdf-am install-pluginLTLIBRARIES install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-ipsecPROGRAMS \ + uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/plugins/sql/pool.c b/src/charon/plugins/sql/pool.c new file mode 100644 index 000000000..86ceddeee --- /dev/null +++ b/src/charon/plugins/sql/pool.c @@ -0,0 +1,726 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#define _GNU_SOURCE +#include <getopt.h> +#include <unistd.h> +#include <stdio.h> +#include <time.h> + +#include <debug.h> +#include <library.h> +#include <utils/host.h> + +/** + * global database handle + */ +database_t *db; + +/** + * --start/--end addresses of various subcommands + */ +host_t *start = NULL, *end = NULL; + +/** + * create a host from a blob + */ +static host_t *host_create_from_blob(chunk_t blob) +{ + return host_create_from_chunk(blob.len == 4 ? AF_INET : AF_INET6, blob, 0); +} + +/** + * calculate the size of a pool using start and end address chunk + */ +static u_int get_pool_size(chunk_t start, chunk_t end) +{ + u_int *start_ptr, *end_ptr; + + if (start.len < sizeof(u_int) || end.len < sizeof(u_int)) + { + return 0; + } + start_ptr = (u_int*)(start.ptr + start.len - sizeof(u_int)); + end_ptr = (u_int*)(end.ptr + end.len - sizeof(u_int)); + return ntohl(*end_ptr) - ntohl(*start_ptr) + 1; +} + +/** + * print usage info + */ +static void usage(void) +{ + printf("\ +Usage:\n\ + ipsec pool --status|--add|--del|--resize|--purge [options]\n\ + \n\ + ipsec pool --status\n\ + Show a list of installed pools with statistics.\n\ + \n\ + ipsec pool --add <name> --start <start> --end <end> [--timeout <timeout>]\n\ + Add a new pool to the database.\n\ + name: Name of the pool, as used in ipsec.conf rightsourceip=%%name\n\ + start: Start address of the pool\n\ + end: End address of the pool\n\ + timeout: Lease time in hours, 0 for static leases\n\ + \n\ + ipsec pool --del <name>\n\ + Delete a pool from the database.\n\ + name: Name of the pool to delete\n\ + \n\ + ipsec pool --resize <name> --end <end>\n\ + Grow or shrink an existing pool.\n\ + name: Name of the pool to resize\n\ + end: New end address for the pool\n\ + \n\ + ipsec pool --leases <name> [--filter <filter>] [--utc]\n\ + Show lease information using filters:\n\ + name: Name of the pool to show leases from\n\ + filter: Filter string containing comma separated key=value filters,\n\ + e.g. id=alice@strongswan.org,addr=1.1.1.1\n\ + pool: name of the pool\n\ + id: assigned identity of the lease\n\ + addr: lease IP address\n\ + tstamp: UNIX timestamp when lease was valid, as integer\n\ + status: status of the lease: online|valid|expired\n\ + utc: Show times in UTC instead of local time\n\ + \n\ + ipsec pool --purge <name>\n\ + Delete expired leases of a pool:\n\ + name: Name of the pool to purge\n\ + \n"); + exit(0); +} + +/** + * ipsec pool --status - show pool overview + */ +static void status(void) +{ + enumerator_t *pool, *lease; + bool found = FALSE; + + pool = db->query(db, "SELECT id, name, start, end, timeout FROM pools", + DB_INT, DB_TEXT, DB_BLOB, DB_BLOB, DB_UINT); + if (pool) + { + char *name; + chunk_t start_chunk, end_chunk; + host_t *start, *end; + u_int id, timeout, online = 0, used = 0, size = 0; + + while (pool->enumerate(pool, &id, &name, + &start_chunk, &end_chunk, &timeout)) + { + if (!found) + { + printf("%8s %15s %15s %8s %6s %11s %11s\n", + "name", "start", "end", "timeout", "size", "online", "leases"); + found = TRUE; + } + + start = host_create_from_blob(start_chunk); + end = host_create_from_blob(end_chunk); + size = get_pool_size(start_chunk, end_chunk); + printf("%8s %15H %15H ", name, start, end); + if (timeout) + { + printf("%7dh ", timeout/3600); + } + else + { + printf("%8s ", "static"); + } + printf("%6d ", size); + /* get number of online hosts */ + lease = db->query(db, "SELECT COUNT(*) FROM leases " + "WHERE pool = ? AND released IS NULL", + DB_UINT, id, DB_INT); + if (lease) + { + lease->enumerate(lease, &online); + lease->destroy(lease); + } + printf("%5d (%2d%%) ", online, online*100/size); + /* get number of online or valid lieases */ + lease = db->query(db, "SELECT COUNT(*) FROM leases JOIN pools " + "ON leases.pool = pools.id " + "WHERE pools.id = ? " + "AND (released IS NULL OR released > ? - timeout) ", + DB_UINT, id, DB_UINT, time(NULL), DB_UINT); + if (lease) + { + lease->enumerate(lease, &used); + lease->destroy(lease); + } + printf("%5d (%2d%%) ", used, used*100/size); + + printf("\n"); + DESTROY_IF(start); + DESTROY_IF(end); + } + pool->destroy(pool); + } + if (!found) + { + printf("no pools found.\n"); + } + exit(0); +} + +/** + * ipsec pool --add - add a new pool + */ +static void add(char *name, host_t *start, host_t *end, int timeout) +{ + chunk_t start_addr, end_addr; + + start_addr = start->get_address(start); + end_addr = end->get_address(end); + + if (start_addr.len != end_addr.len || + memcmp(start_addr.ptr, end_addr.ptr, start_addr.len) > 0) + { + fprintf(stderr, "invalid start/end pair specified.\n"); + exit(-1); + } + if (db->execute(db, NULL, + "INSERT INTO pools (name, start, end, next, timeout) " + "VALUES (?, ?, ?, ?, ?)", + DB_TEXT, name, DB_BLOB, start_addr, + DB_BLOB, end_addr, DB_BLOB, start_addr, + DB_INT, timeout*3600) != 1) + { + fprintf(stderr, "creating pool failed.\n"); + exit(-1); + } + exit(0); +} + +/** + * ipsec pool --del - delete a pool + */ +static void del(char *name) +{ + enumerator_t *query; + u_int id; + bool found = FALSE; + + query = db->query(db, "SELECT id FROM pools WHERE name = ?", + DB_TEXT, name, DB_UINT); + if (!query) + { + fprintf(stderr, "deleting pool failed.\n"); + exit(-1); + } + while (query->enumerate(query, &id)) + { + found = TRUE; + if (db->execute(db, NULL, + "DELETE FROM pools WHERE id = ?", DB_UINT, id) != 1 || + db->execute(db, NULL, + "DELETE FROM leases WHERE pool = ?", DB_UINT, id) < 0) + { + fprintf(stderr, "deleting pool failed.\n"); + query->destroy(query); + exit(-1); + } + } + query->destroy(query); + if (!found) + { + fprintf(stderr, "pool '%s' not found.\n", name); + exit(-1); + } + exit(0); +} + +/** + * ipsec pool --resize - resize a pool + */ +static void resize(char *name, host_t *end) +{ + enumerator_t *query; + chunk_t next_addr, end_addr; + + end_addr = end->get_address(end); + + query = db->query(db, "SELECT next FROM pools WHERE name = ?", + DB_TEXT, name, DB_BLOB); + if (!query || !query->enumerate(query, &next_addr)) + { + DESTROY_IF(query); + fprintf(stderr, "resizing pool failed.\n"); + exit(-1); + } + if (next_addr.len != end_addr.len || + memcmp(end_addr.ptr, next_addr.ptr, end_addr.len) < 0) + { + end = host_create_from_blob(next_addr); + fprintf(stderr, "pool addresses up to %H in use, resizing failed.\n", end); + end->destroy(end); + query->destroy(query); + exit(-1); + } + query->destroy(query); + + if (db->execute(db, NULL, + "UPDATE pools SET end = ? WHERE name = ?", + DB_BLOB, end_addr, DB_TEXT, name) <= 0) + { + fprintf(stderr, "pool '%s' not found.\n", name); + exit(-1); + } + exit(0); +} + +/** + * create the lease query using the filter string + */ +static enumerator_t *create_lease_query(char *filter) +{ + enumerator_t *query; + identification_t *id = NULL; + host_t *addr = NULL; + u_int tstamp = 0; + bool online = FALSE, valid = FALSE, expired = FALSE; + char *value, *pos, *pool = NULL; + enum { + FIL_POOL = 0, + FIL_ID, + FIL_ADDR, + FIL_TSTAMP, + FIL_STATE, + }; + char *const token[] = { + [FIL_POOL] = "pool", + [FIL_ID] = "id", + [FIL_ADDR] = "addr", + [FIL_TSTAMP] = "tstamp", + [FIL_STATE] = "status", + NULL + }; + + /* if the filter string contains a distinguished name as a ID, we replace + * ", " by "/ " in order to not confuse the getsubopt parser */ + pos = filter; + while ((pos = strchr(pos, ','))) + { + if (pos[1] == ' ') + { + pos[0] = '/'; + } + pos++; + } + + while (filter && *filter != '\0') + { + switch (getsubopt(&filter, token, &value)) + { + case FIL_POOL: + if (value) + { + pool = value; + } + break; + case FIL_ID: + if (value) + { + id = identification_create_from_string(value); + } + if (!id) + { + fprintf(stderr, "invalid 'id' in filter string.\n"); + exit(-1); + } + break; + case FIL_ADDR: + if (value) + { + addr = host_create_from_string(value, 0); + } + if (!addr) + { + fprintf(stderr, "invalid 'addr' in filter string.\n"); + exit(-1); + } + break; + case FIL_TSTAMP: + if (value) + { + tstamp = atoi(value); + } + if (tstamp == 0) + { + online = TRUE; + } + break; + case FIL_STATE: + if (value) + { + if (streq(value, "online")) + { + online = TRUE; + } + else if (streq(value, "valid")) + { + valid = TRUE; + } + else if (streq(value, "expired")) + { + expired = TRUE; + } + else + { + fprintf(stderr, "invalid 'state' in filter string.\n"); + exit(-1); + } + } + break; + default: + fprintf(stderr, "invalid filter string.\n"); + exit(-1); + break; + } + } + query = db->query(db, + "SELECT name, address, identities.type, " + "identities.data, acquired, released, timeout " + "FROM leases JOIN pools ON leases.pool = pools.id " + "JOIN identities ON leases.identity = identities.id " + "WHERE (? OR name = ?) " + "AND (? OR (identities.type = ? AND identities.data = ?)) " + "AND (? OR address = ?) " + "AND (? OR (? >= acquired AND (? <= released OR released IS NULL))) " + "AND (? OR released IS NULL) " + "AND (? OR released > ? - timeout) " + "AND (? OR released < ? - timeout)", + DB_INT, pool == NULL, DB_TEXT, pool, + DB_INT, id == NULL, + DB_INT, id ? id->get_type(id) : 0, + DB_BLOB, id ? id->get_encoding(id) : chunk_empty, + DB_INT, addr == NULL, + DB_BLOB, addr ? addr->get_address(addr) : chunk_empty, + DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp, + DB_INT, !online, + DB_INT, !valid, DB_INT, time(NULL), + DB_INT, !expired, DB_INT, time(NULL), + DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT); + /* id and addr leak but we can't destroy them until query is destroyed. */ + return query; +} + +/** + * ipsec pool --leases - show lease information of a pool + */ +static void leases(char *filter, bool utc) +{ + enumerator_t *query; + chunk_t address_chunk, identity_chunk; + int identity_type; + char *name; + u_int acquired, released, timeout; + host_t *address; + identification_t *identity; + bool found = FALSE; + + query = create_lease_query(filter); + if (!query) + { + fprintf(stderr, "querying leases failed.\n"); + exit(-1); + } + while (query->enumerate(query, &name, &address_chunk, &identity_type, + &identity_chunk, &acquired, &released, &timeout)) + { + if (!found) + { + int len = utc ? 25 : 21; + + found = TRUE; + printf("%-8s %-15s %-7s %-*s %-*s %s\n", + "name", "address", "status", len, "start", len, "end", "identity"); + } + address = host_create_from_blob(address_chunk); + identity = identification_create_from_encoding(identity_type, identity_chunk); + + printf("%-8s %-15H ", name, address); + if (released == 0) + { + printf("%-7s ", "online"); + } + else if (timeout == 0) + { + printf("%-7s ", "static"); + } + else if (released >= time(NULL) - timeout) + { + printf("%-7s ", "valid"); + } + else + { + printf("%-7s ", "expired"); + } + + printf(" %#T ", &acquired, utc); + if (released) + { + printf("%#T ", &released, utc); + } + else + { + printf(" "); + if (utc) + { + printf(" "); + } + } + printf("%D\n", identity); + DESTROY_IF(address); + identity->destroy(identity); + } + query->destroy(query); + if (!found) + { + fprintf(stderr, "no matching leases found.\n"); + exit(-1); + } + exit(0); +} + +/** + * ipsec pool --purge - delete expired leases + */ +static void purge(char *name) +{ + enumerator_t *query; + u_int id, timeout, purged = 0; + + query = db->query(db, "SELECT id, timeout FROM pools WHERE name = ?", + DB_TEXT, name, DB_UINT, DB_UINT); + if (!query) + { + fprintf(stderr, "purging pool failed.\n"); + exit(-1); + } + /* we have to keep one lease if we purge. It wouldn't be reallocateable + * as we move on the "next" address for speedy allocation */ + if (query->enumerate(query, &id, &timeout)) + { + timeout = time(NULL) - timeout; + purged = db->execute(db, NULL, + "DELETE FROM leases WHERE pool = ? " + "AND released IS NOT NULL AND released < ? AND id NOT IN (" + " SELECT id FROM leases " + " WHERE released IS NOT NULL and released < ? " + " GROUP BY address)", + DB_UINT, id, DB_UINT, timeout, DB_UINT, timeout); + } + query->destroy(query); + fprintf(stderr, "purged %d leases in pool '%s'.\n", purged, name); + exit(0); +} + +/** + * atexit handler to close db on shutdown + */ +static void cleanup(void) +{ + db->destroy(db); + DESTROY_IF(start); + DESTROY_IF(end); +} + +/** + * Logging hook for library logs, using stderr output + */ +static void dbg_stderr(int level, char *fmt, ...) +{ + va_list args; + + if (level <= 1) + { + va_start(args, fmt); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } +} + +int main(int argc, char *argv[]) +{ + char *uri, *name = "", *filter = ""; + int timeout = 0; + bool utc = FALSE; + enum { + OP_USAGE, + OP_STATUS, + OP_ADD, + OP_DEL, + OP_RESIZE, + OP_LEASES, + OP_PURGE, + } operation = OP_USAGE; + + dbg = dbg_stderr; + library_init(STRONGSWAN_CONF); + atexit(library_deinit); + lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR, + lib->settings->get_str(lib->settings, "pool.load", PLUGINS)); + + uri = lib->settings->get_str(lib->settings, "charon.plugins.sql.database", NULL); + if (!uri) + { + fprintf(stderr, "database URI charon.plugins.sql.database not set.\n"); + exit(-1); + } + db = lib->db->create(lib->db, uri); + if (!db) + { + fprintf(stderr, "opening database failed.\n"); + exit(-1); + } + atexit(cleanup); + + while (TRUE) + { + int c; + + struct option long_opts[] = { + { "help", no_argument, NULL, 'h' }, + + { "utc", no_argument, NULL, 'u' }, + { "status", no_argument, NULL, 'w' }, + { "add", required_argument, NULL, 'a' }, + { "del", required_argument, NULL, 'd' }, + { "resize", required_argument, NULL, 'r' }, + { "leases", no_argument, NULL, 'l' }, + { "purge", required_argument, NULL, 'p' }, + + { "start", required_argument, NULL, 's' }, + { "end", required_argument, NULL, 'e' }, + { "timeout", required_argument, NULL, 't' }, + { "filter", required_argument, NULL, 'f' }, + { 0,0,0,0 } + }; + + c = getopt_long(argc, argv, "", long_opts, NULL); + switch (c) + { + case EOF: + break; + case 'h': + break; + case 'w': + operation = OP_STATUS; + break; + case 'u': + utc = TRUE; + continue; + case 'a': + operation = OP_ADD; + name = optarg; + continue; + case 'd': + operation = OP_DEL; + name = optarg; + continue; + case 'r': + operation = OP_RESIZE; + name = optarg; + continue; + case 'l': + operation = OP_LEASES; + continue; + case 'p': + operation = OP_PURGE; + name = optarg; + continue; + case 's': + start = host_create_from_string(optarg, 0); + if (start == NULL) + { + fprintf(stderr, "invalid start address: '%s'.\n", optarg); + operation = OP_USAGE; + break; + } + continue; + case 'e': + end = host_create_from_string(optarg, 0); + if (end == NULL) + { + fprintf(stderr, "invalid end address: '%s'.\n", optarg); + operation = OP_USAGE; + break; + } + continue; + case 't': + timeout = atoi(optarg); + if (timeout == 0 && strcmp(optarg, "0") != 0) + { + fprintf(stderr, "invalid timeout '%s'.\n", optarg); + operation = OP_USAGE; + break; + } + continue; + case 'f': + filter = optarg; + continue; + default: + operation = OP_USAGE; + break; + } + break; + } + + switch (operation) + { + case OP_USAGE: + usage(); + break; + case OP_STATUS: + status(); + break; + case OP_ADD: + if (start == NULL || end == NULL) + { + fprintf(stderr, "missing arguments.\n"); + usage(); + } + add(name, start, end, timeout); + break; + case OP_DEL: + del(name); + break; + case OP_RESIZE: + if (end == NULL) + { + fprintf(stderr, "missing arguments.\n"); + usage(); + } + resize(name, end); + break; + case OP_LEASES: + leases(filter, utc); + break; + case OP_PURGE: + purge(name); + break; + } + exit(0); +} + diff --git a/src/charon/plugins/sql/sql_attribute.c b/src/charon/plugins/sql/sql_attribute.c new file mode 100644 index 000000000..45c0750c7 --- /dev/null +++ b/src/charon/plugins/sql/sql_attribute.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "sql_attribute.h" + +#include <daemon.h> +#include <utils/mutex.h> + +typedef struct private_sql_attribute_t private_sql_attribute_t; + +/** + * private data of sql_attribute + */ +struct private_sql_attribute_t { + + /** + * public functions + */ + sql_attribute_t public; + + /** + * database connection + */ + database_t *db; + + /** + * mutex to simulate transactions + */ + mutex_t *mutex; +}; + +/** + * convert a address blob to an ip of the correct family + */ +static host_t *ip_from_chunk(chunk_t address) +{ + switch (address.len) + { + case 4: + return host_create_from_chunk(AF_INET, address, 0); + case 16: + return host_create_from_chunk(AF_INET6, address, 0); + default: + return NULL; + } +} + +/** + * increment a chunk, as it would reprensent a network order integer + */ +static void increment_chunk(chunk_t chunk) +{ + int i; + + for (i = chunk.len - 1; i >= 0; i++) + { + if (++chunk.ptr[i] != 0) + { + return; + } + } +} + +/** + * Lookup if we have an existing lease + */ +static host_t* get_lease(private_sql_attribute_t *this, + char *name, identification_t *id) +{ + enumerator_t *e; + chunk_t address; + host_t *ip = NULL; + int lease; + + /* transaction simulation, see create_lease() */ + this->mutex->lock(this->mutex); + + /* select a lease for "id" which still valid */ + e = this->db->query(this->db, + "SELECT l.id, l.address FROM leases AS l " + "JOIN pools AS p ON l.pool = p.id " + "JOIN identities AS i ON l.identity = i.id " + "WHERE p.name = ? AND i.type = ? AND i.data = ? " + "AND (l.released IS NULL OR p.timeout = 0 " + " OR (l.released >= (? - p.timeout))) " + "ORDER BY l.acquired LIMIT 1", DB_TEXT, name, + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), + DB_UINT, time(NULL), + DB_UINT, DB_BLOB); + if (e) + { + if (e->enumerate(e, &lease, &address)) + { + /* found one, set the lease to active */ + if (this->db->execute(this->db, NULL, + "UPDATE leases SET released = NULL WHERE id = ?", + DB_UINT, lease) > 0) + { + ip = ip_from_chunk(address); + DBG1(DBG_CFG, "reassigning address from valid lease " + "from pool '%s'", name); + } + } + e->destroy(e); + } + this->mutex->unlock(this->mutex); + return ip; +} + +/** + * Create a new lease entry for client + */ +static host_t* create_lease(private_sql_attribute_t *this, + char *name, identification_t *id) +{ + enumerator_t *e; + chunk_t address; + host_t *ip = NULL; + u_int pool, identity = 0, released, timeout; + bool new = FALSE; + + /* we currently do not use database transactions. While this would be + * the clean way, there is no real advantage, but some disadvantages: + * - we would require InnoDB for mysql, as MyISAM does not support trans. + * - the mysql plugin uses connection pooling, and we would need a + * mechanism to lock transactions to a single connection. + */ + this->mutex->lock(this->mutex); + + /* find an address which has outdated leases only. The HAVING clause filters + * out leases which are active (released = NULL) or not expired */ + e = this->db->query(this->db, + "SELECT pool, address, released, timeout FROM leases " + "JOIN pools ON leases.pool = pools.id " + "WHERE name = ? and timeout > 0 " + "GROUP BY address HAVING COUNT(released) = COUNT(*) " + "AND MAX(released) < (? - timeout) LIMIT 1", + DB_TEXT, name, DB_UINT, time(NULL), + DB_UINT, DB_BLOB, DB_UINT, DB_UINT); + + if (!e || !e->enumerate(e, &pool, &address, &released, &timeout)) + { + DESTROY_IF(e); + /* no outdated lease found, acquire new address */ + e = this->db->query(this->db, + "SELECT id, next FROM pools WHERE name = ? AND next <= end", + DB_TEXT, name, + DB_UINT, DB_BLOB); + if (!e || !e->enumerate(e, &pool, &address)) + { + /* pool seems full */ + DESTROY_IF(e); + this->mutex->unlock(this->mutex); + return NULL; + } + new = TRUE; + } + address = chunk_clonea(address); + e->destroy(e); + + /* look for peer identity in the identities table */ + e = this->db->query(this->db, + "SELECT id FROM identities WHERE type = ? AND data = ?", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), + DB_UINT); + if (!e || !e->enumerate(e, &identity)) + { + DESTROY_IF(e); + /* not found, insert new one */ + this->db->execute(this->db, &identity, + "INSERT INTO identities (type, data) VALUES (?, ?)", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)); + } + else + { + e->destroy(e); + } + /* if we have an identity, insert a new lease */ + if (identity) + { + if (this->db->execute(this->db, NULL, + "INSERT INTO leases (pool, address, identity, acquired) " + "VALUES (?, ?, ?, ?)", + DB_UINT, pool, DB_BLOB, address, DB_UINT, identity, + DB_UINT, time(NULL)) > 0) + { + ip = ip_from_chunk(address); + if (new) + { /* update next address, as we have consumed one */ + increment_chunk(address); + this->db->execute(this->db, NULL, + "UPDATE pools SET next = ? WHERE id = ?", + DB_BLOB, address, DB_UINT, pool); + DBG1(DBG_CFG, "assigning lease with new address " + "from pool '%s'", name); + } + else + { + DBG1(DBG_CFG, "reassigning address from expired lease " + "from pool '%s'", name); + } + } + } + this->mutex->unlock(this->mutex); + return ip; +} + +/** + * Implementation of attribute_provider_t.acquire_address + */ +static host_t* acquire_address(private_sql_attribute_t *this, + char *name, identification_t *id, + auth_info_t *auth, host_t *requested) +{ + host_t *ip; + + ip = get_lease(this, name, id); + if (!ip) + { + ip = create_lease(this, name, id); + } + return ip; +} + +/** + * Implementation of attribute_provider_t.release_address + */ +static bool release_address(private_sql_attribute_t *this, + char *name, host_t *address) +{ + if (this->db->execute(this->db, NULL, + "UPDATE leases SET released = ? WHERE " + "pool IN (SELECT id FROM pools WHERE name = ?) AND " + "address = ? AND released IS NULL", + DB_UINT, time(NULL), + DB_TEXT, name, DB_BLOB, address->get_address(address)) > 0) + { + return TRUE; + } + return FALSE; +} + +/** + * Implementation of sql_attribute_t.destroy + */ +static void destroy(private_sql_attribute_t *this) +{ + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +sql_attribute_t *sql_attribute_create(database_t *db) +{ + private_sql_attribute_t *this = malloc_thing(private_sql_attribute_t); + + this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,auth_info_t *, host_t *))acquire_address; + this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *))release_address; + this->public.destroy = (void(*)(sql_attribute_t*))destroy; + + this->db = db; + this->mutex = mutex_create(MUTEX_DEFAULT); + + /* close any "online" leases in the case we crashed */ + this->db->execute(this->db, NULL, + "UPDATE leases SET released = ? WHERE released IS NULL", + DB_UINT, time(NULL)); + + return &this->public; +} + diff --git a/src/charon/plugins/sql/sql_attribute.h b/src/charon/plugins/sql/sql_attribute.h new file mode 100644 index 000000000..211204ced --- /dev/null +++ b/src/charon/plugins/sql/sql_attribute.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup sql_attribute sql_attribute + * @{ @ingroup sql + */ + +#ifndef SQL_ATTRIBUTE_H_ +#define SQL_ATTRIBUTE_H_ + +#include <config/attributes/attribute_provider.h> + +typedef struct sql_attribute_t sql_attribute_t; + +/** + * SQL database based IKEv2 cfg attribute provider. + */ +struct sql_attribute_t { + + /** + * Implements attribute provider interface + */ + attribute_provider_t provider; + + /** + * Destroy a sql_attribute instance. + */ + void (*destroy)(sql_attribute_t *this); +}; + +/** + * Create a sql_attribute instance. + */ +sql_attribute_t *sql_attribute_create(database_t *db); + +#endif /* SQL_ATTRIBUTE_H_ @}*/ diff --git a/src/charon/plugins/sql/sql_config.c b/src/charon/plugins/sql/sql_config.c new file mode 100644 index 000000000..3785839cf --- /dev/null +++ b/src/charon/plugins/sql/sql_config.c @@ -0,0 +1,517 @@ +/* + * Copyright (C) 2006-2008 Martin Willi + * 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. + * + * $Id: sql_config.c 4044 2008-06-06 15:05:54Z martin $ + */ + +#include <string.h> + +#include "sql_config.h" + +#include <daemon.h> + +typedef struct private_sql_config_t private_sql_config_t; + +/** + * Private data of an sql_config_t object + */ +struct private_sql_config_t { + + /** + * Public part + */ + sql_config_t public; + + /** + * database connection + */ + database_t *db; +}; + +/** + * forward declaration + */ +static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e, + identification_t *me, identification_t *other); + +/** + * build a traffic selector from a SQL query + */ +static traffic_selector_t *build_traffic_selector(private_sql_config_t *this, + enumerator_t *e, bool *local) +{ + int type, protocol, start_port, end_port; + chunk_t start_addr, end_addr; + traffic_selector_t *ts; + enum { + TS_LOCAL = 0, + TS_REMOTE = 1, + TS_LOCAL_DYNAMIC = 2, + TS_REMOTE_DYNAMIC = 3, + } kind; + + while (e->enumerate(e, &kind, &type, &protocol, + &start_addr, &end_addr, &start_port, &end_port)) + { + *local = FALSE; + switch (kind) + { + case TS_LOCAL: + *local = TRUE; + /* FALL */ + case TS_REMOTE: + ts = traffic_selector_create_from_bytes(protocol, type, + start_addr, start_port, end_addr, end_port); + break; + case TS_LOCAL_DYNAMIC: + *local = TRUE; + /* FALL */ + case TS_REMOTE_DYNAMIC: + ts = traffic_selector_create_dynamic(protocol, + start_port, end_port); + break; + default: + continue; + } + if (ts) + { + return ts; + } + } + return NULL; +} + +/** + * Add traffic selectors to a child config + */ +static void add_traffic_selectors(private_sql_config_t *this, + child_cfg_t *child, int id) +{ + enumerator_t *e; + traffic_selector_t *ts; + bool local; + + e = this->db->query(this->db, + "SELECT kind, type, protocol, " + "start_addr, end_addr, start_port, end_port " + "FROM traffic_selectors JOIN child_config_traffic_selector " + "ON id = traffic_selector WHERE child_cfg = ?", + DB_INT, id, + DB_INT, DB_INT, DB_INT, + DB_BLOB, DB_BLOB, DB_INT, DB_INT); + if (e) + { + while ((ts = build_traffic_selector(this, e, &local))) + { + child->add_traffic_selector(child, local, ts); + } + e->destroy(e); + } +} + +/** + * build a Child configuration from a SQL query + */ +static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e) +{ + int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close, ipcomp; + char *name, *updown; + child_cfg_t *child_cfg; + + if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, + &updown, &hostaccess, &mode, &dpd, &close, &ipcomp)) + { + child_cfg = child_cfg_create(name, lifetime, rekeytime, jitter, + updown, hostaccess, mode, dpd, close, ipcomp); + /* TODO: read proposal from db */ + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + add_traffic_selectors(this, child_cfg, id); + return child_cfg; + } + return NULL; +} + +/** + * Add child configs to peer config + */ +static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id) +{ + enumerator_t *e; + child_cfg_t *child_cfg; + + e = this->db->query(this->db, + "SELECT id, name, lifetime, rekeytime, jitter, " + "updown, hostaccess, mode, dpd_action, close_action, ipcomp " + "FROM child_configs JOIN peer_config_child_config ON id = child_cfg " + "WHERE peer_cfg = ?", + DB_INT, id, + DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, + DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT); + if (e) + { + while ((child_cfg = build_child_cfg(this, e))) + { + peer->add_child_cfg(peer, child_cfg); + } + e->destroy(e); + } +} + +/** + * build a ike configuration from a SQL query + */ +static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, + host_t *my_host, host_t *other_host) +{ + int certreq, force_encap; + char *local, *remote; + + while (e->enumerate(e, &certreq, &force_encap, &local, &remote)) + { + ike_cfg_t *ike_cfg; + + ike_cfg = ike_cfg_create(certreq, force_encap, local, remote); + /* TODO: read proposal from db */ + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + return ike_cfg; + } + return NULL; +} + +/** + * Query a IKE config by its id + */ +static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id) +{ + enumerator_t *e; + ike_cfg_t *ike_cfg = NULL; + + e = this->db->query(this->db, + "SELECT certreq, force_encap, local, remote " + "FROM ike_configs WHERE id = ?", + DB_INT, id, + DB_INT, DB_INT, DB_TEXT, DB_TEXT); + if (e) + { + ike_cfg = build_ike_cfg(this, e, NULL, NULL); + e->destroy(e); + } + return ike_cfg; +} + +/** + * Query a peer config by its id + */ +static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id) +{ + enumerator_t *e; + peer_cfg_t *peer_cfg = NULL; + + e = this->db->query(this->db, + "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, " + "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, " + "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, " + "dpd_delay, virtual, pool, " + "mediation, mediated_by, COALESCE(p.type, 0), p.data " + "FROM peer_configs AS c " + "JOIN identities AS l ON local_id = l.id " + "JOIN identities AS r ON remote_id = r.id " + "LEFT JOIN identities AS p ON peer_id = p.id " + "WHERE id = ?", + DB_INT, id, + DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_TEXT, DB_TEXT, + DB_INT, DB_INT, DB_INT, DB_BLOB); + if (e) + { + peer_cfg = build_peer_cfg(this, e, NULL, NULL); + e->destroy(e); + } + return peer_cfg; +} + +/** + * build a peer configuration from a SQL query + */ +static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e, + identification_t *me, identification_t *other) +{ + int id, ike_cfg, l_type, r_type, + cert_policy, uniqueid, auth_method, eap_type, eap_vendor, keyingtries, + rekeytime, reauthtime, jitter, overtime, mobike, dpd_delay, + mediation, mediated_by, p_type; + chunk_t l_data, r_data, p_data; + char *name, *virtual, *pool; + + while (e->enumerate(e, + &id, &name, &ike_cfg, &l_type, &l_data, &r_type, &r_data, + &cert_policy, &uniqueid, &auth_method, &eap_type, &eap_vendor, + &keyingtries, &rekeytime, &reauthtime, &jitter, &overtime, &mobike, + &dpd_delay, &virtual, &pool, + &mediation, &mediated_by, &p_type, &p_data)) + { + identification_t *local_id, *remote_id, *peer_id = NULL; + peer_cfg_t *peer_cfg, *mediated_cfg; + ike_cfg_t *ike; + host_t *vip = NULL; + + local_id = identification_create_from_encoding(l_type, l_data); + remote_id = identification_create_from_encoding(r_type, r_data); + if ((me && !me->matches(me, local_id)) || + (other && !other->matches(other, remote_id))) + { + local_id->destroy(local_id); + remote_id->destroy(remote_id); + continue; + } + ike = get_ike_cfg_by_id(this, ike_cfg); + mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL; + if (p_type) + { + peer_id = identification_create_from_encoding(p_type, p_data); + } + if (virtual) + { + vip = host_create_from_string(virtual, 0); + } + if (ike) + { + peer_cfg = peer_cfg_create( + name, 2, ike, local_id, remote_id, cert_policy, uniqueid, + auth_method, eap_type, eap_vendor, keyingtries, + rekeytime, reauthtime, jitter, overtime, mobike, + dpd_delay, vip, pool, + mediation, mediated_cfg, peer_id); + add_child_cfgs(this, peer_cfg, id); + return peer_cfg; + } + DESTROY_IF(ike); + DESTROY_IF(mediated_cfg); + DESTROY_IF(peer_id); + DESTROY_IF(local_id); + DESTROY_IF(remote_id); + } + return NULL; +} + +/** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name) +{ + enumerator_t *e; + peer_cfg_t *peer_cfg = NULL; + + e = this->db->query(this->db, + "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, " + "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, " + "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, " + "dpd_delay, virtual, pool, " + "mediation, mediated_by, COALESCE(p.type, 0), p.data " + "FROM peer_configs AS c " + "JOIN identities AS l ON local_id = l.id " + "JOIN identities AS r ON remote_id = r.id " + "LEFT JOIN identities AS p ON peer_id = p.id " + "WHERE ike_version = ? AND name = ?", + DB_INT, 2, DB_TEXT, name, + DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_TEXT, DB_TEXT, + DB_INT, DB_INT, DB_INT, DB_BLOB); + if (e) + { + peer_cfg = build_peer_cfg(this, e, NULL, NULL); + e->destroy(e); + } + return peer_cfg; +} + +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** reference to context */ + private_sql_config_t *this; + /** filtering own host */ + host_t *me; + /** filtering remote host */ + host_t *other; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated peer config */ + ike_cfg_t *current; +} ike_enumerator_t; + +/** + * Implementation of ike_enumerator_t.public.enumerate + */ +static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg) +{ + DESTROY_IF(this->current); + this->current = build_ike_cfg(this->this, this->inner, this->me, this->other); + if (this->current) + { + *cfg = this->current; + return TRUE; + } + return FALSE; +} + +/** + * Implementation of ike_enumerator_t.public.destroy + */ +static void ike_enumerator_destroy(ike_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of backend_t.create_ike_cfg_enumerator. + */ +static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this, + host_t *me, host_t *other) +{ + ike_enumerator_t *e = malloc_thing(ike_enumerator_t); + + e->this = this; + e->me = me; + e->other = other; + e->current = NULL; + e->public.enumerate = (void*)ike_enumerator_enumerate; + e->public.destroy = (void*)ike_enumerator_destroy; + + e->inner = this->db->query(this->db, + "SELECT certreq, force_encap, local, remote " + "FROM ike_configs", + DB_INT, DB_INT, DB_TEXT, DB_TEXT); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + + +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** reference to context */ + private_sql_config_t *this; + /** filtering own identity */ + identification_t *me; + /** filtering remote identity */ + identification_t *other; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated peer config */ + peer_cfg_t *current; +} peer_enumerator_t; + +/** + * Implementation of peer_enumerator_t.public.enumerate + */ +static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) +{ + DESTROY_IF(this->current); + this->current = build_peer_cfg(this->this, this->inner, this->me, this->other); + if (this->current) + { + *cfg = this->current; + return TRUE; + } + return FALSE; +} + +/** + * Implementation of peer_enumerator_t.public.destroy + */ +static void peer_enumerator_destroy(peer_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of backend_t.create_peer_cfg_enumerator. + */ +static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this, + identification_t *me, + identification_t *other) +{ + peer_enumerator_t *e = malloc_thing(peer_enumerator_t); + + e->this = this; + e->me = me; + e->other = other; + e->current = NULL; + e->public.enumerate = (void*)peer_enumerator_enumerate; + e->public.destroy = (void*)peer_enumerator_destroy; + + /* TODO: only get configs whose IDs match exactly or contain wildcards */ + e->inner = this->db->query(this->db, + "SELECT c.id, name, ike_cfg, l.type, l.data, r.type, r.data, " + "cert_policy, uniqueid, auth_method, eap_type, eap_vendor, " + "keyingtries, rekeytime, reauthtime, jitter, overtime, mobike, " + "dpd_delay, virtual, pool, " + "mediation, mediated_by, COALESCE(p.type, 0), p.data " + "FROM peer_configs AS c " + "JOIN identities AS l ON local_id = l.id " + "JOIN identities AS r ON remote_id = r.id " + "LEFT JOIN identities AS p ON peer_id = p.id " + "WHERE ike_version = ?", + DB_INT, 2, + DB_INT, DB_TEXT, DB_INT, DB_INT, DB_BLOB, DB_INT, DB_BLOB, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, + DB_INT, DB_TEXT, DB_TEXT, + DB_INT, DB_INT, DB_INT, DB_BLOB); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * Implementation of sql_config_t.destroy. + */ +static void destroy(private_sql_config_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +sql_config_t *sql_config_create(database_t *db) +{ + private_sql_config_t *this = malloc_thing(private_sql_config_t); + + this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; + this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; + this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; + this->public.destroy = (void(*)(sql_config_t*))destroy; + + this->db = db; + + return &this->public; +} + diff --git a/src/charon/plugins/sql/sql_config.h b/src/charon/plugins/sql/sql_config.h new file mode 100644 index 000000000..d34705c71 --- /dev/null +++ b/src/charon/plugins/sql/sql_config.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: sql_config.h 3594 2008-03-13 14:53:57Z martin $ + */ + +/** + * @defgroup sql_config_i sql_config + * @{ @ingroup sql + */ + +#ifndef SQL_CONFIG_H_ +#define SQL_CONFIG_H_ + +#include <config/backend.h> +#include <database/database.h> + +typedef struct sql_config_t sql_config_t; + +/** + * SQL database configuration backend. + */ +struct sql_config_t { + + /** + * Implements backend_t interface + */ + backend_t backend; + + /** + * Destry the backend. + */ + void (*destroy)(sql_config_t *this); +}; + +/** + * Create a sql_config backend instance. + * + * @param db underlying database + * @return backend instance + */ +sql_config_t *sql_config_create(database_t *db); + +#endif /* SQL_CONFIG_H_ @}*/ diff --git a/src/charon/plugins/sql/sql_cred.c b/src/charon/plugins/sql/sql_cred.c new file mode 100644 index 000000000..9d91973c2 --- /dev/null +++ b/src/charon/plugins/sql/sql_cred.c @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: sql_cred.c 3589 2008-03-13 14:14:44Z martin $ + */ + +#include <string.h> + +#include "sql_cred.h" + +#include <daemon.h> + +typedef struct private_sql_cred_t private_sql_cred_t; + +/** + * Private data of an sql_cred_t object + */ +struct private_sql_cred_t { + + /** + * Public part + */ + sql_cred_t public; + + /** + * database connection + */ + database_t *db; +}; + +/** + * enumerator over private keys + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated private key */ + private_key_t *current; +} private_enumerator_t; + +/** + * Implementation of private_enumerator_t.public.enumerate + */ +static bool private_enumerator_enumerate(private_enumerator_t *this, + private_key_t **key) +{ + chunk_t blob; + int type; + + DESTROY_IF(this->current); + while (this->inner->enumerate(this->inner, &type, &blob)) + { + this->current = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, + BUILD_BLOB_ASN1_DER, chunk_clone(blob), + BUILD_END); + if (this->current) + { + *key = this->current; + return TRUE; + } + } + this->current = NULL; + return FALSE; +} + +/** + * Implementation of private_enumerator_t.public.destroy + */ +static void private_enumerator_destroy(private_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of credential_set_t.create_private_enumerator. + */ +static enumerator_t* create_private_enumerator(private_sql_cred_t *this, + key_type_t type, + identification_t *id) +{ + private_enumerator_t *e; + + e = malloc_thing(private_enumerator_t); + e->current = NULL; + e->public.enumerate = (void*)private_enumerator_enumerate; + e->public.destroy = (void*)private_enumerator_destroy; + if (id && id->get_type(id) != ID_ANY) + { + e->inner = this->db->query(this->db, + "SELECT p.type, p.data FROM private_keys AS p " + "JOIN private_key_identity AS pi ON p.id = pi.private_key " + "JOIN identities AS i ON pi.identity = i.id " + "WHERE i.type = ? AND i.data = ? AND (? OR p.type = ?)", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), + DB_INT, type == KEY_ANY, DB_INT, type, + DB_INT, DB_BLOB); + } + else + { + e->inner = this->db->query(this->db, + "SELECT type, data FROM private_keys WHERE (? OR type = ?)", + DB_INT, type == KEY_ANY, DB_INT, type, + DB_INT, DB_BLOB); + } + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * enumerator over certificates + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated cert */ + certificate_t *current; +} cert_enumerator_t; + +/** + * Implementation of cert_enumerator_t.public.enumerate + */ +static bool cert_enumerator_enumerate(cert_enumerator_t *this, + certificate_t **cert) +{ + chunk_t blob; + int type; + + DESTROY_IF(this->current); + while (this->inner->enumerate(this->inner, &type, &blob)) + { + this->current = lib->creds->create(lib->creds, CRED_CERTIFICATE, type, + BUILD_BLOB_ASN1_DER, chunk_clone(blob), + BUILD_END); + if (this->current) + { + *cert = this->current; + return TRUE; + } + } + this->current = NULL; + return FALSE; +} + +/** + * Implementation of cert_enumerator_t.public.destroy + */ +static void cert_enumerator_destroy(cert_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of credential_set_t.create_cert_enumerator. + */ +static enumerator_t* create_cert_enumerator(private_sql_cred_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + cert_enumerator_t *e; + + e = malloc_thing(cert_enumerator_t); + e->current = NULL; + e->public.enumerate = (void*)cert_enumerator_enumerate; + e->public.destroy = (void*)cert_enumerator_destroy; + if (id && id->get_type(id) != ID_ANY) + { + e->inner = this->db->query(this->db, + "SELECT c.type, c.data FROM certificates AS c " + "JOIN certificate_identity AS ci ON c.id = ci.certificate " + "JOIN identities AS i ON ci.identity = i.id " + "WHERE i.type = ? AND i.data = ? AND " + "(? OR c.type = ?) AND (? OR c.keytype = ?)", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), + DB_INT, cert == CERT_ANY, DB_INT, cert, + DB_INT, key == KEY_ANY, DB_INT, key, + DB_INT, DB_BLOB); + } + else + { + e->inner = this->db->query(this->db, + "SELECT type, data FROM certificates WHERE " + "(? OR type = ?) AND (? OR keytype = ?)", + DB_INT, cert == CERT_ANY, DB_INT, cert, + DB_INT, key == KEY_ANY, DB_INT, key, + DB_INT, DB_BLOB); + } + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * enumerator over shared keys + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** own identity */ + identification_t *me; + /** remote identity */ + identification_t *other; + /** currently enumerated private key */ + shared_key_t *current; +} shared_enumerator_t; + +/** + * Implementation of shared_enumerator_t.public.enumerate + */ +static bool shared_enumerator_enumerate(shared_enumerator_t *this, + shared_key_t **shared, + id_match_t *me, id_match_t *other) +{ + chunk_t blob; + int type; + + DESTROY_IF(this->current); + while (this->inner->enumerate(this->inner, &type, &blob)) + { + this->current = shared_key_create(type, chunk_clone(blob)); + if (this->current) + { + *shared = this->current; + if (me) + { + *me = this->me ? ID_MATCH_PERFECT : ID_MATCH_ANY; + } + if (other) + { + *other = this->other ? ID_MATCH_PERFECT : ID_MATCH_ANY; + } + return TRUE; + } + } + this->current = NULL; + return FALSE; +} + +/** + * Implementation of shared_enumerator_t.public.destroy + */ +static void shared_enumerator_destroy(shared_enumerator_t *this) +{ + DESTROY_IF(this->current); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of credential_set_t.create_shared_enumerator. + */ +static enumerator_t* create_shared_enumerator(private_sql_cred_t *this, + shared_key_type_t type, + identification_t *me, identification_t *other) +{ + shared_enumerator_t *e; + + e = malloc_thing(shared_enumerator_t); + e->me = me; + e->other = other; + e->current = NULL; + e->public.enumerate = (void*)shared_enumerator_enumerate; + e->public.destroy = (void*)shared_enumerator_destroy; + if (!me && !other) + { + e->inner = this->db->query(this->db, + "SELECT type, data FROM shared_secrets WHERE (? OR type = ?)", + DB_INT, type == SHARED_ANY, DB_INT, type, + DB_INT, DB_BLOB); + } + else if (me && other) + { + e->inner = this->db->query(this->db, + "SELECT s.type, s.data FROM shared_secrets AS s " + "JOIN shared_secret_identity AS sm ON s.id = sm.shared_secret " + "JOIN identities AS m ON sm.identity = m.id " + "JOIN shared_secret_identity AS so ON s.id = so.shared_secret " + "JOIN identities AS o ON so.identity = o.id " + "WHERE m.type = ? AND m.data = ? AND o.type = ? AND o.data = ? " + "AND (? OR s.type = ?)", + DB_INT, me->get_type(me), DB_BLOB, me->get_encoding(me), + DB_INT, other->get_type(other), DB_BLOB, other->get_encoding(other), + DB_INT, type == SHARED_ANY, DB_INT, type, + DB_INT, DB_BLOB); + } + else + { + identification_t *id = me ? me : other; + + e->inner = this->db->query(this->db, + "SELECT s.type, s.data FROM shared_secrets AS s " + "JOIN shared_secret_identity AS si ON s.id = si.shared_secret " + "JOIN identities AS i ON si.identity = i.id " + "WHERE i.type = ? AND i.data = ? AND (? OR s.type = ?)", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), + DB_INT, type == SHARED_ANY, DB_INT, type, + DB_INT, DB_BLOB); + } + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * Implementation of credential_set_t.cache_cert. + */ +static void cache_cert(private_sql_cred_t *this, certificate_t *cert) +{ + /* TODO: implement CRL caching to database */ +} + +/** + * Implementation of sql_cred_t.destroy. + */ +static void destroy(private_sql_cred_t *this) +{ + free(this); +} +/** + * Described in header. + */ +sql_cred_t *sql_cred_create(database_t *db) +{ + private_sql_cred_t *this = malloc_thing(private_sql_cred_t); + + this->public.set.create_private_enumerator = (void*)create_private_enumerator; + this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; + this->public.set.create_shared_enumerator = (void*)create_shared_enumerator; + this->public.set.create_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)cache_cert; + this->public.destroy = (void(*)(sql_cred_t*))destroy; + + this->db = db; + + return &this->public; +} + diff --git a/src/charon/plugins/sql/sql_cred.h b/src/charon/plugins/sql/sql_cred.h new file mode 100644 index 000000000..e251abe00 --- /dev/null +++ b/src/charon/plugins/sql/sql_cred.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: sql_cred.h 3594 2008-03-13 14:53:57Z martin $ + */ + +/** + * @defgroup sql_cred_i sql_cred + * @{ @ingroup sql + */ + +#ifndef SQL_CRED_H_ +#define SQL_CRED_H_ + +#include <credentials/credential_set.h> +#include <database/database.h> + +typedef struct sql_cred_t sql_cred_t; + +/** + * SQL database credential set. + */ +struct sql_cred_t { + + /** + * Implements credential_set_t interface + */ + credential_set_t set; + + /** + * Destry the backend. + */ + void (*destroy)(sql_cred_t *this); +}; + +/** + * Create a sql_cred backend instance. + * + * @param db underlying database + * @return credential set + */ +sql_cred_t *sql_cred_create(database_t *db); + +#endif /* SQL_CRED_H_ @}*/ diff --git a/src/charon/plugins/sql/sql_logger.c b/src/charon/plugins/sql/sql_logger.c new file mode 100644 index 000000000..2fb5844b3 --- /dev/null +++ b/src/charon/plugins/sql/sql_logger.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: sql_logger.c 3589 2008-03-13 14:14:44Z martin $ + */ + +#include <string.h> + +#include "sql_logger.h" + +#include <daemon.h> + +typedef struct private_sql_logger_t private_sql_logger_t; + +/** + * Private data of an sql_logger_t object + */ +struct private_sql_logger_t { + + /** + * Public part + */ + sql_logger_t public; + + /** + * database connection + */ + database_t *db; + + /** + * logging level + */ + int level; + + /** + * avoid recursive logging + */ + bool recursive; +}; + + +/** + * Implementation of bus_listener_t.signal. + */ +static bool signal_(private_sql_logger_t *this, signal_t signal, level_t level, + int thread, ike_sa_t* ike_sa, char *format, va_list args) +{ + if (this->recursive) + { + return TRUE; + } + this->recursive = TRUE; + + if (ike_sa && level <= this->level) + { + char buffer[8192]; + chunk_t local_spi, remote_spi; + host_t *local_host, *remote_host; + identification_t *local_id, *remote_id; + u_int64_t ispi, rspi; + ike_sa_id_t *id; + + id = ike_sa->get_id(ike_sa); + ispi = id->get_initiator_spi(id); + rspi = id->get_responder_spi(id); + if (id->is_initiator(id)) + { + local_spi.ptr = (char*)&ispi; + remote_spi.ptr = (char*)&rspi; + } + else + { + local_spi.ptr = (char*)&rspi; + remote_spi.ptr = (char*)&ispi; + } + local_spi.len = remote_spi.len = sizeof(ispi); + local_id = ike_sa->get_my_id(ike_sa); + remote_id = ike_sa->get_other_id(ike_sa); + local_host = ike_sa->get_my_host(ike_sa); + remote_host = ike_sa->get_other_host(ike_sa); + + vsnprintf(buffer, sizeof(buffer), format, args); + + this->db->execute(this->db, NULL, "REPLACE INTO ike_sas (" + "local_spi, remote_spi, id, initiator, " + "local_id_type, local_id_data, " + "remote_id_type, remote_id_data, " + "host_family, local_host_data, remote_host_data) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + DB_BLOB, local_spi, DB_BLOB, remote_spi, + DB_INT, ike_sa->get_unique_id(ike_sa), + DB_INT, id->is_initiator(id), + DB_INT, local_id->get_type(local_id), + DB_BLOB, local_id->get_encoding(local_id), + DB_INT, remote_id->get_type(remote_id), + DB_BLOB, remote_id->get_encoding(remote_id), + DB_INT, local_host->get_family(local_host), + DB_BLOB, local_host->get_address(local_host), + DB_BLOB, remote_host->get_address(remote_host)); + this->db->execute(this->db, NULL, "INSERT INTO logs (" + "local_spi, signal, level, msg) VALUES (?, ?, ?, ?)", + DB_BLOB, local_spi, DB_INT, signal, DB_INT, level, + DB_TEXT, buffer); + } + this->recursive = FALSE; + /* always stay registered */ + return TRUE; +} + +/** + * Implementation of sql_logger_t.destroy. + */ +static void destroy(private_sql_logger_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +sql_logger_t *sql_logger_create(database_t *db) +{ + private_sql_logger_t *this = malloc_thing(private_sql_logger_t); + + this->public.listener.signal = (bool(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,char*,va_list))signal_; + this->public.destroy = (void(*)(sql_logger_t*))destroy; + + this->db = db; + this->recursive = FALSE; + + this->level = lib->settings->get_int(lib->settings, + "charon.plugins.sql.loglevel", -1); + + return &this->public; +} + diff --git a/src/charon/plugins/sql/sql_logger.h b/src/charon/plugins/sql/sql_logger.h new file mode 100644 index 000000000..30507bcaf --- /dev/null +++ b/src/charon/plugins/sql/sql_logger.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: sql_logger.h 3594 2008-03-13 14:53:57Z martin $ + */ + +/** + * @defgroup sql_logger_i sql_logger + * @{ @ingroup sql + */ + +#ifndef SQL_LOGGER_H_ +#define SQL_LOGGER_H_ + +#include <bus/bus.h> +#include <database/database.h> + +typedef struct sql_logger_t sql_logger_t; + +/** + * SQL database logger. + */ +struct sql_logger_t { + + /** + * Implements bus_listener_t interface + */ + bus_listener_t listener; + + /** + * Destry the backend. + */ + void (*destroy)(sql_logger_t *this); +}; + +/** + * Create a sql_logger instance. + * + * @param db underlying database + * @return logger instance + */ +sql_logger_t *sql_logger_create(database_t *db); + +#endif /* SQL_LOGGER_H_ @}*/ diff --git a/src/charon/plugins/sql/sql_plugin.c b/src/charon/plugins/sql/sql_plugin.c new file mode 100644 index 000000000..8c4f20f74 --- /dev/null +++ b/src/charon/plugins/sql/sql_plugin.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: sql_plugin.c 3826 2008-04-17 15:08:48Z martin $ + */ + +#include "sql_plugin.h" + +#include <daemon.h> +#include "sql_config.h" +#include "sql_cred.h" +#include "sql_attribute.h" +#include "sql_logger.h" + +typedef struct private_sql_plugin_t private_sql_plugin_t; + +/** + * private data of sql plugin + */ +struct private_sql_plugin_t { + + /** + * implements plugin interface + */ + sql_plugin_t public; + + /** + * database connection instance + */ + database_t *db; + + /** + * configuration backend + */ + sql_config_t *config; + + /** + * credential set + */ + sql_cred_t *cred; + + /** + * CFG attributes + */ + sql_attribute_t *attribute; + + /** + * bus listener/logger + */ + sql_logger_t *logger; +}; + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_sql_plugin_t *this) +{ + charon->backends->remove_backend(charon->backends, &this->config->backend); + charon->credentials->remove_set(charon->credentials, &this->cred->set); + charon->bus->remove_listener(charon->bus, &this->logger->listener); + this->config->destroy(this->config); + this->cred->destroy(this->cred); + this->attribute->destroy(this->attribute); + this->logger->destroy(this->logger); + this->db->destroy(this->db); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + char *uri; + private_sql_plugin_t *this; + + uri = lib->settings->get_str(lib->settings, "charon.plugins.sql.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "sql plugin: database URI not set"); + return NULL; + } + + this = malloc_thing(private_sql_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + this->db = lib->db->create(lib->db, uri); + if (!this->db) + { + DBG1(DBG_CFG, "sql plugin failed to connect to database"); + free(this); + return NULL; + } + this->config = sql_config_create(this->db); + this->cred = sql_cred_create(this->db); + this->attribute = sql_attribute_create(this->db); + this->logger = sql_logger_create(this->db); + + charon->backends->add_backend(charon->backends, &this->config->backend); + charon->credentials->add_set(charon->credentials, &this->cred->set); + charon->attributes->add_provider(charon->attributes, &this->attribute->provider); + charon->bus->add_listener(charon->bus, &this->logger->listener); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/sql/sql_plugin.h b/src/charon/plugins/sql/sql_plugin.h new file mode 100644 index 000000000..8a7ba3e85 --- /dev/null +++ b/src/charon/plugins/sql/sql_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: sql_plugin.h 3577 2008-03-12 14:38:35Z martin $ + */ + +/** + * @defgroup sql sql + * @ingroup cplugins + * + * @defgroup sql_plugin sql_plugin + * @{ @ingroup sql + */ + +#ifndef SQL_PLUGIN_H_ +#define SQL_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct sql_plugin_t sql_plugin_t; + +/** + * SQL database configuration plugin + */ +struct sql_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a sql_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* SQL_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/stroke/Makefile.am b/src/charon/plugins/stroke/Makefile.am new file mode 100644 index 000000000..7a341102b --- /dev/null +++ b/src/charon/plugins/stroke/Makefile.am @@ -0,0 +1,19 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke + +AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" + +plugin_LTLIBRARIES = libstrongswan-stroke.la + +libstrongswan_stroke_la_SOURCES = stroke_plugin.h stroke_plugin.c \ + stroke_socket.h stroke_socket.c \ + stroke_config.h stroke_config.c \ + stroke_control.h stroke_control.c \ + stroke_cred.h stroke_cred.c \ + stroke_ca.h stroke_ca.c \ + stroke_attribute.h stroke_attribute.c \ + stroke_list.h stroke_list.c \ + stroke_shared_key.h stroke_shared_key.c + +libstrongswan_stroke_la_LDFLAGS = -module + diff --git a/src/charon/plugins/stroke/Makefile.in b/src/charon/plugins/stroke/Makefile.in new file mode 100644 index 000000000..a528377d0 --- /dev/null +++ b/src/charon/plugins/stroke/Makefile.in @@ -0,0 +1,513 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/stroke +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_stroke_la_LIBADD = +am_libstrongswan_stroke_la_OBJECTS = stroke_plugin.lo stroke_socket.lo \ + stroke_config.lo stroke_control.lo stroke_cred.lo stroke_ca.lo \ + stroke_attribute.lo stroke_list.lo stroke_shared_key.lo +libstrongswan_stroke_la_OBJECTS = \ + $(am_libstrongswan_stroke_la_OBJECTS) +libstrongswan_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_stroke_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_stroke_la_SOURCES) +DIST_SOURCES = $(libstrongswan_stroke_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke +AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" +plugin_LTLIBRARIES = libstrongswan-stroke.la +libstrongswan_stroke_la_SOURCES = stroke_plugin.h stroke_plugin.c \ + stroke_socket.h stroke_socket.c \ + stroke_config.h stroke_config.c \ + stroke_control.h stroke_control.c \ + stroke_cred.h stroke_cred.c \ + stroke_ca.h stroke_ca.c \ + stroke_attribute.h stroke_attribute.c \ + stroke_list.h stroke_list.c \ + stroke_shared_key.h stroke_shared_key.c + +libstrongswan_stroke_la_LDFLAGS = -module +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/stroke/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/stroke/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-stroke.la: $(libstrongswan_stroke_la_OBJECTS) $(libstrongswan_stroke_la_DEPENDENCIES) + $(libstrongswan_stroke_la_LINK) -rpath $(plugindir) $(libstrongswan_stroke_la_OBJECTS) $(libstrongswan_stroke_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_attribute.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_ca.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_control.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_cred.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_list.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_shared_key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_socket.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/plugins/stroke/stroke_attribute.c b/src/charon/plugins/stroke/stroke_attribute.c new file mode 100644 index 000000000..71b56bc8a --- /dev/null +++ b/src/charon/plugins/stroke/stroke_attribute.c @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_attribute.h" + +#include <daemon.h> +#include <utils/linked_list.h> +#include <utils/mutex.h> + +#define POOL_LIMIT 16 + +typedef struct private_stroke_attribute_t private_stroke_attribute_t; + +/** + * private data of stroke_attribute + */ +struct private_stroke_attribute_t { + + /** + * public functions + */ + stroke_attribute_t public; + + /** + * list of pools, contains pool_t + */ + linked_list_t *pools; + + /** + * mutex to lock access to pools + */ + mutex_t *mutex; +}; + +typedef struct { + /** name of the pool */ + char *name; + /** base address of the pool */ + host_t *base; + /** number of entries in the pool */ + int count; + /** array of in-use flags, TODO: use bit fields */ + u_int8_t *in_use; +} pool_t; + +/** + * destroy a pool_t + */ +static void pool_destroy(pool_t *this) +{ + DESTROY_IF(this->base); + free(this->name); + free(this->in_use); + free(this); +} + +/** + * find a pool by name + */ +static pool_t *find_pool(private_stroke_attribute_t *this, char *name) +{ + enumerator_t *enumerator; + pool_t *current, *found = NULL; + + enumerator = this->pools->create_enumerator(this->pools); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(name, current->name)) + { + found = current; + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * convert an pool offset to an address + */ +host_t* offset2host(pool_t *pool, int offset) +{ + chunk_t addr; + host_t *host; + u_int32_t *pos; + + if (offset > pool->count) + { + return NULL; + } + + addr = chunk_clone(pool->base->get_address(pool->base)); + if (pool->base->get_family(pool->base) == AF_INET6) + { + pos = (u_int32_t*)(addr.ptr + 12); + } + else + { + pos = (u_int32_t*)addr.ptr; + } + *pos = htonl(offset + ntohl(*pos)); + host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0); + free(addr.ptr); + return host; +} + +/** + * convert a host to a pool offset + */ +int host2offset(pool_t *pool, host_t *addr) +{ + chunk_t host, base; + u_int32_t hosti, basei; + + if (addr->get_family(addr) != pool->base->get_family(pool->base)) + { + return -1; + } + host = addr->get_address(addr); + base = pool->base->get_address(pool->base); + if (addr->get_family(addr) == AF_INET6) + { + /* only look at last /32 block */ + if (!memeq(host.ptr, base.ptr, 12)) + { + return -1; + } + host = chunk_skip(host, 12); + base = chunk_skip(base, 12); + } + hosti = ntohl(*(u_int32_t*)(host.ptr)); + basei = ntohl(*(u_int32_t*)(base.ptr)); + if (hosti > basei + pool->count) + { + return -1; + } + return hosti - basei; +} + +/** + * Implementation of attribute_provider_t.acquire_address + */ +static host_t* acquire_address(private_stroke_attribute_t *this, + char *name, identification_t *id, + auth_info_t *auth, host_t *requested) +{ + pool_t *pool; + host_t *host = NULL; + int i; + + this->mutex->lock(this->mutex); + pool = find_pool(this, name); + if (pool) + { + if (requested && !requested->is_anyaddr(requested)) + { + if (pool->count == 0) + { /* %config, give any */ + host = requested->clone(requested); + } + else + { + i = host2offset(pool, requested); + if (i >= 0 && !pool->in_use[i]) + { + pool->in_use[i] = TRUE; + host = requested->clone(requested); + } + } + } + if (!host) + { + for (i = 0; i < pool->count; i++) + { + if (!pool->in_use[i]) + { + pool->in_use[i] = TRUE; + host = offset2host(pool, i); + break; + } + } + } + } + this->mutex->unlock(this->mutex); + return host; +} + +/** + * Implementation of attribute_provider_t.release_address + */ +static bool release_address(private_stroke_attribute_t *this, + char *name, host_t *address) +{ + pool_t *pool; + bool found = FALSE; + int i; + + this->mutex->lock(this->mutex); + pool = find_pool(this, name); + if (pool) + { + if (pool->count != 0) + { + i = host2offset(pool, address); + if (i >= 0 && pool->in_use[i]) + { + pool->in_use[i] = FALSE; + found = TRUE; + } + } + } + this->mutex->unlock(this->mutex); + return found; +} + +/** + * Implementation of stroke_attribute_t.add_pool. + */ +static void add_pool(private_stroke_attribute_t *this, stroke_msg_t *msg) +{ + if (msg->add_conn.other.sourceip_size) + { + pool_t *pool; + + if (msg->add_conn.other.sourceip) + { + u_int32_t bits; + int family; + + DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d", + msg->add_conn.name, msg->add_conn.other.sourceip, + msg->add_conn.other.sourceip_size); + + pool = malloc_thing(pool_t); + pool->base = host_create_from_string(msg->add_conn.other.sourceip, 0); + if (!pool->base) + { + free(pool); + DBG1(DBG_CFG, "virtual IP address invalid, discarded"); + return; + } + pool->name = strdup(msg->add_conn.name); + family = pool->base->get_family(pool->base); + bits = (family == AF_INET ? 32 : 128) - msg->add_conn.other.sourceip_size; + if (bits > POOL_LIMIT) + { + bits = POOL_LIMIT; + DBG1(DBG_CFG, "virtual IP pool to large, limiting to %s/%d", + msg->add_conn.other.sourceip, + (family == AF_INET ? 32 : 128) - bits); + } + pool->count = 1 << (bits); + pool->in_use = calloc(pool->count, sizeof(u_int8_t)); + + if (pool->count > 2) + { /* do not use first and last addresses of a block */ + pool->in_use[0] = TRUE; + pool->in_use[pool->count-1] = TRUE; + } + } + else + { /* %config, add an empty pool */ + pool = malloc_thing(pool_t); + pool->name = strdup(msg->add_conn.name); + pool->base = NULL; + pool->count = 0; + pool->in_use = NULL; + } + this->mutex->lock(this->mutex); + this->pools->insert_last(this->pools, pool); + this->mutex->unlock(this->mutex); + } +} + +/** + * Implementation of stroke_attribute_t.del_pool. + */ +static void del_pool(private_stroke_attribute_t *this, stroke_msg_t *msg) +{ + enumerator_t *enumerator; + pool_t *pool; + + this->mutex->lock(this->mutex); + enumerator = this->pools->create_enumerator(this->pools); + while (enumerator->enumerate(enumerator, &pool)) + { + if (streq(msg->del_conn.name, pool->name)) + { + this->pools->remove_at(this->pools, enumerator); + pool_destroy(pool); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of stroke_attribute_t.destroy + */ +static void destroy(private_stroke_attribute_t *this) +{ + this->mutex->destroy(this->mutex); + this->pools->destroy_function(this->pools, (void*)pool_destroy); + free(this); +} + +/* + * see header file + */ +stroke_attribute_t *stroke_attribute_create() +{ + private_stroke_attribute_t *this = malloc_thing(private_stroke_attribute_t); + + this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,auth_info_t *, host_t *))acquire_address; + this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *))release_address; + this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool; + this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool; + this->public.destroy = (void(*)(stroke_attribute_t*))destroy; + + this->pools = linked_list_create(); + this->mutex = mutex_create(MUTEX_DEFAULT); + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_attribute.h b/src/charon/plugins/stroke/stroke_attribute.h new file mode 100644 index 000000000..f871d5a13 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_attribute.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_attribute stroke_attribute + * @{ @ingroup stroke + */ + +#ifndef STROKE_ATTRIBUTE_H_ +#define STROKE_ATTRIBUTE_H_ + +#include <stroke_msg.h> +#include <config/attributes/attribute_provider.h> + +typedef struct stroke_attribute_t stroke_attribute_t; + +/** + * Stroke IKEv2 cfg attribute provider + */ +struct stroke_attribute_t { + + /** + * Implements attribute provider interface + */ + attribute_provider_t provider; + + /** + * Add a virtual IP address. + * + * @param msg stroke message + * @param end end of stroke message that contains virtual IP. + */ + void (*add_pool)(stroke_attribute_t *this, stroke_msg_t *msg); + + /** + * Remove a virtual IP address. + * + * @param msg stroke message + */ + void (*del_pool)(stroke_attribute_t *this, stroke_msg_t *msg); + + /** + * Destroy a stroke_attribute instance. + */ + void (*destroy)(stroke_attribute_t *this); +}; + +/** + * Create a stroke_attribute instance. + */ +stroke_attribute_t *stroke_attribute_create(); + +#endif /* STROKE_ATTRIBUTE_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_ca.c b/src/charon/plugins/stroke/stroke_ca.c new file mode 100644 index 000000000..897365eb0 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_ca.c @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_ca.h" +#include "stroke_cred.h" + +#include <utils/mutex.h> +#include <utils/linked_list.h> +#include <crypto/hashers/hasher.h> + +#include <daemon.h> + +typedef struct private_stroke_ca_t private_stroke_ca_t; + +/** + * private data of stroke_ca + */ +struct private_stroke_ca_t { + + /** + * public functions + */ + stroke_ca_t public; + + /** + * mutex to lock access to list + */ + mutex_t *mutex; + + /** + * list of starters CA sections and its certificates (ca_section_t) + */ + linked_list_t *sections; + + /** + * stroke credentials, stores our CA certificates + */ + stroke_cred_t *cred; +}; + +typedef struct ca_section_t ca_section_t; + +/** + * loaded ipsec.conf CA sections + */ +struct ca_section_t { + + /** + * name of the CA section + */ + char *name; + + /** + * reference to cert in trusted_credential_t + */ + certificate_t *cert; + + /** + * CRL URIs + */ + linked_list_t *crl; + + /** + * OCSP URIs + */ + linked_list_t *ocsp; + + /** + * Hashes of certificates issued by this CA + */ + linked_list_t *hashes; + + /** + * Base URI used for certificates from this CA + */ + char *certuribase; +}; + +/** + * create a new CA section + */ +static ca_section_t *ca_section_create(char *name, certificate_t *cert) +{ + ca_section_t *ca = malloc_thing(ca_section_t); + + ca->name = strdup(name); + ca->crl = linked_list_create(); + ca->ocsp = linked_list_create(); + ca->cert = cert; + ca->hashes = linked_list_create(); + ca->certuribase = NULL; + return ca; +} + +/** + * destroy a ca section entry + */ +static void ca_section_destroy(ca_section_t *this) +{ + this->crl->destroy_function(this->crl, free); + this->ocsp->destroy_function(this->ocsp, free); + this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy)); + free(this->certuribase); + free(this->name); + free(this); +} + +/** + * data to pass to create_inner_cdp + */ +typedef struct { + private_stroke_ca_t *this; + certificate_type_t type; + identification_t *id; +} cdp_data_t; + +/** + * destroy cdp enumerator data and unlock list + */ +static void cdp_data_destroy(cdp_data_t *data) +{ + data->this->mutex->unlock(data->this->mutex); + free(data); +} + +/** + * inner enumerator constructor for CDP URIs + */ +static enumerator_t *create_inner_cdp(ca_section_t *section, cdp_data_t *data) +{ + public_key_t *public; + identification_t *keyid; + enumerator_t *enumerator = NULL; + linked_list_t *list; + + if (data->type == CERT_X509_OCSP_RESPONSE) + { + list = section->ocsp; + } + else + { + list = section->crl; + } + + public = section->cert->get_public_key(section->cert); + if (public) + { + if (!data->id) + { + enumerator = list->create_enumerator(list); + } + else + { + keyid = public->get_id(public, data->id->get_type(data->id)); + if (keyid && keyid->matches(keyid, data->id)) + { + enumerator = list->create_enumerator(list); + } + } + public->destroy(public); + } + return enumerator; +} + +/** + * inner enumerator constructor for "Hash and URL" + */ +static enumerator_t *create_inner_cdp_hashandurl(ca_section_t *section, cdp_data_t *data) +{ + enumerator_t *enumerator = NULL, *hash_enum; + identification_t *current; + + if (!data->id || !section->certuribase) + { + return NULL; + } + + hash_enum = section->hashes->create_enumerator(section->hashes); + while (hash_enum->enumerate(hash_enum, ¤t)) + { + if (current->matches(current, data->id)) + { + char *url, *hash; + + url = malloc(strlen(section->certuribase) + 40 + 1); + strcpy(url, section->certuribase); + hash = chunk_to_hex(current->get_encoding(current), NULL, FALSE).ptr; + strncat(url, hash, 40); + free(hash); + + enumerator = enumerator_create_single(url, free); + break; + } + } + hash_enum->destroy(hash_enum); + return enumerator; +} + +/** + * Implementation of credential_set_t.create_cdp_enumerator. + */ +static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this, + certificate_type_t type, identification_t *id) +{ + cdp_data_t *data; + + switch (type) + { /* we serve CRLs, OCSP responders and URLs for "Hash and URL" */ + case CERT_X509: + case CERT_X509_CRL: + case CERT_X509_OCSP_RESPONSE: + case CERT_ANY: + break; + default: + return NULL; + } + data = malloc_thing(cdp_data_t); + data->this = this; + data->type = type; + data->id = id; + + this->mutex->lock(this->mutex); + return enumerator_create_nested(this->sections->create_enumerator(this->sections), + (type == CERT_X509) ? (void*)create_inner_cdp_hashandurl : (void*)create_inner_cdp, + data, (void*)cdp_data_destroy); +} +/** + * Implementation of stroke_ca_t.add. + */ +static void add(private_stroke_ca_t *this, stroke_msg_t *msg) +{ + certificate_t *cert; + ca_section_t *ca; + + if (msg->add_ca.cacert == NULL) + { + DBG1(DBG_CFG, "missing cacert parameter"); + return; + } + cert = this->cred->load_ca(this->cred, msg->add_ca.cacert); + if (cert) + { + ca = ca_section_create(msg->add_ca.name, cert); + if (msg->add_ca.crluri) + { + ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri)); + } + if (msg->add_ca.crluri2) + { + ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri2)); + } + if (msg->add_ca.ocspuri) + { + ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri)); + } + if (msg->add_ca.ocspuri2) + { + ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri2)); + } + if (msg->add_ca.certuribase) + { + ca->certuribase = strdup(msg->add_ca.certuribase); + } + this->mutex->lock(this->mutex); + this->sections->insert_last(this->sections, ca); + this->mutex->unlock(this->mutex); + DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name); + } +} + +/** + * Implementation of stroke_ca_t.del. + */ +static void del(private_stroke_ca_t *this, stroke_msg_t *msg) +{ + enumerator_t *enumerator; + ca_section_t *ca = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->sections->create_enumerator(this->sections); + while (enumerator->enumerate(enumerator, &ca)) + { + if (streq(ca->name, msg->del_ca.name)) + { + this->sections->remove_at(this->sections, enumerator); + break; + } + ca = NULL; + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + if (ca == NULL) + { + DBG1(DBG_CFG, "no ca named '%s' found\n", msg->del_ca.name); + return; + } + ca_section_destroy(ca); + /* TODO: flush cached certs */ +} + +/** + * list crl or ocsp URIs + */ +static void list_uris(linked_list_t *list, char *label, FILE *out) +{ + bool first = TRUE; + char *uri; + enumerator_t *enumerator; + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, (void**)&uri)) + { + if (first) + { + fprintf(out, label); + first = FALSE; + } + else + { + fprintf(out, " "); + } + fprintf(out, "'%s'\n", uri); + } + enumerator->destroy(enumerator); +} + +/** + * Implementation of stroke_ca_t.check_for_hash_and_url. + */ +static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cert) +{ + ca_section_t *section; + enumerator_t *enumerator; + + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher == NULL) + { + DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported"); + return; + } + + this->mutex->lock(this->mutex); + enumerator = this->sections->create_enumerator(this->sections); + while (enumerator->enumerate(enumerator, (void**)§ion)) + { + if (section->certuribase && cert->issued_by(cert, section->cert)) + { + chunk_t hash, encoded = cert->get_encoding(cert); + hasher->allocate_hash(hasher, encoded, &hash); + section->hashes->insert_last(section->hashes, + identification_create_from_encoding(ID_CERT_DER_SHA1, hash)); + chunk_free(&hash); + chunk_free(&encoded); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + hasher->destroy(hasher); +} + +/** + * Implementation of stroke_ca_t.list. + */ +static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out) +{ + bool first = TRUE; + ca_section_t *section; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->sections->create_enumerator(this->sections); + while (enumerator->enumerate(enumerator, (void**)§ion)) + { + certificate_t *cert = section->cert; + public_key_t *public = cert->get_public_key(cert); + + if (first) + { + fprintf(out, "\n"); + fprintf(out, "List of CA Information Sections:\n"); + first = FALSE; + } + fprintf(out, "\n"); + fprintf(out, " authname: \"%D\"\n", cert->get_subject(cert)); + + /* list authkey and keyid */ + if (public) + { + fprintf(out, " authkey: %D\n", + public->get_id(public, ID_PUBKEY_SHA1)); + fprintf(out, " keyid: %D\n", + public->get_id(public, ID_PUBKEY_INFO_SHA1)); + public->destroy(public); + } + list_uris(section->crl, " crluris: ", out); + list_uris(section->ocsp, " ocspuris: ", out); + if (section->certuribase) + { + fprintf(out, " certuribase: '%s'\n", section->certuribase); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of stroke_ca_t.destroy + */ +static void destroy(private_stroke_ca_t *this) +{ + this->sections->destroy_function(this->sections, (void*)ca_section_destroy); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +stroke_ca_t *stroke_ca_create(stroke_cred_t *cred) +{ + private_stroke_ca_t *this = malloc_thing(private_stroke_ca_t); + + this->public.set.create_private_enumerator = (void*)return_null; + this->public.set.create_cert_enumerator = (void*)return_null; + this->public.set.create_shared_enumerator = (void*)return_null; + this->public.set.create_cdp_enumerator = (void*)create_cdp_enumerator; + this->public.set.cache_cert = (void*)nop; + this->public.add = (void(*)(stroke_ca_t*, stroke_msg_t *msg))add; + this->public.del = (void(*)(stroke_ca_t*, stroke_msg_t *msg))del; + this->public.list = (void(*)(stroke_ca_t*, stroke_msg_t *msg, FILE *out))list; + this->public.check_for_hash_and_url = (void(*)(stroke_ca_t*, certificate_t*))check_for_hash_and_url; + this->public.destroy = (void(*)(stroke_ca_t*))destroy; + + this->sections = linked_list_create(); + this->mutex = mutex_create(MUTEX_RECURSIVE); + this->cred = cred; + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_ca.h b/src/charon/plugins/stroke/stroke_ca.h new file mode 100644 index 000000000..882446afe --- /dev/null +++ b/src/charon/plugins/stroke/stroke_ca.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_ca stroke_ca + * @{ @ingroup stroke + */ + +#ifndef STROKE_CA_H_ +#define STROKE_CA_H_ + +#include <stroke_msg.h> + +#include "stroke_cred.h" + +typedef struct stroke_ca_t stroke_ca_t; + +/** + * ipsec.conf ca section handling. + */ +struct stroke_ca_t { + + /** + * Implements credential_set_t + */ + credential_set_t set; + + /** + * Add a CA to the set using a stroke_msg_t. + * + * @param msg stroke message containing CA info + */ + void (*add)(stroke_ca_t *this, stroke_msg_t *msg); + + /** + * Remove a CA from the set using a stroke_msg_t. + * + * @param msg stroke message containing CA info + */ + void (*del)(stroke_ca_t *this, stroke_msg_t *msg); + + /** + * List CA sections to stroke console. + * + * @param msg stroke message + */ + void (*list)(stroke_ca_t *this, stroke_msg_t *msg, FILE *out); + + /** + * Check if a certificate can be made available through hash and URL. + * + * @param cert peer certificate + */ + void (*check_for_hash_and_url)(stroke_ca_t *this, certificate_t* cert); + + /** + * Destroy a stroke_ca instance. + */ + void (*destroy)(stroke_ca_t *this); +}; + +/** + * Create a stroke_ca instance. + */ +stroke_ca_t *stroke_ca_create(stroke_cred_t *cred); + +#endif /* STROKE_CA_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c new file mode 100644 index 000000000..0069191b5 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_config.c @@ -0,0 +1,844 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_config.h" + +#include <daemon.h> +#include <utils/mutex.h> + +typedef struct private_stroke_config_t private_stroke_config_t; + +/** + * private data of stroke_config + */ +struct private_stroke_config_t { + + /** + * public functions + */ + stroke_config_t public; + + /** + * list of peer_cfg_t + */ + linked_list_t *list; + + /** + * mutex to lock config list + */ + mutex_t *mutex; + + /** + * ca sections + */ + stroke_ca_t *ca; + + /** + * credentials + */ + stroke_cred_t *cred; +}; + +/** + * data to pass peer_filter + */ +typedef struct { + private_stroke_config_t *this; + identification_t *me; + identification_t *other; +} peer_data_t; + +/** + * destroy id enumerator data and unlock list + */ +static void peer_data_destroy(peer_data_t *data) +{ + data->this->mutex->unlock(data->this->mutex); + free(data); +} + +/** + * filter function for peer configs + */ +static bool peer_filter(peer_data_t *data, peer_cfg_t **in, peer_cfg_t **out) +{ + bool match_me = FALSE, match_other = FALSE; + identification_t *me, *other; + + me = (*in)->get_my_id(*in); + other = (*in)->get_other_id(*in); + + /* own ID may have wildcards in data (no IDr payload) or in config */ + match_me = (!data->me || data->me->matches(data->me, me) || + me->matches(me, data->me)); + /* others ID has wildcards in config only */ + match_other = (!data->other || data->other->matches(data->other, other)); + + if (match_me && match_other) + { + *out = *in; + return TRUE; + } + return FALSE; +} + +/** + * Implementation of backend_t.create_peer_cfg_enumerator. + */ +static enumerator_t* create_peer_cfg_enumerator(private_stroke_config_t *this, + identification_t *me, + identification_t *other) +{ + peer_data_t *data; + + data = malloc_thing(peer_data_t); + data->this = this; + data->me = me; + data->other = other; + + this->mutex->lock(this->mutex); + return enumerator_create_filter(this->list->create_enumerator(this->list), + (void*)peer_filter, data, + (void*)peer_data_destroy); +} + +/** + * data to pass ike_filter + */ +typedef struct { + private_stroke_config_t *this; + host_t *me; + host_t *other; +} ike_data_t; + +/** + * destroy id enumerator data and unlock list + */ +static void ike_data_destroy(ike_data_t *data) +{ + data->this->mutex->unlock(data->this->mutex); + free(data); +} + +/** + * filter function for ike configs + */ +static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out) +{ + *out = (*in)->get_ike_cfg(*in); + return TRUE; +} + +/** + * Implementation of backend_t.create_ike_cfg_enumerator. + */ +static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this, + host_t *me, host_t *other) +{ + ike_data_t *data; + + data = malloc_thing(ike_data_t); + data->this = this; + data->me = me; + data->other = other; + + this->mutex->lock(this->mutex); + return enumerator_create_filter(this->list->create_enumerator(this->list), + (void*)ike_filter, data, + (void*)ike_data_destroy); +} + +/** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *name) +{ + enumerator_t *e1, *e2; + peer_cfg_t *current, *found = NULL; + child_cfg_t *child; + + this->mutex->lock(this->mutex); + e1 = this->list->create_enumerator(this->list); + while (e1->enumerate(e1, ¤t)) + { + /* compare peer_cfgs name first */ + if (streq(current->get_name(current), name)) + { + found = current; + found->get_ref(found); + break; + } + /* compare all child_cfg names otherwise */ + e2 = current->create_child_cfg_enumerator(current); + while (e2->enumerate(e2, &child)) + { + if (streq(child->get_name(child), name)) + { + found = current; + found->get_ref(found); + break; + } + } + e2->destroy(e2); + if (found) + { + break; + } + } + e1->destroy(e1); + this->mutex->unlock(this->mutex); + return found; +} + +/** + * check if a certificate has an ID + */ +static identification_t *update_peerid(certificate_t *cert, identification_t *id) +{ + if (!cert->has_subject(cert, id)) + { + DBG1(DBG_CFG, " peerid %D not confirmed by certificate, " + "defaulting to subject DN", id); + id->destroy(id); + id = cert->get_subject(cert); + return id->clone(id); + } + return id; +} + +/** + * parse a proposal string, either into ike_cfg or child_cfg + */ +static void add_proposals(private_stroke_config_t *this, char *string, + ike_cfg_t *ike_cfg, child_cfg_t *child_cfg) +{ + if (string) + { + char *single; + char *strict; + proposal_t *proposal; + protocol_id_t proto = PROTO_ESP; + + if (ike_cfg) + { + proto = PROTO_IKE; + } + strict = string + strlen(string) - 1; + if (*strict == '!') + { + *strict = '\0'; + } + else + { + strict = NULL; + } + while ((single = strsep(&string, ","))) + { + proposal = proposal_create_from_string(proto, single); + if (proposal) + { + if (ike_cfg) + { + ike_cfg->add_proposal(ike_cfg, proposal); + } + else + { + child_cfg->add_proposal(child_cfg, proposal); + } + continue; + } + DBG1(DBG_CFG, "skipped invalid proposal string: %s", single); + } + if (strict) + { + return; + } + /* add default porposal to the end if not strict */ + } + if (ike_cfg) + { + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + } + else + { + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + } +} + +/** + * Build an IKE config from a stroke message + */ +static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg) +{ + stroke_end_t tmp_end; + ike_cfg_t *ike_cfg; + char *interface; + host_t *host; + + host = host_create_from_dns(msg->add_conn.other.address, 0, 0); + if (host) + { + interface = charon->kernel_interface->get_interface( + charon->kernel_interface, host); + host->destroy(host); + if (interface) + { + DBG2(DBG_CFG, "left is other host, swapping ends"); + tmp_end = msg->add_conn.me; + msg->add_conn.me = msg->add_conn.other; + msg->add_conn.other = tmp_end; + free(interface); + } + else + { + host = host_create_from_dns(msg->add_conn.me.address, 0, 0); + if (host) + { + interface = charon->kernel_interface->get_interface( + charon->kernel_interface, host); + host->destroy(host); + if (!interface) + { + DBG1(DBG_CFG, "left nor right host is our side, " + "assuming left=local"); + } + else + { + free(interface); + } + + } + } + } + ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND, + msg->add_conn.force_encap, + msg->add_conn.me.address, + msg->add_conn.other.address); + add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL); + return ike_cfg; +} +/** + * build a peer_cfg from a stroke msg + */ +static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, + stroke_msg_t *msg, ike_cfg_t *ike_cfg) +{ + identification_t *me, *other, *peer_id = NULL; + peer_cfg_t *mediated_by = NULL; + host_t *vip = NULL; + certificate_t *cert; + unique_policy_t unique; + u_int32_t rekey = 0, reauth = 0, over, jitter; + + me = identification_create_from_string(msg->add_conn.me.id ? + msg->add_conn.me.id : msg->add_conn.me.address); + if (!me) + { + DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id); + return NULL; + } + other = identification_create_from_string(msg->add_conn.other.id ? + msg->add_conn.other.id : msg->add_conn.other.address); + if (!other) + { + DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id); + me->destroy(me); + return NULL; + } + + +#ifdef ME + if (msg->add_conn.ikeme.mediation && msg->add_conn.ikeme.mediated_by) + { + DBG1(DBG_CFG, "a mediation connection cannot be a" + " mediated connection at the same time, aborting"); + me->destroy(me); + other->destroy(other); + return NULL; + } + + if (msg->add_conn.ikeme.mediated_by) + { + mediated_by = charon->backends->get_peer_cfg_by_name(charon->backends, + msg->add_conn.ikeme.mediated_by); + if (!mediated_by) + { + DBG1(DBG_CFG, "mediation connection '%s' not found, aborting", + msg->add_conn.ikeme.mediated_by); + me->destroy(me); + other->destroy(other); + return NULL; + } + + if (!mediated_by->is_mediation(mediated_by)) + { + DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is" + "no mediation connection, aborting", + msg->add_conn.ikeme.mediated_by, msg->add_conn.name); + mediated_by->destroy(mediated_by); + me->destroy(me); + other->destroy(other); + return NULL; + } + } + + if (msg->add_conn.ikeme.peerid) + { + peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid); + if (!peer_id) + { + DBG1(DBG_CFG, "invalid peer ID: %s\n", msg->add_conn.ikeme.peerid); + mediated_by->destroy(mediated_by); + me->destroy(me); + other->destroy(other); + return NULL; + } + } + else + { + /* no peer ID supplied, assume right ID */ + peer_id = other->clone(other); + } +#endif /* ME */ + + if (msg->add_conn.me.cert) + { + cert = this->cred->load_peer(this->cred, msg->add_conn.me.cert); + if (cert) + { + this->ca->check_for_hash_and_url(this->ca, cert); + me = update_peerid(cert, me); + cert->destroy(cert); + } + } + if (msg->add_conn.other.cert) + { + cert = this->cred->load_peer(this->cred, msg->add_conn.other.cert); + if (cert) + { + other = update_peerid(cert, other); + cert->destroy(cert); + } + } + jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100; + over = msg->add_conn.rekey.margin; + if (msg->add_conn.rekey.reauth) + { + reauth = msg->add_conn.rekey.ike_lifetime - over; + } + else + { + rekey = msg->add_conn.rekey.ike_lifetime - over; + } + if (msg->add_conn.me.sourceip_size) + { + if (msg->add_conn.me.sourceip) + { + vip = host_create_from_string(msg->add_conn.me.sourceip, 0); + } + if (!vip) + { /* if it is set to something like %poolname, request an address */ + if (msg->add_conn.me.subnets) + { /* use the same address as in subnet, if any */ + if (strchr(msg->add_conn.me.subnets, '.')) + { + vip = host_create_any(AF_INET); + } + else + { + vip = host_create_any(AF_INET6); + } + } + else + { + if (strchr(ike_cfg->get_my_addr(ike_cfg), ':')) + { + vip = host_create_any(AF_INET6); + } + else + { + vip = host_create_any(AF_INET); + } + } + } + } + switch (msg->add_conn.unique) + { + case 1: /* yes */ + case 2: /* replace */ + unique = UNIQUE_REPLACE; + break; + case 3: /* keep */ + unique = UNIQUE_KEEP; + break; + default: /* no */ + unique = UNIQUE_NO; + break; + } + if (msg->add_conn.dpd.action == 0) + { /* dpdaction=none disables DPD */ + msg->add_conn.dpd.delay = 0; + } + + /* other.sourceip is managed in stroke_attributes. If it is set, we define + * the pool name as the connection name, which the attribute provider + * uses to serve pool addresses. */ + return peer_cfg_create(msg->add_conn.name, + msg->add_conn.ikev2 ? 2 : 1, ike_cfg, me, other, + msg->add_conn.me.sendcert, unique, msg->add_conn.auth_method, + msg->add_conn.eap_type, msg->add_conn.eap_vendor, + msg->add_conn.rekey.tries, rekey, reauth, jitter, over, + msg->add_conn.mobike, msg->add_conn.dpd.delay, + vip, msg->add_conn.other.sourceip_size ? + msg->add_conn.name : msg->add_conn.other.sourceip, + msg->add_conn.ikeme.mediation, mediated_by, peer_id); +} + +/** + * fill in auth_info from stroke message + */ +static void build_auth_info(private_stroke_config_t *this, + stroke_msg_t *msg, auth_info_t *auth) +{ + identification_t *my_ca = NULL, *other_ca = NULL; + bool my_ca_same = FALSE; + bool other_ca_same = FALSE; + cert_validation_t valid; + + if (msg->add_conn.other.groups) + { + /* TODO: AC groups */ + } + + switch (msg->add_conn.crl_policy) + { + case CRL_STRICT_YES: + valid = VALIDATION_GOOD; + auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid); + break; + case CRL_STRICT_IFURI: + valid = VALIDATION_SKIPPED; + auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid); + break; + default: + break; + } + + if (msg->add_conn.me.ca) + { + if (streq(msg->add_conn.me.ca, "%same")) + { + my_ca_same = TRUE; + } + else + { + my_ca = identification_create_from_string(msg->add_conn.me.ca); + } + } + if (msg->add_conn.other.ca) + { + if (streq(msg->add_conn.other.ca, "%same")) + { + other_ca_same = TRUE; + } + else + { + other_ca = identification_create_from_string(msg->add_conn.other.ca); + } + } + if (other_ca_same && my_ca) + { + other_ca = my_ca->clone(my_ca); + } + else if (my_ca_same && other_ca) + { + my_ca = other_ca->clone(other_ca); + } + + if (other_ca) + { + DBG2(DBG_CFG, " other ca: %D", other_ca); + certificate_t *cert = charon->credentials->get_cert(charon->credentials, + CERT_X509, KEY_ANY, other_ca, TRUE); + if (cert) + { + auth->add_item(auth, AUTHZ_CA_CERT, cert); + cert->destroy(cert); + } + else + { + auth->add_item(auth, AUTHZ_CA_CERT_NAME, other_ca); + } + other_ca->destroy(other_ca); + } + if (my_ca) + { + DBG2(DBG_CFG, " my ca: %D", my_ca); + certificate_t *cert = charon->credentials->get_cert(charon->credentials, + CERT_X509, KEY_ANY, my_ca, TRUE); + if (cert) + { + auth->add_item(auth, AUTHN_CA_CERT, cert); + cert->destroy(cert); + } + else + { + auth->add_item(auth, AUTHN_CA_CERT_NAME, my_ca); + } + my_ca->destroy(my_ca); + } +} + +/** + * build a traffic selector from a stroke_end + */ +static void add_ts(private_stroke_config_t *this, + stroke_end_t *end, child_cfg_t *child_cfg, bool local) +{ + traffic_selector_t *ts; + + if (end->tohost) + { + ts = traffic_selector_create_dynamic(end->protocol, + end->port ? end->port : 0, end->port ? end->port : 65535); + child_cfg->add_traffic_selector(child_cfg, local, ts); + } + else + { + host_t *net; + + if (!end->subnets) + { + net = host_create_from_string(end->address, IKEV2_UDP_PORT); + if (net) + { + ts = traffic_selector_create_from_subnet(net, 0, end->protocol, + end->port); + child_cfg->add_traffic_selector(child_cfg, local, ts); + } + } + else + { + char *del, *start, *bits; + + start = end->subnets; + do + { + int intbits = 0; + + del = strchr(start, ','); + if (del) + { + *del = '\0'; + } + bits = strchr(start, '/'); + if (bits) + { + *bits = '\0'; + intbits = atoi(bits + 1); + } + + net = host_create_from_string(start, IKEV2_UDP_PORT); + if (net) + { + ts = traffic_selector_create_from_subnet(net, intbits, + end->protocol, end->port); + child_cfg->add_traffic_selector(child_cfg, local, ts); + } + else + { + DBG1(DBG_CFG, "invalid subnet: %s, skipped", start); + } + start = del + 1; + } + while (del); + } + } +} + +/** + * build a child config from the stroke message + */ +static child_cfg_t *build_child_cfg(private_stroke_config_t *this, + stroke_msg_t *msg) +{ + child_cfg_t *child_cfg; + action_t dpd; + + switch (msg->add_conn.dpd.action) + { /* map startes magic values to our action type */ + case 2: /* =hold */ + dpd = ACTION_ROUTE; + break; + case 3: /* =restart */ + dpd = ACTION_RESTART; + break; + default: + dpd = ACTION_NONE; + break; + } + child_cfg = child_cfg_create( + msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime, + msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin, + msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100, + msg->add_conn.me.updown, msg->add_conn.me.hostaccess, + msg->add_conn.mode, dpd, ACTION_NONE, msg->add_conn.ipcomp); + + add_ts(this, &msg->add_conn.me, child_cfg, TRUE); + add_ts(this, &msg->add_conn.other, child_cfg, FALSE); + + add_proposals(this, msg->add_conn.algorithms.esp, NULL, child_cfg); + + return child_cfg; +} + +/** + * Implementation of stroke_config_t.add. + */ +static void add(private_stroke_config_t *this, stroke_msg_t *msg) +{ + ike_cfg_t *ike_cfg, *existing_ike; + peer_cfg_t *peer_cfg, *existing; + child_cfg_t *child_cfg; + enumerator_t *enumerator; + bool use_existing = FALSE; + + ike_cfg = build_ike_cfg(this, msg); + if (!ike_cfg) + { + return; + } + peer_cfg = build_peer_cfg(this, msg, ike_cfg); + if (!peer_cfg) + { + ike_cfg->destroy(ike_cfg); + return; + } + + build_auth_info(this, msg, peer_cfg->get_auth(peer_cfg)); + enumerator = create_peer_cfg_enumerator(this, NULL, NULL); + while (enumerator->enumerate(enumerator, &existing)) + { + existing_ike = existing->get_ike_cfg(existing); + if (existing->equals(existing, peer_cfg) && + existing_ike->equals(existing_ike, peer_cfg->get_ike_cfg(peer_cfg))) + { + use_existing = TRUE; + peer_cfg->destroy(peer_cfg); + peer_cfg = existing; + peer_cfg->get_ref(peer_cfg); + DBG1(DBG_CFG, "added child to existing configuration '%s'", + peer_cfg->get_name(peer_cfg)); + break; + } + } + enumerator->destroy(enumerator); + + child_cfg = build_child_cfg(this, msg); + if (!child_cfg) + { + peer_cfg->destroy(peer_cfg); + return; + } + peer_cfg->add_child_cfg(peer_cfg, child_cfg); + + if (use_existing) + { + peer_cfg->destroy(peer_cfg); + } + else + { + /* add config to backend */ + DBG1(DBG_CFG, "added configuration '%s': %s[%D]...%s[%D]", msg->add_conn.name, + ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg), + ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg)); + this->mutex->lock(this->mutex); + this->list->insert_last(this->list, peer_cfg); + this->mutex->unlock(this->mutex); + } +} + +/** + * Implementation of stroke_config_t.del. + */ +static void del(private_stroke_config_t *this, stroke_msg_t *msg) +{ + enumerator_t *enumerator, *children; + peer_cfg_t *peer; + child_cfg_t *child; + + this->mutex->lock(this->mutex); + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, (void**)&peer)) + { + /* remove peer config with such a name */ + if (streq(peer->get_name(peer), msg->del_conn.name)) + { + this->list->remove_at(this->list, enumerator); + peer->destroy(peer); + continue; + } + /* remove any child with such a name */ + children = peer->create_child_cfg_enumerator(peer); + while (children->enumerate(children, &child)) + { + if (streq(child->get_name(child), msg->del_conn.name)) + { + peer->remove_child_cfg(peer, enumerator); + child->destroy(child); + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + DBG1(DBG_CFG, "deleted connection '%s'", msg->del_conn.name); +} + +/** + * Implementation of stroke_config_t.destroy + */ +static void destroy(private_stroke_config_t *this) +{ + this->list->destroy_offset(this->list, offsetof(peer_cfg_t, destroy)); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred) +{ + private_stroke_config_t *this = malloc_thing(private_stroke_config_t); + + this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; + this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; + this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; + this->public.add = (void(*)(stroke_config_t*, stroke_msg_t *msg))add; + this->public.del = (void(*)(stroke_config_t*, stroke_msg_t *msg))del; + this->public.destroy = (void(*)(stroke_config_t*))destroy; + + this->list = linked_list_create(); + this->mutex = mutex_create(MUTEX_RECURSIVE); + this->ca = ca; + this->cred = cred; + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_config.h b/src/charon/plugins/stroke/stroke_config.h new file mode 100644 index 000000000..22b493cd2 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_config.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_config stroke_config + * @{ @ingroup stroke + */ + +#ifndef STROKE_CONFIG_H_ +#define STROKE_CONFIG_H_ + +#include <config/backend.h> +#include <stroke_msg.h> +#include "stroke_ca.h" +#include "stroke_cred.h" + +typedef struct stroke_config_t stroke_config_t; + +/** + * Stroke in-memory configuration backend + */ +struct stroke_config_t { + + /** + * Implements the backend_t interface + */ + backend_t backend; + + /** + * Add a configuration to the backend. + * + * @param msg received stroke message containing config + */ + void (*add)(stroke_config_t *this, stroke_msg_t *msg); + + /** + * Remove a configuration from the backend. + * + * @param msg received stroke message containing config name + */ + void (*del)(stroke_config_t *this, stroke_msg_t *msg); + + /** + * Destroy a stroke_config instance. + */ + void (*destroy)(stroke_config_t *this); +}; + +/** + * Create a stroke_config instance. + */ +stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred); + +#endif /* STROKE_CONFIG_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_control.c b/src/charon/plugins/stroke/stroke_control.c new file mode 100644 index 000000000..2956b1576 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_control.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_control.h" + +#include <daemon.h> + +typedef struct private_stroke_control_t private_stroke_control_t; + +/** + * private data of stroke_control + */ +struct private_stroke_control_t { + + /** + * public functions + */ + stroke_control_t public; +}; + + +typedef struct stroke_log_info_t stroke_log_info_t; + +/** + * helper struct to say what and where to log when using controller callback + */ +struct stroke_log_info_t { + + /** + * level to log up to + */ + level_t level; + + /** + * where to write log + */ + FILE* out; +}; + +/** + * logging to the stroke interface + */ +static bool stroke_log(stroke_log_info_t *info, signal_t signal, level_t level, + ike_sa_t *ike_sa, char *format, va_list args) +{ + if (level <= info->level) + { + if (vfprintf(info->out, format, args) < 0 || + fprintf(info->out, "\n") < 0 || + fflush(info->out) != 0) + { + return FALSE; + } + } + return TRUE; +} + +/** + * get the child_cfg with the same name as the peer cfg + */ +static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name) +{ + child_cfg_t *current, *found = NULL; + enumerator_t *enumerator; + + enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(current->get_name(current), name)) + { + found = current; + found->get_ref(found); + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * Implementation of stroke_control_t.initiate. + */ +static void initiate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +{ + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg; + stroke_log_info_t info; + + peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, + msg->initiate.name); + if (peer_cfg == NULL) + { + DBG1(DBG_CFG, "no config named '%s'\n", msg->initiate.name); + return; + } + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { + DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config", + peer_cfg->get_ike_version(peer_cfg)); + peer_cfg->destroy(peer_cfg); + return; + } + + child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name); + if (child_cfg == NULL) + { + DBG1(DBG_CFG, "no child config named '%s'\n", msg->initiate.name); + peer_cfg->destroy(peer_cfg); + return; + } + + if (msg->output_verbosity < 0) + { + charon->controller->initiate(charon->controller, peer_cfg, child_cfg, + NULL, NULL); + } + else + { + info.out = out; + info.level = msg->output_verbosity; + charon->controller->initiate(charon->controller, peer_cfg, child_cfg, + (controller_cb_t)stroke_log, &info); + } +} + +/** + * Implementation of stroke_control_t.terminate. + */ +static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +{ + char *string, *pos = NULL, *name = NULL; + u_int32_t id = 0; + bool child; + int len; + ike_sa_t *ike_sa; + enumerator_t *enumerator; + stroke_log_info_t info; + + string = msg->terminate.name; + + len = strlen(string); + if (len < 1) + { + DBG1(DBG_CFG, "error parsing string"); + return; + } + switch (string[len-1]) + { + case '}': + child = TRUE; + pos = strchr(string, '{'); + break; + case ']': + child = FALSE; + pos = strchr(string, '['); + break; + default: + name = string; + child = FALSE; + break; + } + + if (name) + { + /* is a single name */ + } + else if (pos == string + len - 2) + { /* is name[] or name{} */ + string[len-2] = '\0'; + name = string; + } + else + { /* is name[123] or name{23} */ + string[len-1] = '\0'; + id = atoi(pos + 1); + if (id == 0) + { + DBG1(DBG_CFG, "error parsing string"); + return; + } + } + + info.out = out; + info.level = msg->output_verbosity; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + child_sa_t *child_sa; + iterator_t *children; + + if (child) + { + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if ((name && streq(name, child_sa->get_name(child_sa))) || + (id && id == child_sa->get_reqid(child_sa))) + { + id = child_sa->get_reqid(child_sa); + children->destroy(children); + enumerator->destroy(enumerator); + + charon->controller->terminate_child(charon->controller, id, + (controller_cb_t)stroke_log, &info); + return; + } + } + children->destroy(children); + } + else if ((name && streq(name, ike_sa->get_name(ike_sa))) || + (id && id == ike_sa->get_unique_id(ike_sa))) + { + id = ike_sa->get_unique_id(ike_sa); + /* unlock manager first */ + enumerator->destroy(enumerator); + + charon->controller->terminate_ike(charon->controller, id, + (controller_cb_t)stroke_log, &info); + return; + } + + } + enumerator->destroy(enumerator); + DBG1(DBG_CFG, "no such SA found"); +} + +/** + * Implementation of stroke_control_t.route. + */ +static void route(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +{ + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg; + stroke_log_info_t info; + + peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, + msg->route.name); + if (peer_cfg == NULL) + { + fprintf(out, "no config named '%s'\n", msg->route.name); + return; + } + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { + peer_cfg->destroy(peer_cfg); + return; + } + + child_cfg = get_child_from_peer(peer_cfg, msg->route.name); + if (child_cfg == NULL) + { + fprintf(out, "no child config named '%s'\n", msg->route.name); + peer_cfg->destroy(peer_cfg); + return; + } + + info.out = out; + info.level = msg->output_verbosity; + charon->controller->route(charon->controller, peer_cfg, child_cfg, + (controller_cb_t)stroke_log, &info); + peer_cfg->destroy(peer_cfg); + child_cfg->destroy(child_cfg); +} + +/** + * Implementation of stroke_control_t.unroute. + */ +static void unroute(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +{ + char *name; + ike_sa_t *ike_sa; + enumerator_t *enumerator; + stroke_log_info_t info; + + name = msg->terminate.name; + + info.out = out; + info.level = msg->output_verbosity; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + child_sa_t *child_sa; + iterator_t *children; + u_int32_t id; + + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if (child_sa->get_state(child_sa) == CHILD_ROUTED && + streq(name, child_sa->get_name(child_sa))) + { + id = child_sa->get_reqid(child_sa); + children->destroy(children); + enumerator->destroy(enumerator); + charon->controller->unroute(charon->controller, id, + (controller_cb_t)stroke_log, &info); + return; + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + DBG1(DBG_CFG, "no such SA found"); +} + +/** + * Implementation of stroke_control_t.destroy + */ +static void destroy(private_stroke_control_t *this) +{ + free(this); +} + +/* + * see header file + */ +stroke_control_t *stroke_control_create() +{ + private_stroke_control_t *this = malloc_thing(private_stroke_control_t); + + this->public.initiate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))initiate; + this->public.terminate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate; + this->public.route = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))route; + this->public.unroute = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))unroute; + this->public.destroy = (void(*)(stroke_control_t*))destroy; + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_control.h b/src/charon/plugins/stroke/stroke_control.h new file mode 100644 index 000000000..917679209 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_control.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_control stroke_control + * @{ @ingroup stroke + */ + +#ifndef STROKE_CONTROL_H_ +#define STROKE_CONTROL_H_ + +#include <stroke_msg.h> +#include <library.h> +#include <stdio.h> + +typedef struct stroke_control_t stroke_control_t; + +/** + * Process stroke control messages + */ +struct stroke_control_t { + + /** + * Initiate a connection. + * + * @param msg stroke message + */ + void (*initiate)(stroke_control_t *this, stroke_msg_t *msg, FILE *out); + + /** + * Terminate a connection. + * + * @param msg stroke message + */ + void (*terminate)(stroke_control_t *this, stroke_msg_t *msg, FILE *out); + + /** + * Route a connection. + * + * @param msg stroke message + */ + void (*route)(stroke_control_t *this, stroke_msg_t *msg, FILE *out); + + /** + * Unroute a connection. + * + * @param msg stroke message + */ + void (*unroute)(stroke_control_t *this, stroke_msg_t *msg, FILE *out); + + /** + * Destroy a stroke_control instance. + */ + void (*destroy)(stroke_control_t *this); +}; + +/** + * Create a stroke_control instance. + */ +stroke_control_t *stroke_control_create(); + +#endif /* STROKE_CONTROL_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c new file mode 100644 index 000000000..223500488 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_cred.c @@ -0,0 +1,977 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_cred.h" +#include "stroke_shared_key.h" + +#include <sys/stat.h> +#include <limits.h> + +#include <credentials/certificates/x509.h> +#include <credentials/certificates/crl.h> +#include <credentials/certificates/ac.h> +#include <utils/linked_list.h> +#include <utils/mutex.h> +#include <utils/lexparser.h> +#include <asn1/pem.h> +#include <daemon.h> + +/* configuration directories and files */ +#define CONFIG_DIR IPSEC_CONFDIR +#define IPSEC_D_DIR CONFIG_DIR "/ipsec.d" +#define PRIVATE_KEY_DIR IPSEC_D_DIR "/private" +#define CERTIFICATE_DIR IPSEC_D_DIR "/certs" +#define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts" +#define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts" +#define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts" +#define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts" +#define CRL_DIR IPSEC_D_DIR "/crls" +#define SECRETS_FILE CONFIG_DIR "/ipsec.secrets" + +typedef struct private_stroke_cred_t private_stroke_cred_t; + +/** + * private data of stroke_cred + */ +struct private_stroke_cred_t { + + /** + * public functions + */ + stroke_cred_t public; + + /** + * list of trusted peer/signer/CA certificates (certificate_t) + */ + linked_list_t *certs; + + /** + * list of shared secrets (private_shared_key_t) + */ + linked_list_t *shared; + + /** + * list of private keys (private_key_t) + */ + linked_list_t *private; + + /** + * mutex to lock lists above + */ + mutex_t *mutex; + + /** + * cache CRLs to disk? + */ + bool cachecrl; +}; + +/** + * data to pass to various filters + */ +typedef struct { + private_stroke_cred_t *this; + identification_t *id; +} id_data_t; + +/** + * destroy id enumerator data and unlock list + */ +static void id_data_destroy(id_data_t *data) +{ + data->this->mutex->unlock(data->this->mutex); + free(data); +} + +/** + * filter function for private key enumerator + */ +static bool private_filter(id_data_t *data, + private_key_t **in, private_key_t **out) +{ + identification_t *candidate; + id_type_t type; + + if (data->id == NULL) + { + *out = *in; + return TRUE; + } + type = data->id->get_type(data->id); + if (type == ID_KEY_ID) + { /* handle ID_KEY_ID as a ID_PUBKEY_SHA1 */ + type = ID_PUBKEY_SHA1; + } + candidate = (*in)->get_id(*in, type); + if (candidate && + chunk_equals(candidate->get_encoding(candidate), + data->id->get_encoding(data->id))) + { + *out = *in; + return TRUE; + } + return FALSE; +} + +/** + * Implements credential_set_t.create_private_enumerator + */ +static enumerator_t* create_private_enumerator(private_stroke_cred_t *this, + key_type_t type, identification_t *id) +{ + id_data_t *data; + + data = malloc_thing(id_data_t); + data->this = this; + data->id = id; + + this->mutex->lock(this->mutex); + return enumerator_create_filter(this->private->create_enumerator(this->private), + (void*)private_filter, data, + (void*)id_data_destroy); +} + +/** + * filter function for certs enumerator + */ +static bool certs_filter(id_data_t *data, certificate_t **in, certificate_t **out) +{ + public_key_t *public; + identification_t *candidate; + certificate_t *cert = *in; + certificate_type_t type = cert->get_type(cert); + + if (type == CERT_X509_CRL || type == CERT_X509_AC) + { + return FALSE; + } + + if (data->id == NULL || cert->has_subject(cert, data->id)) + { + *out = *in; + return TRUE; + } + + public = (cert)->get_public_key(cert); + if (public) + { + candidate = public->get_id(public, data->id->get_type(data->id)); + if (candidate && data->id->equals(data->id, candidate)) + { + public->destroy(public); + *out = *in; + return TRUE; + } + public->destroy(public); + } + return FALSE; +} + +/** + * filter function for crl enumerator + */ +static bool crl_filter(id_data_t *data, certificate_t **in, certificate_t **out) +{ + certificate_t *cert = *in; + + if (cert->get_type(cert) != CERT_X509_CRL) + { + return FALSE; + } + + if (data->id == NULL || cert->has_issuer(cert, data->id)) + { + *out = *in; + return TRUE; + } + return FALSE; +} + +/** + * filter function for attribute certificate enumerator + */ +static bool ac_filter(id_data_t *data, certificate_t **in, certificate_t **out) +{ + certificate_t *cert = *in; + + if (cert->get_type(cert) != CERT_X509_AC) + { + return FALSE; + } + + if (data->id == NULL || cert->has_subject(cert, data->id)) + { + *out = *in; + return TRUE; + } + return FALSE; +} + +/** + * Implements credential_set_t.create_cert_enumerator + */ +static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + id_data_t *data; + + if (cert == CERT_X509_CRL || cert == CERT_X509_AC) + { + if (trusted) + { + return NULL; + } + data = malloc_thing(id_data_t); + data->this = this; + data->id = id; + + this->mutex->lock(this->mutex); + return enumerator_create_filter(this->certs->create_enumerator(this->certs), + (cert == CERT_X509_CRL)? (void*)crl_filter : (void*)ac_filter, + data, (void*)id_data_destroy); + } + if (cert != CERT_X509 && cert != CERT_ANY) + { /* we only have X509 certificates. TODO: ACs? */ + return NULL; + } + data = malloc_thing(id_data_t); + data->this = this; + data->id = id; + + this->mutex->lock(this->mutex); + return enumerator_create_filter(this->certs->create_enumerator(this->certs), + (void*)certs_filter, data, + (void*)id_data_destroy); +} + +typedef struct { + private_stroke_cred_t *this; + identification_t *me; + identification_t *other; + shared_key_type_t type; +} shared_data_t; + +/** + * free shared key enumerator data and unlock list + */ +static void shared_data_destroy(shared_data_t *data) +{ + data->this->mutex->unlock(data->this->mutex); + free(data); +} + +/** + * filter function for certs enumerator + */ +static bool shared_filter(shared_data_t *data, + stroke_shared_key_t **in, shared_key_t **out, + void **unused1, id_match_t *me, + void **unused2, id_match_t *other) +{ + id_match_t my_match, other_match; + stroke_shared_key_t *stroke = *in; + shared_key_t *shared = &stroke->shared; + + if (data->type != SHARED_ANY && shared->get_type(shared) != data->type) + { + return FALSE; + } + + my_match = stroke->has_owner(stroke, data->me); + other_match = stroke->has_owner(stroke, data->other); + if (!my_match && !other_match) + { + return FALSE; + } + *out = shared; + if (me) + { + *me = my_match; + } + if (other) + { + *other = other_match; + } + return TRUE; +} + +/** + * Implements credential_set_t.create_shared_enumerator + */ +static enumerator_t* create_shared_enumerator(private_stroke_cred_t *this, + shared_key_type_t type, identification_t *me, + identification_t *other) +{ + shared_data_t *data = malloc_thing(shared_data_t); + + data->this = this; + data->me = me; + data->other = other; + data->type = type; + this->mutex->lock(this->mutex); + return enumerator_create_filter(this->shared->create_enumerator(this->shared), + (void*)shared_filter, data, + (void*)shared_data_destroy); +} + +/** + * Add a certificate to chain + */ +static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert) +{ + certificate_t *current; + enumerator_t *enumerator; + bool new = TRUE; + + this->mutex->lock(this->mutex); + enumerator = this->certs->create_enumerator(this->certs); + while (enumerator->enumerate(enumerator, (void**)¤t)) + { + if (current->equals(current, cert)) + { + /* cert already in queue */ + cert->destroy(cert); + cert = current; + new = FALSE; + break; + } + } + enumerator->destroy(enumerator); + + if (new) + { + this->certs->insert_last(this->certs, cert); + } + this->mutex->unlock(this->mutex); + return cert; +} + +/** + * Implementation of stroke_cred_t.load_ca. + */ +static certificate_t* load_ca(private_stroke_cred_t *this, char *filename) +{ + certificate_t *cert; + char path[PATH_MAX]; + + if (*filename == '/') + { + snprintf(path, sizeof(path), "%s", filename); + } + else + { + snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename); + } + + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, + BUILD_X509_FLAG, X509_CA, + BUILD_END); + if (cert) + { + return (certificate_t*)add_cert(this, cert); + } + return NULL; +} + +/** + * Add X.509 CRL to chain + */ +static bool add_crl(private_stroke_cred_t *this, crl_t* crl) +{ + certificate_t *current, *cert = &crl->certificate; + enumerator_t *enumerator; + bool new = TRUE, found = FALSE; + + this->mutex->lock(this->mutex); + enumerator = this->certs->create_enumerator(this->certs); + while (enumerator->enumerate(enumerator, (void**)¤t)) + { + if (current->get_type(current) == CERT_X509_CRL) + { + crl_t *crl_c = (crl_t*)current; + identification_t *authkey = crl->get_authKeyIdentifier(crl); + identification_t *authkey_c = crl_c->get_authKeyIdentifier(crl_c); + + /* if compare authorityKeyIdentifiers if available */ + if (authkey != NULL && authkey_c != NULL && + authkey->equals(authkey, authkey_c)) + { + found = TRUE; + } + else + { + identification_t *issuer = cert->get_issuer(cert); + identification_t *issuer_c = current->get_issuer(current); + + /* otherwise compare issuer distinguished names */ + if (issuer->equals(issuer, issuer_c)) + { + found = TRUE; + } + } + if (found) + { + new = cert->is_newer(cert, current); + if (new) + { + this->certs->remove_at(this->certs, enumerator); + } + else + { + cert->destroy(cert); + } + break; + } + } + } + enumerator->destroy(enumerator); + + if (new) + { + this->certs->insert_last(this->certs, cert); + } + this->mutex->unlock(this->mutex); + return new; +} + +/** + * Add X.509 attribute certificate to chain + */ +static bool add_ac(private_stroke_cred_t *this, ac_t* ac) +{ + certificate_t *cert = &ac->certificate; + + this->mutex->lock(this->mutex); + this->certs->insert_last(this->certs, cert); + this->mutex->unlock(this->mutex); + return TRUE; +} + +/** + * Implementation of stroke_cred_t.load_peer. + */ +static certificate_t* load_peer(private_stroke_cred_t *this, char *filename) +{ + certificate_t *cert; + char path[PATH_MAX]; + + if (*filename == '/') + { + snprintf(path, sizeof(path), "%s", filename); + } + else + { + snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename); + } + + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, + BUILD_X509_FLAG, 0, + BUILD_END); + if (cert) + { + cert = add_cert(this, cert); + return cert->get_ref(cert); + } + return NULL; +} + +/** + * load trusted certificates from a directory + */ +static void load_certdir(private_stroke_cred_t *this, char *path, + certificate_type_t type, x509_flag_t flag) +{ + struct stat st; + char *file; + + enumerator_t *enumerator = enumerator_create_directory(path); + + if (!enumerator) + { + DBG1(DBG_CFG, " reading directory failed"); + return; + } + + while (enumerator->enumerate(enumerator, NULL, &file, &st)) + { + certificate_t *cert; + + if (!S_ISREG(st.st_mode)) + { + /* skip special file */ + continue; + } + switch (type) + { + case CERT_X509: + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, + BUILD_X509_FLAG, flag, + BUILD_END); + if (cert) + { + add_cert(this, cert); + } + break; + case CERT_X509_CRL: + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_CRL, + BUILD_FROM_FILE, file, + BUILD_END); + if (cert) + { + add_crl(this, (crl_t*)cert); + } + break; + case CERT_X509_AC: + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_AC, + BUILD_FROM_FILE, file, + BUILD_END); + if (cert) + { + add_ac(this, (ac_t*)cert); + } + break; + default: + break; + } + } + enumerator->destroy(enumerator); +} + +/** + * Implementation of credential_set_t.cache_cert. + */ +static void cache_cert(private_stroke_cred_t *this, certificate_t *cert) +{ + if (cert->get_type(cert) == CERT_X509_CRL && this->cachecrl) + { + /* CRLs get written to /etc/ipsec.d/crls/authkeyId.crl */ + crl_t *crl = (crl_t*)cert; + + cert->get_ref(cert); + if (add_crl(this, crl)) + { + char buf[256]; + chunk_t chunk, hex; + identification_t *id; + + id = crl->get_authKeyIdentifier(crl); + chunk = id->get_encoding(id); + hex = chunk_to_hex(chunk, NULL, FALSE); + snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex); + free(hex.ptr); + + chunk = cert->get_encoding(cert); + if (chunk_write(chunk, buf, 022, TRUE)) + { + DBG1(DBG_CFG, " written crl to '%s'", buf); + } + else + { + DBG1(DBG_CFG, " writing crl to '%s' failed", buf); + } + free(chunk.ptr); + } + } +} + +/** + * Implementation of stroke_cred_t.cachecrl. + */ +static void cachecrl(private_stroke_cred_t *this, bool enabled) +{ + DBG1(DBG_CFG, "crl caching to %s %s", + CRL_DIR, enabled ? "enabled" : "disabled"); + this->cachecrl = enabled; +} + + +/** + * Convert a string of characters into a binary secret + * A string between single or double quotes is treated as ASCII characters + * A string prepended by 0x is treated as HEX and prepended by 0s as Base64 + */ +static err_t extract_secret(chunk_t *secret, chunk_t *line) +{ + chunk_t raw_secret; + char delimiter = ' '; + bool quotes = FALSE; + + if (!eat_whitespace(line)) + { + return "missing secret"; + } + + if (*line->ptr == '\'' || *line->ptr == '"') + { + quotes = TRUE; + delimiter = *line->ptr; + line->ptr++; line->len--; + } + + if (!extract_token(&raw_secret, delimiter, line)) + { + if (delimiter == ' ') + { + raw_secret = *line; + } + else + { + return "missing second delimiter"; + } + } + + if (quotes) + { + /* treat as an ASCII string */ + *secret = chunk_clone(raw_secret); + return NULL; + } + /* treat 0x as hex, 0s as base64 */ + if (raw_secret.len > 2) + { + if (strncasecmp("0x", raw_secret.ptr, 2) == 0) + { + *secret = chunk_from_hex(chunk_skip(raw_secret, 2), NULL); + return NULL; + } + if (strncasecmp("0s", raw_secret.ptr, 2) == 0) + { + *secret = chunk_from_base64(chunk_skip(raw_secret, 2), NULL); + return NULL; + } + } + *secret = chunk_clone(raw_secret); + return NULL; +} + +/** + * reload ipsec.secrets + */ +static void load_secrets(private_stroke_cred_t *this) +{ + size_t bytes; + int line_nr = 0; + chunk_t chunk, src, line; + FILE *fd; + private_key_t *private; + shared_key_t *shared; + + DBG1(DBG_CFG, "loading secrets from '%s'", SECRETS_FILE); + + fd = fopen(SECRETS_FILE, "r"); + if (fd == NULL) + { + DBG1(DBG_CFG, "opening secrets file '%s' failed"); + return; + } + + /* TODO: do error checks */ + fseek(fd, 0, SEEK_END); + chunk.len = ftell(fd); + rewind(fd); + chunk.ptr = malloc(chunk.len); + bytes = fread(chunk.ptr, 1, chunk.len, fd); + fclose(fd); + src = chunk; + + this->mutex->lock(this->mutex); + while (this->shared->remove_last(this->shared, + (void**)&shared) == SUCCESS) + { + shared->destroy(shared); + } + while (this->private->remove_last(this->private, + (void**)&private) == SUCCESS) + { + private->destroy(private); + } + + while (fetchline(&src, &line)) + { + chunk_t ids, token; + shared_key_type_t type; + + line_nr++; + + if (!eat_whitespace(&line)) + { + continue; + } + if (!extract_last_token(&ids, ':', &line)) + { + DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr); + goto error; + } + /* NULL terminate the ids string by replacing the : separator */ + *(ids.ptr + ids.len) = '\0'; + + if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) + { + DBG1(DBG_CFG, "line %d: missing token", line_nr); + goto error; + } + if (match("RSA", &token) || match("ECDSA", &token)) + { + char path[PATH_MAX]; + chunk_t filename; + chunk_t secret = chunk_empty; + private_key_t *key; + bool pgp = FALSE; + chunk_t chunk = chunk_empty; + key_type_t key_type = match("RSA", &token) ? KEY_RSA : KEY_ECDSA; + + err_t ugh = extract_value(&filename, &line); + + if (ugh != NULL) + { + DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); + goto error; + } + if (filename.len == 0) + { + DBG1(DBG_CFG, "line %d: empty filename", line_nr); + goto error; + } + if (*filename.ptr == '/') + { + /* absolute path name */ + snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr); + } + else + { + /* relative path name */ + snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR, + filename.len, filename.ptr); + } + + /* check for optional passphrase */ + if (eat_whitespace(&line)) + { + ugh = extract_secret(&secret, &line); + if (ugh != NULL) + { + DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh); + goto error; + } + } + + if (pem_asn1_load_file(path, &secret, &chunk, &pgp)) + { + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, + BUILD_BLOB_ASN1_DER, chunk, BUILD_END); + if (key) + { + DBG1(DBG_CFG, " loaded private key file '%s'", path); + this->private->insert_last(this->private, key); + } + } + chunk_clear(&secret); + } + else if ((match("PSK", &token) && (type = SHARED_IKE)) || + (match("EAP", &token) && (type = SHARED_EAP)) || + (match("XAUTH", &token) && (type = SHARED_EAP)) || + (match("PIN", &token) && (type = SHARED_PIN))) + { + stroke_shared_key_t *shared_key; + chunk_t secret = chunk_empty; + bool any = TRUE; + + err_t ugh = extract_secret(&secret, &line); + if (ugh != NULL) + { + DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh); + goto error; + } + shared_key = stroke_shared_key_create(type, secret); + DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type, + ids.len > 0 ? (char*)ids.ptr : "%any"); + DBG4(DBG_CFG, " secret: %#B", &secret); + + this->shared->insert_last(this->shared, shared_key); + while (ids.len > 0) + { + chunk_t id; + identification_t *peer_id; + + ugh = extract_value(&id, &ids); + if (ugh != NULL) + { + DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); + goto error; + } + if (id.len == 0) + { + continue; + } + + /* NULL terminate the ID string */ + *(id.ptr + id.len) = '\0'; + + peer_id = identification_create_from_string(id.ptr); + if (peer_id == NULL) + { + DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr); + goto error; + } + if (peer_id->get_type(peer_id) == ID_ANY) + { + peer_id->destroy(peer_id); + continue; + } + + shared_key->add_owner(shared_key, peer_id); + any = FALSE; + } + if (any) + { + shared_key->add_owner(shared_key, + identification_create_from_encoding(ID_ANY, chunk_empty)); + } + } + else + { + DBG1(DBG_CFG, "line %d: token must be either " + "RSA, EC, PSK, EAP, or PIN", line_nr); + goto error; + } + } +error: + this->mutex->unlock(this->mutex); + chunk_clear(&chunk); +} + +/** + * load all certificates from ipsec.d + */ +static void load_certs(private_stroke_cred_t *this) +{ + DBG1(DBG_CFG, "loading ca certificates from '%s'", + CA_CERTIFICATE_DIR); + load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA); + + DBG1(DBG_CFG, "loading aa certificates from '%s'", + AA_CERTIFICATE_DIR); + load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA); + + DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'", + OCSP_CERTIFICATE_DIR); + load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER); + + DBG1(DBG_CFG, "loading attribute certificates from '%s'", + ATTR_CERTIFICATE_DIR); + load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0); + + DBG1(DBG_CFG, "loading crls from '%s'", + CRL_DIR); + load_certdir(this, CRL_DIR, CERT_X509_CRL, 0); +} + +/** + * Implementation of stroke_cred_t.reread. + */ +static void reread(private_stroke_cred_t *this, stroke_msg_t *msg) +{ + if (msg->reread.flags & REREAD_SECRETS) + { + DBG1(DBG_CFG, "rereading secrets"); + load_secrets(this); + } + if (msg->reread.flags & REREAD_CACERTS) + { + DBG1(DBG_CFG, "rereading ca certificates from '%s'", + CA_CERTIFICATE_DIR); + load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA); + } + if (msg->reread.flags & REREAD_OCSPCERTS) + { + DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'", + OCSP_CERTIFICATE_DIR); + load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, + X509_OCSP_SIGNER); + } + if (msg->reread.flags & REREAD_AACERTS) + { + DBG1(DBG_CFG, "rereading aa certificates from '%s'", + AA_CERTIFICATE_DIR); + load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA); + } + if (msg->reread.flags & REREAD_ACERTS) + { + DBG1(DBG_CFG, "rereading attribute certificates from '%s'", + ATTR_CERTIFICATE_DIR); + load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0); + } + if (msg->reread.flags & REREAD_CRLS) + { + DBG1(DBG_CFG, "rereading crls from '%s'", + CRL_DIR); + load_certdir(this, CRL_DIR, CERT_X509_CRL, 0); + } +} + +/** + * Implementation of stroke_cred_t.destroy + */ +static void destroy(private_stroke_cred_t *this) +{ + this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy)); + this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy)); + this->private->destroy_offset(this->private, offsetof(private_key_t, destroy)); + this->mutex->destroy(this->mutex); + free(this); +} + +/* + * see header file + */ +stroke_cred_t *stroke_cred_create() +{ + private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t); + + this->public.set.create_private_enumerator = (void*)create_private_enumerator; + this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; + this->public.set.create_shared_enumerator = (void*)create_shared_enumerator; + this->public.set.create_cdp_enumerator = (void*)return_null; + this->public.set.cache_cert = (void*)cache_cert; + this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg))reread; + this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca; + this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer; + this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl; + this->public.destroy = (void(*)(stroke_cred_t*))destroy; + + this->certs = linked_list_create(); + this->shared = linked_list_create(); + this->private = linked_list_create(); + this->mutex = mutex_create(MUTEX_RECURSIVE); + + load_certs(this); + load_secrets(this); + + this->cachecrl = FALSE; + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_cred.h b/src/charon/plugins/stroke/stroke_cred.h new file mode 100644 index 000000000..1b9ef986e --- /dev/null +++ b/src/charon/plugins/stroke/stroke_cred.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_cred stroke_cred + * @{ @ingroup stroke + */ + +#ifndef STROKE_CRED_H_ +#define STROKE_CRED_H_ + +#include <stroke_msg.h> +#include <credentials/credential_set.h> +#include <credentials/certificates/certificate.h> + +typedef struct stroke_cred_t stroke_cred_t; + +/** + * Stroke in-memory credential storage. + */ +struct stroke_cred_t { + + /** + * Implements credential_set_t + */ + credential_set_t set; + + /** + * Reread secrets from config files. + * + * @param msg stroke message + */ + void (*reread)(stroke_cred_t *this, stroke_msg_t *msg); + + /** + * Load a CA certificate, and serve it through the credential_set. + * + * @param filename file to load CA cert from + * @return reference to loaded certificate, or NULL + */ + certificate_t* (*load_ca)(stroke_cred_t *this, char *filename); + + /** + * Load a peer certificate and serve it rhrough the credential_set. + * + * @param filename file to load peer cert from + * @return reference to loaded certificate, or NULL + */ + certificate_t* (*load_peer)(stroke_cred_t *this, char *filename); + + /** + * Enable/Disable CRL caching to disk. + * + * @param enabled TRUE to enable, FALSE to disable + */ + void (*cachecrl)(stroke_cred_t *this, bool enabled); + + /** + * Destroy a stroke_cred instance. + */ + void (*destroy)(stroke_cred_t *this); +}; + +/** + * Create a stroke_cred instance. + */ +stroke_cred_t *stroke_cred_create(); + +#endif /* STROKE_CRED_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c new file mode 100644 index 000000000..44699ba0a --- /dev/null +++ b/src/charon/plugins/stroke/stroke_list.c @@ -0,0 +1,729 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_list.h" + +#include <daemon.h> +#include <utils/linked_list.h> +#include <credentials/certificates/x509.h> +#include <credentials/certificates/ac.h> +#include <credentials/certificates/crl.h> + +/* warning intervals for list functions */ +#define CERT_WARNING_INTERVAL 30 /* days */ +#define CRL_WARNING_INTERVAL 7 /* days */ +#define AC_WARNING_INTERVAL 1 /* day */ + +typedef struct private_stroke_list_t private_stroke_list_t; + +/** + * private data of stroke_list + */ +struct private_stroke_list_t { + + /** + * public functions + */ + stroke_list_t public; + + /** + * timestamp of daemon start + */ + time_t uptime; +}; + +/** + * log an IKE_SA to out + */ +static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) +{ + ike_sa_id_t *id = ike_sa->get_id(ike_sa); + + fprintf(out, "%12s[%d]: %N, %H[%D]...%H[%D]\n", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), + ike_sa_state_names, ike_sa->get_state(ike_sa), + ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa), + ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa)); + + if (all) + { + char *ike_proposal = ike_sa->get_proposal(ike_sa); + + fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), + id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "", + id->get_responder_spi(id), id->is_initiator(id) ? "" : "*"); + + + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED) + { + u_int32_t rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY_TIME); + u_int32_t reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH_TIME); + + if (rekey) + { + fprintf(out, ", rekeying in %V", &rekey); + } + if (reauth) + { + fprintf(out, ", reauthentication in %V", &reauth); + } + if (!rekey && !reauth) + { + fprintf(out, ", rekeying disabled"); + } + } + fprintf(out, "\n"); + + if (ike_proposal) + { + fprintf(out, "%12s[%d]: IKE proposal: %s\n", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), + ike_proposal); + } + } +} + +/** + * log an CHILD_SA to out + */ +static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) +{ + u_int32_t rekey, now = time(NULL); + u_int32_t use_in, use_out, use_fwd; + encryption_algorithm_t encr_alg; + integrity_algorithm_t int_alg; + size_t encr_len, int_len; + mode_t mode; + + child_sa->get_stats(child_sa, &mode, &encr_alg, &encr_len, + &int_alg, &int_len, &rekey, &use_in, &use_out, + &use_fwd); + + fprintf(out, "%12s{%d}: %N, %N", + child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + child_sa_state_names, child_sa->get_state(child_sa), + mode_names, mode); + + if (child_sa->get_state(child_sa) == CHILD_INSTALLED) + { + fprintf(out, ", %N SPIs: %.8x_i %.8x_o", + protocol_id_names, child_sa->get_protocol(child_sa), + htonl(child_sa->get_spi(child_sa, TRUE)), + htonl(child_sa->get_spi(child_sa, FALSE))); + + if (all) + { + fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa), + child_sa->get_reqid(child_sa)); + + + if (child_sa->get_protocol(child_sa) == PROTO_ESP) + { + fprintf(out, "%N", encryption_algorithm_names, encr_alg); + + if (encr_len) + { + fprintf(out, "-%d", encr_len); + } + if (int_alg != AUTH_UNDEFINED) + { + fprintf(out, "/"); + } + } + + if (int_alg != AUTH_UNDEFINED) + { + fprintf(out, "%N", integrity_algorithm_names, int_alg); + if (int_len) + { + fprintf(out, "-%d", int_len); + } + } + fprintf(out, ", rekeying "); + + if (rekey) + { + fprintf(out, "in %#V", &now, &rekey); + } + else + { + fprintf(out, "disabled"); + } + + fprintf(out, ", last use: "); + use_in = max(use_in, use_fwd); + if (use_in) + { + fprintf(out, "%ds_i ", now - use_in); + } + else + { + fprintf(out, "no_i "); + } + if (use_out) + { + fprintf(out, "%ds_o ", now - use_out); + } + else + { + fprintf(out, "no_o "); + } + } + } + + fprintf(out, "\n%12s{%d}: %#R=== %#R\n", + child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + child_sa->get_traffic_selectors(child_sa, TRUE), + child_sa->get_traffic_selectors(child_sa, FALSE)); +} + +/** + * Implementation of stroke_list_t.status. + */ +static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all) +{ + enumerator_t *enumerator, *children; + iterator_t *iterator; + host_t *host; + peer_cfg_t *peer_cfg; + ike_cfg_t *ike_cfg; + child_cfg_t *child_cfg; + ike_sa_t *ike_sa; + char *name = NULL, *plugin; + bool found = FALSE; + time_t uptime; + + name = msg->status.name; + + if (all) + { + uptime = time(NULL) - this->uptime; + fprintf(out, "Performance:\n"); + fprintf(out, " uptime: %V, since %#T\n", &uptime, &this->uptime, FALSE); + fprintf(out, " worker threads: %d idle of %d,", + charon->processor->get_idle_threads(charon->processor), + charon->processor->get_total_threads(charon->processor)); + fprintf(out, " job queue load: %d,", + charon->processor->get_job_load(charon->processor)); + fprintf(out, " scheduled events: %d\n", + charon->scheduler->get_job_load(charon->scheduler)); + fprintf(out, " loaded plugins: "); + enumerator = lib->plugins->create_plugin_enumerator(lib->plugins); + while (enumerator->enumerate(enumerator, &plugin)) + { + fprintf(out, "%s ", plugin); + } + enumerator->destroy(enumerator); + fprintf(out, "\n"); + + iterator = charon->kernel_interface->create_address_iterator( + charon->kernel_interface); + fprintf(out, "Listening IP addresses:\n"); + while (iterator->iterate(iterator, (void**)&host)) + { + fprintf(out, " %H\n", host); + } + iterator->destroy(iterator); + + fprintf(out, "Connections:\n"); + enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends); + while (enumerator->enumerate(enumerator, (void**)&peer_cfg)) + { + if (peer_cfg->get_ike_version(peer_cfg) != 2 || + (name && !streq(name, peer_cfg->get_name(peer_cfg)))) + { + continue; + } + + ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); + fprintf(out, "%12s: %s[%D]...%s[%D]\n", peer_cfg->get_name(peer_cfg), + ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg), + ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg)); + /* TODO: list CAs and groups */ + children = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (children->enumerate(children, &child_cfg)) + { + linked_list_t *my_ts, *other_ts; + my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); + other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL); + fprintf(out, "%12s: %#R=== %#R\n", child_cfg->get_name(child_cfg), + my_ts, other_ts); + my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); + other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); + } + children->destroy(children); + } + enumerator->destroy(enumerator); + } + + fprintf(out, "Security Associations:\n"); + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + bool ike_printed = FALSE; + child_sa_t *child_sa; + iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa); + + if (name == NULL || streq(name, ike_sa->get_name(ike_sa))) + { + log_ike_sa(out, ike_sa, all); + found = TRUE; + ike_printed = TRUE; + } + + while (children->iterate(children, (void**)&child_sa)) + { + if (name == NULL || streq(name, child_sa->get_name(child_sa))) + { + if (!ike_printed) + { + log_ike_sa(out, ike_sa, all); + found = TRUE; + ike_printed = TRUE; + } + log_child_sa(out, child_sa, all); + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + + if (!found) + { + if (name) + { + fprintf(out, " no match\n"); + } + else + { + fprintf(out, " none\n"); + } + } +} + +/** + * create a unique certificate list without duplicates + * certicates having the same issuer are grouped together. + */ +static linked_list_t* create_unique_cert_list(certificate_type_t type) +{ + linked_list_t *list = linked_list_create(); + enumerator_t *enumerator = charon->credentials->create_cert_enumerator( + charon->credentials, type, KEY_ANY, + NULL, FALSE); + certificate_t *cert; + + while (enumerator->enumerate(enumerator, (void**)&cert)) + { + iterator_t *iterator = list->create_iterator(list, TRUE); + identification_t *issuer = cert->get_issuer(cert); + bool previous_same, same = FALSE, last = TRUE; + certificate_t *list_cert; + + while (iterator->iterate(iterator, (void**)&list_cert)) + { + /* exit if we have a duplicate? */ + if (list_cert->equals(list_cert, cert)) + { + last = FALSE; + break; + } + /* group certificates with same issuer */ + previous_same = same; + same = list_cert->has_issuer(list_cert, issuer); + if (previous_same && !same) + { + iterator->insert_before(iterator, (void *)cert->get_ref(cert)); + last = FALSE; + break; + } + } + iterator->destroy(iterator); + + if (last) + { + list->insert_last(list, (void *)cert->get_ref(cert)); + } + } + enumerator->destroy(enumerator); + return list; +} + +/** + * list all X.509 certificates matching the flags + */ +static void stroke_list_certs(linked_list_t *list, char *label, + x509_flag_t flags, bool utc, FILE *out) +{ + bool first = TRUE; + time_t now = time(NULL); + enumerator_t *enumerator = list->create_enumerator(list); + certificate_t *cert; + + while (enumerator->enumerate(enumerator, (void**)&cert)) + { + x509_t *x509 = (x509_t*)cert; + x509_flag_t x509_flags = x509->get_flags(x509); + + /* list only if flag is set, or flags == 0 (ignoring self-signed) */ + if ((x509_flags & flags) || (flags == (x509_flags & ~X509_SELF_SIGNED))) + { + enumerator_t *enumerator; + identification_t *altName; + bool first_altName = TRUE; + chunk_t serial = x509->get_serial(x509); + identification_t *authkey = x509->get_authKeyIdentifier(x509); + time_t notBefore, notAfter; + public_key_t *public = cert->get_public_key(cert); + + if (first) + { + fprintf(out, "\n"); + fprintf(out, "List of %s:\n", label); + first = FALSE; + } + fprintf(out, "\n"); + + /* list subjectAltNames */ + enumerator = x509->create_subjectAltName_enumerator(x509); + while (enumerator->enumerate(enumerator, (void**)&altName)) + { + if (first_altName) + { + fprintf(out, " altNames: "); + first_altName = FALSE; + } + else + { + fprintf(out, ", "); + } + fprintf(out, "%D", altName); + } + if (!first_altName) + { + fprintf(out, "\n"); + } + enumerator->destroy(enumerator); + + fprintf(out, " subject: \"%D\"\n", cert->get_subject(cert)); + fprintf(out, " issuer: \"%D\"\n", cert->get_issuer(cert)); + fprintf(out, " serial: %#B\n", &serial); + + /* list validity */ + cert->get_validity(cert, &now, ¬Before, ¬After); + fprintf(out, " validity: not before %#T, ", ¬Before, utc); + if (now < notBefore) + { + fprintf(out, "not valid yet (valid in %#V)\n", &now, ¬Before); + } + else + { + fprintf(out, "ok\n"); + } + fprintf(out, " not after %#T, ", ¬After, utc); + if (now > notAfter) + { + fprintf(out, "expired (%#V ago)\n", &now, ¬After); + } + else + { + fprintf(out, "ok"); + if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24) + { + fprintf(out, " (expires in %#V)", &now, ¬After); + } + fprintf(out, " \n"); + } + + /* list public key information */ + if (public) + { + private_key_t *private = NULL; + identification_t *id, *keyid; + + id = public->get_id(public, ID_PUBKEY_SHA1); + keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1); + + private = charon->credentials->get_private( + charon->credentials, + public->get_type(public), keyid, NULL); + fprintf(out, " pubkey: %N %d bits%s\n", + key_type_names, public->get_type(public), + public->get_keysize(public) * 8, + private ? ", has private key" : ""); + fprintf(out, " keyid: %D\n", keyid); + fprintf(out, " subjkey: %D\n", id); + DESTROY_IF(private); + public->destroy(public); + } + + /* list optional authorityKeyIdentifier */ + if (authkey) + { + fprintf(out, " authkey: %D\n", authkey); + } + } + } + enumerator->destroy(enumerator); +} + +/** + * list all X.509 attribute certificates + */ +static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out) +{ + bool first = TRUE; + time_t thisUpdate, nextUpdate, now = time(NULL); + enumerator_t *enumerator = list->create_enumerator(list); + certificate_t *cert; + + while (enumerator->enumerate(enumerator, (void**)&cert)) + { + ac_t *ac = (ac_t*)cert; + chunk_t serial = ac->get_serial(ac); + chunk_t holderSerial = ac->get_holderSerial(ac); + identification_t *holderIssuer = ac->get_holderIssuer(ac); + identification_t *authkey = ac->get_authKeyIdentifier(ac); + identification_t *entityName = cert->get_subject(cert); + + if (first) + { + fprintf(out, "\n"); + fprintf(out, "List of X.509 Attribute Certificates:\n"); + first = FALSE; + } + fprintf(out, "\n"); + + if (entityName) + { + fprintf(out, " holder: \"%D\"\n", entityName); + } + if (holderIssuer) + { + fprintf(out, " hissuer: \"%D\"\n", holderIssuer); + } + if (holderSerial.ptr) + { + fprintf(out, " hserial: %#B\n", &holderSerial); + } + fprintf(out, " issuer: \"%D\"\n", cert->get_issuer(cert)); + fprintf(out, " serial: %#B\n", &serial); + + /* list validity */ + cert->get_validity(cert, &now, &thisUpdate, &nextUpdate); + fprintf(out, " updates: this %#T\n", &thisUpdate, utc); + fprintf(out, " next %#T, ", &nextUpdate, utc); + if (now > nextUpdate) + { + fprintf(out, "expired (%#V ago)\n", &now, &nextUpdate); + } + else + { + fprintf(out, "ok"); + if (now > nextUpdate - AC_WARNING_INTERVAL * 60 * 60 * 24) + { + fprintf(out, " (expires in %#V)", &now, &nextUpdate); + } + fprintf(out, " \n"); + } + + /* list optional authorityKeyIdentifier */ + if (authkey) + { + fprintf(out, " authkey: %D\n", authkey); + } + } + enumerator->destroy(enumerator); +} + +/** + * list all X.509 CRLs + */ +static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out) +{ + bool first = TRUE; + time_t thisUpdate, nextUpdate, now = time(NULL); + enumerator_t *enumerator = list->create_enumerator(list); + certificate_t *cert; + + while (enumerator->enumerate(enumerator, (void**)&cert)) + { + crl_t *crl = (crl_t*)cert; + chunk_t serial = crl->get_serial(crl); + identification_t *authkey = crl->get_authKeyIdentifier(crl); + + if (first) + { + fprintf(out, "\n"); + fprintf(out, "List of X.509 CRLs:\n"); + first = FALSE; + } + fprintf(out, "\n"); + + fprintf(out, " issuer: \"%D\"\n", cert->get_issuer(cert)); + + /* list optional crlNumber */ + if (serial.ptr) + { + fprintf(out, " serial: %#B\n", &serial); + } + + /* count the number of revoked certificates */ + { + int count = 0; + enumerator_t *enumerator = crl->create_enumerator(crl); + + while (enumerator->enumerate(enumerator, NULL, NULL, NULL)) + { + count++; + } + fprintf(out, " revoked: %d certificate%s\n", count, + (count == 1)? "" : "s"); + enumerator->destroy(enumerator); + } + + /* list validity */ + cert->get_validity(cert, &now, &thisUpdate, &nextUpdate); + fprintf(out, " updates: this %#T\n", &thisUpdate, utc); + fprintf(out, " next %#T, ", &nextUpdate, utc); + if (now > nextUpdate) + { + fprintf(out, "expired (%#V ago)\n", &now, &nextUpdate); + } + else + { + fprintf(out, "ok"); + if (now > nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24) + { + fprintf(out, " (expires in %#V)", &now, &nextUpdate); + } + fprintf(out, " \n"); + } + + /* list optional authorityKeyIdentifier */ + if (authkey) + { + fprintf(out, " authkey: %D\n", authkey); + } + } + enumerator->destroy(enumerator); +} + +/** + * list all OCSP responses + */ +static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out) +{ + bool first = TRUE; + enumerator_t *enumerator = list->create_enumerator(list); + certificate_t *cert; + + while (enumerator->enumerate(enumerator, (void**)&cert)) + { + if (first) + { + fprintf(out, "\n"); + fprintf(out, "List of OCSP responses:\n"); + fprintf(out, "\n"); + first = FALSE; + } + + fprintf(out, " signer: \"%D\"\n", cert->get_issuer(cert)); + } + enumerator->destroy(enumerator); +} + +/** + * Implementation of stroke_list_t.list. + */ +static void list(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out) +{ + linked_list_t *cert_list = NULL; + + if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS)) + { + cert_list = create_unique_cert_list(CERT_X509); + } + if (msg->list.flags & LIST_CERTS) + { + stroke_list_certs(cert_list, "X.509 End Entity Certificates", + 0, msg->list.utc, out); + } + if (msg->list.flags & LIST_CACERTS) + { + stroke_list_certs(cert_list, "X.509 CA Certificates", + X509_CA, msg->list.utc, out); + } + if (msg->list.flags & LIST_OCSPCERTS) + { + stroke_list_certs(cert_list, "X.509 OCSP Signer Certificates", + X509_OCSP_SIGNER, msg->list.utc, out); + } + if (msg->list.flags & LIST_AACERTS) + { + stroke_list_certs(cert_list, "X.509 AA Certificates", + X509_AA, msg->list.utc, out); + } + if (msg->list.flags & LIST_ACERTS) + { + linked_list_t *ac_list = create_unique_cert_list(CERT_X509_AC); + + stroke_list_acerts(ac_list, msg->list.utc, out); + ac_list->destroy_offset(ac_list, offsetof(certificate_t, destroy)); + } + if (msg->list.flags & LIST_CRLS) + { + linked_list_t *crl_list = create_unique_cert_list(CERT_X509_CRL); + + stroke_list_crls(crl_list, msg->list.utc, out); + crl_list->destroy_offset(crl_list, offsetof(certificate_t, destroy)); + } + if (msg->list.flags & LIST_OCSP) + { + linked_list_t *ocsp_list = create_unique_cert_list(CERT_X509_OCSP_RESPONSE); + + stroke_list_ocsp(ocsp_list, msg->list.utc, out); + ocsp_list->destroy_offset(ocsp_list, offsetof(certificate_t, destroy)); + } + DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy)); +} + +/** + * Implementation of stroke_list_t.destroy + */ +static void destroy(private_stroke_list_t *this) +{ + free(this); +} + +/* + * see header file + */ +stroke_list_t *stroke_list_create() +{ + private_stroke_list_t *this = malloc_thing(private_stroke_list_t); + + this->public.list = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))list; + this->public.status = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out,bool))status; + this->public.destroy = (void(*)(stroke_list_t*))destroy; + + this->uptime = time(NULL); + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_list.h b/src/charon/plugins/stroke/stroke_list.h new file mode 100644 index 000000000..dabdbff39 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_list.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_list stroke_list + * @{ @ingroup stroke + */ + +#ifndef STROKE_LIST_H_ +#define STROKE_LIST_H_ + +#include <stroke_msg.h> +#include <library.h> + +typedef struct stroke_list_t stroke_list_t; + +/** + * Log status information to stroke console + */ +struct stroke_list_t { + + /** + * List certificate information to stroke console. + * + * @param msg stroke message + * @param out stroke console stream + */ + void (*list)(stroke_list_t *this, stroke_msg_t *msg, FILE *out); + + /** + * Log status information to stroke console. + * + * @param msg stroke message + * @param out stroke console stream + * @param all TRUE for "statusall" + */ + void (*status)(stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all); + + /** + * Destroy a stroke_list instance. + */ + void (*destroy)(stroke_list_t *this); +}; + +/** + * Create a stroke_list instance. + */ +stroke_list_t *stroke_list_create(); + +#endif /* STROKE_LIST_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_plugin.c b/src/charon/plugins/stroke/stroke_plugin.c new file mode 100644 index 000000000..6933fc074 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_plugin.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_plugin.h" + +#include <library.h> +#include "stroke_socket.h" + +typedef struct private_stroke_plugin_t private_stroke_plugin_t; + +/** + * private data of stroke_plugin + */ +struct private_stroke_plugin_t { + + /** + * public functions + */ + stroke_plugin_t public; + + /** + * stroke socket, receives strokes + */ + stroke_socket_t *socket; +}; + +/** + * Implementation of stroke_plugin_t.destroy + */ +static void destroy(private_stroke_plugin_t *this) +{ + this->socket->destroy(this->socket); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_stroke_plugin_t *this = malloc_thing(private_stroke_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + this->socket = stroke_socket_create(); + if (this->socket == NULL) + { + free(this); + return NULL; + } + return &this->public.plugin; +} + diff --git a/src/charon/control/interfaces/stroke_interface.h b/src/charon/plugins/stroke/stroke_plugin.h index f1b68023a..7ea18b8af 100644 --- a/src/charon/control/interfaces/stroke_interface.h +++ b/src/charon/plugins/stroke/stroke_plugin.h @@ -1,12 +1,5 @@ -/** - * @file stroke_interface.h - * - * @brief Interface of stroke_t. - * - */ - /* - * Copyright (C) 2006 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,43 +11,42 @@ * 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. + * + * $Id: stroke.h 3589 2008-03-13 14:14:44Z martin $ */ -#ifndef STROKE_INTERFACE_H_ -#define STROKE_INTERFACE_H_ +/** + * @defgroup stroke stroke + * @ingroup cplugins + * + * @defgroup stroke_plugin stroke_plugin + * @{ @ingroup stroke + */ + +#ifndef STROKE_PLUGIN_H_ +#define STROKE_PLUGIN_H_ -typedef struct stroke_interface_t stroke_interface_t; +#include <plugins/plugin.h> -#include <control/interfaces/interface.h> +typedef struct stroke_plugin_t stroke_plugin_t; /** - * @brief Simple configuration interface using unix-sockets. - * + * strongSwan 2.x style configuration and control interface. + * * Stroke is a home-brewed communication interface inspired by whack. It * uses a unix socket (/var/run/charon.ctl). - * - * @b Constructors: - * - stroke_create() - * - * @ingroup interfaces */ -struct stroke_interface_t { - +struct stroke_plugin_t { + /** - * implements interface_t. + * implements plugin interface */ - interface_t interface; + plugin_t plugin; }; - /** - * @brief Create the stroke interface and listen on the socket. - * - * @return interface_t for the stroke interface - * - * @ingroup interfaces + * Instanciate stroke plugin. */ -interface_t *interface_create(void); - -#endif /* STROKE_INTERFACE_H_ */ +plugin_t *plugin_create(); +#endif /* STROKE_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_shared_key.c b/src/charon/plugins/stroke/stroke_shared_key.c new file mode 100644 index 000000000..9c21eb830 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_shared_key.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_shared_key.h" + +#include <utils/linked_list.h> + +typedef struct private_stroke_shared_key_t private_stroke_shared_key_t; + +/** + * private data of shared_key + */ +struct private_stroke_shared_key_t { + + /** + * implements shared_key_t + */ + stroke_shared_key_t public; + + /** + * type of this key + */ + shared_key_type_t type; + + /** + * data of the key + */ + chunk_t key; + + /** + * list of key owners, as identification_t + */ + linked_list_t *owners; + + /** + * reference counter + */ + refcount_t ref; +}; + +/** + * Implementation of shared_key_t.get_type. + */ +static shared_key_type_t get_type(private_stroke_shared_key_t *this) +{ + return this->type; +} + +/** + * Implementation of shared_key_t.get_ref. + */ +static private_stroke_shared_key_t* get_ref(private_stroke_shared_key_t *this) +{ + ref_get(&this->ref); + return this; +} + +/** + * Implementation of shared_key_t.get_key. + */ +static chunk_t get_key(private_stroke_shared_key_t *this) +{ + return this->key; +} + +/** + * Implementation of stroke_shared_key_t.has_owner. + */ +static id_match_t has_owner(private_stroke_shared_key_t *this, identification_t *owner) +{ + enumerator_t *enumerator; + id_match_t match, best = ID_MATCH_NONE; + identification_t *current; + + enumerator = this->owners->create_enumerator(this->owners); + while (enumerator->enumerate(enumerator, ¤t)) + { + match = owner->matches(owner, current); + if (match > best) + { + best = match; + } + } + enumerator->destroy(enumerator); + return best; +} +/** + * Implementation of stroke_shared_key_t.add_owner. + */ +static void add_owner(private_stroke_shared_key_t *this, identification_t *owner) +{ + this->owners->insert_last(this->owners, owner); +} + +/** + * Implementation of stroke_shared_key_t.destroy + */ +static void destroy(private_stroke_shared_key_t *this) +{ + if (ref_put(&this->ref)) + { + this->owners->destroy_offset(this->owners, offsetof(identification_t, destroy)); + chunk_free(&this->key); + free(this); + } +} + +/** + * create a shared key + */ +stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key) +{ + private_stroke_shared_key_t *this = malloc_thing(private_stroke_shared_key_t); + + this->public.shared.get_type = (shared_key_type_t(*)(shared_key_t*))get_type; + this->public.shared.get_key = (chunk_t(*)(shared_key_t*))get_key; + this->public.shared.get_ref = (shared_key_t*(*)(shared_key_t*))get_ref; + this->public.shared.destroy = (void(*)(shared_key_t*))destroy; + this->public.add_owner = (void(*)(stroke_shared_key_t*, identification_t *owner))add_owner; + this->public.has_owner = (id_match_t(*)(stroke_shared_key_t*, identification_t *owner))has_owner; + + this->owners = linked_list_create(); + this->type = type; + this->key = key; + this->ref = 1; + + return &this->public; +} diff --git a/src/charon/plugins/stroke/stroke_shared_key.h b/src/charon/plugins/stroke/stroke_shared_key.h new file mode 100644 index 000000000..e93d8cee2 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_shared_key.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_shared_key stroke_shared_key + * @{ @ingroup stroke + */ + +#ifndef STROKE_SHARED_KEY_H_ +#define STROKE_SHARED_KEY_H_ + +#include <utils/identification.h> +#include <credentials/keys/shared_key.h> + +typedef struct stroke_shared_key_t stroke_shared_key_t; + +/** + * Shared key implementation for keys read from ipsec.secrets + */ +struct stroke_shared_key_t { + + /** + * Implements the shared_key_t interface. + */ + shared_key_t shared; + + /** + * Add an owner to the key. + * + * @param owner owner to add + */ + void (*add_owner)(stroke_shared_key_t *this, identification_t *owner); + + /** + * Check if a key has a specific owner. + * + * @param owner owner to check + * @return best match found + */ + id_match_t (*has_owner)(stroke_shared_key_t *this, identification_t *owner); +}; + +/** + * Create a stroke_shared_key instance. + */ +stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key); + +#endif /* STROKE_SHARED_KEY_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c new file mode 100644 index 000000000..92e295a0c --- /dev/null +++ b/src/charon/plugins/stroke/stroke_socket.c @@ -0,0 +1,602 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#include "stroke_socket.h" + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include <processing/jobs/callback_job.h> +#include <daemon.h> + +#include "stroke_config.h" +#include "stroke_control.h" +#include "stroke_cred.h" +#include "stroke_ca.h" +#include "stroke_attribute.h" +#include "stroke_list.h" + +typedef struct stroke_job_context_t stroke_job_context_t; +typedef struct private_stroke_socket_t private_stroke_socket_t; + +/** + * private data of stroke_socket + */ +struct private_stroke_socket_t { + + /** + * public functions + */ + stroke_socket_t public; + + /** + * Unix socket to listen for strokes + */ + int socket; + + /** + * job accepting stroke messages + */ + callback_job_t *job; + + /** + * configuration backend + */ + stroke_config_t *config; + + /** + * attribute provider + */ + stroke_attribute_t *attribute; + + /** + * controller to control daemon + */ + stroke_control_t *control; + + /** + * credential set + */ + stroke_cred_t *cred; + + /** + * CA sections + */ + stroke_ca_t *ca; + + /** + * Status information logging + */ + stroke_list_t *list; +}; + +/** + * job context to pass to processing thread + */ +struct stroke_job_context_t { + + /** + * file descriptor to read from + */ + int fd; + + /** + * global stroke interface + */ + private_stroke_socket_t *this; +}; + +/** + * Helper function which corrects the string pointers + * in a stroke_msg_t. Strings in a stroke_msg sent over "wire" + * contains RELATIVE addresses (relative to the beginning of the + * stroke_msg). They must be corrected if they reach our address + * space... + */ +static void pop_string(stroke_msg_t *msg, char **string) +{ + if (*string == NULL) + { + return; + } + + /* check for sanity of string pointer and string */ + if (string < (char**)msg || + string > (char**)msg + sizeof(stroke_msg_t) || + (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) || + (unsigned long)*string > msg->length) + { + *string = "(invalid pointer in stroke msg)"; + } + else + { + *string = (char*)msg + (unsigned long)*string; + } +} + +/** + * Pop the strings of a stroke_end_t struct and log them for debugging purposes + */ +static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end) +{ + pop_string(msg, &end->address); + pop_string(msg, &end->subnets); + pop_string(msg, &end->sourceip); + pop_string(msg, &end->id); + pop_string(msg, &end->cert); + pop_string(msg, &end->ca); + pop_string(msg, &end->groups); + pop_string(msg, &end->updown); + + DBG2(DBG_CFG, " %s=%s", label, end->address); + DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets); + DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip); + DBG2(DBG_CFG, " %sid=%s", label, end->id); + DBG2(DBG_CFG, " %scert=%s", label, end->cert); + DBG2(DBG_CFG, " %sca=%s", label, end->ca); + DBG2(DBG_CFG, " %sgroups=%s", label, end->groups); + DBG2(DBG_CFG, " %supdown=%s", label, end->updown); +} + +/** + * Add a connection to the configuration list + */ +static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg) +{ + pop_string(msg, &msg->add_conn.name); + DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name); + + DBG2(DBG_CFG, "conn %s", msg->add_conn.name); + pop_end(msg, "left", &msg->add_conn.me); + pop_end(msg, "right", &msg->add_conn.other); + pop_string(msg, &msg->add_conn.algorithms.ike); + pop_string(msg, &msg->add_conn.algorithms.esp); + pop_string(msg, &msg->add_conn.ikeme.mediated_by); + pop_string(msg, &msg->add_conn.ikeme.peerid); + DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike); + DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp); + DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no"); + DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by); + DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid); + + this->config->add(this->config, msg); + this->attribute->add_pool(this->attribute, msg); +} + +/** + * Delete a connection from the list + */ +static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg) +{ + pop_string(msg, &msg->del_conn.name); + DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name); + + this->config->del(this->config, msg); + this->attribute->del_pool(this->attribute, msg); +} + +/** + * initiate a connection by name + */ +static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->initiate.name); + DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name); + + this->control->initiate(this->control, msg, out); +} + +/** + * terminate a connection by name + */ +static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->terminate.name); + DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name); + + this->control->terminate(this->control, msg, out); +} + +/** + * route a policy (install SPD entries) + */ +static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->route.name); + DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name); + + this->control->route(this->control, msg, out); +} + +/** + * unroute a policy + */ +static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->terminate.name); + DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name); + + this->control->unroute(this->control, msg, out); +} + +/** + * Add a ca information record to the cainfo list + */ +static void stroke_add_ca(private_stroke_socket_t *this, + stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->add_ca.name); + DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name); + + pop_string(msg, &msg->add_ca.cacert); + pop_string(msg, &msg->add_ca.crluri); + pop_string(msg, &msg->add_ca.crluri2); + pop_string(msg, &msg->add_ca.ocspuri); + pop_string(msg, &msg->add_ca.ocspuri2); + pop_string(msg, &msg->add_ca.certuribase); + DBG2(DBG_CFG, "ca %s", msg->add_ca.name); + DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert); + DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri); + DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2); + DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri); + DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2); + DBG2(DBG_CFG, " certuribase=%s", msg->add_ca.certuribase); + + this->ca->add(this->ca, msg); +} + +/** + * Delete a ca information record from the cainfo list + */ +static void stroke_del_ca(private_stroke_socket_t *this, + stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->del_ca.name); + DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name); + + this->ca->del(this->ca, msg); +} + + +/** + * show status of daemon + */ +static void stroke_status(private_stroke_socket_t *this, + stroke_msg_t *msg, FILE *out, bool all) +{ + pop_string(msg, &(msg->status.name)); + + this->list->status(this->list, msg, out, all); +} + +/** + * list various information + */ +static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + if (msg->list.flags & LIST_CAINFOS) + { + this->ca->list(this->ca, msg, out); + } + this->list->list(this->list, msg, out); +} + +/** + * reread various information + */ +static void stroke_reread(private_stroke_socket_t *this, + stroke_msg_t *msg, FILE *out) +{ + this->cred->reread(this->cred, msg); +} + +/** + * purge various information + */ +static void stroke_purge(private_stroke_socket_t *this, + stroke_msg_t *msg, FILE *out) +{ + charon->credentials->flush_cache(charon->credentials, + CERT_X509_OCSP_RESPONSE); +} + +signal_t get_signal_from_logtype(char *type) +{ + if (strcasecmp(type, "any") == 0) return SIG_ANY; + else if (strcasecmp(type, "mgr") == 0) return DBG_MGR; + else if (strcasecmp(type, "ike") == 0) return DBG_IKE; + else if (strcasecmp(type, "chd") == 0) return DBG_CHD; + else if (strcasecmp(type, "job") == 0) return DBG_JOB; + else if (strcasecmp(type, "cfg") == 0) return DBG_CFG; + else if (strcasecmp(type, "knl") == 0) return DBG_KNL; + else if (strcasecmp(type, "net") == 0) return DBG_NET; + else if (strcasecmp(type, "enc") == 0) return DBG_ENC; + else if (strcasecmp(type, "lib") == 0) return DBG_LIB; + else return -1; +} + +/** + * set the verbosity debug output + */ +static void stroke_loglevel(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + signal_t signal; + + pop_string(msg, &(msg->loglevel.type)); + DBG1(DBG_CFG, "received stroke: loglevel %d for %s", + msg->loglevel.level, msg->loglevel.type); + + signal = get_signal_from_logtype(msg->loglevel.type); + if (signal < 0) + { + fprintf(out, "invalid type (%s)!\n", msg->loglevel.type); + return; + } + + charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level); + charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level); +} + +/** + * set various config options + */ +static void stroke_config(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + this->cred->cachecrl(this->cred, msg->config.cachecrl); +} + +/** + * destroy a job context + */ +static void stroke_job_context_destroy(stroke_job_context_t *this) +{ + if (this->fd) + { + close(this->fd); + } + free(this); +} + +/** + * process a stroke request from the socket pointed by "fd" + */ +static job_requeue_t process(stroke_job_context_t *ctx) +{ + stroke_msg_t *msg; + u_int16_t msg_length; + ssize_t bytes_read; + FILE *out; + private_stroke_socket_t *this = ctx->this; + int strokefd = ctx->fd; + + /* peek the length */ + bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK); + if (bytes_read != sizeof(msg_length)) + { + DBG1(DBG_CFG, "reading length of stroke message failed: %s", + strerror(errno)); + return JOB_REQUEUE_NONE; + } + + /* read message */ + msg = alloca(msg_length); + bytes_read = recv(strokefd, msg, msg_length, 0); + if (bytes_read != msg_length) + { + DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno)); + return JOB_REQUEUE_NONE; + } + + out = fdopen(strokefd, "w"); + if (out == NULL) + { + DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno)); + return JOB_REQUEUE_NONE; + } + + DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length); + + switch (msg->type) + { + case STR_INITIATE: + stroke_initiate(this, msg, out); + break; + case STR_ROUTE: + stroke_route(this, msg, out); + break; + case STR_UNROUTE: + stroke_unroute(this, msg, out); + break; + case STR_TERMINATE: + stroke_terminate(this, msg, out); + break; + case STR_STATUS: + stroke_status(this, msg, out, FALSE); + break; + case STR_STATUS_ALL: + stroke_status(this, msg, out, TRUE); + break; + case STR_ADD_CONN: + stroke_add_conn(this, msg); + break; + case STR_DEL_CONN: + stroke_del_conn(this, msg); + break; + case STR_ADD_CA: + stroke_add_ca(this, msg, out); + break; + case STR_DEL_CA: + stroke_del_ca(this, msg, out); + break; + case STR_LOGLEVEL: + stroke_loglevel(this, msg, out); + break; + case STR_CONFIG: + stroke_config(this, msg, out); + break; + case STR_LIST: + stroke_list(this, msg, out); + break; + case STR_REREAD: + stroke_reread(this, msg, out); + break; + case STR_PURGE: + stroke_purge(this, msg, out); + break; + default: + DBG1(DBG_CFG, "received unknown stroke"); + break; + } + fclose(out); + /* fclose() closes underlying FD */ + ctx->fd = 0; + return JOB_REQUEUE_NONE; +} + +/** + * Implementation of private_stroke_socket_t.stroke_receive. + */ +static job_requeue_t receive(private_stroke_socket_t *this) +{ + struct sockaddr_un strokeaddr; + int strokeaddrlen = sizeof(strokeaddr); + int strokefd; + int oldstate; + callback_job_t *job; + stroke_job_context_t *ctx; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen); + pthread_setcancelstate(oldstate, NULL); + + if (strokefd < 0) + { + DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno)); + return JOB_REQUEUE_FAIR; + } + + ctx = malloc_thing(stroke_job_context_t); + ctx->fd = strokefd; + ctx->this = this; + job = callback_job_create((callback_job_cb_t)process, + ctx, (void*)stroke_job_context_destroy, this->job); + charon->processor->queue_job(charon->processor, (job_t*)job); + + return JOB_REQUEUE_FAIR; +} + + +/** + * initialize and open stroke socket + */ +static bool open_socket(private_stroke_socket_t *this) +{ + struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET}; + mode_t old; + + /* set up unix socket */ + this->socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (this->socket == -1) + { + DBG1(DBG_CFG, "could not create stroke socket"); + return FALSE; + } + + unlink(socket_addr.sun_path); + old = umask(~(S_IRWXU | S_IRWXG)); + if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0) + { + DBG1(DBG_CFG, "could not bind stroke socket: %s", strerror(errno)); + close(this->socket); + return FALSE; + } + umask(old); + if (chown(socket_addr.sun_path, charon->uid, charon->gid) != 0) + { + DBG1(DBG_CFG, "changing stroke socket permissions failed: %s", + strerror(errno)); + } + + if (listen(this->socket, 0) < 0) + { + DBG1(DBG_CFG, "could not listen on stroke socket: %s", strerror(errno)); + close(this->socket); + unlink(socket_addr.sun_path); + return FALSE; + } + return TRUE; +} + +/** + * Implementation of stroke_socket_t.destroy + */ +static void destroy(private_stroke_socket_t *this) +{ + this->job->cancel(this->job); + charon->credentials->remove_set(charon->credentials, &this->ca->set); + charon->credentials->remove_set(charon->credentials, &this->cred->set); + charon->backends->remove_backend(charon->backends, &this->config->backend); + charon->attributes->remove_provider(charon->attributes, &this->attribute->provider); + this->cred->destroy(this->cred); + this->ca->destroy(this->ca); + this->config->destroy(this->config); + this->attribute->destroy(this->attribute); + this->control->destroy(this->control); + this->list->destroy(this->list); + free(this); +} + +/* + * see header file + */ +stroke_socket_t *stroke_socket_create() +{ + private_stroke_socket_t *this = malloc_thing(private_stroke_socket_t); + + this->public.destroy = (void(*)(stroke_socket_t*))destroy; + + if (!open_socket(this)) + { + free(this); + return NULL; + } + + this->cred = stroke_cred_create(); + this->attribute = stroke_attribute_create(); + this->ca = stroke_ca_create(this->cred); + this->config = stroke_config_create(this->ca, this->cred); + this->control = stroke_control_create(); + this->list = stroke_list_create(); + + charon->credentials->add_set(charon->credentials, &this->ca->set); + charon->credentials->add_set(charon->credentials, &this->cred->set); + charon->backends->add_backend(charon->backends, &this->config->backend); + charon->attributes->add_provider(charon->attributes, &this->attribute->provider); + + this->job = callback_job_create((callback_job_cb_t)receive, + this, NULL, NULL); + charon->processor->queue_job(charon->processor, (job_t*)this->job); + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_socket.h b/src/charon/plugins/stroke/stroke_socket.h new file mode 100644 index 000000000..7bc96686f --- /dev/null +++ b/src/charon/plugins/stroke/stroke_socket.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_socket stroke_socket + * @{ @ingroup stroke + */ + +#ifndef STROKE_SOCKET_H_ +#define STROKE_SOCKET_H_ + +typedef struct stroke_socket_t stroke_socket_t; + +/** + * Stroke socket, opens UNIX communication socket, reads and dispatches. + */ +struct stroke_socket_t { + + /** + * Destroy a stroke_socket instance. + */ + void (*destroy)(stroke_socket_t *this); +}; + +/** + * Create a stroke_socket instance. + */ +stroke_socket_t *stroke_socket_create(); + +#endif /* STROKE_SOCKET_H_ @}*/ diff --git a/src/charon/plugins/uci/Makefile.am b/src/charon/plugins/uci/Makefile.am new file mode 100644 index 000000000..47a55ae17 --- /dev/null +++ b/src/charon/plugins/uci/Makefile.am @@ -0,0 +1,13 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-uci.la +libstrongswan_uci_la_SOURCES = \ + uci_plugin.h uci_plugin.c uci_parser.h uci_parser.c \ + uci_config.h uci_config.c uci_creds.h uci_creds.c +libstrongswan_uci_la_LDFLAGS = -module +libstrongswan_uci_la_LIBADD = -luci + + diff --git a/src/charon/plugins/uci/Makefile.in b/src/charon/plugins/uci/Makefile.in new file mode 100644 index 000000000..297f25768 --- /dev/null +++ b/src/charon/plugins/uci/Makefile.in @@ -0,0 +1,501 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/uci +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_uci_la_DEPENDENCIES = +am_libstrongswan_uci_la_OBJECTS = uci_plugin.lo uci_parser.lo \ + uci_config.lo uci_creds.lo +libstrongswan_uci_la_OBJECTS = $(am_libstrongswan_uci_la_OBJECTS) +libstrongswan_uci_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_uci_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_uci_la_SOURCES) +DIST_SOURCES = $(libstrongswan_uci_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-uci.la +libstrongswan_uci_la_SOURCES = \ + uci_plugin.h uci_plugin.c uci_parser.h uci_parser.c \ + uci_config.h uci_config.c uci_creds.h uci_creds.c + +libstrongswan_uci_la_LDFLAGS = -module +libstrongswan_uci_la_LIBADD = -luci +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/uci/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/uci/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-uci.la: $(libstrongswan_uci_la_OBJECTS) $(libstrongswan_uci_la_DEPENDENCIES) + $(libstrongswan_uci_la_LINK) -rpath $(plugindir) $(libstrongswan_uci_la_OBJECTS) $(libstrongswan_uci_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_creds.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/plugins/uci/uci_config.c b/src/charon/plugins/uci/uci_config.c new file mode 100644 index 000000000..cc44eaa9b --- /dev/null +++ b/src/charon/plugins/uci/uci_config.c @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +#define _GNU_SOURCE +#include <string.h> + +#include "uci_config.h" +#include "uci_parser.h" + +#include <daemon.h> + +typedef struct private_uci_config_t private_uci_config_t; + +/** + * Private data of an uci_config_t object + */ +struct private_uci_config_t { + + /** + * Public part + */ + uci_config_t public; + + /** + * UCI parser context + */ + uci_parser_t *parser; +}; + +/** + * enumerator implementation for create_peer_cfg_enumerator + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** currently enumerated peer config */ + peer_cfg_t *peer_cfg; + /** inner uci_parser section enumerator */ + enumerator_t *inner; +} peer_enumerator_t; + +/** + * create a proposal from a string, with fallback to default + */ +static proposal_t *create_proposal(char *string, protocol_id_t proto) +{ + proposal_t *proposal = NULL; + + if (string) + { + proposal = proposal_create_from_string(proto, string); + } + if (!proposal) + { /* UCI default is aes/sha1 only */ + if (proto == PROTO_IKE) + { + proposal = proposal_create_from_string(proto, + "aes128-aes192-aes256-sha1-modp1536-modp2048"); + } + else + { + proposal = proposal_create_from_string(proto, + "aes128-aes192-aes256-sha1"); + } + } + return proposal; +} + +/** + * create an identity, with fallback to %any + */ +static identification_t *create_id(char *string) +{ + identification_t *id = NULL; + + if (string) + { + id = identification_create_from_string(string); + } + if (!id) + { + id = identification_create_from_encoding(ID_ANY, chunk_empty); + } + return id; +} + +/** + * create an traffic selector, fallback to dynamic + */ +static traffic_selector_t *create_ts(char *string) +{ + if (string) + { + int netbits = 32; + host_t *net; + char *pos; + + string = strdupa(string); + pos = strchr(string, '/'); + if (pos) + { + *pos++ = '\0'; + netbits = atoi(pos); + } + else + { + if (strchr(string, ':')) + { + netbits = 128; + } + } + net = host_create_from_string(string, 0); + if (net) + { + return traffic_selector_create_from_subnet(net, netbits, 0, 0); + } + } + return traffic_selector_create_dynamic(0, 0, 65535); +} + +/** + * create a rekey time from a string with hours, with fallback + */ +static u_int create_rekey(char *string) +{ + u_int rekey = 0; + + if (string) + { + rekey = atoi(string); + if (rekey) + { + return rekey * 3600; + } + } + /* every 12 hours */ + return 12 * 3600; +} + +/** + * Implementation of peer_enumerator_t.public.enumerate + */ +static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) +{ + char *name, *ike_proposal, *esp_proposal, *ike_rekey, *esp_rekey; + char *local_id, *local_addr, *local_net; + char *remote_id, *remote_addr, *remote_net; + child_cfg_t *child_cfg; + ike_cfg_t *ike_cfg; + + /* defaults */ + name = "unnamed"; + local_id = NULL; + remote_id = NULL; + local_addr = "0.0.0.0"; + remote_addr = "0.0.0.0"; + local_net = NULL; + remote_net = NULL; + ike_proposal = NULL; + esp_proposal = NULL; + ike_rekey = NULL; + esp_rekey = NULL; + + if (this->inner->enumerate(this->inner, &name, &local_id, &remote_id, + &local_addr, &remote_addr, &local_net, &remote_net, + &ike_proposal, &esp_proposal, &ike_rekey, &esp_rekey)) + { + DESTROY_IF(this->peer_cfg); + ike_cfg = ike_cfg_create(FALSE, FALSE, local_addr, remote_addr); + ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); + this->peer_cfg = peer_cfg_create( + name, 2, ike_cfg, create_id(local_id), create_id(remote_id), + CERT_SEND_IF_ASKED, UNIQUE_NO, CONF_AUTH_PSK, + 0, 0, /* EAP method, vendor */ + 1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */ + 1800, 900, /* jitter, overtime */ + TRUE, 60, /* mobike, dpddelay */ + NULL, NULL, /* vip, pool */ + FALSE, NULL, NULL); /* mediation, med by, peer id */ + child_cfg = child_cfg_create(name, + create_rekey(esp_rekey) + 300, create_rekey(ike_rekey), 300, + NULL, TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE); + child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP)); + child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net)); + child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net)); + this->peer_cfg->add_child_cfg(this->peer_cfg, child_cfg); + *cfg = this->peer_cfg; + return TRUE; + } + return FALSE; +} + +/** + * Implementation of peer_enumerator_t.public.destroy + */ +static void peer_enumerator_destroy(peer_enumerator_t *this) +{ + DESTROY_IF(this->peer_cfg); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of backend_t.create_peer_cfg_enumerator. + */ +static enumerator_t* create_peer_cfg_enumerator(private_uci_config_t *this, + identification_t *me, + identification_t *other) +{ + peer_enumerator_t *e = malloc_thing(peer_enumerator_t); + + e->public.enumerate = (void*)peer_enumerator_enumerate; + e->public.destroy = (void*)peer_enumerator_destroy; + e->peer_cfg = NULL; + e->inner = this->parser->create_section_enumerator(this->parser, + "local_id", "remote_id", "local_addr", "remote_addr", + "local_net", "remote_net", "ike_proposal", "esp_proposal", + "ike_rekey", "esp_rekey", NULL); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * enumerator implementation for create_ike_cfg_enumerator + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** currently enumerated ike config */ + ike_cfg_t *ike_cfg; + /** inner uci_parser section enumerator */ + enumerator_t *inner; +} ike_enumerator_t; + +/** + * Implementation of peer_enumerator_t.public.enumerate + */ +static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg) +{ + char *local_addr, *remote_addr, *ike_proposal; + + /* defaults */ + local_addr = "0.0.0.0"; + remote_addr = "0.0.0.0"; + ike_proposal = NULL; + + if (this->inner->enumerate(this->inner, NULL, + &local_addr, &remote_addr, &ike_proposal)) + { + DESTROY_IF(this->ike_cfg); + this->ike_cfg = ike_cfg_create(FALSE, FALSE, local_addr, remote_addr); + this->ike_cfg->add_proposal(this->ike_cfg, + create_proposal(ike_proposal, PROTO_IKE)); + + *cfg = this->ike_cfg; + return TRUE; + } + return FALSE; +} + +/** + * Implementation of ike_enumerator_t.public.destroy + */ +static void ike_enumerator_destroy(ike_enumerator_t *this) +{ + DESTROY_IF(this->ike_cfg); + this->inner->destroy(this->inner); + free(this); +} + +/** + * Implementation of backend_t.create_ike_cfg_enumerator. + */ +static enumerator_t* create_ike_cfg_enumerator(private_uci_config_t *this, + host_t *me, host_t *other) +{ + ike_enumerator_t *e = malloc_thing(ike_enumerator_t); + + e->public.enumerate = (void*)ike_enumerator_enumerate; + e->public.destroy = (void*)ike_enumerator_destroy; + e->ike_cfg = NULL; + e->inner = this->parser->create_section_enumerator(this->parser, + "local_addr", "remote_addr", "ike_proposal", NULL); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * implements backend_t.get_peer_cfg_by_name. + */ +static peer_cfg_t *get_peer_cfg_by_name(private_uci_config_t *this, char *name) +{ + enumerator_t *enumerator; + peer_cfg_t *current, *found = NULL; + + enumerator = create_peer_cfg_enumerator(this, NULL, NULL); + if (enumerator) + { + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(name, current->get_name(current))) + { + found = current->get_ref(current); + break; + } + } + enumerator->destroy(enumerator); + } + return found; +} + +/** + * Implementation of uci_config_t.destroy. + */ +static void destroy(private_uci_config_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +uci_config_t *uci_config_create(uci_parser_t *parser) +{ + private_uci_config_t *this = malloc_thing(private_uci_config_t); + + this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; + this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; + this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; + this->public.destroy = (void(*)(uci_config_t*))destroy; + + this->parser = parser; + + return &this->public; +} + diff --git a/src/charon/plugins/uci/uci_config.h b/src/charon/plugins/uci/uci_config.h new file mode 100644 index 000000000..4d8b286c6 --- /dev/null +++ b/src/charon/plugins/uci/uci_config.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008 Thomas Kallenberg + * 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. + * + * $Id$ + */ + +/** + * @defgroup uci_config_t uci_config + * @{ @ingroup uci + */ + +#ifndef UCI_CONFIG_H_ +#define UCI_CONFIG_H_ + +#include "uci_parser.h" + +#include <config/backend.h> + +typedef struct uci_config_t uci_config_t; + +/** + * OpenWRT UCI configuration backend. + */ +struct uci_config_t { + + /** + * Implements backend_t interface + */ + backend_t backend; + + /** + * Destroy the backend. + */ + void (*destroy)(uci_config_t *this); +}; + +/** + * Create a UCI based configuration backend. + * + * @param parser UCI parser to use + * @return configuration backend + */ +uci_config_t *uci_config_create(uci_parser_t *parser); + +#endif /* UCI_CONFIG_H_ @}*/ diff --git a/src/charon/plugins/uci/uci_creds.c b/src/charon/plugins/uci/uci_creds.c new file mode 100644 index 000000000..60f6fc934 --- /dev/null +++ b/src/charon/plugins/uci/uci_creds.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008 Tobias Brunner + * 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. + * + * $Id$ + */ + +#include "uci_creds.h" + +#include <daemon.h> +#include <credentials/keys/shared_key.h> +#include <utils/identification.h> + +typedef struct private_uci_creds_t private_uci_creds_t; + +/** + * Private data of an uci_creds_t object + */ +struct private_uci_creds_t { + /** + * Public part + */ + uci_creds_t public; + + /** + * UCI parser context + */ + uci_parser_t *parser; +}; + +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inneer UCI enumerator */ + enumerator_t *inner; + /** currently enumerated shared shared */ + shared_key_t *current; + /** local ID to match */ + identification_t *me; + /** remote ID to match */ + identification_t *other; +} shared_enumerator_t; + +/** + * Implementation of shared_enumerator_t.public.enumerate + */ +static bool shared_enumerator_enumerate(shared_enumerator_t *this, + shared_key_t **key, id_match_t *me, id_match_t *other) +{ + char *local_id, *remote_id, *psk; + identification_t *local, *remote; + + while (TRUE) + { + /* defaults */ + local_id = "%any"; + remote_id = "%any"; + psk = NULL; + + if (!this->inner->enumerate(this->inner, NULL, + &local_id, &remote_id, &psk)) + { + return FALSE; + } + if (psk == NULL) + { + continue; + } + if (me) + { + local = identification_create_from_string(local_id); + if (!local) + { + continue; + } + *me = this->me ? this->me->matches(this->me, local) + : ID_MATCH_ANY; + local->destroy(local); + if (!*me) + { + continue; + } + } + if (other) + { + remote = identification_create_from_string(remote_id); + if (!remote) + { + continue; + } + *other = this->other ? this->other->matches(this->other, remote) + : ID_MATCH_ANY; + remote->destroy(remote); + if (!*other) + { + continue; + } + } + break; + } + DESTROY_IF(this->current); + this->current = shared_key_create(SHARED_IKE, + chunk_clone(chunk_create(psk, strlen(psk)))); + *key = this->current; + return TRUE; +} + +/** + * Implementation of shared_enumerator_t.public.destroy + */ +static void shared_enumerator_destroy(shared_enumerator_t *this) +{ + this->inner->destroy(this->inner); + DESTROY_IF(this->current); + free(this); +} + +/** + * Implementation of backend_t.create_shared_cfg_enumerator. + */ +static enumerator_t* create_shared_enumerator(private_uci_creds_t *this, + shared_key_type_t type, + identification_t *me, + identification_t *other) +{ + shared_enumerator_t *e; + + if (type != SHARED_IKE) + { + return NULL; + } + + e = malloc_thing(shared_enumerator_t); + e->current = NULL; + e->public.enumerate = (void*)shared_enumerator_enumerate; + e->public.destroy = (void*)shared_enumerator_destroy; + e->me = me; + e->other = other; + e->inner = this->parser->create_section_enumerator(this->parser, + "local_id", "remote_id", "psk", NULL); + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +/** + * Implementation of uci_creds_t.destroy + */ +static void destroy(private_uci_creds_t *this) +{ + free(this); +} + +uci_creds_t *uci_creds_create(uci_parser_t *parser) +{ + private_uci_creds_t *this = malloc_thing(private_uci_creds_t); + + this->public.credential_set.create_shared_enumerator = (enumerator_t*(*)(credential_set_t*, shared_key_type_t, identification_t*, identification_t*))create_shared_enumerator; + this->public.credential_set.create_private_enumerator = (enumerator_t*(*) (credential_set_t*, key_type_t, identification_t*))return_null; + this->public.credential_set.create_cert_enumerator = (enumerator_t*(*) (credential_set_t*, certificate_type_t, key_type_t,identification_t *, bool))return_null; + this->public.credential_set.create_cdp_enumerator = (enumerator_t*(*) (credential_set_t *,certificate_type_t, identification_t *))return_null; + this->public.credential_set.cache_cert = (void (*)(credential_set_t *, certificate_t *))nop; + this->public.destroy = (void(*) (uci_creds_t*))destroy; + + this->parser = parser; + + return &this->public; +} + diff --git a/src/charon/plugins/uci/uci_creds.h b/src/charon/plugins/uci/uci_creds.h new file mode 100644 index 000000000..cf82f1c07 --- /dev/null +++ b/src/charon/plugins/uci/uci_creds.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008 Thomas Kallenberg + * 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. + * + * $Id$ + */ + +/** + * @defgroup uci_creds_t uci_creds + * @{ @ingroup uci + */ + +#ifndef UCI_CREDS_H_ +#define UCI_CREDS_H_ + +#include "uci_parser.h" + +#include <credentials/credential_set.h> + +typedef struct uci_creds_t uci_creds_t; + +/** + * OpenWRT UCI credential set implementation. + */ +struct uci_creds_t { + + /** + * Implements credential set interface. + */ + credential_set_t credential_set; + + /** + * Destroy the backend. + */ + void (*destroy)(uci_creds_t *this); +}; + +/** + * Create a UCI based credential set. + * + * @param parser UCI parser to use + * @return credential set + */ +uci_creds_t *uci_creds_create(uci_parser_t *parser); + +#endif /* UCI_CREDS_H_ @}*/ diff --git a/src/charon/plugins/uci/uci_parser.c b/src/charon/plugins/uci/uci_parser.c new file mode 100644 index 000000000..796d2993a --- /dev/null +++ b/src/charon/plugins/uci/uci_parser.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008 Thomas Kallenberg + * 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. + * + * $Id$ + */ + +#include "uci_parser.h" + +#include <stdarg.h> + +#include <library.h> +#include <uci.h> + +typedef struct private_uci_parser_t private_uci_parser_t; + +/** + * Private data of an uci_parser_t object + */ +struct private_uci_parser_t { + + /** + * Public part + */ + uci_parser_t public; + + /** + * UCI package name this parser reads + */ + char *package; +}; + +/** + * enumerator implementation create_section_enumerator + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** currently enumerated uci section */ + struct uci_element *current; + /** all uci ipsec config sections */ + struct uci_list *list; + /** uci conntext */ + struct uci_context *ctx; + /** ipsec uci package */ + struct uci_package *package; + /** NULL terminated list of keywords */ + char *keywords[]; +} section_enumerator_t; + +/** + * Implementation of section_enumerator_t.enumerate + */ +static bool section_enumerator_enumerate(section_enumerator_t *this, ...) +{ + struct uci_element *element; + char **value; + va_list args; + int i; + + if (&this->current->list == this->list) + { + return FALSE; + } + + va_start(args, this); + + /* name is first parameter */ + value = va_arg(args, char**); + if (value) + { + *value = uci_to_section(this->current)->type; + } + + /* followed by keyword parameters */ + for (i = 0; this->keywords[i]; i++) + { + value = va_arg(args, char**); + if (value && uci_lookup(this->ctx, &element, this->package, + this->current->name, this->keywords[i]) == UCI_OK) + { + *value = uci_to_option(element)->value; + } + } + va_end(args); + + this->current = list_to_element(this->current->list.next); + return TRUE; +} + +/** + * Implementation of section_enumerator_t.public.destroy + */ +static void section_enumerator_destroy(section_enumerator_t *this) +{ + uci_free_context(this->ctx); + free(this); +} + +/** + * Implementation of backend_t.create_section_enumerator. + */ +static enumerator_t* create_section_enumerator(private_uci_parser_t *this, ...) +{ + section_enumerator_t *e; + va_list args; + int i; + + /* allocate enumerator large enought to hold keyword pointers */ + i = 1; + va_start(args, this); + while (va_arg(args, char*)) + { + i++; + } + va_end(args); + e = malloc(sizeof(section_enumerator_t) + sizeof(char*) * i); + i = 0; + va_start(args, this); + do + { + e->keywords[i] = va_arg(args, char*); + } + while (e->keywords[i++]); + va_end(args); + + e->public.enumerate = (void*)section_enumerator_enumerate; + e->public.destroy = (void*)section_enumerator_destroy; + + /* load uci context */ + e->ctx = uci_alloc_context(); + if (uci_load(e->ctx, this->package, &e->package) != UCI_OK) + { + section_enumerator_destroy(e); + return NULL; + } + e->list = &e->package->sections; + e->current = list_to_element(e->list->next); + if (e->current->type != UCI_TYPE_SECTION) + { + section_enumerator_destroy(e); + return NULL; + } + return &e->public; +} + +/** + * Implementation of uci_parser_t.destroy. + */ +static void destroy(private_uci_parser_t *this) +{ + free(this->package); + free(this); +} + +/** + * Described in header. + */ +uci_parser_t *uci_parser_create(char *package) +{ + private_uci_parser_t *this = malloc_thing(private_uci_parser_t); + + this->public.create_section_enumerator = (enumerator_t*(*)(uci_parser_t*, ...))create_section_enumerator; + this->public.destroy = (void(*)(uci_parser_t*))destroy; + + this->package = strdup(package); + + return &this->public; +} + diff --git a/src/charon/plugins/uci/uci_parser.h b/src/charon/plugins/uci/uci_parser.h new file mode 100644 index 000000000..a8633ca2e --- /dev/null +++ b/src/charon/plugins/uci/uci_parser.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008 Thomas Kallenberg + * 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. + * + * $Id$ + */ + +/** + * @defgroup uci_parser_t uci_parser + * @{ @ingroup uci + */ + +#ifndef UCI_PARSER_H_ +#define UCI_PARSER_H_ + +#include <utils/enumerator.h> + +typedef struct uci_parser_t uci_parser_t; + +/** + * Wrapper to parse UCI sections with an enumerator. + */ +struct uci_parser_t { + + /** + * Create an enumerator over a section. + * + * The enumerator returns a section name followed by values for the keywords + * specified in the variable argument list of this function. + * + * @param ... variable argument list with keywords, NULL terminated + * @return enumerator over sections + */ + enumerator_t* (*create_section_enumerator)(uci_parser_t *this, ...); + + /** + * Destroy the parser. + */ + void (*destroy)(uci_parser_t *this); +}; + +/** + * Create a UCI parser. + * + * @param package UCI package this parser should read + * @return parser context + */ +uci_parser_t *uci_parser_create(char *package); + +#endif /* UCI_PARSER_H_ @}*/ + diff --git a/src/charon/plugins/uci/uci_plugin.c b/src/charon/plugins/uci/uci_plugin.c new file mode 100644 index 000000000..918523826 --- /dev/null +++ b/src/charon/plugins/uci/uci_plugin.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * 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. + * + * $Id$ + */ + +#include "uci_plugin.h" +#include "uci_config.h" +#include "uci_creds.h" + +#include <daemon.h> + +/** + * UCI package name to use for lookups + */ +#define UCI_PACKAGE "strongswan" + +typedef struct private_uci_plugin_t private_uci_plugin_t; + +/** + * private data of uci plugin + */ +struct private_uci_plugin_t { + + /** + * implements plugin interface + */ + uci_plugin_t public; + + /** + * UCI configuration backend + */ + uci_config_t *config; + + /** + * UCI credential set implementation + */ + uci_creds_t *creds; + + /** + * UCI parser wrapper + */ + uci_parser_t *parser; +}; + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_uci_plugin_t *this) +{ + charon->backends->remove_backend(charon->backends, &this->config->backend); + charon->credentials->remove_set(charon->credentials, &this->creds->credential_set); + this->config->destroy(this->config); + this->creds->destroy(this->creds); + this->parser->destroy(this->parser); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_uci_plugin_t *this = malloc_thing(private_uci_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + this->parser = uci_parser_create(UCI_PACKAGE); + this->config = uci_config_create(this->parser); + this->creds = uci_creds_create(this->parser); + charon->backends->add_backend(charon->backends, &this->config->backend); + charon->credentials->add_set(charon->credentials, &this->creds->credential_set); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/uci/uci_plugin.h b/src/charon/plugins/uci/uci_plugin.h new file mode 100644 index 000000000..cac95dc13 --- /dev/null +++ b/src/charon/plugins/uci/uci_plugin.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id$ + */ + +/** + * @defgroup uci uci + * @ingroup cplugins + * + * @defgroup uci_plugin uci_plugin + * @{ @ingroup uci + */ + +#ifndef UCI_PLUGIN_H_ +#define UCI_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct uci_plugin_t uci_plugin_t; + +/** + * OpenWRT UCI (Unified Configuration Interface) configuration plugin. + */ +struct uci_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a uci_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* UCI_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/unit_tester/Makefile.am b/src/charon/plugins/unit_tester/Makefile.am new file mode 100644 index 000000000..2487cf207 --- /dev/null +++ b/src/charon/plugins/unit_tester/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-unit-tester.la + +libstrongswan_unit_tester_la_SOURCES = unit_tester.c unit_tester.h \ + tests/test_enumerator.c \ + tests/test_auth_info.c \ + tests/test_fips_prf.c \ + tests/test_curl.c \ + tests/test_mysql.c \ + tests/test_sqlite.c \ + tests/test_mutex.c \ + tests/test_rsa_gen.c \ + tests/test_med_db.c \ + tests/test_aes.c \ + tests/test_chunk.c +libstrongswan_unit_tester_la_LDFLAGS = -module + diff --git a/src/charon/plugins/unit_tester/Makefile.in b/src/charon/plugins/unit_tester/Makefile.in new file mode 100644 index 000000000..fe5dfa6cf --- /dev/null +++ b/src/charon/plugins/unit_tester/Makefile.in @@ -0,0 +1,598 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/charon/plugins/unit_tester +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(plugindir)" +pluginLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(plugin_LTLIBRARIES) +libstrongswan_unit_tester_la_LIBADD = +am_libstrongswan_unit_tester_la_OBJECTS = unit_tester.lo \ + test_enumerator.lo test_auth_info.lo test_fips_prf.lo \ + test_curl.lo test_mysql.lo test_sqlite.lo test_mutex.lo \ + test_rsa_gen.lo test_med_db.lo test_aes.lo test_chunk.lo +libstrongswan_unit_tester_la_OBJECTS = \ + $(am_libstrongswan_unit_tester_la_OBJECTS) +libstrongswan_unit_tester_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_unit_tester_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_unit_tester_la_SOURCES) +DIST_SOURCES = $(libstrongswan_unit_tester_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ +IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +confdir = @confdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libstrongswan_plugins = @libstrongswan_plugins@ +linuxdir = @linuxdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +resolv_conf = @resolv_conf@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +simreader = @simreader@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-unit-tester.la +libstrongswan_unit_tester_la_SOURCES = unit_tester.c unit_tester.h \ + tests/test_enumerator.c \ + tests/test_auth_info.c \ + tests/test_fips_prf.c \ + tests/test_curl.c \ + tests/test_mysql.c \ + tests/test_sqlite.c \ + tests/test_mutex.c \ + tests/test_rsa_gen.c \ + tests/test_med_db.c \ + tests/test_aes.c \ + tests/test_chunk.c + +libstrongswan_unit_tester_la_LDFLAGS = -module +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/unit_tester/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/unit_tester/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-unit-tester.la: $(libstrongswan_unit_tester_la_OBJECTS) $(libstrongswan_unit_tester_la_DEPENDENCIES) + $(libstrongswan_unit_tester_la_LINK) -rpath $(plugindir) $(libstrongswan_unit_tester_la_OBJECTS) $(libstrongswan_unit_tester_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_aes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auth_info.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_chunk.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_curl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_enumerator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fips_prf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_med_db.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mutex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mysql.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_rsa_gen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_sqlite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unit_tester.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +test_enumerator.lo: tests/test_enumerator.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_enumerator.lo -MD -MP -MF $(DEPDIR)/test_enumerator.Tpo -c -o test_enumerator.lo `test -f 'tests/test_enumerator.c' || echo '$(srcdir)/'`tests/test_enumerator.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_enumerator.Tpo $(DEPDIR)/test_enumerator.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_enumerator.c' object='test_enumerator.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 test_enumerator.lo `test -f 'tests/test_enumerator.c' || echo '$(srcdir)/'`tests/test_enumerator.c + +test_auth_info.lo: tests/test_auth_info.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_auth_info.lo -MD -MP -MF $(DEPDIR)/test_auth_info.Tpo -c -o test_auth_info.lo `test -f 'tests/test_auth_info.c' || echo '$(srcdir)/'`tests/test_auth_info.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_auth_info.Tpo $(DEPDIR)/test_auth_info.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_auth_info.c' object='test_auth_info.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 test_auth_info.lo `test -f 'tests/test_auth_info.c' || echo '$(srcdir)/'`tests/test_auth_info.c + +test_fips_prf.lo: tests/test_fips_prf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_fips_prf.lo -MD -MP -MF $(DEPDIR)/test_fips_prf.Tpo -c -o test_fips_prf.lo `test -f 'tests/test_fips_prf.c' || echo '$(srcdir)/'`tests/test_fips_prf.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_fips_prf.Tpo $(DEPDIR)/test_fips_prf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_fips_prf.c' object='test_fips_prf.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 test_fips_prf.lo `test -f 'tests/test_fips_prf.c' || echo '$(srcdir)/'`tests/test_fips_prf.c + +test_curl.lo: tests/test_curl.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_curl.lo -MD -MP -MF $(DEPDIR)/test_curl.Tpo -c -o test_curl.lo `test -f 'tests/test_curl.c' || echo '$(srcdir)/'`tests/test_curl.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_curl.Tpo $(DEPDIR)/test_curl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_curl.c' object='test_curl.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 test_curl.lo `test -f 'tests/test_curl.c' || echo '$(srcdir)/'`tests/test_curl.c + +test_mysql.lo: tests/test_mysql.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_mysql.lo -MD -MP -MF $(DEPDIR)/test_mysql.Tpo -c -o test_mysql.lo `test -f 'tests/test_mysql.c' || echo '$(srcdir)/'`tests/test_mysql.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_mysql.Tpo $(DEPDIR)/test_mysql.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_mysql.c' object='test_mysql.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 test_mysql.lo `test -f 'tests/test_mysql.c' || echo '$(srcdir)/'`tests/test_mysql.c + +test_sqlite.lo: tests/test_sqlite.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_sqlite.lo -MD -MP -MF $(DEPDIR)/test_sqlite.Tpo -c -o test_sqlite.lo `test -f 'tests/test_sqlite.c' || echo '$(srcdir)/'`tests/test_sqlite.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_sqlite.Tpo $(DEPDIR)/test_sqlite.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_sqlite.c' object='test_sqlite.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 test_sqlite.lo `test -f 'tests/test_sqlite.c' || echo '$(srcdir)/'`tests/test_sqlite.c + +test_mutex.lo: tests/test_mutex.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_mutex.lo -MD -MP -MF $(DEPDIR)/test_mutex.Tpo -c -o test_mutex.lo `test -f 'tests/test_mutex.c' || echo '$(srcdir)/'`tests/test_mutex.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_mutex.Tpo $(DEPDIR)/test_mutex.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_mutex.c' object='test_mutex.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 test_mutex.lo `test -f 'tests/test_mutex.c' || echo '$(srcdir)/'`tests/test_mutex.c + +test_rsa_gen.lo: tests/test_rsa_gen.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_rsa_gen.lo -MD -MP -MF $(DEPDIR)/test_rsa_gen.Tpo -c -o test_rsa_gen.lo `test -f 'tests/test_rsa_gen.c' || echo '$(srcdir)/'`tests/test_rsa_gen.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_rsa_gen.Tpo $(DEPDIR)/test_rsa_gen.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_rsa_gen.c' object='test_rsa_gen.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 test_rsa_gen.lo `test -f 'tests/test_rsa_gen.c' || echo '$(srcdir)/'`tests/test_rsa_gen.c + +test_med_db.lo: tests/test_med_db.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_med_db.lo -MD -MP -MF $(DEPDIR)/test_med_db.Tpo -c -o test_med_db.lo `test -f 'tests/test_med_db.c' || echo '$(srcdir)/'`tests/test_med_db.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_med_db.Tpo $(DEPDIR)/test_med_db.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_med_db.c' object='test_med_db.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 test_med_db.lo `test -f 'tests/test_med_db.c' || echo '$(srcdir)/'`tests/test_med_db.c + +test_aes.lo: tests/test_aes.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_aes.lo -MD -MP -MF $(DEPDIR)/test_aes.Tpo -c -o test_aes.lo `test -f 'tests/test_aes.c' || echo '$(srcdir)/'`tests/test_aes.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_aes.Tpo $(DEPDIR)/test_aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_aes.c' object='test_aes.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 test_aes.lo `test -f 'tests/test_aes.c' || echo '$(srcdir)/'`tests/test_aes.c + +test_chunk.lo: tests/test_chunk.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_chunk.lo -MD -MP -MF $(DEPDIR)/test_chunk.Tpo -c -o test_chunk.lo `test -f 'tests/test_chunk.c' || echo '$(srcdir)/'`tests/test_chunk.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/test_chunk.Tpo $(DEPDIR)/test_chunk.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_chunk.c' object='test_chunk.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 test_chunk.lo `test -f 'tests/test_chunk.c' || echo '$(srcdir)/'`tests/test_chunk.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pluginLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/charon/plugins/unit_tester/tests/test_aes.c b/src/charon/plugins/unit_tester/tests/test_aes.c new file mode 100644 index 000000000..06e891d83 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_aes.c @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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 <daemon.h> +#include <library.h> +#include <utils/mutex.h> + +#include <unistd.h> +#include <sched.h> +#include <pthread.h> + +/** + * run a test using given values + */ +static bool do_aes_test(u_char *key, int keysize, u_char *iv, + u_char *plain, u_char *cipher, int len) +{ + crypter_t *crypter; + chunk_t enc, dec; + bool good = TRUE; + + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, keysize); + if (!crypter) + { + return FALSE; + } + crypter->set_key(crypter, chunk_create(key, keysize)); + crypter->encrypt(crypter, + chunk_create(plain, len), chunk_create(iv, 16), &enc); + if (!memeq(enc.ptr, cipher, len)) + { + good = FALSE; + } + crypter->decrypt(crypter, enc, chunk_create(iv, 16), &dec); + if (!memeq(dec.ptr, plain, len)) + { + good = FALSE; + } + free(enc.ptr); + free(dec.ptr); + crypter->destroy(crypter); + return good; +} + +/******************************************************************************* + * AES-128 test + ******************************************************************************/ +bool test_aes128() +{ + /* + * Test 1 of RFC3602 + * Key : 0x06a9214036b8a15b512e03d534120006 + * IV : 0x3dafba429d9eb430b422da802c9fac41 + * Plaintext : "Single block msg" + * Ciphertext: 0xe353779c1079aeb82708942dbe77181a + */ + u_char key1[] = { + 0x06,0xa9,0x21,0x40,0x36,0xb8,0xa1,0x5b, + 0x51,0x2e,0x03,0xd5,0x34,0x12,0x00,0x06 + }; + u_char iv1[] = { + 0x3d,0xaf,0xba,0x42,0x9d,0x9e,0xb4,0x30, + 0xb4,0x22,0xda,0x80,0x2c,0x9f,0xac,0x41 + }; + u_char plain1[] = { + 'S','i','n','g','l','e',' ','b','l','o','c','k',' ','m','s','g' + }; + u_char cipher1[] = { + 0xe3,0x53,0x77,0x9c,0x10,0x79,0xae,0xb8, + 0x27,0x08,0x94,0x2d,0xbe,0x77,0x18,0x1a + }; + if (!do_aes_test(key1, 16, iv1, plain1, cipher1, sizeof(plain1))) + { + return FALSE; + } + + /* + * Test 2 of RFC3602 + * Key : 0xc286696d887c9aa0611bbb3e2025a45a + * IV : 0x562e17996d093d28ddb3ba695a2e6f58 + * Plaintext : 0x000102030405060708090a0b0c0d0e0f + * 101112131415161718191a1b1c1d1e1f + * Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a + * 7586602d253cfff91b8266bea6d61ab1 + */ + u_char key2[] = { + 0xc2,0x86,0x69,0x6d,0x88,0x7c,0x9a,0xa0, + 0x61,0x1b,0xbb,0x3e,0x20,0x25,0xa4,0x5a + }; + u_char iv2[] = { + 0x56,0x2e,0x17,0x99,0x6d,0x09,0x3d,0x28, + 0xdd,0xb3,0xba,0x69,0x5a,0x2e,0x6f,0x58 + }; + u_char plain2[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f + }; + u_char cipher2[] = { + 0xd2,0x96,0xcd,0x94,0xc2,0xcc,0xcf,0x8a, + 0x3a,0x86,0x30,0x28,0xb5,0xe1,0xdc,0x0a, + 0x75,0x86,0x60,0x2d,0x25,0x3c,0xff,0xf9, + 0x1b,0x82,0x66,0xbe,0xa6,0xd6,0x1a,0xb1 + }; + if (!do_aes_test(key2, 16, iv2, plain2, cipher2, sizeof(plain2))) + { + return FALSE; + } + + /* + * Test 3 of RFC3603 + * Key : 0x56e47a38c5598974bc46903dba290349 + * IV : 0x8ce82eefbea0da3c44699ed7db51b7d9 + * Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf + * b0b1b2b3b4b5b6b7b8b9babbbcbdbebf + * c0c1c2c3c4c5c6c7c8c9cacbcccdcecf + * d0d1d2d3d4d5d6d7d8d9dadbdcdddedf + * Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa + * 0f3af07a9a31a9c684db207eb0ef8e4e + * 35907aa632c3ffdf868bb7b29d3d46ad + * 83ce9f9a102ee99d49a53e87f4c3da55 + */ + u_char key3[] = { + 0x56,0xe4,0x7a,0x38,0xc5,0x59,0x89,0x74, + 0xbc,0x46,0x90,0x3d,0xba,0x29,0x03,0x49 + }; + u_char iv3[] = { + 0x8c,0xe8,0x2e,0xef,0xbe,0xa0,0xda,0x3c, + 0x44,0x69,0x9e,0xd7,0xdb,0x51,0xb7,0xd9 + }; + u_char plain3[] = { + 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, + 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, + 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7, + 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, + 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, + 0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, + 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7, + 0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf + }; + u_char cipher3[] = { + 0xc3,0x0e,0x32,0xff,0xed,0xc0,0x77,0x4e, + 0x6a,0xff,0x6a,0xf0,0x86,0x9f,0x71,0xaa, + 0x0f,0x3a,0xf0,0x7a,0x9a,0x31,0xa9,0xc6, + 0x84,0xdb,0x20,0x7e,0xb0,0xef,0x8e,0x4e, + 0x35,0x90,0x7a,0xa6,0x32,0xc3,0xff,0xdf, + 0x86,0x8b,0xb7,0xb2,0x9d,0x3d,0x46,0xad, + 0x83,0xce,0x9f,0x9a,0x10,0x2e,0xe9,0x9d, + 0x49,0xa5,0x3e,0x87,0xf4,0xc3,0xda,0x55 + }; + if (!do_aes_test(key3, 16, iv3, plain3, cipher3, sizeof(plain3))) + { + return FALSE; + } + return TRUE; +} + +/** + * run a single xcbc test for prf and signer + */ +static bool do_xcbc_test(u_int8_t *key, size_t keylen, u_int8_t *mac, + u_int8_t *plain, size_t len) +{ + signer_t *signer; + prf_t *prf; + u_int8_t res[16]; + + prf = lib->crypto->create_prf(lib->crypto, PRF_AES128_XCBC); + if (!prf) + { + return FALSE; + } + prf->set_key(prf, chunk_create(key, keylen)); + prf->get_bytes(prf, chunk_create(plain, len), res); + if (!memeq(res, mac, 16)) + { + DBG1(DBG_CFG, "expected %b\ngot %b", mac, 16, res, 16); + prf->destroy(prf); + return FALSE; + } + prf->destroy(prf); + + signer = lib->crypto->create_signer(lib->crypto, AUTH_AES_XCBC_96); + if (!signer) + { + return FALSE; + } + signer->set_key(signer, chunk_create(key, keylen)); + if (!signer->verify_signature(signer, chunk_create(plain, len), + chunk_create(mac, 12))) + { + return FALSE; + } + signer->destroy(signer); + return TRUE; +} + + +/******************************************************************************* + * AES_XCBC mac test + ******************************************************************************/ +bool test_aes_xcbc() +{ + /* Vectors from RFC 3566 */ + + /* Test Case #1 : AES-XCBC-MAC-96 with 0-byte input + * Key (K) : 000102030405060708090a0b0c0d0e0f + * Message (M) : <empty string> + * AES-XCBC-MAC : 75f0251d528ac01c4573dfd584d79f29 + * AES-XCBC-MAC-96: 75f0251d528ac01c4573dfd5 + */ + u_char key1[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char plain1[] = { + }; + u_char mac1[] = { + 0x75,0xf0,0x25,0x1d,0x52,0x8a,0xc0,0x1c, + 0x45,0x73,0xdf,0xd5,0x84,0xd7,0x9f,0x29 + }; + if (!do_xcbc_test(key1, 16, mac1, plain1, sizeof(plain1))) + { + return FALSE; + } + + /* + * Test Case #2 : AES-XCBC-MAC-96 with 3-byte input + * Key (K) : 000102030405060708090a0b0c0d0e0f + * Message (M) : 000102 + * AES-XCBC-MAC : 5b376580ae2f19afe7219ceef172756f + * AES-XCBC-MAC-96: 5b376580ae2f19afe7219cee + */ + u_char key2[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char plain2[] = { + 0x00,0x01,0x02 + }; + u_char mac2[] = { + 0x5b,0x37,0x65,0x80,0xae,0x2f,0x19,0xaf, + 0xe7,0x21,0x9c,0xee,0xf1,0x72,0x75,0x6f + }; + if (!do_xcbc_test(key2, 16, mac2, plain2, sizeof(plain2))) + { + return FALSE; + } + + /* Test Case #3 : AES-XCBC-MAC-96 with 16-byte input + * Key (K) : 000102030405060708090a0b0c0d0e0f + * Message (M) : 000102030405060708090a0b0c0d0e0f + * AES-XCBC-MAC : d2a246fa349b68a79998a4394ff7a263 + * AES-XCBC-MAC-96: d2a246fa349b68a79998a439 + */ + u_char key3[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char plain3[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char mac3[] = { + 0xd2,0xa2,0x46,0xfa,0x34,0x9b,0x68,0xa7, + 0x99,0x98,0xa4,0x39,0x4f,0xf7,0xa2,0x63 + }; + if (!do_xcbc_test(key3, 16, mac3, plain3, sizeof(plain3))) + { + return FALSE; + } + + /* Test Case #4 : AES-XCBC-MAC-96 with 20-byte input + * Key (K) : 000102030405060708090a0b0c0d0e0f + * Message (M) : 000102030405060708090a0b0c0d0e0f10111213 + * AES-XCBC-MAC : 47f51b4564966215b8985c63055ed308 + * AES-XCBC-MAC-96: 47f51b4564966215b8985c63 + */ + u_char key4[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char plain4[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13 + }; + u_char mac4[] = { + 0x47,0xf5,0x1b,0x45,0x64,0x96,0x62,0x15, + 0xb8,0x98,0x5c,0x63,0x05,0x5e,0xd3,0x08 + }; + if (!do_xcbc_test(key4, 16, mac4, plain4, sizeof(plain4))) + { + return FALSE; + } + + /* Test Case #5 : AES-XCBC-MAC-96 with 32-byte input + * Key (K) : 000102030405060708090a0b0c0d0e0f + * Message (M) : 000102030405060708090a0b0c0d0e0f10111213141516171819 + * 1a1b1c1d1e1f + * AES-XCBC-MAC : f54f0ec8d2b9f3d36807734bd5283fd4 + * AES-XCBC-MAC-96: f54f0ec8d2b9f3d36807734b + */ + u_char key5[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char plain5[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f + }; + u_char mac5[] = { + 0xf5,0x4f,0x0e,0xc8,0xd2,0xb9,0xf3,0xd3, + 0x68,0x07,0x73,0x4b,0xd5,0x28,0x3f,0xd4 + }; + if (!do_xcbc_test(key5, 16, mac5, plain5, sizeof(plain5))) + { + return FALSE; + } + + /* Test Case #7 : AES-XCBC-MAC-96 with 1000-byte input + * Key (K) : 000102030405060708090a0b0c0d0e0f + * Message (M) : 00000000000000000000 ... 00000000000000000000 + * [1000 bytes] + * AES-XCBC-MAC : f0dafee895db30253761103b5d84528f + * AES-XCBC-MAC-96: f0dafee895db30253761103b + */ + u_char key7[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char plain7[1000]; + memset(plain7, 0, 1000); + u_char mac7[] = { + 0xf0,0xda,0xfe,0xe8,0x95,0xdb,0x30,0x25, + 0x37,0x61,0x10,0x3b,0x5d,0x84,0x52,0x8f + }; + if (!do_xcbc_test(key7, 16, mac7, plain7, sizeof(plain7))) + { + return FALSE; + } + + /* variable key test, RFC4434 */ + + /* Test Case AES-XCBC-PRF-128 with 20-byte input + * Key : 00010203040506070809 + * Message : 000102030405060708090a0b0c0d0e0f10111213 + * PRF Output : 0fa087af7d866e7653434e602fdde835 + */ + u_char key8[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09, + }; + u_char plain8[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13 + }; + u_char mac8[] = { + 0x0f,0xa0,0x87,0xaf,0x7d,0x86,0x6e,0x76, + 0x53,0x43,0x4e,0x60,0x2f,0xdd,0xe8,0x35 + }; + if (!do_xcbc_test(key8, 10, mac8, plain8, sizeof(plain8))) + { + return FALSE; + } + + /* Test Case AES-XCBC-PRF-128 with 20-byte input + * Key : 000102030405060708090a0b0c0d0e0fedcb + * Message : 000102030405060708090a0b0c0d0e0f10111213 + * PRF Output : 8cd3c93ae598a9803006ffb67c40e9e4 + */ + u_char key9[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0xed,0xcb + }; + u_char plain9[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13 + }; + u_char mac9[] = { + 0x8c,0xd3,0xc9,0x3a,0xe5,0x98,0xa9,0x80, + 0x30,0x06,0xff,0xb6,0x7c,0x40,0xe9,0xe4 + }; + if (!do_xcbc_test(key9, 18, mac9, plain9, sizeof(plain9))) + { + return FALSE; + } + + + /* Test Case #10 : AES-XCBC-MAC-96 with 32-byte input using append mode + * Key (K) : 000102030405060708090a0b0c0d0e0f + * Message (M) : 000102030405060708090a0b0c0d0e0f10111213141516171819 + * 1a1b1c1d1e1f + * AES-XCBC-MAC : f54f0ec8d2b9f3d36807734bd5283fd4 + * AES-XCBC-MAC-96: f54f0ec8d2b9f3d36807734b + */ + u_char key10[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + u_char plain10[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f + }; + u_char mac10[] = { + 0xf5,0x4f,0x0e,0xc8,0xd2,0xb9,0xf3,0xd3, + 0x68,0x07,0x73,0x4b,0xd5,0x28,0x3f,0xd4 + }; + int i; + prf_t *prf = lib->crypto->create_prf(lib->crypto, PRF_AES128_XCBC); + u_char res[16]; + if (!prf) + { + return FALSE; + } + prf->set_key(prf, chunk_create(key10, sizeof(key10))); + for (i = 0; i < 4; i++) + { /* bytes 0 - 3, 1 byte at once */ + prf->get_bytes(prf, chunk_create(plain10 + i, 1), NULL); + } + for (i = 4; i < 5; i+=8) + { /* bytes 4 - 11, at once */ + prf->get_bytes(prf, chunk_create(plain10 + i, 8), NULL); + } + for (i = 12; i < 24; i+=4) + { /* bytes 12 - 23, in blocks of 4 */ + prf->get_bytes(prf, chunk_create(plain10 + i, 4), NULL); + } + for (i = 0; i < 4; i++) + { /* 4 zero blobs */ + prf->get_bytes(prf, chunk_create(NULL, 0), NULL); + } + for (i = 24; i < 25; i+=8) + { /* bytes 24 - 32, at once */ + prf->get_bytes(prf, chunk_create(plain10 + i, 8), res); + } + if (!memeq(res, mac10, 16)) + { + DBG1(DBG_CFG, "expected %b\ngot %b", mac10, 16, res, 16); + prf->destroy(prf); + return FALSE; + } + prf->destroy(prf); + + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_auth_info.c b/src/charon/plugins/unit_tester/tests/test_auth_info.c new file mode 100644 index 000000000..2640c951c --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_auth_info.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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 <daemon.h> +#include <library.h> +#include <credentials/auth_info.h> + + +char buf[] = {0x01,0x02,0x03,0x04}; +chunk_t chunk = chunk_from_buf(buf); +char certbuf[] = { + 0x30,0x82,0x02,0xfa,0x30,0x82,0x01,0xe2,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x5a, + 0xf2,0x65,0xae,0x78,0xff,0x23,0xde,0xf7,0xa6,0xa3,0x94,0x8c,0x3f,0xa0,0xc1,0x30, + 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x39, + 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30, + 0x17,0x06,0x03,0x55,0x04,0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74, + 0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04, + 0x03,0x13,0x06,0x6d,0x61,0x72,0x74,0x69,0x6e,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30, + 0x34,0x32,0x37,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x17,0x0d,0x31,0x32,0x30,0x34, + 0x32,0x35,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x30,0x39,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04, + 0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53, + 0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x03,0x13,0x06,0x6d,0x61, + 0x72,0x74,0x69,0x6e,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a, + 0x02,0x82,0x01,0x01,0x00,0xd7,0xb9,0xba,0x4d,0xe2,0x3b,0x3d,0x35,0x7a,0x3f,0x88, + 0x67,0x95,0xe7,0xfd,0x9f,0xe9,0x0a,0x0d,0x79,0x3a,0x9e,0x21,0x8f,0xcb,0xe4,0x67, + 0x24,0xae,0x0c,0xda,0xb3,0xcc,0xec,0x36,0xb4,0xa8,0x4d,0xf1,0x3d,0xad,0xe4,0x8c, + 0x63,0x92,0x54,0xb7,0xb2,0x02,0xa2,0x00,0x62,0x8b,0x04,0xac,0xa0,0x17,0xad,0x17, + 0x9a,0x05,0x0d,0xd7,0xb3,0x08,0x02,0xc5,0x26,0xcf,0xdd,0x05,0x42,0xfc,0x13,0x6d, + 0x9f,0xb1,0xf3,0x4f,0x82,0x1d,0xef,0x01,0xc9,0x91,0xea,0x37,0x1b,0x79,0x28,0xfa, + 0xbf,0x9f,0xb3,0xeb,0x82,0x4f,0x10,0xc6,0x4b,0xa4,0x08,0xf7,0x8e,0xf2,0x00,0xea, + 0x04,0x97,0x80,0x9f,0x65,0x86,0xde,0x6b,0xc7,0xda,0x83,0xfc,0xad,0x4a,0xaf,0x52, + 0x8b,0x4d,0x33,0xee,0x49,0x87,0x2f,0x3b,0x60,0x45,0x66,0x8f,0xe6,0x89,0xcc,0xb1, + 0x92,0x02,0x17,0x2b,0x7b,0x8e,0x90,0x47,0x84,0x84,0x59,0x95,0x81,0xd8,0xe0,0xf3, + 0x87,0xe0,0x04,0x09,0xfd,0xcc,0x3a,0x21,0x34,0xfa,0xec,0xbe,0xf5,0x9c,0xcf,0x55, + 0x80,0x7b,0xe3,0x75,0x9d,0x36,0x68,0xab,0x83,0xe3,0xad,0x01,0x53,0x0d,0x8a,0x9a, + 0xa6,0xb0,0x15,0xc9,0xc5,0xf8,0x9b,0x51,0x32,0xcf,0x97,0x6c,0xfe,0x4a,0x56,0x3c, + 0xc8,0x8f,0x4a,0x70,0x23,0x4f,0xf6,0xf7,0xe6,0x9f,0x09,0xcd,0x8f,0xea,0x20,0x7d, + 0x34,0xc0,0xc5,0xc0,0x34,0x06,0x6f,0x8b,0xeb,0x04,0x54,0x3f,0x0e,0xcd,0xe2,0x85, + 0xab,0x94,0x3e,0x91,0x6c,0x18,0x6f,0x96,0x5d,0xf2,0x8b,0x10,0xe9,0x90,0x43,0xb0, + 0x61,0x52,0xac,0xcf,0x75,0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86, + 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x09,0x63, + 0x42,0xad,0xe5,0xa3,0xf6,0xc9,0x5d,0x08,0xf2,0x78,0x7b,0xeb,0x8a,0xef,0x50,0x00, + 0xc8,0xeb,0xe9,0x26,0x94,0xcb,0x84,0x10,0x7e,0x42,0x6b,0x86,0x38,0x57,0xa6,0x02, + 0x98,0x5a,0x2c,0x8f,0x44,0x32,0x1b,0x97,0x8c,0x7e,0x4b,0xd8,0xe8,0xe8,0x0f,0x4a, + 0xb9,0x31,0x9f,0xf6,0x9f,0x0e,0x67,0x26,0x05,0x2a,0x99,0x14,0x35,0x41,0x47,0x9a, + 0xfa,0x12,0x94,0x0b,0xe9,0x27,0x7c,0x71,0x20,0xd7,0x8d,0x3b,0x97,0x19,0x2d,0x15, + 0xff,0xa4,0xf3,0x89,0x8d,0x29,0x5f,0xf6,0x3f,0x93,0xaf,0x78,0x61,0xe4,0xe1,0x2e, + 0x75,0xc1,0x2c,0xc4,0x76,0x95,0x19,0xf8,0x37,0xdc,0xd8,0x00,0x7a,0x3c,0x0f,0x49, + 0x2e,0x88,0x09,0x16,0xb3,0x92,0x33,0xdf,0x77,0x83,0x4f,0xb5,0x9e,0x30,0x8c,0x48, + 0x1d,0xd8,0x84,0xfb,0xf1,0xb9,0xa0,0xbe,0x25,0xff,0x4c,0xeb,0xef,0x2b,0xcd,0xfa, + 0x0b,0x94,0x66,0x3b,0x28,0x08,0x3f,0x3a,0xda,0x41,0xd0,0x6b,0xab,0x5e,0xbb,0x8a, + 0x9f,0xdc,0x98,0x3e,0x59,0x37,0x48,0xbe,0x69,0xde,0x85,0x82,0xf2,0x53,0x8b,0xe4, + 0x44,0xe4,0x71,0x91,0x14,0x85,0x0e,0x1e,0x79,0xdd,0x62,0xf5,0xdc,0x25,0x89,0xab, + 0x50,0x5b,0xaa,0xae,0xe3,0x64,0x6a,0x23,0x34,0xd7,0x30,0xe2,0x2a,0xc8,0x81,0x0c, + 0xec,0xd2,0x31,0xc6,0x1e,0xb6,0xc0,0x57,0xd9,0xe1,0x14,0x06,0x9b,0xf8,0x51,0x69, + 0x47,0xf0,0x9c,0xcd,0x69,0xef,0x8e,0x5f,0x62,0xda,0x10,0xf7,0x3c,0x6d,0x0f,0x33, + 0xec,0x6f,0xfd,0x94,0x07,0x16,0x41,0x32,0x06,0xa4,0xe1,0x08,0x31,0x87, +}; +chunk_t certchunk = chunk_from_buf(certbuf); + +/******************************************************************************* + * auth info test + ******************************************************************************/ +bool test_auth_info() +{ + auth_info_t *auth = auth_info_create(), *auth2; + certificate_t *c1, *c2; + enumerator_t *enumerator; + int round = 0; + void *value; + auth_item_t type; + + c1 = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, chunk_clone(certchunk), + BUILD_END); + if (!c1) + { + return FALSE; + } + + auth->add_item(auth, AUTHN_SUBJECT_CERT, c1); + if (!auth->get_item(auth, AUTHN_SUBJECT_CERT, (void**)&c2)) + { + return FALSE; + } + if (!c1->equals(c1, c2)) + { + return FALSE; + } + + enumerator = auth->create_item_enumerator(auth); + while (enumerator->enumerate(enumerator, &type, &value)) + { + round++; + if (round == 1 && type == AUTHN_SUBJECT_CERT && value == c1) + { + continue; + } + return FALSE; + } + enumerator->destroy(enumerator); + + auth2 = auth_info_create(); + auth2->add_item(auth2, AUTHN_CA_CERT, c1); + auth2->merge(auth2, auth); + + round = 0; + enumerator = auth2->create_item_enumerator(auth2); + while (enumerator->enumerate(enumerator, &type, &value)) + { + round++; + if (round == 1 && type == AUTHN_CA_CERT && value == c1) + { + continue; + } + if (round == 2 && type == AUTHN_SUBJECT_CERT && value == c1) + { + continue; + } + return FALSE; + } + enumerator->destroy(enumerator); + auth->destroy(auth); + auth2->destroy(auth2); + c1->destroy(c1); + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_chunk.c b/src/charon/plugins/unit_tester/tests/test_chunk.c new file mode 100644 index 000000000..e7a8586c9 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_chunk.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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 <library.h> +#include <daemon.h> + +#define countof(array) (sizeof(array)/sizeof(typeof(array[0]))) + +/******************************************************************************* + * Base64 encoding/decoding test + ******************************************************************************/ +bool test_chunk_base64() +{ + /* test vectors from RFC4648: + * + * BASE64("") = "" + * BASE64("f") = "Zg==" + * BASE64("fo") = "Zm8=" + * BASE64("foo") = "Zm9v" + * BASE64("foob") = "Zm9vYg==" + * BASE64("fooba") = "Zm9vYmE=" + * BASE64("foobar") = "Zm9vYmFy" + */ + + typedef struct { + char *in; + char *out; + } testdata_t; + + testdata_t test[] = { + {"", ""}, + {"f", "Zg=="}, + {"fo", "Zm8="}, + {"foo", "Zm9v"}, + {"foob", "Zm9vYg=="}, + {"fooba", "Zm9vYmE="}, + {"foobar", "Zm9vYmFy"}, + }; + int i; + + for (i = 0; i < countof(test); i++) + { + chunk_t out; + + out = chunk_to_base64(chunk_create(test[i].in, strlen(test[i].in)), NULL); + + if (!streq(out.ptr, test[i].out)) + { + DBG1(DBG_CFG, "base64 conversion error - should %s, is %s", + test[i].out, out.ptr); + return FALSE; + } + free(out.ptr); + } + + for (i = 0; i < countof(test); i++) + { + chunk_t out; + + out = chunk_from_base64(chunk_create(test[i].out, strlen(test[i].out)), NULL); + + if (!strneq(out.ptr, test[i].in, out.len)) + { + DBG1(DBG_CFG, "base64 conversion error - should %s, is %#B", + test[i].in, &out); + return FALSE; + } + free(out.ptr); + } + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_curl.c b/src/charon/plugins/unit_tester/tests/test_curl.c new file mode 100644 index 000000000..c011617a7 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_curl.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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 <daemon.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> + +/******************************************************************************* + * curl get test + ******************************************************************************/ + +bool test_curl_get() +{ + chunk_t chunk; + + if (lib->fetcher->fetch(lib->fetcher, "http://www.strongswan.org", + &chunk, FETCH_END) != SUCCESS) + { + return FALSE; + } + free(chunk.ptr); + + if (lib->fetcher->fetch(lib->fetcher, "http://www.google.com", + &chunk, FETCH_END) != SUCCESS) + { + return FALSE; + } + free(chunk.ptr); + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_enumerator.c b/src/charon/plugins/unit_tester/tests/test_enumerator.c new file mode 100644 index 000000000..d17d62bef --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_enumerator.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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 <utils/linked_list.h> + + +/******************************************************************************* + * linked list remove test + ******************************************************************************/ +bool test_list_remove() +{ + void *a = (void*)1, *b = (void*)2; + linked_list_t *list; + + list = linked_list_create(); + list->insert_last(list, a); + if (list->remove(list, a, NULL) != 1) + { + return FALSE; + } + list->insert_last(list, a); + list->insert_first(list, a); + list->insert_last(list, a); + list->insert_last(list, b); + if (list->remove(list, a, NULL) != 3) + { + return FALSE; + } + if (list->remove(list, a, NULL) != 0) + { + return FALSE; + } + if (list->get_count(list) != 1) + { + return FALSE; + } + if (list->remove(list, b, NULL) != 1) + { + return FALSE; + } + if (list->remove(list, b, NULL) != 0) + { + return FALSE; + } + list->destroy(list); + return TRUE; +} + +/******************************************************************************* + * Simple insert first/last and enumerate test + ******************************************************************************/ +bool test_enumerate() +{ + int round, x; + void *a = (void*)4, *b = (void*)3, *c = (void*)2, *d = (void*)5, *e = (void*)1; + linked_list_t *list; + enumerator_t *enumerator; + + list = linked_list_create(); + + list->insert_last(list, a); + list->insert_first(list, b); + list->insert_first(list, c); + list->insert_last(list, d); + list->insert_first(list, e); + + round = 1; + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &x)) + { + if (round != x) + { + return FALSE; + } + round++; + } + enumerator->destroy(enumerator); + + list->destroy(list); + return TRUE; +} + +/******************************************************************************* + * nested enumerator test + ******************************************************************************/ + +static bool bad_data; + +static enumerator_t* create_inner(linked_list_t *outer, void *data) +{ + if (data != (void*)101) + { + bad_data = TRUE; + } + return outer->create_enumerator(outer); +} + + +static void destroy_data(void *data) +{ + if (data != (void*)101) + { + bad_data = TRUE; + } +} + +bool test_enumerate_nested() +{ + int round, x; + void *a = (void*)1, *b = (void*)2, *c = (void*)3, *d = (void*)4, *e = (void*)5; + linked_list_t *list, *l1, *l2, *l3; + enumerator_t *enumerator; + + bad_data = FALSE; + list = linked_list_create(); + l1 = linked_list_create(); + l2 = linked_list_create(); + l3 = linked_list_create(); + list->insert_last(list, l1); + list->insert_last(list, l2); + list->insert_last(list, l3); + + l1->insert_last(l1, a); + l1->insert_last(l1, b); + l3->insert_last(l3, c); + l3->insert_last(l3, d); + l3->insert_last(l3, e); + + round = 1; + enumerator = enumerator_create_nested(list->create_enumerator(list), + (void*)create_inner, (void*)101, destroy_data); + while (enumerator->enumerate(enumerator, &x)) + { + if (round != x) + { + return FALSE; + } + round++; + } + enumerator->destroy(enumerator); + + list->destroy(list); + l1->destroy(l1); + l2->destroy(l2); + l3->destroy(l3); + return !bad_data; +} + + +/******************************************************************************* + * filtered enumerator test + ******************************************************************************/ +static bool filter(void *data, int *v, int *vo, int *w, int *wo, + int *x, int *xo, int *y, int *yo, int *z, int *zo) +{ + int val = *v; + + *vo = val++; + *wo = val++; + *xo = val++; + *yo = val++; + *zo = val++; + if (data != (void*)101) + { + return FALSE; + } + return TRUE; +} + +bool test_enumerate_filtered() +{ + int round, v, w, x, y, z; + void *a = (void*)1, *b = (void*)2, *c = (void*)3, *d = (void*)4, *e = (void*)5; + linked_list_t *list; + enumerator_t *enumerator; + + bad_data = FALSE; + list = linked_list_create(); + + list->insert_last(list, a); + list->insert_last(list, b); + list->insert_last(list, c); + list->insert_last(list, d); + list->insert_last(list, e); + + round = 1; + enumerator = enumerator_create_filter(list->create_enumerator(list), + (void*)filter, (void*)101, destroy_data); + while (enumerator->enumerate(enumerator, &v, &w, &x, &y, &z)) + { + if (v != round || w != round + 1 || x != round + 2 || + y != round + 3 || z != round + 4) + { + return FALSE; + } + round++; + } + enumerator->destroy(enumerator); + + list->destroy(list); + return !bad_data; +} diff --git a/src/charon/plugins/unit_tester/tests/test_fips_prf.c b/src/charon/plugins/unit_tester/tests/test_fips_prf.c new file mode 100644 index 000000000..29612143e --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_fips_prf.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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 <utils/linked_list.h> +#include <daemon.h> + +/******************************************************************************* + * fips prf known value test + ******************************************************************************/ +bool fips_prf_test() +{ + prf_t *prf; + u_int8_t key_buf[] = { + 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b, + 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f, + 0xeb, 0x5a, 0x38, 0xb6 + }; + u_int8_t seed_buf[] = { + 0x00 + }; + u_int8_t result_buf[] = { + 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, + 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49, + 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba, + 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78, + 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16 + }; + chunk_t key = chunk_from_buf(key_buf); + chunk_t seed = chunk_from_buf(seed_buf); + chunk_t expected = chunk_from_buf(result_buf); + chunk_t result; + + prf = lib->crypto->create_prf(lib->crypto, PRF_FIPS_SHA1_160); + if (prf == NULL) + { + DBG1(DBG_CFG, "FIPS PRF implementation not found"); + return FALSE; + } + prf->set_key(prf, key); + prf->allocate_bytes(prf, seed, &result); + prf->destroy(prf); + if (!chunk_equals(result, expected)) + { + DBG1(DBG_CFG, "FIPS PRF result invalid:\nexpected: %Bresult: %B", + &expected, &result); + chunk_free(&result); + return FALSE; + } + chunk_free(&result); + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_med_db.c b/src/charon/plugins/unit_tester/tests/test_med_db.c new file mode 100644 index 000000000..d65eb0cc4 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_med_db.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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 <library.h> +#include <daemon.h> +#include <utils/enumerator.h> + +#include <unistd.h> + +/******************************************************************************* + * fetch public key from mediation database + ******************************************************************************/ + +bool test_med_db() +{ + char keyid_buf[] = { + 0xed,0x90,0xe6,0x4f,0xec,0xa2,0x1f,0x4b, + 0x68,0x97,0x99,0x24,0x22,0xe0,0xde,0x21, + 0xb9,0xd6,0x26,0x29 + }; + chunk_t keyid = chunk_from_buf(keyid_buf); + identification_t *id, *found; + enumerator_t *enumerator; + auth_info_t *auth; + public_key_t *public; + bool good = FALSE; + + id = identification_create_from_encoding(ID_KEY_ID, keyid); + enumerator = charon->credentials->create_public_enumerator( + charon->credentials, KEY_ANY, id, NULL); + while (enumerator->enumerate(enumerator, &public, &auth)) + { + found = public->get_id(public, ID_PUBKEY_SHA1); + good = chunk_equals(id->get_encoding(id), found->get_encoding(found)); + } + enumerator->destroy(enumerator); + id->destroy(id); + return good; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_mutex.c b/src/charon/plugins/unit_tester/tests/test_mutex.c new file mode 100644 index 000000000..a305d5082 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_mutex.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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 <library.h> +#include <utils/mutex.h> + +#include <unistd.h> +#include <sched.h> +#include <pthread.h> + + +static mutex_t *mutex; + +static int locked = 0; + +static bool failed = FALSE; + +static pthread_barrier_t barrier; + +static void* run(void* null) +{ + int i; + + /* wait for all threads before getting in action */ + pthread_barrier_wait(&barrier); + + for (i = 0; i < 100; i++) + { + mutex->lock(mutex); + mutex->lock(mutex); + mutex->lock(mutex); + locked++; + sched_yield(); + if (locked > 1) + { + failed = TRUE; + } + locked--; + mutex->unlock(mutex); + mutex->unlock(mutex); + mutex->unlock(mutex); + } + return NULL; +} + +#define THREADS 20 + +/******************************************************************************* + * mutex test + ******************************************************************************/ +bool test_mutex() +{ + int i; + pthread_t threads[THREADS]; + + mutex = mutex_create(MUTEX_RECURSIVE); + + for (i = 0; i < 10; i++) + { + mutex->lock(mutex); + mutex->unlock(mutex); + } + for (i = 0; i < 10; i++) + { + mutex->lock(mutex); + } + for (i = 0; i < 10; i++) + { + mutex->unlock(mutex); + } + + pthread_barrier_init(&barrier, NULL, THREADS); + + for (i = 0; i < THREADS; i++) + { + pthread_create(&threads[i], NULL, run, NULL); + } + for (i = 0; i < THREADS; i++) + { + pthread_join(threads[i], NULL); + } + pthread_barrier_destroy(&barrier); + + mutex->destroy(mutex); + + return !failed; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_mysql.c b/src/charon/plugins/unit_tester/tests/test_mysql.c new file mode 100644 index 000000000..ff3d38ad8 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_mysql.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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 <library.h> +#include <daemon.h> +#include <utils/enumerator.h> + +/******************************************************************************* + * mysql simple test + ******************************************************************************/ +bool test_mysql() +{ + database_t *db; + char *txt = "I'm a superduper test"; + char buf[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; + chunk_t data = chunk_from_buf(buf); + int row; + chunk_t qdata; + char *qtxt; + bool good = FALSE; + enumerator_t *enumerator; + + db = lib->db->create(lib->db, "mysql://testuser:testpass@localhost/test"); + if (!db) + { + return FALSE; + } + if (db->execute(db, NULL, "CREATE TABLE test (" + "id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, " + "txt TEXT, data BLOB)") < 0) + { + return FALSE; + } + if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)", + DB_TEXT, txt, DB_BLOB, data) < 0) + { + return FALSE; + } + if (row != 1) + { + return FALSE; + } + enumerator = db->query(db, "SELECT txt, data FROM test WHERE id = ?", + DB_INT, row, + DB_TEXT, DB_BLOB); + if (!enumerator) + { + return FALSE; + } + while (enumerator->enumerate(enumerator, &qtxt, &qdata)) + { + if (good) + { /* only one row */ + good = FALSE; + break; + } + if (streq(qtxt, txt) && chunk_equals(data, qdata)) + { + good = TRUE; + } + } + enumerator->destroy(enumerator); + if (!good) + { + return FALSE; + } + if (db->execute(db, NULL, "DELETE FROM test WHERE id = ?", DB_INT, row) != 1) + { + return FALSE; + } + if (db->execute(db, NULL, "DROP TABLE test") < 0) + { + return FALSE; + } + db->destroy(db); + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_rsa_gen.c b/src/charon/plugins/unit_tester/tests/test_rsa_gen.c new file mode 100644 index 000000000..783a4c913 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_rsa_gen.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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 <library.h> +#include <daemon.h> + +/******************************************************************************* + * RSA key generation and signature + ******************************************************************************/ +bool test_rsa_gen() +{ + char buf[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; + chunk_t data = chunk_from_buf(buf), sig; + private_key_t *private; + public_key_t *public; + u_int key_size; + + for (key_size = 512; key_size <= 2048; key_size *= 2) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + BUILD_KEY_SIZE, key_size, BUILD_END); + if (!private) + { + DBG1(DBG_CFG, "generating %d bit RSA key failed"); + return FALSE; + } + public = private->get_public_key(private); + if (!public) + { + DBG1(DBG_CFG, "generating public from private key failed"); + return FALSE; + } + if (!private->sign(private, SIGN_RSA_EMSA_PKCS1_SHA1, data, &sig)) + { + DBG1(DBG_CFG, "creating RSA signature failed"); + return FALSE; + } + if (!public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig)) + { + DBG1(DBG_CFG, "verifying RSA signature failed"); + return FALSE; + } + sig.ptr[sig.len-1]++; + if (public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig)) + { + DBG1(DBG_CFG, "verifying faked RSA signature succeeded!"); + return FALSE; + } + free(sig.ptr); + public->destroy(public); + private->destroy(private); + } + return TRUE; +} + + +/******************************************************************************* + * Load a subjectPubkeyInfo wrapped key (RSA in this case) + ******************************************************************************/ +static char public_any[] = { + 0x30,0x82,0x01,0x20,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x01,0x05,0x00,0x03,0x82,0x01,0x0d,0x00,0x30,0x82,0x01,0x08,0x02,0x82,0x01,0x01, + 0x00,0xc6,0x68,0x99,0x1d,0xc8,0x06,0xdb,0xcf,0x1c,0x66,0xbb,0x91,0xc3,0xd4,0x10, + 0xb2,0x08,0xa9,0xc5,0x71,0x39,0x1c,0xbe,0x5b,0x1d,0xce,0xfd,0x1b,0xfa,0xec,0x04, + 0x89,0x9f,0x79,0xc8,0x46,0x00,0xd2,0x71,0xfb,0x22,0x16,0x52,0x2f,0xda,0xbf,0x0f, + 0xe7,0x16,0xb1,0xd7,0x6a,0xa5,0xa5,0xfc,0xee,0xff,0x84,0x4c,0x81,0x3f,0xab,0x84, + 0x0e,0xed,0x4a,0x26,0x59,0xd0,0x9b,0xb5,0xe1,0xec,0x61,0xc4,0xd3,0x15,0x4c,0x29, + 0x51,0xa0,0xde,0x33,0x07,0x58,0x6c,0x36,0x1b,0x18,0x61,0xd9,0x56,0x18,0x39,0x54, + 0x8b,0xd2,0xea,0x4e,0x87,0x28,0x58,0xb9,0x88,0x3d,0x30,0xbc,0xfc,0x6d,0xad,0xab, + 0x43,0x26,0x09,0x48,0x4e,0x6e,0x8a,0x8b,0x88,0xb3,0xf0,0x29,0x25,0x79,0xb6,0xb6, + 0x71,0x3c,0x93,0x59,0xd2,0x36,0x94,0xd5,0xfc,0xf3,0x62,0x2b,0x69,0xa3,0x7a,0x47, + 0x4e,0x53,0xa2,0x35,0x1b,0x26,0x89,0xaa,0x09,0xfd,0x56,0xd7,0x75,0x2a,0xd4,0x91, + 0xc0,0xf2,0x78,0xd7,0x05,0xca,0x12,0x1d,0xd9,0xd4,0x81,0x23,0xb2,0x3c,0x38,0xd9, + 0xb4,0xdc,0x21,0xe0,0xe5,0x2d,0xd4,0xbe,0x61,0x39,0x8a,0x46,0x90,0x46,0x73,0x31, + 0xba,0x48,0xbb,0x51,0xbb,0x91,0xd5,0x62,0xad,0xd1,0x53,0x5b,0x85,0xc9,0x1d,0xa7, + 0xf6,0xa0,0xe1,0x0e,0x6c,0x22,0x5d,0x29,0x9a,0xe7,0x0f,0xe8,0x0a,0x50,0xa7,0x19, + 0x11,0xc2,0x8b,0xe0,0x8a,0xfd,0x2b,0x94,0x31,0x7a,0x78,0x9c,0x9b,0x75,0x63,0x49, + 0xa9,0xe5,0x58,0xe6,0x3a,0x99,0xcb,0x2b,0xdd,0x0e,0xdc,0x7d,0x1b,0x98,0x80,0xc3, + 0x9f,0x02,0x01,0x23, +}; + +bool test_rsa_load_any() +{ + chunk_t chunk = chunk_from_buf(public_any); + public_key_t *public; + + public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + BUILD_BLOB_ASN1_DER, chunk_clone(chunk), + BUILD_END); + if (!public || public->get_keysize(public) != 256) + { + return FALSE; + } + public->destroy(public); + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/tests/test_sqlite.c b/src/charon/plugins/unit_tester/tests/test_sqlite.c new file mode 100644 index 000000000..d152fc594 --- /dev/null +++ b/src/charon/plugins/unit_tester/tests/test_sqlite.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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 <library.h> +#include <daemon.h> +#include <utils/enumerator.h> + +#include <unistd.h> + + +#define DBFILE "/tmp/strongswan-test.db" + +/******************************************************************************* + * sqlite simple test + ******************************************************************************/ +bool test_sqlite() +{ + database_t *db; + char *txt = "I'm a superduper test"; + char buf[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; + chunk_t data = chunk_from_buf(buf); + int row; + chunk_t qdata; + char *qtxt; + bool good = FALSE; + enumerator_t *enumerator; + + db = lib->db->create(lib->db, "sqlite://" DBFILE); + if (!db) + { + return FALSE; + } + if (db->execute(db, NULL, "CREATE TABLE test (txt TEXT, data BLOB)") < 0) + { + return FALSE; + } + if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)", + DB_TEXT, txt, DB_BLOB, data) < 0) + { + return FALSE; + } + if (row != 1) + { + return FALSE; + } + enumerator = db->query(db, "SELECT txt, data FROM test WHERE oid = ?", + DB_INT, row, + DB_TEXT, DB_BLOB); + if (!enumerator) + { + return FALSE; + } + while (enumerator->enumerate(enumerator, &qtxt, &qdata)) + { + if (good) + { /* only one row */ + good = FALSE; + break; + } + if (streq(qtxt, txt) && chunk_equals(data, qdata)) + { + good = TRUE; + } + } + enumerator->destroy(enumerator); + if (!good) + { + return FALSE; + } + if (db->execute(db, NULL, "DELETE FROM test WHERE oid = ?", DB_INT, row) != 1) + { + return FALSE; + } + if (db->execute(db, NULL, "DROP TABLE test") < 0) + { + return FALSE; + } + db->destroy(db); + unlink(DBFILE); + return TRUE; +} + diff --git a/src/charon/plugins/unit_tester/unit_tester.c b/src/charon/plugins/unit_tester/unit_tester.c new file mode 100644 index 000000000..28c6b4c11 --- /dev/null +++ b/src/charon/plugins/unit_tester/unit_tester.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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. + * + * $Id: unit_tester.c 3491 2008-02-22 14:04:00Z martin $ + */ + +#include "unit_tester.h" + +#include <daemon.h> + +typedef struct private_unit_tester_t private_unit_tester_t; +typedef struct unit_test_t unit_test_t; +typedef enum test_status_t test_status_t; + +/** + * private data of unit_tester + */ +struct private_unit_tester_t { + + /** + * public functions + */ + unit_tester_t public; +}; + +struct unit_test_t { + + /** + * name of the test + */ + char *name; + + /** + * test function + */ + bool (*test)(void); + + /** + * run the test? + */ + bool enabled; +}; + +#undef DEFINE_TEST +#define DEFINE_TEST(name, function, enabled) bool function(); +#include <plugins/unit_tester/tests.h> +#undef DEFINE_TEST +#define DEFINE_TEST(name, function, enabled) {name, function, enabled}, +static unit_test_t tests[] = { +#include <plugins/unit_tester/tests.h> +}; + +static void run_tests(private_unit_tester_t *this) +{ + int i, run = 0, failed = 0, success = 0, skipped = 0; + + DBG1(DBG_CFG, "running unit tests, %d tests registered", + sizeof(tests)/sizeof(unit_test_t)); + + for (i = 0; i < sizeof(tests)/sizeof(unit_test_t); i++) + { + if (tests[i].enabled) + { + run++; + if (tests[i].test()) + { + DBG1(DBG_CFG, "test '%s' successful", tests[i].name); + success++; + } + else + { + DBG1(DBG_CFG, "test '%s' failed", tests[i].name); + failed++; + } + } + else + { + DBG1(DBG_CFG, "test '%s' disabled", tests[i].name); + skipped++; + } + } + DBG1(DBG_CFG, "%d/%d tests successful (%d failed, %d disabled)", + success, run, failed, skipped); +} + +/** + * Implementation of 2007_t.destroy + */ +static void destroy(private_unit_tester_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_unit_tester_t *this = malloc_thing(private_unit_tester_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + run_tests(this); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/unit_tester/unit_tester.h b/src/charon/plugins/unit_tester/unit_tester.h new file mode 100644 index 000000000..af946c2e0 --- /dev/null +++ b/src/charon/plugins/unit_tester/unit_tester.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007 Martin Willi + * 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. + * + * $Id: unit_tester.h 3491 2008-02-22 14:04:00Z martin $ + */ + +/** + * @defgroup unit_tester unit_tester + * @{ @ingroup cplugins + */ + +#ifndef UNIT_TESTER_H_ +#define UNIT_TESTER_H_ + +#include <plugins/plugin.h> + +typedef struct unit_tester_t unit_tester_t; + +/** + * Unit testing plugin. + * + * The unit testing plugin runs tests on plugin initialization. Tests are + * defined in tests.h using the DEFINE_TEST macro. Implementation of the + * tests is done in the tests folder. Each test has uses a function which + * returns TRUE for success or FALSE for failure. + */ +struct unit_tester_t { + + /** + * Implements the plugin interface. + */ + plugin_t plugin; +}; + +/** + * Create a unit_tester plugin. + */ +plugin_t *plugin_create(); + +#endif /* UNIT_TESTER_H_ @}*/ diff --git a/src/charon/processing/jobs/acquire_job.c b/src/charon/processing/jobs/acquire_job.c index 48a77f558..b39e8e680 100644 --- a/src/charon/processing/jobs/acquire_job.c +++ b/src/charon/processing/jobs/acquire_job.c @@ -1,10 +1,3 @@ -/** - * @file acquire_job.c - * - * @brief Implementation of acquire_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: acquire_job.c 3589 2008-03-13 14:14:44Z martin $ */ #include "acquire_job.h" diff --git a/src/charon/processing/jobs/acquire_job.h b/src/charon/processing/jobs/acquire_job.h index 226966215..17c993d8e 100644 --- a/src/charon/processing/jobs/acquire_job.h +++ b/src/charon/processing/jobs/acquire_job.h @@ -1,10 +1,3 @@ -/** - * @file acquire_job.h - * - * @brief Interface of acquire_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: acquire_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup acquire_job acquire_job + * @{ @ingroup jobs */ #ifndef ACQUIRE_JOB_H_ @@ -29,14 +29,9 @@ typedef struct acquire_job_t acquire_job_t; #include <processing/jobs/job.h> /** - * @brief Class representing an ACQUIRE Job. + * Class representing an ACQUIRE Job. * * This job initiates a CHILD SA on kernel request. - * - * @b Constructors: - * - acquire_job_create() - * - * @ingroup jobs */ struct acquire_job_t { /** @@ -46,15 +41,13 @@ struct acquire_job_t { }; /** - * @brief Creates a job of type ACQUIRE. + * Creates a job of type ACQUIRE. * * We use the reqid to find the routed CHILD_SA. * * @param reqid reqid of the CHILD_SA to acquire * @return acquire_job_t object - * - * @ingroup jobs */ acquire_job_t *acquire_job_create(u_int32_t reqid); -#endif /* REKEY_CHILD_SA_JOB_H_ */ +#endif /* REKEY_CHILD_SA_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/callback_job.c b/src/charon/processing/jobs/callback_job.c index 53297916e..e8892ee82 100644 --- a/src/charon/processing/jobs/callback_job.c +++ b/src/charon/processing/jobs/callback_job.c @@ -1,10 +1,3 @@ -/** - * @file callback_job.c - * - * @brief Implementation of callback_job_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: callback_job.c 3742 2008-04-03 09:19:12Z tobias $ */ #include "callback_job.h" @@ -61,11 +56,6 @@ struct private_callback_job_t { pthread_mutex_t mutex; /** - * condvar to synchronize thread startup/cancellation - */ - pthread_cond_t condvar; - - /** * list of asociated child jobs */ linked_list_t *children; @@ -145,7 +135,6 @@ static void execute(private_callback_job_t *this) pthread_mutex_lock(&this->mutex); this->thread = pthread_self(); - pthread_cond_signal(&this->condvar); pthread_mutex_unlock(&this->mutex); pthread_cleanup_push((void*)destroy, this); @@ -192,7 +181,6 @@ callback_job_t *callback_job_create(callback_job_cb_t cb, void *data, /* private variables */ pthread_mutex_init(&this->mutex, NULL); - pthread_cond_init(&this->condvar, NULL); this->callback = cb; this->data = data; this->cleanup = cleanup; diff --git a/src/charon/processing/jobs/callback_job.h b/src/charon/processing/jobs/callback_job.h index 169f2d207..4e2eab235 100644 --- a/src/charon/processing/jobs/callback_job.h +++ b/src/charon/processing/jobs/callback_job.h @@ -1,10 +1,3 @@ -/** - * @file callback_job.h - * - * @brief Interface of callback_job_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: callback_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup callback_job callback_job + * @{ @ingroup jobs */ #ifndef CALLBACK_JOB_H_ @@ -32,12 +32,10 @@ typedef struct callback_job_t callback_job_t; typedef enum job_requeue_t job_requeue_t; /** - * @brief Job requeueing policy + * Job requeueing policy * * The job requeueing policy defines how a job is handled when the callback * function returns. - * - * @ingroup jobs */ enum job_requeue_t { @@ -58,20 +56,18 @@ enum job_requeue_t { }; /** - * @brief The callback function to use for the callback job. + * The callback function to use for the callback job. * * This is the function to use as callback for a callback job. It receives * a parameter supplied to the callback jobs constructor. * * @param data param supplied to job * @return requeing policy how to requeue the job - * - * @ingroup jobs */ typedef job_requeue_t (*callback_job_cb_t)(void *data); /** - * @brief Cleanup function to use for data cleanup. + * Cleanup function to use for data cleanup. * * The callback has an optional user argument which receives data. However, * this data may be cleaned up if it is allocated. This is the function @@ -79,22 +75,15 @@ typedef job_requeue_t (*callback_job_cb_t)(void *data); * * @param data param supplied to job * @return requeing policy how to requeue the job - * - * @ingroup jobs */ typedef void (*callback_job_cleanup_t)(void *data); /** - * @brief Class representing an callback Job. + * Class representing an callback Job. * * This is a special job which allows a simple callback function to * be executed by a thread of the thread pool. This allows simple execution * of asynchronous methods, without to manage threads. - * - * @b Constructors: - * - callback_job_create() - * - * @ingroup jobs */ struct callback_job_t { /** @@ -103,15 +92,13 @@ struct callback_job_t { job_t job_interface; /** - * @brief Cancel the jobs thread and wait for its termination. - * - * @param this calling object + * Cancel the jobs thread and wait for its termination. */ void (*cancel)(callback_job_t *this); }; /** - * @brief Creates a callback job. + * Creates a callback job. * * The cleanup function is called when the job gets destroyed to destroy * the associated data. @@ -124,12 +111,9 @@ struct callback_job_t { * @param cleanup destructor for data on destruction, or NULL * @param parent parent of this job * @return callback_job_t object - * - * @ingroup jobs */ callback_job_t *callback_job_create(callback_job_cb_t cb, void *data, callback_job_cleanup_t cleanup, callback_job_t *parent); -#endif /* CALLBACK_JOB_H_ */ - +#endif /* CALLBACK_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/delete_child_sa_job.c b/src/charon/processing/jobs/delete_child_sa_job.c index 23f330293..26f538d67 100644 --- a/src/charon/processing/jobs/delete_child_sa_job.c +++ b/src/charon/processing/jobs/delete_child_sa_job.c @@ -1,10 +1,3 @@ -/** - * @file delete_child_sa_job.c - * - * @brief Implementation of delete_child_sa_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: delete_child_sa_job.c 3589 2008-03-13 14:14:44Z martin $ */ #include "delete_child_sa_job.h" diff --git a/src/charon/processing/jobs/delete_child_sa_job.h b/src/charon/processing/jobs/delete_child_sa_job.h index 0b90e008d..c11e8fab4 100644 --- a/src/charon/processing/jobs/delete_child_sa_job.h +++ b/src/charon/processing/jobs/delete_child_sa_job.h @@ -1,10 +1,3 @@ -/** - * @file delete_child_sa_job.h - * - * @brief Interface of delete_child_sa_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: delete_child_sa_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup delete_child_sa_job delete_child_sa_job + * @{ @ingroup jobs */ #ifndef DELETE_CHILD_SA_JOB_H_ @@ -32,14 +32,9 @@ typedef struct delete_child_sa_job_t delete_child_sa_job_t; /** - * @brief Class representing an DELETE_CHILD_SA Job. + * Class representing an DELETE_CHILD_SA Job. * * This job initiates the delete of a CHILD SA. - * - * @b Constructors: - * - delete_child_sa_job_create() - * - * @ingroup jobs */ struct delete_child_sa_job_t { /** @@ -49,7 +44,7 @@ struct delete_child_sa_job_t { }; /** - * @brief Creates a job of type DELETE_CHILD_SA. + * Creates a job of type DELETE_CHILD_SA. * * The CHILD_SA is identified by its reqid, protocol (AH/ESP) and its * inbound SPI. @@ -58,11 +53,9 @@ struct delete_child_sa_job_t { * @param protocol protocol of the CHILD_SA * @param spi security parameter index of the CHILD_SA * @return delete_child_sa_job_t object - * - * @ingroup jobs */ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, protocol_id_t protocol, u_int32_t spi); -#endif /* DELETE_CHILD_SA_JOB_H_ */ +#endif /* DELETE_CHILD_SA_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/delete_ike_sa_job.c b/src/charon/processing/jobs/delete_ike_sa_job.c index 8d8c0cf36..95b60ad01 100644 --- a/src/charon/processing/jobs/delete_ike_sa_job.c +++ b/src/charon/processing/jobs/delete_ike_sa_job.c @@ -1,10 +1,3 @@ -/** - * @file delete_ike_sa_job.c - * - * @brief Implementation of delete_ike_sa_job_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: delete_ike_sa_job.c 3589 2008-03-13 14:14:44Z martin $ */ #include "delete_ike_sa_job.h" diff --git a/src/charon/processing/jobs/delete_ike_sa_job.h b/src/charon/processing/jobs/delete_ike_sa_job.h index 11bb46e73..cf666bb48 100644 --- a/src/charon/processing/jobs/delete_ike_sa_job.h +++ b/src/charon/processing/jobs/delete_ike_sa_job.h @@ -1,10 +1,3 @@ -/** - * @file delete_ike_sa_job.h - * - * @brief Interface of delete_ike_sa_job_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: delete_ike_sa_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup delete_child_sa_job delete_child_sa_job + * @{ @ingroup jobs */ #ifndef DELETE_IKE_SA_JOB_H_ @@ -32,16 +32,11 @@ typedef struct delete_ike_sa_job_t delete_ike_sa_job_t; /** - * @brief Class representing an DELETE_IKE_SA Job. + * Class representing an DELETE_IKE_SA Job. * * This job is responsible for deleting established or half open IKE_SAs. * A half open IKE_SA is every IKE_SA which hasn't reache the SA_ESTABLISHED * state. - * - * @b Constructors: - * - delete_ike_sa_job_create() - * - * @ingroup jobs */ struct delete_ike_sa_job_t { @@ -52,15 +47,13 @@ struct delete_ike_sa_job_t { }; /** - * @brief Creates a job of type DELETE_IKE_SA. + * Creates a job of type DELETE_IKE_SA. * * @param ike_sa_id id of the IKE_SA to delete * @param delete_if_established should the IKE_SA be deleted if it is established? * @return created delete_ike_sa_job_t object - * - * @ingroup jobs */ delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool delete_if_established); -#endif /* DELETE_IKE_SA_JOB_H_ */ +#endif /* DELETE_IKE_SA_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/initiate_mediation_job.c b/src/charon/processing/jobs/initiate_mediation_job.c index b8d516e22..de97daafa 100644 --- a/src/charon/processing/jobs/initiate_mediation_job.c +++ b/src/charon/processing/jobs/initiate_mediation_job.c @@ -1,12 +1,5 @@ -/** - * @file initiate_mediation_job.c - * - * @brief Implementation of initiate_mediation_job_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,9 +11,10 @@ * 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. + * + * $Id: initiate_mediation_job.c 3792 2008-04-10 12:51:04Z tobias $ */ - #include "initiate_mediation_job.h" #include <sa/ike_sa.h> @@ -44,11 +38,6 @@ struct private_initiate_mediation_job_t { ike_sa_id_t *mediated_sa_id; /** - * Child config of the CHILD_SA of the mediated connection. - */ - child_cfg_t *mediated_child; - - /** * ID of the IKE_SA of the mediation connection. */ ike_sa_id_t *mediation_sa_id; @@ -61,7 +50,6 @@ static void destroy(private_initiate_mediation_job_t *this) { DESTROY_IF(this->mediation_sa_id); DESTROY_IF(this->mediated_sa_id); - DESTROY_IF(this->mediated_child); free(this); } @@ -100,11 +88,12 @@ static void initiate(private_initiate_mediation_job_t *this) charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa); mediation_cfg = mediated_cfg->get_mediated_by(mediated_cfg); + mediation_cfg->get_ref(mediation_cfg); if (charon->connect_manager->check_and_register(charon->connect_manager, mediation_cfg->get_my_id(mediation_cfg), mediated_cfg->get_peer_id(mediated_cfg), - this->mediated_sa_id, this->mediated_child)) + this->mediated_sa_id)) { mediated_cfg->destroy(mediated_cfg); mediation_cfg->destroy(mediation_cfg); @@ -121,8 +110,8 @@ static void initiate(private_initiate_mediation_job_t *this) * we do not check the status, but NEED_MORE would be returned on success * because the registered callback returns FALSE then * this->mediation_sa_id is set in the callback */ - charon->interfaces->initiate(charon->interfaces, - mediation_cfg, NULL, (interface_manager_cb_t)initiate_callback, this); + charon->controller->initiate(charon->controller, + mediation_cfg, NULL, (controller_cb_t)initiate_callback, this); if (!this->mediation_sa_id) { DBG1(DBG_JOB, "initiating mediation connection '%s' failed", @@ -216,7 +205,6 @@ static private_initiate_mediation_job_t *initiate_mediation_job_create_empty() /* private variables */ this->mediation_sa_id = NULL; this->mediated_sa_id = NULL; - this->mediated_child = NULL; return this; } @@ -224,16 +212,13 @@ static private_initiate_mediation_job_t *initiate_mediation_job_create_empty() /* * Described in header */ -initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id, - child_cfg_t *child_cfg) +initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id) { private_initiate_mediation_job_t *this = initiate_mediation_job_create_empty(); this->public.job_interface.execute = (void (*) (job_t *)) initiate; this->mediated_sa_id = ike_sa_id->clone(ike_sa_id); - child_cfg->get_ref(child_cfg); - this->mediated_child = child_cfg; return &this->public; } diff --git a/src/charon/processing/jobs/initiate_mediation_job.h b/src/charon/processing/jobs/initiate_mediation_job.h index 9fb3b0f7d..966da95d3 100644 --- a/src/charon/processing/jobs/initiate_mediation_job.h +++ b/src/charon/processing/jobs/initiate_mediation_job.h @@ -1,11 +1,5 @@ -/** - * @file initiate_mediation_job.h - * - * @brief Interface of initiate_mediation_job_t. - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -17,6 +11,13 @@ * 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. + * + * $Id: initiate_mediation_job.h 3792 2008-04-10 12:51:04Z tobias $ + */ + +/** + * @defgroup initiate_mediation_job initiate_mediation_job + * @{ @ingroup jobs */ #ifndef INITIATE_MEDIATION_JOB_H_ @@ -25,19 +26,13 @@ typedef struct initiate_mediation_job_t initiate_mediation_job_t; #include <processing/jobs/job.h> -#include <config/child_cfg.h> #include <sa/ike_sa_id.h> /** - * @brief Class representing a INITIATE_MEDIATION Job. + * Class representing a INITIATE_MEDIATION Job. * * This job will initiate a mediation on behalf of a mediated connection. * If required the mediation connection is established. - * - * @b Constructors: - * - initiate_mediation_job_create() - * - * @ingroup jobs */ struct initiate_mediation_job_t { /** @@ -47,28 +42,22 @@ struct initiate_mediation_job_t { }; /** - * @brief Creates a job of type INITIATE_MEDIATION. + * Creates a job of type INITIATE_MEDIATION. * * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) - * @param child_cfg child config of the child_sa (gets cloned) * @return job object - * - * @ingroup jobs */ -initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id, - child_cfg_t *child_cfg); +initiate_mediation_job_t *initiate_mediation_job_create(ike_sa_id_t *ike_sa_id); /** - * @brief Creates a special job of type INITIATE_MEDIATION that reinitiates a + * Creates a special job of type INITIATE_MEDIATION that reinitiates a * specific connection. * * @param mediation_sa_id identification of the mediation sa (gets cloned) * @param mediated_sa_id identification of the mediated sa (gets cloned) * @return job object - * - * @ingroup jobs */ initiate_mediation_job_t *reinitiate_mediation_job_create(ike_sa_id_t *mediation_sa_id, ike_sa_id_t *mediated_sa_id); -#endif /*INITIATE_MEDIATION_JOB_H_*/ +#endif /*INITIATE_MEDIATION_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/job.h b/src/charon/processing/jobs/job.h index 1826c53b4..61f639936 100644 --- a/src/charon/processing/jobs/job.h +++ b/src/charon/processing/jobs/job.h @@ -1,10 +1,3 @@ -/** - * @file job.h - * - * @brief Interface job_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup job job + * @{ @ingroup jobs */ #ifndef JOB_H_ @@ -28,38 +28,27 @@ typedef struct job_t job_t; #include <library.h> - /** - * @brief Job-Interface as it is stored in the job queue. - * - * @b Constructors: - * - None, use specific implementation of the interface. - * - * @ingroup jobs + * Job-Interface as it is stored in the job queue. */ struct job_t { /** - * @brief Execute a job. + * Execute a job. * * The processing facility executes a job using this method. Jobs are * one-shot, they destroy themself after execution, so don't use a job * once it has been executed. - * - * @param this calling object */ void (*execute) (job_t *this); /** - * @brief Destroy a job. + * Destroy a job. * * Is only called whenever a job was not executed (e.g. due daemon shutdown). * After execution, jobs destroy themself. - * - * @param job_t calling object */ void (*destroy) (job_t *job); }; -#endif /* JOB_H_ */ - +#endif /* JOB_H_ @} */ diff --git a/src/charon/processing/jobs/mediation_job.c b/src/charon/processing/jobs/mediation_job.c index 3b9d363d7..c177d8db3 100644 --- a/src/charon/processing/jobs/mediation_job.c +++ b/src/charon/processing/jobs/mediation_job.c @@ -1,10 +1,3 @@ -/** - * @file mediation_job.c - * - * @brief Implementation of mediation_job_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Hochschule fuer Technik Rapperswil @@ -18,9 +11,10 @@ * 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. + * + * $Id: mediation_job.c 3666 2008-03-26 18:40:19Z tobias $ */ - #include "mediation_job.h" #include <encoding/payloads/endpoint_notify.h> @@ -49,14 +43,14 @@ struct private_mediation_job_t { identification_t *source; /** - * P2P_SESSIONID + * ME_CONNECTID */ - chunk_t session_id; + chunk_t connect_id; /** - * P2P_SESSIONKEY + * ME_CONNECTKEY */ - chunk_t session_key; + chunk_t connect_key; /** * Submitted endpoints @@ -81,8 +75,8 @@ static void destroy(private_mediation_job_t *this) { DESTROY_IF(this->target); DESTROY_IF(this->source); - chunk_free(&this->session_id); - chunk_free(&this->session_key); + chunk_free(&this->connect_id); + chunk_free(&this->connect_key); DESTROY_OFFSET_IF(this->endpoints, offsetof(endpoint_notify_t, destroy)); free(this); } @@ -117,8 +111,8 @@ static void execute(private_mediation_job_t *this) else { /* normal mediation between two peers */ - if (target_sa->relay(target_sa, this->source, this->session_id, - this->session_key, this->endpoints, this->response) != SUCCESS) + if (target_sa->relay(target_sa, this->source, this->connect_id, + this->connect_key, this->endpoints, this->response) != SUCCESS) { DBG1(DBG_JOB, "mediation between '%D' and '%D' failed", this->source, this->target); @@ -160,8 +154,8 @@ static private_mediation_job_t *mediation_job_create_empty() this->target = NULL; this->source = NULL; this->callback = FALSE; - this->session_id = chunk_empty; - this->session_key = chunk_empty; + this->connect_id = chunk_empty; + this->connect_key = chunk_empty; this->endpoints = NULL; this->response = FALSE; @@ -172,15 +166,15 @@ static private_mediation_job_t *mediation_job_create_empty() * Described in header */ mediation_job_t *mediation_job_create(identification_t *peer_id, - identification_t *requester, chunk_t session_id, chunk_t session_key, + identification_t *requester, chunk_t connect_id, chunk_t connect_key, linked_list_t *endpoints, bool response) { private_mediation_job_t *this = mediation_job_create_empty(); this->target = peer_id->clone(peer_id); this->source = requester->clone(requester); - this->session_id = chunk_clone(session_id); - this->session_key = chunk_clone(session_key); + this->connect_id = chunk_clone(connect_id); + this->connect_key = chunk_clone(connect_key); this->endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone)); this->response = response; diff --git a/src/charon/processing/jobs/mediation_job.h b/src/charon/processing/jobs/mediation_job.h index 6130b2e27..0e2901180 100644 --- a/src/charon/processing/jobs/mediation_job.h +++ b/src/charon/processing/jobs/mediation_job.h @@ -1,9 +1,3 @@ -/** - * @file mediation_job.h - * - * @brief Interface of mediation_job_t. - */ - /* * Copyright (C) 2007 Tobias Brunner * Hochschule fuer Technik Rapperswil @@ -17,6 +11,13 @@ * 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. + * + * $Id: mediation_job.h 3666 2008-03-26 18:40:19Z tobias $ + */ + +/** + * @defgroup mediation_job mediation_job + * @{ @ingroup jobs */ #ifndef MEDIATION_JOB_H_ @@ -30,14 +31,9 @@ typedef struct mediation_job_t mediation_job_t; #include <utils/linked_list.h> /** - * @brief Class representing a MEDIATION Job. + * Class representing a MEDIATION Job. * * This job handles the mediation on the mediation server. - * - * @b Constructors: - * - mediation_job_create() - * - * @ingroup jobs */ struct mediation_job_t { /** @@ -47,27 +43,25 @@ struct mediation_job_t { }; /** - * @brief Creates a job of type MEDIATION. + * Creates a job of type MEDIATION. * * Parameters get cloned. * * @param peer_id ID of the requested peer * @param requester ID of the requesting peer - * @param session_id content of P2P_SESSIONID (could be NULL) - * @param session_key content of P2P_SESSIONKEY + * @param connect_id content of ME_CONNECTID (could be NULL) + * @param connect_key content of ME_CONNECTKEY * @param endpoints list of submitted endpoints * @param response TRUE if this is a response * @return job object - * - * @ingroup jobs */ mediation_job_t *mediation_job_create(identification_t *peer_id, - identification_t *requester, chunk_t session_id, chunk_t session_key, + identification_t *requester, chunk_t connect_id, chunk_t connect_key, linked_list_t *endpoints, bool response); /** - * @brief Creates a special job of type MEDIATION that is used to send a callback + * Creates a special job of type MEDIATION that is used to send a callback * notification to a peer. * * Parameters get cloned. @@ -75,10 +69,8 @@ mediation_job_t *mediation_job_create(identification_t *peer_id, * @param requester ID of the waiting peer * @param peer_id ID of the requested peer * @return job object - * - * @ingroup jobs */ mediation_job_t *mediation_callback_job_create(identification_t *requester, identification_t *peer_id); -#endif /*MEDIATION_JOB_H_*/ +#endif /*MEDIATION_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/process_message_job.c b/src/charon/processing/jobs/process_message_job.c index 91e7a80bf..33bcae6f0 100644 --- a/src/charon/processing/jobs/process_message_job.c +++ b/src/charon/processing/jobs/process_message_job.c @@ -1,10 +1,3 @@ -/** - * @file process_message_job.h - * - * @brief Implementation of process_message_job_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,9 +12,10 @@ * 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. + * + * $Id: process_message_job.c 3666 2008-03-26 18:40:19Z tobias $ */ - #include "process_message_job.h" #include <daemon.h> @@ -59,7 +53,7 @@ static void execute(private_process_message_job_t *this) { ike_sa_t *ike_sa; -#ifdef P2P +#ifdef ME /* if this is an unencrypted INFORMATIONAL exchange it is likely a * connectivity check. */ if (this->message->get_exchange_type(this->message) == INFORMATIONAL && @@ -74,7 +68,7 @@ static void execute(private_process_message_job_t *this) destroy(this); return; } -#endif /* P2P */ +#endif /* ME */ ike_sa = charon->ike_sa_manager->checkout_by_message(charon->ike_sa_manager, this->message); diff --git a/src/charon/processing/jobs/process_message_job.h b/src/charon/processing/jobs/process_message_job.h index 5bb18155a..920444db1 100644 --- a/src/charon/processing/jobs/process_message_job.h +++ b/src/charon/processing/jobs/process_message_job.h @@ -1,10 +1,3 @@ -/** - * @file process_message_job.h - * - * @brief Interface of process_message_job_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: process_message_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup process_message_job process_message_job + * @{ @ingroup jobs */ #ifndef PROCESS_MESSAGE_JOB_H_ @@ -31,12 +31,7 @@ typedef struct process_message_job_t process_message_job_t; #include <processing/jobs/job.h> /** - * @brief Class representing an PROCESS_MESSAGE job. - * - * @b Constructors: - * - process_message_job_create() - * - * @ingroup jobs + * Class representing an PROCESS_MESSAGE job. */ struct process_message_job_t { /** @@ -46,13 +41,11 @@ struct process_message_job_t { }; /** - * @brief Creates a job of type PROCESS_MESSAGE. + * Creates a job of type PROCESS_MESSAGE. * * @param message message to process * @return created process_message_job_t object - * - * @ingroup jobs */ process_message_job_t *process_message_job_create(message_t *message); -#endif /*PROCESS_MESSAGE_JOB_H_*/ +#endif /*PROCESS_MESSAGE_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/rekey_child_sa_job.c b/src/charon/processing/jobs/rekey_child_sa_job.c index f754e5a1f..42bf79d26 100644 --- a/src/charon/processing/jobs/rekey_child_sa_job.c +++ b/src/charon/processing/jobs/rekey_child_sa_job.c @@ -1,10 +1,3 @@ -/** - * @file rekey_child_sa_job.c - * - * @brief Implementation of rekey_child_sa_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: rekey_child_sa_job.c 3589 2008-03-13 14:14:44Z martin $ */ #include "rekey_child_sa_job.h" diff --git a/src/charon/processing/jobs/rekey_child_sa_job.h b/src/charon/processing/jobs/rekey_child_sa_job.h index df86070bc..38fd04f10 100644 --- a/src/charon/processing/jobs/rekey_child_sa_job.h +++ b/src/charon/processing/jobs/rekey_child_sa_job.h @@ -1,10 +1,3 @@ -/** - * @file rekey_child_sa_job.h - * - * @brief Interface of rekey_child_sa_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: rekey_child_sa_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup rekey_child_sa_job rekey_child_sa_job + * @{ @ingroup jobs */ #ifndef REKEY_CHILD_SA_JOB_H_ @@ -31,14 +31,9 @@ typedef struct rekey_child_sa_job_t rekey_child_sa_job_t; #include <config/proposal.h> /** - * @brief Class representing an REKEY_CHILD_SA Job. + * Class representing an REKEY_CHILD_SA Job. * * This job initiates the rekeying of a CHILD SA. - * - * @b Constructors: - * - rekey_child_sa_job_create() - * - * @ingroup jobs */ struct rekey_child_sa_job_t { /** @@ -48,7 +43,7 @@ struct rekey_child_sa_job_t { }; /** - * @brief Creates a job of type REKEY_CHILD_SA. + * Creates a job of type REKEY_CHILD_SA. * * The CHILD_SA is identified by its protocol (AH/ESP) and its * inbound SPI. @@ -57,9 +52,8 @@ struct rekey_child_sa_job_t { * @param protocol protocol of the CHILD_SA * @param spi security parameter index of the CHILD_SA * @return rekey_child_sa_job_t object - * - * @ingroup jobs */ -rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, protocol_id_t protocol, u_int32_t spi); - -#endif /* REKEY_CHILD_SA_JOB_H_ */ +rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, + protocol_id_t protocol, + u_int32_t spi); +#endif /* REKEY_CHILD_SA_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/rekey_ike_sa_job.c b/src/charon/processing/jobs/rekey_ike_sa_job.c index 020c3cce8..38aa41c27 100644 --- a/src/charon/processing/jobs/rekey_ike_sa_job.c +++ b/src/charon/processing/jobs/rekey_ike_sa_job.c @@ -1,10 +1,3 @@ -/** - * @file rekey_ike_sa_job.c - * - * @brief Implementation of rekey_ike_sa_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,13 +11,14 @@ * 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. + * + * $Id: rekey_ike_sa_job.c 3793 2008-04-11 08:14:48Z martin $ */ - + #include "rekey_ike_sa_job.h" #include <daemon.h> - typedef struct private_rekey_ike_sa_job_t private_rekey_ike_sa_job_t; /** @@ -74,7 +68,7 @@ static void execute(private_rekey_ike_sa_job_t *this) { if (this->reauth) { - status = ike_sa->reestablish(ike_sa); + status = ike_sa->reauth(ike_sa); } else { diff --git a/src/charon/processing/jobs/rekey_ike_sa_job.h b/src/charon/processing/jobs/rekey_ike_sa_job.h index 4031b3813..c8d9abee3 100644 --- a/src/charon/processing/jobs/rekey_ike_sa_job.h +++ b/src/charon/processing/jobs/rekey_ike_sa_job.h @@ -1,10 +1,3 @@ -/** - * @file rekey_ike_sa_job.h - * - * @brief Interface of rekey_ike_sa_job_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: rekey_ike_sa_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup rekey_ike_sa_job rekey_ike_sa_job + * @{ @ingroup jobs */ #ifndef REKEY_IKE_SA_JOB_H_ @@ -30,14 +30,9 @@ typedef struct rekey_ike_sa_job_t rekey_ike_sa_job_t; #include <processing/jobs/job.h> /** - * @brief Class representing an REKEY_IKE_SA Job. + * Class representing an REKEY_IKE_SA Job. * * This job initiates the rekeying of an IKE_SA. - * - * @b Constructors: - * - rekey_ike_sa_job_create() - * - * @ingroup jobs */ struct rekey_ike_sa_job_t { /** @@ -47,14 +42,12 @@ struct rekey_ike_sa_job_t { }; /** - * @brief Creates a job of type REKEY_IKE_SA. + * Creates a job of type REKEY_IKE_SA. * * @param ike_sa_id ID of the IKE_SA to rekey * @param reauth TRUE to reauthenticate peer, FALSE for rekeying only * @return rekey_ike_sa_job_t object - * - * @ingroup jobs */ rekey_ike_sa_job_t *rekey_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool reauth); -#endif /* REKEY_IKE_SA_JOB_H_ */ +#endif /* REKEY_IKE_SA_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/retransmit_job.c b/src/charon/processing/jobs/retransmit_job.c index 8c15aa651..89858786e 100644 --- a/src/charon/processing/jobs/retransmit_job.c +++ b/src/charon/processing/jobs/retransmit_job.c @@ -1,10 +1,3 @@ -/** - * @file retransmit_job.c - * - * @brief Implementation of retransmit_job_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: retransmit_job.c 3589 2008-03-13 14:14:44Z martin $ */ #include "retransmit_job.h" diff --git a/src/charon/processing/jobs/retransmit_job.h b/src/charon/processing/jobs/retransmit_job.h index 93bb548e7..60932b304 100644 --- a/src/charon/processing/jobs/retransmit_job.h +++ b/src/charon/processing/jobs/retransmit_job.h @@ -1,10 +1,3 @@ -/** - * @file retransmit_job.h - * - * @brief Interface of retransmit_job_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: retransmit_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup retransmit_job retransmit_job + * @{ @ingroup jobs */ #ifndef RETRANSMIT_JOB_H_ @@ -31,16 +31,11 @@ typedef struct retransmit_job_t retransmit_job_t; #include <sa/ike_sa_id.h> /** - * @brief Class representing an retransmit Job. + * Class representing an retransmit Job. * * This job is scheduled every time a request is sent over the * wire. If the response to the request is not received at schedule * time, the retransmission will be initiated. - * - * @b Constructors: - * - retransmit_job_create() - * - * @ingroup jobs */ struct retransmit_job_t { /** @@ -50,15 +45,13 @@ struct retransmit_job_t { }; /** - * @brief Creates a job of type retransmit. + * Creates a job of type retransmit. * * @param message_id message_id of the request to resend * @param ike_sa_id identification of the ike_sa as ike_sa_id_t * @return retransmit_job_t object - * - * @ingroup jobs */ retransmit_job_t *retransmit_job_create(u_int32_t message_id, ike_sa_id_t *ike_sa_id); -#endif /* RETRANSMIT_JOB_H_ */ +#endif /* RETRANSMIT_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/roam_job.c b/src/charon/processing/jobs/roam_job.c index 842f57405..0b323ae8b 100644 --- a/src/charon/processing/jobs/roam_job.c +++ b/src/charon/processing/jobs/roam_job.c @@ -1,10 +1,3 @@ -/** - * @file roam_job.c - * - * @brief Implementation of roam_job_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,9 +11,10 @@ * 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. + * + * $Id: roam_job.c 3804 2008-04-14 11:37:46Z martin $ */ - #include <stdlib.h> #include "roam_job.h" @@ -62,18 +56,18 @@ static void execute(private_roam_job_t *this) ike_sa_t *ike_sa; linked_list_t *list; ike_sa_id_t *id; - iterator_t *iterator; + enumerator_t *enumerator; - /* iterating over all IKE_SAs gives us no way to checkin_and_destroy + /* enumerator over all IKE_SAs gives us no way to checkin_and_destroy * after a DESTROY_ME, so we check out each available IKE_SA by hand. */ list = linked_list_create(); - iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager); - while (iterator->iterate(iterator, (void**)&ike_sa)) + enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager); + while (enumerator->enumerate(enumerator, &ike_sa)) { id = ike_sa->get_id(ike_sa); list->insert_last(list, id->clone(id)); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); while (list->remove_last(list, (void**)&id) == SUCCESS) { diff --git a/src/charon/processing/jobs/roam_job.h b/src/charon/processing/jobs/roam_job.h index 293b09f08..763416b4a 100644 --- a/src/charon/processing/jobs/roam_job.h +++ b/src/charon/processing/jobs/roam_job.h @@ -1,9 +1,3 @@ -/** - * @file roam_job.h - * - * @brief Interface of roam_job_t. - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -17,6 +11,13 @@ * 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. + * + * $Id: roam_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup roam_job roam_job + * @{ @ingroup jobs */ #ifndef ROAM_JOB_H_ @@ -29,15 +30,10 @@ typedef struct roam_job_t roam_job_t; #include <processing/jobs/job.h> /** - * @brief A job to inform IKE_SAs about changed local address setup. + * A job to inform IKE_SAs about changed local address setup. * * If a local address appears or disappears, the kernel fires this job to * update all IKE_SAs. - * - * @b Constructors: - * - roam_job_create() - * - * @ingroup jobs */ struct roam_job_t { @@ -48,14 +44,11 @@ struct roam_job_t { }; /** - * @brief Creates a job to inform IKE_SAs about an updated address list. + * Creates a job to inform IKE_SAs about an updated address list. * * @param address TRUE if address list changed, FALSE if routing changed * @return initiate_ike_sa_job_t object - * - * @ingroup jobs */ roam_job_t *roam_job_create(bool address); -#endif /*ROAM_JOB_H_*/ - +#endif /*ROAM_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/send_dpd_job.c b/src/charon/processing/jobs/send_dpd_job.c index d9c457ab6..a7d0cf3f3 100644 --- a/src/charon/processing/jobs/send_dpd_job.c +++ b/src/charon/processing/jobs/send_dpd_job.c @@ -1,10 +1,3 @@ -/** - * @file send_dpd_job.c - * - * @brief Implementation of send_dpd_job_t. - * - */ - /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger * Hochschule fuer Technik Rapperswil @@ -18,9 +11,10 @@ * 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. + * + * $Id: send_dpd_job.c 3589 2008-03-13 14:14:44Z martin $ */ - #include <stdlib.h> #include "send_dpd_job.h" diff --git a/src/charon/processing/jobs/send_dpd_job.h b/src/charon/processing/jobs/send_dpd_job.h index 0e4059131..032823edd 100644 --- a/src/charon/processing/jobs/send_dpd_job.h +++ b/src/charon/processing/jobs/send_dpd_job.h @@ -1,9 +1,3 @@ -/** - * @file send_dpd_job.h - * - * @brief Interface of send_dpd_job_t. - */ - /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger * Hochschule fuer Technik Rapperswil @@ -17,6 +11,13 @@ * 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. + * + * $Id: send_dpd_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup send_dpd_job send_dpd_job + * @{ @ingroup jobs */ #ifndef SEND_DPD_JOB_H_ @@ -29,16 +30,11 @@ typedef struct send_dpd_job_t send_dpd_job_t; #include <sa/ike_sa_id.h> /** - * @brief Class representing a SEND_DPD Job. + * Class representing a SEND_DPD Job. * * Job to periodically send a Dead Peer Detection (DPD) request, * ie. an IKE request with no payloads other than the encrypted payload * required by the syntax. - * - * @b Constructors: - * - send_dpd_job_create() - * - * @ingroup jobs */ struct send_dpd_job_t { /** @@ -48,13 +44,11 @@ struct send_dpd_job_t { }; /** - * @brief Creates a job of type SEND_DPD. + * Creates a job of type SEND_DPD. * * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) * @return initiate_ike_sa_job_t object - * - * @ingroup jobs */ send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id); -#endif /*SEND_DPD_JOB_H_*/ +#endif /*SEND_DPD_JOB_H_ @} */ diff --git a/src/charon/processing/jobs/send_keepalive_job.c b/src/charon/processing/jobs/send_keepalive_job.c index 34198deb0..82f6a5f55 100644 --- a/src/charon/processing/jobs/send_keepalive_job.c +++ b/src/charon/processing/jobs/send_keepalive_job.c @@ -1,10 +1,3 @@ -/** - * @file send_keepalive_job.c - * - * @brief Implementation of send_keepalive_job_t. - * - */ - /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger * Hochschule fuer Technik Rapperswil @@ -18,9 +11,10 @@ * 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. + * + * $Id: send_keepalive_job.c 3589 2008-03-13 14:14:44Z martin $ */ - #include <stdlib.h> #include "send_keepalive_job.h" diff --git a/src/charon/processing/jobs/send_keepalive_job.h b/src/charon/processing/jobs/send_keepalive_job.h index e8d214aed..44bab09b4 100644 --- a/src/charon/processing/jobs/send_keepalive_job.h +++ b/src/charon/processing/jobs/send_keepalive_job.h @@ -1,9 +1,3 @@ -/** - * @file send_keepalive_job.h - * - * @brief Interface of send_keepalive_job_t. - */ - /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger * Hochschule fuer Technik Rapperswil @@ -17,6 +11,13 @@ * 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. + * + * $Id: send_keepalive_job.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup send_keepalive_job send_keepalive_job + * @{ @ingroup jobs */ #ifndef SEND_KEEPALIVE_JOB_H_ @@ -29,15 +30,10 @@ typedef struct send_keepalive_job_t send_keepalive_job_t; #include <sa/ike_sa_id.h> /** - * @brief Class representing a SEND_KEEPALIVE Job. + * Class representing a SEND_KEEPALIVE Job. * * This job will send a NAT keepalive packet if the IKE SA is still alive, * and reinsert itself into the event queue. - * - * @b Constructors: - * - send_keepalive_job_create() - * - * @ingroup jobs */ struct send_keepalive_job_t { /** @@ -47,13 +43,11 @@ struct send_keepalive_job_t { }; /** - * @brief Creates a job of type SEND_KEEPALIVE. + * Creates a job of type SEND_KEEPALIVE. * * @param ike_sa_id identification of the ike_sa as ike_sa_id_t object (gets cloned) * @return initiate_ike_sa_job_t object - * - * @ingroup jobs */ send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id); -#endif /*SEND_KEEPALIVE_JOB_H_*/ +#endif /*SEND_KEEPALIVE_JOB_H_ @} */ diff --git a/src/charon/processing/processor.c b/src/charon/processing/processor.c index b3815eeb1..010f6624f 100644 --- a/src/charon/processing/processor.c +++ b/src/charon/processing/processor.c @@ -1,10 +1,3 @@ -/** - * @file processor.c - * - * @brief Implementation of processor_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: processor.c 3742 2008-04-03 09:19:12Z tobias $ */ #include <stdlib.h> @@ -35,7 +30,7 @@ typedef struct private_processor_t private_processor_t; /** - * @brief Private data of processor_t class. + * Private data of processor_t class. */ struct private_processor_t { /** @@ -71,7 +66,12 @@ struct private_processor_t { /** * Condvar to wait for new jobs */ - pthread_cond_t condvar; + pthread_cond_t jobadded; + + /** + * Condvar to wait for terminated threads + */ + pthread_cond_t threadterminated; }; static void process_jobs(private_processor_t *this); @@ -85,7 +85,10 @@ static void restart(private_processor_t *this) if (pthread_create(&thread, NULL, (void*)process_jobs, this) != 0) { + pthread_mutex_lock(&this->mutex); this->total_threads--; + pthread_cond_broadcast(&this->threadterminated); + pthread_mutex_unlock(&this->mutex); } } @@ -108,7 +111,7 @@ static void process_jobs(private_processor_t *this) if (this->list->get_count(this->list) == 0) { this->idle_threads++; - pthread_cond_wait(&this->condvar, &this->mutex); + pthread_cond_wait(&this->jobadded, &this->mutex); this->idle_threads--; continue; } @@ -121,7 +124,7 @@ static void process_jobs(private_processor_t *this) pthread_mutex_lock(&this->mutex); } this->total_threads--; - pthread_cond_broadcast(&this->condvar); + pthread_cond_signal(&this->threadterminated); pthread_mutex_unlock(&this->mutex); } @@ -130,7 +133,11 @@ static void process_jobs(private_processor_t *this) */ static u_int get_total_threads(private_processor_t *this) { - return this->total_threads; + u_int count; + pthread_mutex_lock(&this->mutex); + count = this->total_threads; + pthread_mutex_unlock(&this->mutex); + return count; } /** @@ -138,7 +145,11 @@ static u_int get_total_threads(private_processor_t *this) */ static u_int get_idle_threads(private_processor_t *this) { - return this->idle_threads; + u_int count; + pthread_mutex_lock(&this->mutex); + count = this->idle_threads; + pthread_mutex_unlock(&this->mutex); + return count; } /** @@ -160,8 +171,8 @@ static void queue_job(private_processor_t *this, job_t *job) { pthread_mutex_lock(&this->mutex); this->list->insert_last(this->list, job); + pthread_cond_signal(&this->jobadded); pthread_mutex_unlock(&this->mutex); - pthread_cond_signal(&this->condvar); } /** @@ -189,6 +200,7 @@ static void set_threads(private_processor_t *this, u_int count) { /* decrease thread count */ this->desired_threads = count; } + pthread_cond_broadcast(&this->jobadded); pthread_mutex_unlock(&this->mutex); } @@ -198,11 +210,13 @@ static void set_threads(private_processor_t *this, u_int count) static void destroy(private_processor_t *this) { set_threads(this, 0); + pthread_mutex_lock(&this->mutex); while (this->total_threads > 0) { - pthread_cond_broadcast(&this->condvar); - pthread_cond_wait(&this->condvar, &this->mutex); + pthread_cond_broadcast(&this->jobadded); + pthread_cond_wait(&this->threadterminated, &this->mutex); } + pthread_mutex_unlock(&this->mutex); this->list->destroy_offset(this->list, offsetof(job_t, destroy)); free(this); } @@ -223,7 +237,8 @@ processor_t *processor_create(size_t pool_size) this->list = linked_list_create(); pthread_mutex_init(&this->mutex, NULL); - pthread_cond_init(&this->condvar, NULL); + pthread_cond_init(&this->jobadded, NULL); + pthread_cond_init(&this->threadterminated, NULL); this->total_threads = 0; this->desired_threads = 0; this->idle_threads = 0; diff --git a/src/charon/processing/processor.h b/src/charon/processing/processor.h index f12c7f10e..530fbc24b 100644 --- a/src/charon/processing/processor.h +++ b/src/charon/processing/processor.h @@ -1,10 +1,3 @@ -/** - * @file processor.h - * - * @brief Interface of processor_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: processor.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup processor processor + * @{ @ingroup processing */ #ifndef PROCESSOR_H_ @@ -32,80 +32,65 @@ typedef struct processor_t processor_t; #include <processing/jobs/job.h> /** - * @brief The processor uses threads to process queued jobs. - * - * @b Constructors: - * - processor_create() - * - * @ingroup processing + * The processor uses threads to process queued jobs. */ struct processor_t { /** - * @brief Get the total number of threads used by the processor. - * - * @param this calling object + * Get the total number of threads used by the processor. + * * @return size of thread pool */ u_int (*get_total_threads) (processor_t *this); /** - * @brief Get the number of threads currently waiting. - * - * @param this calling object + * Get the number of threads currently waiting. + * * @return number of idle threads */ u_int (*get_idle_threads) (processor_t *this); /** - * @brief Get the number of queued jobs. + * Get the number of queued jobs. * - * @param this calling object * @returns number of items in queue */ u_int (*get_job_load) (processor_t *this); /** - * @brief Adds a job to the queue. + * Adds a job to the queue. * * This function is non blocking and adds a job_t to the queue. * - * @param this calling object * @param job job to add to the queue */ void (*queue_job) (processor_t *this, job_t *job); /** - * @brief Set the number of threads to use in the processor. + * Set the number of threads to use in the processor. * * If the number of threads is smaller than number of currently running * threads, thread count is decreased. Use 0 to disable the processor. * This call blocks if it decreases thread count until threads have * terminated, so make sure there are not too many blocking jobs. * - * @param this calling object * @param count number of threads to allocate */ void (*set_threads)(processor_t *this, u_int count); /** - * @brief Destroy a processor object. - * - * @param processor calling object + * Destroy a processor object. */ void (*destroy) (processor_t *processor); }; /** - * @brief Create the thread pool without any threads. + * Create the thread pool without any threads. * * Use the set_threads method to start processing jobs. * * @return processor_t object - * - * @ingroup processing */ processor_t *processor_create(); -#endif /*PROCESSOR_H_*/ - +#endif /*PROCESSOR_H_ @} */ diff --git a/src/charon/processing/scheduler.c b/src/charon/processing/scheduler.c index ededb479a..42aa2579e 100644 --- a/src/charon/processing/scheduler.c +++ b/src/charon/processing/scheduler.c @@ -1,10 +1,3 @@ -/** - * @file scheduler.c - * - * @brief Implementation of scheduler_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: scheduler.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stdlib.h> diff --git a/src/charon/processing/scheduler.h b/src/charon/processing/scheduler.h index 7bde6e638..edc17a02b 100644 --- a/src/charon/processing/scheduler.h +++ b/src/charon/processing/scheduler.h @@ -1,10 +1,3 @@ -/** - * @file scheduler.h - * - * @brief Interface of scheduler_t. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: scheduler.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup scheduler scheduler + * @{ @ingroup processing */ #ifndef SCHEDULER_H_ @@ -30,52 +30,40 @@ typedef struct scheduler_t scheduler_t; #include <processing/jobs/job.h> /** - * @brief The scheduler queues and executes timed events. + * The scheduler queues and executes timed events. * * The scheduler stores timed events and passes them to the processor. - * - * @b Constructors: - * - scheduler_create() - * - * @ingroup processing */ struct scheduler_t { /** - * @brief Adds a event to the queue, using a relative time offset. + * Adds a event to the queue, using a relative time offset. * * Schedules a job for execution using a relative time offset. * - * @param this calling object * @param job job to schedule * @param time relative to to schedule job (in ms) */ void (*schedule_job) (scheduler_t *this, job_t *job, u_int32_t time); /** - * @brief Returns number of jobs scheduled. + * Returns number of jobs scheduled. * - * @param this calling object * @return number of scheduled jobs */ u_int (*get_job_load) (scheduler_t *this); /** - * @brief Destroys a scheduler object. - * - * @param this calling object + * Destroys a scheduler object. */ void (*destroy) (scheduler_t *this); }; /** - * @brief Create a scheduler. + * Create a scheduler. * * @return scheduler_t object - * - * @ingroup processing */ scheduler_t *scheduler_create(void); -#endif /*SCHEDULER_H_*/ - +#endif /*SCHEDULER_H_ @} */ diff --git a/src/charon/sa/authenticators/authenticator.c b/src/charon/sa/authenticators/authenticator.c index 707aae9ad..c301e4933 100644 --- a/src/charon/sa/authenticators/authenticator.c +++ b/src/charon/sa/authenticators/authenticator.c @@ -1,11 +1,5 @@ -/** - * @file authenticator.c - * - * @brief Generic constructor for authenticators. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -18,13 +12,15 @@ * 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. + * + * $Id: authenticator.c 4051 2008-06-10 09:08:27Z tobias $ */ #include <string.h> #include "authenticator.h" -#include <sa/authenticators/rsa_authenticator.h> +#include <sa/authenticators/pubkey_authenticator.h> #include <sa/authenticators/psk_authenticator.h> #include <sa/authenticators/eap_authenticator.h> @@ -33,23 +29,46 @@ ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS, "RSA signature", "pre-shared key", "DSS signature"); -ENUM_NEXT(auth_method_names, AUTH_EAP, AUTH_EAP, AUTH_DSS, +ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS, + "ECDSA-256 signature", + "ECDSA-384 signature", + "ECDSA-521 signature"); +ENUM_NEXT(auth_method_names, AUTH_EAP, AUTH_EAP, AUTH_ECDSA_521, "EAP"); ENUM_END(auth_method_names, AUTH_EAP); -/* +/** * Described in header. */ -authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method) +authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method) { switch (auth_method) { + case CONF_AUTH_PUBKEY: + return (authenticator_t*)pubkey_authenticator_create(ike_sa); + case CONF_AUTH_PSK: + return (authenticator_t*)psk_authenticator_create(ike_sa); + case CONF_AUTH_EAP: + return (authenticator_t*)eap_authenticator_create(ike_sa); + default: + return NULL; + } +} + +/** + * Described in header. + */ +authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload) +{ + switch (auth_payload->get_auth_method(auth_payload)) + { case AUTH_RSA: - return (authenticator_t*)rsa_authenticator_create(ike_sa); + case AUTH_ECDSA_256: + case AUTH_ECDSA_384: + case AUTH_ECDSA_521: + return (authenticator_t*)pubkey_authenticator_create(ike_sa); case AUTH_PSK: return (authenticator_t*)psk_authenticator_create(ike_sa); - case AUTH_EAP: - return (authenticator_t*)eap_authenticator_create(ike_sa); default: return NULL; } diff --git a/src/charon/sa/authenticators/authenticator.h b/src/charon/sa/authenticators/authenticator.h index c7b0fc81a..3c961d23e 100644 --- a/src/charon/sa/authenticators/authenticator.h +++ b/src/charon/sa/authenticators/authenticator.h @@ -1,11 +1,5 @@ -/** - * @file authenticator.h - * - * @brief Interface of authenticator_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -19,6 +13,13 @@ * 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. + * + * $Id: authenticator.h 4051 2008-06-10 09:08:27Z tobias $ + */ + +/** + * @defgroup authenticator authenticator + * @{ @ingroup authenticators */ #ifndef AUTHENTICATOR_H_ @@ -29,12 +30,11 @@ typedef struct authenticator_t authenticator_t; #include <library.h> #include <sa/ike_sa.h> +#include <config/peer_cfg.h> #include <encoding/payloads/auth_payload.h> /** * Method to use for authentication. - * - * @ingroup authenticators */ enum auth_method_t { /** @@ -57,6 +57,21 @@ enum auth_method_t { AUTH_DSS = 3, /** + * ECDSA with SHA-256 on the P-256 curve as specified in RFC 4754 + */ + AUTH_ECDSA_256 = 9, + + /** + * ECDSA with SHA-384 on the P-384 curve as specified in RFC 4754 + */ + AUTH_ECDSA_384 = 10, + + /** + * ECDSA with SHA-512 on the P-521 curve as specified in RFC 4754 + */ + AUTH_ECDSA_521 = 11, + + /** * EAP authentication. This value is never negotiated and therefore * a value from private use. */ @@ -65,29 +80,22 @@ enum auth_method_t { /** * enum names for auth_method_t. - * - * @ingroup authenticators */ extern enum_name_t *auth_method_names; /** - * @brief Authenticator interface implemented by the various authenticators. + * Authenticator interface implemented by the various authenticators. * * Currently the following two AUTH methods are supported: - * - shared key message integrity code (AUTH_PSK) - * - RSA digital signature (AUTH_RSA) - * - * @b Constructors: - * - authenticator_create() - * - * @ingroup authenticators + * - shared key message integrity code + * - RSA digital signature + * - ECDSA is supported using OpenSSL */ struct authenticator_t { /** - * @brief Verify a received authentication payload. + * Verify a received authentication payload. * - * @param this calling object * @param ike_sa_init binary representation of received ike_sa_init * @param my_nonce the sent nonce * @param auth_payload authentication payload to verify @@ -102,9 +110,8 @@ struct authenticator_t { chunk_t my_nonce, auth_payload_t *auth_payload); /** - * @brief Build an authentication payload to send to the other peer. + * Build an authentication payload to send to the other peer. * - * @param this calling object * @param ike_sa_init binary representation of sent ike_sa_init * @param other_nonce the received nonce * @param[out] auth_payload the resulting authentication payload @@ -117,23 +124,29 @@ struct authenticator_t { chunk_t other_nonce, auth_payload_t **auth_payload); /** - * @brief Destroys a authenticator_t object. - * - * @param this calling object + * Destroys a authenticator_t object. */ void (*destroy) (authenticator_t *this); }; /** - * @brief Creates an authenticator for the specified auth method. + * Creates an authenticator for the specified auth method (as configured). * * @param ike_sa associated ike_sa * @param auth_method authentication method to use for build()/verify() * * @return authenticator_t object - * - * @ingroup authenticators */ -authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method); +authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method); + +/** + * Creates an authenticator from the given auth payload. + * + * @param ike_sa associated ike_sa + * @param auth_payload auth payload + * + * @return authenticator_t object + */ +authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload); -#endif /* AUTHENTICATOR_H_ */ +#endif /* AUTHENTICATOR_H_ @} */ diff --git a/src/charon/sa/authenticators/eap/eap_manager.c b/src/charon/sa/authenticators/eap/eap_manager.c new file mode 100644 index 000000000..44d84156c --- /dev/null +++ b/src/charon/sa/authenticators/eap/eap_manager.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_manager.c 3589 2008-03-13 14:14:44Z martin $ + */ + +#include "eap_manager.h" + +#include <pthread.h> + +#include <utils/linked_list.h> + +typedef struct private_eap_manager_t private_eap_manager_t; +typedef struct eap_entry_t eap_entry_t; + +/** + * EAP constructor entry + */ +struct eap_entry_t { + + /** + * EAP method type, vendor specific if vendor is set + */ + eap_type_t type; + + /** + * vendor ID, 0 for default EAP methods + */ + u_int32_t vendor; + + /** + * Role of the method returned by the constructor, EAP_SERVER or EAP_PEER + */ + eap_role_t role; + + /** + * constructor function to create instance + */ + eap_constructor_t constructor; +}; + +/** + * private data of eap_manager + */ +struct private_eap_manager_t { + + /** + * public functions + */ + eap_manager_t public; + + /** + * list of eap_entry_t's + */ + linked_list_t *methods; + + /** + * mutex to lock methods + */ + pthread_mutex_t mutex; +}; + +/** + * Implementation of eap_manager_t.add_method. + */ +static void add_method(private_eap_manager_t *this, eap_type_t type, + u_int32_t vendor, eap_role_t role, + eap_constructor_t constructor) +{ + eap_entry_t *entry = malloc_thing(eap_entry_t); + + entry->type = type; + entry->vendor = vendor; + entry->role = role; + entry->constructor = constructor; + + pthread_mutex_lock(&this->mutex); + this->methods->insert_last(this->methods, entry); + pthread_mutex_unlock(&this->mutex); +} + +/** + * Implementation of eap_manager_t.remove_method. + */ +static void remove_method(private_eap_manager_t *this, eap_constructor_t constructor) +{ + enumerator_t *enumerator; + eap_entry_t *entry; + + pthread_mutex_lock(&this->mutex); + enumerator = this->methods->create_enumerator(this->methods); + while (enumerator->enumerate(enumerator, &entry)) + { + if (constructor == entry->constructor) + { + this->methods->remove_at(this->methods, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + pthread_mutex_unlock(&this->mutex); +} + +/** + * Implementation of eap_manager_t.create_instance. + */ +static eap_method_t* create_instance(private_eap_manager_t *this, + eap_type_t type, u_int32_t vendor, + eap_role_t role, identification_t *server, + identification_t *peer) +{ + enumerator_t *enumerator; + eap_entry_t *entry; + eap_method_t *method = NULL; + + pthread_mutex_lock(&this->mutex); + enumerator = this->methods->create_enumerator(this->methods); + while (enumerator->enumerate(enumerator, &entry)) + { + if (type == entry->type && vendor == entry->vendor && + role == entry->role) + { + method = entry->constructor(server, peer); + if (method) + { + break; + } + } + } + enumerator->destroy(enumerator); + pthread_mutex_unlock(&this->mutex); + return method; +} + +/** + * Implementation of 2008_t.destroy + */ +static void destroy(private_eap_manager_t *this) +{ + this->methods->destroy_function(this->methods, free); + free(this); +} + +/* + * see header file + */ +eap_manager_t *eap_manager_create() +{ + private_eap_manager_t *this = malloc_thing(private_eap_manager_t); + + this->public.add_method = (void(*)(eap_manager_t*, eap_type_t type, u_int32_t vendor, eap_role_t role, eap_constructor_t constructor))add_method; + this->public.remove_method = (void(*)(eap_manager_t*, eap_constructor_t constructor))remove_method; + this->public.create_instance = (eap_method_t*(*)(eap_manager_t*, eap_type_t type, u_int32_t vendor, eap_role_t role, identification_t*,identification_t*))create_instance; + this->public.destroy = (void(*)(eap_manager_t*))destroy; + + this->methods = linked_list_create(); + pthread_mutex_init(&this->mutex, NULL); + + return &this->public; +} + diff --git a/src/charon/sa/authenticators/eap/eap_manager.h b/src/charon/sa/authenticators/eap/eap_manager.h new file mode 100644 index 000000000..74bfa1f51 --- /dev/null +++ b/src/charon/sa/authenticators/eap/eap_manager.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + * + * $Id: eap_manager.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup eap_manager eap_manager + * @{ @ingroup eap + */ + +#ifndef EAP_MANAGER_H_ +#define EAP_MANAGER_H_ + +#include <sa/authenticators/eap/eap_method.h> + +typedef struct eap_manager_t eap_manager_t; + +/** + * The EAP manager manages all EAP implementations and creates instances. + * + * A plugin registers it's implemented EAP method at the manager by + * providing type and a contructor function. The manager then instanciates + * eap_method_t instances through the provided constructor to handle + * EAP authentication. + */ +struct eap_manager_t { + + /** + * Register a EAP method implementation. + * + * @param method vendor specific method, if vendor != 0 + * @param vendor vendor ID, 0 for non-vendor (default) EAP methods + * @param role EAP role of the registered method + * @param constructor constructor function, returns an eap_method_t + */ + void (*add_method)(eap_manager_t *this, eap_type_t type, u_int32_t vendor, + eap_role_t role, eap_constructor_t constructor); + + /** + * Unregister a EAP method implementation using it's constructor. + * + * @param constructor constructor function to remove, as added in add_method + */ + void (*remove_method)(eap_manager_t *this, eap_constructor_t constructor); + + /** + * Create a new EAP method instance. + * + * @param type type of the EAP method + * @param vendor vendor ID, 0 for non-vendor (default) EAP methods + * @param role role of EAP method, either EAP_SERVER or EAP_PEER + * @param server identity of the server + * @param peer identity of the peer (client) + * @return EAP method instance, NULL if no constructor found + */ + eap_method_t* (*create_instance)(eap_manager_t *this, eap_type_t type, + u_int32_t vendor, eap_role_t role, + identification_t *server, + identification_t *peer); + + /** + * Destroy a eap_manager instance. + */ + void (*destroy)(eap_manager_t *this); +}; + +/** + * Create a eap_manager instance. + */ +eap_manager_t *eap_manager_create(); + +#endif /* EAP_MANAGER_H_ @}*/ diff --git a/src/charon/sa/authenticators/eap/eap_method.c b/src/charon/sa/authenticators/eap/eap_method.c index 7434ca2a1..5e2db5489 100644 --- a/src/charon/sa/authenticators/eap/eap_method.c +++ b/src/charon/sa/authenticators/eap/eap_method.c @@ -1,10 +1,3 @@ -/** - * @file eap_method.c - * - * @brief Generic constructor for eap_methods. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,22 +11,12 @@ * 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. + * + * $Id: eap_method.c 3589 2008-03-13 14:14:44Z martin $ */ -#include <string.h> -#include <sys/stat.h> -#include <dirent.h> -#include <error.h> -#include <dlfcn.h> - #include "eap_method.h" -#include <daemon.h> -#include <library.h> -#include <utils/linked_list.h> -#include <utils/identification.h> - - ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_TOKEN_CARD, "EAP_IDENTITY", "EAP_NOTIFICATION", @@ -62,171 +45,3 @@ ENUM(eap_role_names, EAP_SERVER, EAP_PEER, "EAP_PEER", ); - -typedef struct module_entry_t module_entry_t; - -/** - * Representation of a loaded module: EAP type, library handle, constructor - */ -struct module_entry_t { - eap_type_t type; - u_int32_t vendor; - void *handle; - eap_constructor_t constructor; -}; - -/** List of module_entry_t's */ -static linked_list_t *modules = NULL; - -/** - * unload modules at daemon shutdown - */ -void eap_method_unload() -{ - if (modules) - { - module_entry_t *entry; - - while (modules->remove_last(modules, (void**)&entry) == SUCCESS) - { - DBG2(DBG_CFG, "unloaded module EAP module %d-%d", - entry->type, entry->vendor); - dlclose(entry->handle); - free(entry); - } - modules->destroy(modules); - modules = NULL; - } -} - -/** - * Load EAP modules at daemon startup - */ -void eap_method_load(char *directory) -{ - struct dirent* entry; - DIR* dir; - - eap_method_unload(); - modules = linked_list_create(); - - dir = opendir(directory); - if (dir == NULL) - { - DBG1(DBG_CFG, "error opening EAP modules directory %s", directory); - return; - } - - DBG1(DBG_CFG, "loading EAP modules from '%s'", directory); - - while ((entry = readdir(dir)) != NULL) - { - char file[256]; - module_entry_t module, *loaded_module; - eap_method_t *method; - identification_t *id; - char *ending; - - snprintf(file, sizeof(file), "%s/%s", directory, entry->d_name); - - ending = entry->d_name + strlen(entry->d_name) - 3; - if (ending <= entry->d_name || !streq(ending, ".so")) - { - /* skip anything which does not look like a library */ - DBG2(DBG_CFG, " skipping %s, doesn't look like a library", - entry->d_name); - continue; - } - - /* try to load the library */ - module.handle = dlopen(file, RTLD_LAZY); - if (module.handle == NULL) - { - DBG1(DBG_CFG, " opening EAP module %s failed: %s", entry->d_name, - dlerror()); - continue; - } - module.constructor = dlsym(module.handle, "eap_create"); - if (module.constructor == NULL) - { - DBG1(DBG_CFG, " EAP module %s has no eap_create() function, skipped", - entry->d_name); - dlclose(module.handle); - continue; - } - - /* get the type implemented in the method, create an instance for it */ - id = identification_create_from_string("john@doe.xyz"); - method = module.constructor(EAP_SERVER, id, id); - if (method == NULL) - { - method = module.constructor(EAP_PEER, id, id); - } - id->destroy(id); - if (method == NULL) - { - DBG1(DBG_CFG, " unable to create instance of EAP method %s, skipped", - entry->d_name); - dlclose(module.handle); - continue; - } - module.type = method->get_type(method, &module.vendor); - method->destroy(method); - - if (module.vendor) - { - DBG1(DBG_CFG, " loaded EAP method %d, vendor %d successfully from %s", - module.type, module.vendor, entry->d_name); - } - else - { - DBG1(DBG_CFG, " loaded EAP method %N successfully from %s", - eap_type_names, module.type, entry->d_name); - } - - loaded_module = malloc_thing(module_entry_t); - memcpy(loaded_module, &module, sizeof(module)); - modules->insert_last(modules, loaded_module); - } - closedir(dir); -} - -/* - * Described in header. - */ -eap_method_t *eap_method_create(eap_type_t type, u_int32_t vendor, eap_role_t role, - identification_t *server, identification_t *peer) -{ - eap_method_t *method = NULL; - iterator_t *iterator; - module_entry_t *entry; - - iterator = modules->create_iterator(modules, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) - { - if (entry->type == type && entry->vendor == vendor) - { - method = entry->constructor(role, server, peer); - if (method) - { - break; - } - } - } - iterator->destroy(iterator); - - if (method == NULL) - { - if (vendor) - { - DBG1(DBG_CFG, "no vendor %d specific EAP module found for method " - "%d %N", vendor, type, eap_role_names, role); - } - else - { - DBG1(DBG_CFG, "no EAP module found for %N %N", - eap_type_names, type, eap_role_names, role); - } - } - return method; -} diff --git a/src/charon/sa/authenticators/eap/eap_method.h b/src/charon/sa/authenticators/eap/eap_method.h index 8675fd8ec..eda6f545e 100644 --- a/src/charon/sa/authenticators/eap/eap_method.h +++ b/src/charon/sa/authenticators/eap/eap_method.h @@ -1,10 +1,3 @@ -/** - * @file eap_method.h - * - * @brief Interface eap_method_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: eap_method.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup eap_method eap_method + * @{ @ingroup eap */ #ifndef EAP_METHOD_H_ @@ -34,8 +34,6 @@ typedef enum eap_code_t eap_code_t; /** * Role of an eap_method, SERVER or PEER (client) - * - * @ingroup eap */ enum eap_role_t { EAP_SERVER, @@ -43,15 +41,11 @@ enum eap_role_t { }; /** * enum names for eap_role_t. - * - * @ingroup eap */ extern enum_name_t *eap_role_names; /** * EAP types, defines the EAP method implementation - * - * @ingroup eap */ enum eap_type_t { EAP_IDENTITY = 1, @@ -68,15 +62,11 @@ enum eap_type_t { /** * enum names for eap_type_t. - * - * @ingroup eap */ extern enum_name_t *eap_type_names; /** * EAP code, type of an EAP message - * - * @ingroup eap */ enum eap_code_t { EAP_REQUEST = 1, @@ -87,14 +77,12 @@ enum eap_code_t { /** * enum names for eap_code_t. - * - * @ingroup eap */ extern enum_name_t *eap_code_names; /** - * @brief Interface of an EAP method for server and client side. + * Interface of an EAP method for server and client side. * * An EAP method initiates an EAP exchange and processes requests and * responses. An EAP method may need multiple exchanges before succeeding, and @@ -107,22 +95,16 @@ extern enum_name_t *eap_code_names; * authentication. Even if a mutual EAP method is used, the traditional * AUTH payloads are required. Only these include the nonces and messages from * ike_sa_init and therefore prevent man in the middle attacks. - * - * @b Constructors: - * - eap_method_create() - * - * @ingroup eap */ struct eap_method_t { /** - * @brief Initiate the EAP exchange. + * Initiate the EAP exchange. * * initiate() is only useable for server implementations, as clients only * reply to server requests. * A eap_payload is created in "out" if result is NEED_MORE. * - * @param this calling object * @param out eap_payload to send to the client * @return * - NEED_MORE, if an other exchange is required @@ -131,11 +113,10 @@ struct eap_method_t { status_t (*initiate) (eap_method_t *this, eap_payload_t **out); /** - * @brief Process a received EAP message. + * Process a received EAP message. * * A eap_payload is created in "out" if result is NEED_MORE. * - * @param this calling object * @param in eap_payload response received * @param out created eap_payload to send * @return @@ -147,31 +128,28 @@ struct eap_method_t { eap_payload_t **out); /** - * @brief Get the EAP type implemented in this method. + * Get the EAP type implemented in this method. * - * @param this calling object * @param vendor pointer receiving vendor identifier for type, 0 for none * @return type of the EAP method */ eap_type_t (*get_type) (eap_method_t *this, u_int32_t *vendor); /** - * @brief Check if this EAP method authenticates the server. + * Check if this EAP method authenticates the server. * * Some EAP methods provide mutual authentication and * allow authentication using only EAP, if the peer supports it. * - * @param this calling object * @return TRUE if methods provides mutual authentication */ bool (*is_mutual) (eap_method_t *this); /** - * @brief Get the MSK established by this EAP method. + * Get the MSK established by this EAP method. * * Not all EAP methods establish a shared secret. * - * @param this calling object * @param msk chunk receiving internal stored MSK * @return * - SUCCESS, or @@ -180,68 +158,25 @@ struct eap_method_t { status_t (*get_msk) (eap_method_t *this, chunk_t *msk); /** - * @brief Destroys a eap_method_t object. - * - * @param this calling object + * Destroys a eap_method_t object. */ void (*destroy) (eap_method_t *this); }; /** - * @brief Creates an EAP method for a specific type and role. - * - * @param eap_type EAP type to use - * @param eap_vendor vendor identifier if a vendor specifc EAP type is used - * @param role role of the eap_method, server or peer - * @param server ID of acting server - * @param peer ID of involved peer (client) - * @return eap_method_t object - * - * @ingroup eap - */ -eap_method_t *eap_method_create(eap_type_t eap_type, u_int32_t eap_vendor, - eap_role_t role, identification_t *server, - identification_t *peer); - -/** - * @brief (Re-)Load all EAP modules in the EAP modules directory. - * - * For security reasons, the directory and all it's modules must be owned - * by root and must not be writeable by someone else. - * - * @param dir directory of the EAP modules - * - * @ingroup eap - */ -void eap_method_load(char *directory); - -/** - * @brief Unload all loaded EAP modules - * - * @ingroup eap - */ -void eap_method_unload(); - -/** - * @brief Constructor definition for a pluggable EAP module. + * Constructor definition for a pluggable EAP method. * * Each EAP module must define a constructor function which will return - * an initialized object with the methods defined in eap_method_t. The - * constructor must be named eap_create() and it's signature must be equal - * to that of eap_constructor_t. - * A module may implement only a single role. If it does not support the role - * requested, NULL should be returned. Multiple modules are allowed of the - * same EAP type to support seperate implementations of peer/server. + * an initialized object with the methods defined in eap_method_t. + * Constructors for server and peers are identical, to support both roles + * of a EAP method, a plugin needs register two constructors in the + * eap_manager_t. * - * @param role role the module will play, peer or server * @param server ID of the server to use for credential lookup * @param peer ID of the peer to use for credential lookup * @return implementation of the eap_method_t interface - * - * @ingroup eap */ -typedef eap_method_t *(*eap_constructor_t)(eap_role_t role, - identification_t *server, +typedef eap_method_t *(*eap_constructor_t)(identification_t *server, identification_t *peer); -#endif /* EAP_METHOD_H_ */ +#endif /* EAP_METHOD_H_ @} */ diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c index edd75da43..95bb5e57f 100644 --- a/src/charon/sa/authenticators/eap_authenticator.c +++ b/src/charon/sa/authenticators/eap_authenticator.c @@ -1,10 +1,3 @@ -/** - * @file eap_authenticator.c - * - * @brief Implementation of eap_authenticator_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: eap_authenticator.c 3589 2008-03-13 14:14:44Z martin $ */ #include <string.h> @@ -160,9 +155,9 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, { DBG1(DBG_IKE, "requesting %N authentication", eap_type_names, type); } - this->method = eap_method_create(type, vendor, this->role, - this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); + this->method = charon->eap->create_instance(charon->eap, type, vendor, + this->role, this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa)); if (this->method == NULL) { @@ -195,9 +190,11 @@ static status_t process_peer(private_eap_authenticator_t *this, if (!vendor && type == EAP_IDENTITY) { - eap_method_t *method = eap_method_create(type, 0, EAP_PEER, - this->ike_sa->get_other_id(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa)); + eap_method_t *method; + + method = charon->eap->create_instance(charon->eap, type, 0, EAP_PEER, + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_my_id(this->ike_sa)); if (method == NULL || method->process(method, in, out) != SUCCESS) { @@ -227,9 +224,10 @@ static status_t process_peer(private_eap_authenticator_t *this, DBG1(DBG_IKE, "EAP server requested %N authentication", eap_type_names, type); } - this->method = eap_method_create(type, vendor, EAP_PEER, - this->ike_sa->get_other_id(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa)); + this->method = charon->eap->create_instance(charon->eap, + type, vendor, EAP_PEER, + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_my_id(this->ike_sa)); if (this->method == NULL) { DBG1(DBG_IKE, "EAP server requested unsupported " diff --git a/src/charon/sa/authenticators/eap_authenticator.h b/src/charon/sa/authenticators/eap_authenticator.h index cf2180ee3..2dad59fbb 100644 --- a/src/charon/sa/authenticators/eap_authenticator.h +++ b/src/charon/sa/authenticators/eap_authenticator.h @@ -1,10 +1,3 @@ -/** - * @file eap_authenticator.h - * - * @brief Interface of eap_authenticator_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: eap_authenticator.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup eap_authenticator eap_authenticator + * @{ @ingroup authenticators */ #ifndef EAP_AUTHENTICATOR_H_ @@ -29,7 +29,7 @@ typedef struct eap_authenticator_t eap_authenticator_t; #include <encoding/payloads/eap_payload.h> /** - * @brief Implementation of the authenticator_t interface using AUTH_EAP. + * Implementation of the authenticator_t interface using AUTH_EAP. * * Authentication using EAP involves the most complex authenticator. It stays * alive over multiple ike_auth transactions and handles multiple EAP @@ -68,11 +68,6 @@ typedef struct eap_authenticator_t eap_authenticator_t; +--------+ +--------+ @endverbatim - * @b Constructors: - * - eap_authenticator_create() - * - authenticator_create() using auth_method AUTH_EAP - * - * @ingroup authenticators */ struct eap_authenticator_t { @@ -82,7 +77,7 @@ struct eap_authenticator_t { authenticator_t authenticator_interface; /** - * @brief Check if the EAP method was/is mutual and secure. + * Check if the EAP method was/is mutual and secure. * * RFC4306 proposes to authenticate the EAP responder (server) by standard * IKEv2 methods (RSA, psk). Not all, but some EAP methods @@ -93,19 +88,17 @@ struct eap_authenticator_t { * AUTH payload, the client must verify that the server initiated mutual * EAP authentication before it can trust the server. * - * @param this calling object * @return TRUE, if no AUTH payload required, FALSE otherwise */ bool (*is_mutual) (eap_authenticator_t* this); /** - * @brief Initiate the EAP exchange. + * Initiate the EAP exchange. * * The server initiates EAP exchanges, so the client never calls * this method. If initiate() returns NEED_MORE, the EAP authentication * process started. In any case, a payload is created in "out". * - * @param this calling object * @param type EAP method to use to authenticate client * @param vendor EAP vendor identifier, if type is vendor specific, or 0 * @param out created initiaal EAP message to send @@ -117,7 +110,7 @@ struct eap_authenticator_t { u_int32_t vendor, eap_payload_t **out); /** - * @brief Process an EAP message. + * Process an EAP message. * * After receiving an EAP message "in", the peer/server processes * the payload and creates a reply/subsequent request. @@ -132,7 +125,6 @@ struct eap_authenticator_t { * If a SUCCESS is returned (on any side), the EAP authentication was * successful and the AUTH payload can be exchanged. * - * @param this calling object * @param in received EAP message * @param out created EAP message to send * @return @@ -145,13 +137,11 @@ struct eap_authenticator_t { }; /** - * @brief Creates an authenticator for AUTH_EAP. + * Creates an authenticator for AUTH_EAP. * * @param ike_sa associated ike_sa * @return eap_authenticator_t object - * - * @ingroup authenticators */ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa); -#endif /* EAP_AUTHENTICATOR_H_ */ +#endif /* EAP_AUTHENTICATOR_H_ @} */ diff --git a/src/charon/sa/authenticators/psk_authenticator.c b/src/charon/sa/authenticators/psk_authenticator.c index 6b76088bb..d003dc2c9 100644 --- a/src/charon/sa/authenticators/psk_authenticator.c +++ b/src/charon/sa/authenticators/psk_authenticator.c @@ -1,10 +1,3 @@ -/** - * @file psk_authenticator.c - * - * @brief Implementation of psk_authenticator_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: psk_authenticator.c 3589 2008-03-13 14:14:44Z martin $ */ #include <string.h> @@ -26,6 +21,7 @@ #include "psk_authenticator.h" #include <daemon.h> +#include <credentials/auth_info.h> /** * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE. @@ -105,39 +101,49 @@ chunk_t build_shared_key_signature(chunk_t ike_sa_init, chunk_t nonce, * Implementation of authenticator_t.verify. */ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init, - chunk_t my_nonce, auth_payload_t *auth_payload) + chunk_t my_nonce, auth_payload_t *auth_payload) { - status_t status; - chunk_t auth_data, recv_auth_data, shared_key; + chunk_t auth_data, recv_auth_data; identification_t *my_id, *other_id; + shared_key_t *shared_key; + enumerator_t *enumerator; + bool authenticated = FALSE; + int keys_found = 0; my_id = this->ike_sa->get_my_id(this->ike_sa); other_id = this->ike_sa->get_other_id(this->ike_sa); - status = charon->credentials->get_shared_key(charon->credentials, my_id, - other_id, &shared_key); - if (status != SUCCESS) + enumerator = charon->credentials->create_shared_enumerator( + charon->credentials, SHARED_IKE, my_id, other_id); + while (!authenticated && enumerator->enumerate(enumerator, &shared_key, NULL, NULL)) { - DBG1(DBG_IKE, "no shared key found for '%D' - '%D'", my_id, other_id); - return status; + keys_found++; + auth_data = build_shared_key_signature(ike_sa_init, my_nonce, + shared_key->get_key(shared_key), other_id, + this->ike_sa->get_skp_verify(this->ike_sa), + this->ike_sa->get_prf(this->ike_sa)); + recv_auth_data = auth_payload->get_data(auth_payload); + if (auth_data.len == recv_auth_data.len && + memeq(auth_data.ptr, recv_auth_data.ptr, auth_data.len)) + { + DBG1(DBG_IKE, "authentication of '%D' with %N successful", + other_id, auth_method_names, AUTH_PSK); + authenticated = TRUE; + } + chunk_free(&auth_data); } + enumerator->destroy(enumerator); - auth_data = build_shared_key_signature(ike_sa_init, my_nonce, shared_key, - other_id, this->ike_sa->get_skp_verify(this->ike_sa), - this->ike_sa->get_prf(this->ike_sa)); - chunk_free_randomized(&shared_key); - - recv_auth_data = auth_payload->get_data(auth_payload); - if (auth_data.len != recv_auth_data.len || - !memeq(auth_data.ptr, recv_auth_data.ptr, auth_data.len)) + if (!authenticated) { - DBG1(DBG_IKE, "PSK MAC verification failed"); - chunk_free(&auth_data); + if (keys_found == 0) + { + DBG1(DBG_IKE, "no shared key found for '%D' - '%D'", my_id, other_id); + return NOT_FOUND; + } + DBG1(DBG_IKE, "tried %d shared key%s for '%D' - '%D', but MAC mismatched", + keys_found, keys_found == 1 ? "" : "s", my_id, other_id); return FAILED; } - chunk_free(&auth_data); - - DBG1(DBG_IKE, "authentication of '%D' with %N successful", - other_id, auth_method_names, AUTH_PSK); return SUCCESS; } @@ -147,28 +153,27 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init, static status_t build(private_psk_authenticator_t *this, chunk_t ike_sa_init, chunk_t other_nonce, auth_payload_t **auth_payload) { - chunk_t shared_key; + shared_key_t *shared_key; chunk_t auth_data; - status_t status; identification_t *my_id, *other_id; my_id = this->ike_sa->get_my_id(this->ike_sa); other_id = this->ike_sa->get_other_id(this->ike_sa); DBG1(DBG_IKE, "authentication of '%D' (myself) with %N", my_id, auth_method_names, AUTH_PSK); - status = charon->credentials->get_shared_key(charon->credentials, my_id, - other_id, &shared_key); - if (status != SUCCESS) + shared_key = charon->credentials->get_shared(charon->credentials, SHARED_IKE, + my_id, other_id); + if (shared_key == NULL) { DBG1(DBG_IKE, "no shared key found for '%D' - '%D'", my_id, other_id); - return status; + return NOT_FOUND; } - - auth_data = build_shared_key_signature(ike_sa_init, other_nonce, shared_key, - my_id, this->ike_sa->get_skp_build(this->ike_sa), - this->ike_sa->get_prf(this->ike_sa)); + auth_data = build_shared_key_signature(ike_sa_init, other_nonce, + shared_key->get_key(shared_key), my_id, + this->ike_sa->get_skp_build(this->ike_sa), + this->ike_sa->get_prf(this->ike_sa)); + shared_key->destroy(shared_key); DBG2(DBG_IKE, "successfully created shared key MAC"); - chunk_free_randomized(&shared_key); *auth_payload = auth_payload_create(); (*auth_payload)->set_auth_method(*auth_payload, AUTH_PSK); (*auth_payload)->set_data(*auth_payload, auth_data); diff --git a/src/charon/sa/authenticators/psk_authenticator.h b/src/charon/sa/authenticators/psk_authenticator.h index c1c5bcaac..c7cb5a23c 100644 --- a/src/charon/sa/authenticators/psk_authenticator.h +++ b/src/charon/sa/authenticators/psk_authenticator.h @@ -1,10 +1,3 @@ -/** - * @file psk_authenticator.h - * - * @brief Interface of psk_authenticator_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: psk_authenticator.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup psk_authenticator psk_authenticator + * @{ @ingroup authenticators */ #ifndef PSK_AUTHENTICATOR_H_ @@ -28,13 +28,7 @@ typedef struct psk_authenticator_t psk_authenticator_t; #include <sa/authenticators/authenticator.h> /** - * @brief Implementation of the authenticator_t interface using AUTH_PSK. - * - * @b Constructors: - * - psk_authenticator_create() - * - authenticator_create() using auth_method AUTH_PSK - * - * @ingroup authenticators + * Implementation of the authenticator_t interface using AUTH_PSK. */ struct psk_authenticator_t { @@ -45,13 +39,11 @@ struct psk_authenticator_t { }; /** - * @brief Creates an authenticator for AUTH_PSK. + * Creates an authenticator for AUTH_PSK. * * @param ike_sa associated ike_sa * @return psk_authenticator_t object - * - * @ingroup authenticators */ psk_authenticator_t *psk_authenticator_create(ike_sa_t *ike_sa); -#endif /* PSK_AUTHENTICATOR_H_ */ +#endif /* PSK_AUTHENTICATOR_H_ @} */ diff --git a/src/charon/sa/authenticators/pubkey_authenticator.c b/src/charon/sa/authenticators/pubkey_authenticator.c new file mode 100644 index 000000000..2c02ca84c --- /dev/null +++ b/src/charon/sa/authenticators/pubkey_authenticator.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * 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. + * + * $Id: pubkey_authenticator.c 4054 2008-06-10 20:31:53Z andreas $ + */ + +#include <string.h> + +#include "pubkey_authenticator.h" + +#include <daemon.h> +#include <credentials/auth_info.h> + + +typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t; + +/** + * Private data of an pubkey_authenticator_t object. + */ +struct private_pubkey_authenticator_t { + + /** + * Public authenticator_t interface. + */ + pubkey_authenticator_t public; + + /** + * Assigned IKE_SA + */ + ike_sa_t *ike_sa; +}; + +/** + * Function implemented in psk_authenticator.c + */ +extern chunk_t build_tbs_octets(chunk_t ike_sa_init, chunk_t nonce, + identification_t *id, prf_t *prf); + +/** + * Implementation of authenticator_t.verify. + */ +static status_t verify(private_pubkey_authenticator_t *this, chunk_t ike_sa_init, + chunk_t my_nonce, auth_payload_t *auth_payload) +{ + public_key_t *public; + auth_method_t auth_method; + chunk_t auth_data, octets; + identification_t *other_id; + prf_t *prf; + auth_info_t *auth, *current_auth; + enumerator_t *enumerator; + key_type_t key_type = KEY_ECDSA; + signature_scheme_t scheme; + status_t status = FAILED; + + other_id = this->ike_sa->get_other_id(this->ike_sa); + auth_method = auth_payload->get_auth_method(auth_payload); + switch (auth_method) + { + case AUTH_RSA: + /* We are currently fixed to SHA1 hashes. + * TODO: allow other hash algorithms and note it in "auth" */ + key_type = KEY_RSA; + scheme = SIGN_RSA_EMSA_PKCS1_SHA1; + break; + case AUTH_ECDSA_256: + scheme = SIGN_ECDSA_256; + break; + case AUTH_ECDSA_384: + scheme = SIGN_ECDSA_384; + break; + case AUTH_ECDSA_521: + scheme = SIGN_ECDSA_521; + break; + default: + return INVALID_ARG; + } + auth_data = auth_payload->get_data(auth_payload); + prf = this->ike_sa->get_prf(this->ike_sa); + prf->set_key(prf, this->ike_sa->get_skp_verify(this->ike_sa)); + octets = build_tbs_octets(ike_sa_init, my_nonce, other_id, prf); + + auth = this->ike_sa->get_other_auth(this->ike_sa); + enumerator = charon->credentials->create_public_enumerator( + charon->credentials, key_type, other_id, auth); + while (enumerator->enumerate(enumerator, &public, ¤t_auth)) + { + if (public->verify(public, scheme, octets, auth_data)) + { + DBG1(DBG_IKE, "authentication of '%D' with %N successful", + other_id, auth_method_names, auth_method); + status = SUCCESS; + auth->merge(auth, current_auth); + break; + } + else + { + DBG1(DBG_IKE, "signature validation failed, looking for another key"); + } + } + enumerator->destroy(enumerator); + chunk_free(&octets); + return status; +} + +/** + * Implementation of authenticator_t.build. + */ +static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init, + chunk_t other_nonce, auth_payload_t **auth_payload) +{ + chunk_t octets, auth_data; + status_t status = FAILED; + private_key_t *private; + identification_t *my_id; + prf_t *prf; + auth_info_t *auth; + auth_method_t auth_method; + signature_scheme_t scheme; + + my_id = this->ike_sa->get_my_id(this->ike_sa); + auth = this->ike_sa->get_my_auth(this->ike_sa); + private = charon->credentials->get_private(charon->credentials, KEY_ANY, + my_id, auth); + if (private == NULL) + { + DBG1(DBG_IKE, "no private key found for '%D'", my_id); + return NOT_FOUND; + } + + switch (private->get_type(private)) + { + case KEY_RSA: + /* we currently use always SHA1 for signatures, + * TODO: support other hashes depending on configuration/auth */ + scheme = SIGN_RSA_EMSA_PKCS1_SHA1; + auth_method = AUTH_RSA; + break; + case KEY_ECDSA: + /* we try to deduct the signature scheme from the keysize */ + switch (private->get_keysize(private)) + { + case 32: + scheme = SIGN_ECDSA_256; + auth_method = AUTH_ECDSA_256; + break; + case 48: + scheme = SIGN_ECDSA_384; + auth_method = AUTH_ECDSA_384; + break; + case 66: + scheme = SIGN_ECDSA_521; + auth_method = AUTH_ECDSA_521; + break; + default: + DBG1(DBG_IKE, "%d bit ECDSA private key size not supported", + private->get_keysize(private)); + return status; + } + break; + default: + DBG1(DBG_IKE, "private key of type %N not supported", + key_type_names, private->get_type(private)); + return status; + } + prf = this->ike_sa->get_prf(this->ike_sa); + prf->set_key(prf, this->ike_sa->get_skp_build(this->ike_sa)); + octets = build_tbs_octets(ike_sa_init, other_nonce, my_id, prf); + + if (private->sign(private, scheme, octets, &auth_data)) + { + auth_payload_t *payload = auth_payload_create(); + payload->set_auth_method(payload, auth_method); + payload->set_data(payload, auth_data); + *auth_payload = payload; + chunk_free(&auth_data); + status = SUCCESS; + } + DBG1(DBG_IKE, "authentication of '%D' (myself) with %N %s", my_id, + auth_method_names, auth_method, + (status == SUCCESS)? "successful":"failed"); + chunk_free(&octets); + private->destroy(private); + + return status; +} + +/** + * Implementation of authenticator_t.destroy. + */ +static void destroy(private_pubkey_authenticator_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +pubkey_authenticator_t *pubkey_authenticator_create(ike_sa_t *ike_sa) +{ + private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t); + + /* public functions */ + this->public.authenticator_interface.verify = (status_t(*)(authenticator_t*,chunk_t,chunk_t,auth_payload_t*))verify; + this->public.authenticator_interface.build = (status_t(*)(authenticator_t*,chunk_t,chunk_t,auth_payload_t**))build; + this->public.authenticator_interface.destroy = (void(*)(authenticator_t*))destroy; + + /* private data */ + this->ike_sa = ike_sa; + + return &this->public; +} diff --git a/src/charon/sa/authenticators/rsa_authenticator.h b/src/charon/sa/authenticators/pubkey_authenticator.h index cc5cc0150..038d8b1d2 100644 --- a/src/charon/sa/authenticators/rsa_authenticator.h +++ b/src/charon/sa/authenticators/pubkey_authenticator.h @@ -1,11 +1,5 @@ -/** - * @file rsa_authenticator.h - * - * @brief Interface of rsa_authenticator_t. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -18,25 +12,26 @@ * 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. + * + * $Id: pubkey_authenticator.h 4051 2008-06-10 09:08:27Z tobias $ */ -#ifndef RSA_AUTHENTICATOR_H_ -#define RSA_AUTHENTICATOR_H_ +/** + * @defgroup pubkey_authenticator pubkey_authenticator + * @{ @ingroup authenticators + */ + +#ifndef PUBKEY_AUTHENTICATOR_H_ +#define PUBKEY_AUTHENTICATOR_H_ -typedef struct rsa_authenticator_t rsa_authenticator_t; +typedef struct pubkey_authenticator_t pubkey_authenticator_t; #include <sa/authenticators/authenticator.h> /** - * @brief Implementation of the authenticator_t interface using AUTH_RSA. - * - * @b Constructors: - * - rsa_authenticator_create() - * - authenticator_create() using auth_method AUTH_RSA - * - * @ingroup authenticators + * Implementation of the authenticator_t interface using AUTH_PUBKEY. */ -struct rsa_authenticator_t { +struct pubkey_authenticator_t { /** * Implemented authenticator_t interface. @@ -45,13 +40,11 @@ struct rsa_authenticator_t { }; /** - * @brief Creates an authenticator for AUTH_RSA. + * Creates an authenticator for AUTH_PUBKEY. * * @param ike_sa associated ike_sa - * @return rsa_authenticator_t object - * - * @ingroup authenticators + * @return pubkey_authenticator_t object */ -rsa_authenticator_t *rsa_authenticator_create(ike_sa_t *ike_sa); +pubkey_authenticator_t *pubkey_authenticator_create(ike_sa_t *ike_sa); -#endif /* RSA_AUTHENTICATOR_H_ */ +#endif /* PUBKEY_AUTHENTICATOR_H_ @} */ diff --git a/src/charon/sa/authenticators/rsa_authenticator.c b/src/charon/sa/authenticators/rsa_authenticator.c deleted file mode 100644 index ba0fad1e3..000000000 --- a/src/charon/sa/authenticators/rsa_authenticator.c +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @file rsa_authenticator.c - * - * @brief Implementation of rsa_authenticator_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * 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 <string.h> - -#include "rsa_authenticator.h" - -#include <daemon.h> - - -typedef struct private_rsa_authenticator_t private_rsa_authenticator_t; - -/** - * Private data of an rsa_authenticator_t object. - */ -struct private_rsa_authenticator_t { - - /** - * Public authenticator_t interface. - */ - rsa_authenticator_t public; - - /** - * Assigned IKE_SA - */ - ike_sa_t *ike_sa; -}; - -/** - * Function implemented in psk_authenticator.c - */ -extern chunk_t build_tbs_octets(chunk_t ike_sa_init, chunk_t nonce, - identification_t *id, prf_t *prf); - -/** - * Implementation of authenticator_t.verify. - */ -static status_t verify(private_rsa_authenticator_t *this, chunk_t ike_sa_init, - chunk_t my_nonce, auth_payload_t *auth_payload) -{ - status_t status; - chunk_t auth_data, octets; - identification_t *other_id; - ca_info_t *issuer; - prf_t *prf; - - other_id = this->ike_sa->get_other_id(this->ike_sa); - - if (auth_payload->get_auth_method(auth_payload) != AUTH_RSA) - { - return INVALID_ARG; - } - auth_data = auth_payload->get_data(auth_payload); - prf = this->ike_sa->get_prf(this->ike_sa); - prf->set_key(prf, this->ike_sa->get_skp_verify(this->ike_sa)); - octets = build_tbs_octets(ike_sa_init, my_nonce, other_id, prf); - status = charon->credentials->verify_signature(charon->credentials, - octets, auth_data, other_id, &issuer); - chunk_free(&octets); - - if (status == SUCCESS) - { - this->ike_sa->set_other_ca(this->ike_sa, issuer); - DBG1(DBG_IKE, "authentication of '%D' with %N successful", - other_id, auth_method_names, AUTH_RSA); - } - return status; -} - -/** - * Implementation of authenticator_t.build. - */ -static status_t build(private_rsa_authenticator_t *this, chunk_t ike_sa_init, - chunk_t other_nonce, auth_payload_t **auth_payload) -{ - chunk_t octets, auth_data; - status_t status; - rsa_public_key_t *my_pubkey; - identification_t *my_id; - prf_t *prf; - - my_id = this->ike_sa->get_my_id(this->ike_sa); - DBG1(DBG_IKE, "authentication of '%D' (myself) with %N", - my_id, auth_method_names, AUTH_RSA); - DBG2(DBG_IKE, "looking for RSA public key belonging to '%D'...", my_id); - - my_pubkey = charon->credentials->get_rsa_public_key(charon->credentials, my_id); - if (my_pubkey == NULL) - { - DBG1(DBG_IKE, "no RSA public key found for '%D'", my_id); - return NOT_FOUND; - } - DBG2(DBG_IKE, " matching RSA public key found"); - - prf = this->ike_sa->get_prf(this->ike_sa); - prf->set_key(prf, this->ike_sa->get_skp_build(this->ike_sa)); - octets = build_tbs_octets(ike_sa_init, other_nonce, my_id, prf); - status = charon->credentials->rsa_signature(charon->credentials, - my_pubkey, HASH_SHA1, octets, &auth_data); - chunk_free(&octets); - - if (status != SUCCESS) - { - DBG1(DBG_IKE, "building RSA signature with SHA-1 hash failed"); - return status; - } - DBG2(DBG_IKE, "successfully signed with RSA private key"); - - *auth_payload = auth_payload_create(); - (*auth_payload)->set_auth_method(*auth_payload, AUTH_RSA); - (*auth_payload)->set_data(*auth_payload, auth_data); - chunk_free(&auth_data); - return SUCCESS; -} - -/** - * Implementation of authenticator_t.destroy. - */ -static void destroy(private_rsa_authenticator_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -rsa_authenticator_t *rsa_authenticator_create(ike_sa_t *ike_sa) -{ - private_rsa_authenticator_t *this = malloc_thing(private_rsa_authenticator_t); - - /* public functions */ - this->public.authenticator_interface.verify = (status_t(*)(authenticator_t*,chunk_t,chunk_t,auth_payload_t*))verify; - this->public.authenticator_interface.build = (status_t(*)(authenticator_t*,chunk_t,chunk_t,auth_payload_t**))build; - this->public.authenticator_interface.destroy = (void(*)(authenticator_t*))destroy; - - /* private data */ - this->ike_sa = ike_sa; - - return &this->public; -} diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index b6c71a8b5..2a6b6f67c 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -1,13 +1,7 @@ -/** - * @file child_sa.c - * - * @brief Implementation of child_sa_t. - * - */ - /* + * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -20,6 +14,8 @@ * 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. + * + * $Id: child_sa.c 3920 2008-05-08 16:19:11Z tobias $ */ #define _GNU_SOURCE @@ -75,6 +71,8 @@ struct private_child_sa_t { identification_t *id; /** actual used SPI, 0 if unused */ u_int32_t spi; + /** Compression Parameter Index (CPI) used, 0 if unused */ + u_int16_t cpi; } me, other; /** @@ -115,12 +113,22 @@ struct private_child_sa_t { /** * encryption algorithm used for this SA */ - algorithm_t encryption; + u_int16_t enc_alg; + + /** + * key size of enc_alg + */ + u_int16_t enc_size; /** * integrity protection algorithm used for this SA */ - algorithm_t integrity; + u_int16_t int_alg; + + /** + * key size of int_alg + */ + u_int16_t int_size; /** * time, on which SA was installed @@ -143,6 +151,16 @@ struct private_child_sa_t { bool encap; /** + * Specifies the IPComp transform used (IPCOMP_NONE if disabled) + */ + ipcomp_transform_t ipcomp; + + /** + * TRUE if we allocated (or tried to allocate) a CPI + */ + bool cpi_allocated; + + /** * mode this SA uses, tunnel/transport */ mode_t mode; @@ -251,10 +269,10 @@ static void get_stats(private_child_sa_t *this, mode_t *mode, iterator->destroy(iterator); *mode = this->mode; - *encr_algo = this->encryption.algorithm; - *encr_len = this->encryption.key_size; - *int_algo = this->integrity.algorithm; - *int_len = this->integrity.key_size; + *encr_algo = this->enc_alg; + *encr_len = this->enc_size; + *int_algo = this->int_alg; + *int_len = this->int_size; *rekey = this->rekey_time; *use_in = in; *use_out = out; @@ -498,10 +516,7 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) static status_t install(private_child_sa_t *this, proposal_t *proposal, mode_t mode, prf_plus_t *prf_plus, bool mine) { - u_int32_t spi, soft, hard;; - algorithm_t *enc_algo, *int_algo; - algorithm_t enc_algo_none = {ENCR_UNDEFINED, 0}; - algorithm_t int_algo_none = {AUTH_UNDEFINED, 0}; + u_int32_t spi, soft, hard; host_t *src; host_t *dst; status_t status; @@ -549,43 +564,43 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, protocol_id_names, this->protocol); /* select encryption algo */ - if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_algo)) + if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, + &this->enc_alg, &this->enc_size)) { - DBG2(DBG_CHD, " using %N for encryption", - encryption_algorithm_names, enc_algo->algorithm); - } - else - { - enc_algo = &enc_algo_none; + DBG2(DBG_CHD, " using %N for encryption", + encryption_algorithm_names, this->enc_alg); } /* select integrity algo */ - if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_algo)) + if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, + &this->int_alg, &this->int_size)) { DBG2(DBG_CHD, " using %N for integrity", - integrity_algorithm_names, int_algo->algorithm); - } - else - { - int_algo = &int_algo_none; + integrity_algorithm_names, this->int_alg); } - soft = this->config->get_lifetime(this->config, TRUE); hard = this->config->get_lifetime(this->config, FALSE); /* send SA down to the kernel */ DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst); - status = charon->kernel_interface->add_sa(charon->kernel_interface, - src, dst, spi, this->protocol, - this->reqid, mine ? soft : 0, - hard, enc_algo, int_algo, - prf_plus, mode, this->encap, mine); - this->encryption = *enc_algo; - this->integrity = *int_algo; + if (this->ipcomp != IPCOMP_NONE) + { + /* we install an additional IPComp SA */ + u_int32_t cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi)); + status = charon->kernel_interface->add_sa(charon->kernel_interface, + src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0, + ENCR_UNDEFINED, 0, AUTH_UNDEFINED, 0, NULL, mode, + this->ipcomp, FALSE, mine); + } + + status = charon->kernel_interface->add_sa(charon->kernel_interface, + src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard, + this->enc_alg, this->enc_size, this->int_alg, this->int_size, + prf_plus, mode, IPCOMP_NONE, this->encap, mine); + this->install_time = time(NULL); this->rekey_time = this->install_time + soft; - return status; } @@ -686,15 +701,15 @@ static status_t add_policies(private_child_sa_t *this, /* install 3 policies: out, in and forward */ status = charon->kernel_interface->add_policy(charon->kernel_interface, this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT, - this->protocol, this->reqid, high_prio, mode); + this->protocol, this->reqid, high_prio, mode, this->ipcomp); status |= charon->kernel_interface->add_policy(charon->kernel_interface, this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN, - this->protocol, this->reqid, high_prio, mode); + this->protocol, this->reqid, high_prio, mode, this->ipcomp); status |= charon->kernel_interface->add_policy(charon->kernel_interface, this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD, - this->protocol, this->reqid, high_prio, mode); + this->protocol, this->reqid, high_prio, mode, this->ipcomp); if (status != SUCCESS) { @@ -795,10 +810,20 @@ static status_t update_hosts(private_child_sa_t *this, this->encap = encap; - /* update our (initator) SAs */ + if (this->ipcomp != IPCOMP_NONE) + { + /* update our (initator) IPComp SA */ + charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)), + IPPROTO_COMP, this->other.addr, this->me.addr, other, me, FALSE); + /* update his (responder) IPComp SA */ + charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->other.cpi)), + IPPROTO_COMP, this->me.addr, this->other.addr, me, other, FALSE); + } + + /* update our (initator) SA */ charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi, this->protocol, this->other.addr, this->me.addr, other, me, encap); - /* update his (responder) SAs */ + /* update his (responder) SA */ charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi, this->protocol, this->me.addr, this->other.addr, me, other, encap); @@ -846,13 +871,13 @@ static status_t update_hosts(private_child_sa_t *this, /* reinstall updated policies */ charon->kernel_interface->add_policy(charon->kernel_interface, me, other, policy->my_ts, policy->other_ts, POLICY_OUT, - this->protocol, this->reqid, TRUE, this->mode); + this->protocol, this->reqid, TRUE, this->mode, this->ipcomp); charon->kernel_interface->add_policy(charon->kernel_interface, other, me, policy->other_ts, policy->my_ts, POLICY_IN, - this->protocol, this->reqid, TRUE, this->mode); + this->protocol, this->reqid, TRUE, this->mode, this->ipcomp); charon->kernel_interface->add_policy(charon->kernel_interface, other, me, policy->other_ts, policy->my_ts, POLICY_FWD, - this->protocol, this->reqid, TRUE, this->mode); + this->protocol, this->reqid, TRUE, this->mode, this->ipcomp); } iterator->destroy(iterator); } @@ -884,6 +909,30 @@ static void set_virtual_ip(private_child_sa_t *this, host_t *ip) } /** + * Implementation of child_sa_t.activate_ipcomp. + */ +static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp, + u_int16_t other_cpi) +{ + this->ipcomp = ipcomp; + this->other.cpi = other_cpi; +} + +/** + * Implementation of child_sa_t.get_my_cpi. + */ +static u_int16_t get_my_cpi(private_child_sa_t *this) +{ + if (!this->cpi_allocated) + { + charon->kernel_interface->get_cpi(charon->kernel_interface, + this->other.addr, this->me.addr, this->reqid, &this->me.cpi); + this->cpi_allocated = TRUE; + } + return this->me.cpi; +} + +/** * Implementation of child_sa_t.destroy. */ static void destroy(private_child_sa_t *this) @@ -916,6 +965,16 @@ static void destroy(private_child_sa_t *this) charon->kernel_interface->del_sa(charon->kernel_interface, this->other.addr, this->other.spi, this->protocol); } + if (this->me.cpi) + { + charon->kernel_interface->del_sa(charon->kernel_interface, + this->other.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP); + } + if (this->other.cpi) + { + charon->kernel_interface->del_sa(charon->kernel_interface, + this->other.addr, htonl(ntohs(this->other.cpi)), IPPROTO_COMP); + } /* delete all policies in the kernel */ while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) @@ -976,6 +1035,8 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state; this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state; this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config; + this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp; + this->public.get_my_cpi = (u_int16_t(*)(child_sa_t*))get_my_cpi; this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip; this->public.destroy = (void(*)(child_sa_t*))destroy; @@ -985,17 +1046,21 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->me.id = my_id->clone(my_id); this->other.id = other_id->clone(other_id); this->me.spi = 0; + this->me.cpi = 0; this->other.spi = 0; + this->other.cpi = 0; this->alloc_ah_spi = 0; this->alloc_esp_spi = 0; this->encap = encap; + this->cpi_allocated = FALSE; + this->ipcomp = IPCOMP_NONE; this->state = CHILD_CREATED; /* reuse old reqid if we are rekeying an existing CHILD_SA */ this->reqid = rekey ? rekey : ++reqid; - this->encryption.algorithm = ENCR_UNDEFINED; - this->encryption.key_size = 0; - this->integrity.algorithm = AUTH_UNDEFINED; - this->encryption.key_size = 0; + this->enc_alg = ENCR_UNDEFINED; + this->enc_size = 0; + this->int_alg = AUTH_UNDEFINED; + this->int_size = 0; this->policies = linked_list_create(); this->my_ts = linked_list_create(); this->other_ts = linked_list_create(); diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h index b801dd012..5bd66acad 100644 --- a/src/charon/sa/child_sa.h +++ b/src/charon/sa/child_sa.h @@ -1,13 +1,7 @@ -/** - * @file child_sa.h - * - * @brief Interface of child_sa_t. - * - */ - /* + * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2006-2007 Martin Willi - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Copyright (C) 2006 Daniel Roethlisberger * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -19,8 +13,14 @@ * 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. + * + * $Id: child_sa.h 3920 2008-05-08 16:19:11Z tobias $ */ +/** + * @defgroup child_sa child_sa + * @{ @ingroup sa + */ #ifndef CHILD_SA_H_ #define CHILD_SA_H_ @@ -35,7 +35,7 @@ typedef struct child_sa_t child_sa_t; #include <config/child_cfg.h> /** - * @brief States of a CHILD_SA + * States of a CHILD_SA */ enum child_sa_state_t { @@ -71,7 +71,7 @@ enum child_sa_state_t { extern enum_name_t *child_sa_state_names; /** - * @brief Represents an IPsec SAs between two hosts. + * Represents an IPsec SAs between two hosts. * * A child_sa_t contains two SAs. SAs for both * directions are managed in one child_sa_t object. Both @@ -86,57 +86,47 @@ extern enum_name_t *child_sa_state_names; * - A calls child_sa_t.update to update the already allocated SPIs with the chosen proposal * * Once SAs are set up, policies can be added using add_policies. - * - * - * @b Constructors: - * - child_sa_create() - * - * @ingroup sa */ struct child_sa_t { /** - * @brief Get the name of the config this CHILD_SA uses. + * Get the name of the config this CHILD_SA uses. * - * @param this calling object - * @return name + * @return name */ char* (*get_name) (child_sa_t *this); /** - * @brief Get the reqid of the CHILD SA. + * Get the reqid of the CHILD SA. * * Every CHILD_SA has a reqid. The kernel uses this ID to * identify it. * - * @param this calling object * @return reqid of the CHILD SA */ u_int32_t (*get_reqid)(child_sa_t *this); /** - * @brief Get the SPI of this CHILD_SA. + * Get the SPI of this CHILD_SA. * * Set the boolean parameter inbound to TRUE to * get the SPI for which we receive packets, use * FALSE to get those we use for sending packets. * - * @param this calling object * @param inbound TRUE to get inbound SPI, FALSE for outbound. * @return spi of the CHILD SA */ u_int32_t (*get_spi) (child_sa_t *this, bool inbound); /** - * @brief Get the protocol which this CHILD_SA uses to protect traffic. + * Get the protocol which this CHILD_SA uses to protect traffic. * - * @param this calling object * @return AH | ESP */ protocol_id_t (*get_protocol) (child_sa_t *this); /** - * @brief Get info and statistics about this CHILD_SA. + * Get info and statistics about this CHILD_SA. * * @param mode mode this IKE_SA uses * @param encr_algo encryption algorithm used by this CHILD_SA. @@ -155,7 +145,7 @@ struct child_sa_t { u_int32_t *use_fwd); /** - * @brief Allocate SPIs for given proposals. + * Allocate SPIs for given proposals. * * Since the kernel manages SPIs for us, we need * to allocate them. If a proposal contains more @@ -163,15 +153,13 @@ struct child_sa_t { * allocated. SPIs are stored internally and written * back to the proposal. * - * @param this calling object * @param proposals list of proposals for which SPIs are allocated */ status_t (*alloc)(child_sa_t *this, linked_list_t* proposals); /** - * @brief Install the kernel SAs for a proposal, without previous SPI allocation. + * Install the kernel SAs for a proposal, without previous SPI allocation. * - * @param this calling object * @param proposal proposal for which SPIs are allocated * @param mode mode for the CHILD_SA * @param prf_plus key material to use for key derivation @@ -181,11 +169,10 @@ struct child_sa_t { prf_plus_t *prf_plus); /** - * @brief Install the kernel SAs for a proposal, after SPIs have been allocated. + * Install the kernel SAs for a proposal, after SPIs have been allocated. * * Updates an SA, for which SPIs are already allocated via alloc(). * - * @param this calling object * @param proposal proposal for which SPIs are allocated * @param mode mode for the CHILD_SA * @param prf_plus key material to use for key derivation @@ -195,11 +182,10 @@ struct child_sa_t { prf_plus_t *prf_plus); /** - * @brief Update the hosts in the kernel SAs and policies. + * Update the hosts in the kernel SAs and policies. * * The CHILD must be INSTALLED to do this update. * - * @param this calling object * @param me the new local host * @param other the new remote host * @param TRUE to use UDP encapsulation for NAT traversal @@ -209,12 +195,11 @@ struct child_sa_t { bool encap); /** - * @brief Install the policies using some traffic selectors. + * Install the policies using some traffic selectors. * * Supplied lists of traffic_selector_t's specify the policies * to use for this child sa. * - * @param this calling object * @param my_ts traffic selectors for local site * @param other_ts traffic selectors for remote site * @param mode mode for the SA: tunnel/transport @@ -224,18 +209,16 @@ struct child_sa_t { linked_list_t *other_ts_list, mode_t mode); /** - * @brief Get the traffic selectors of added policies of local host. + * Get the traffic selectors of added policies of local host. * - * @param this calling object * @param local TRUE for own traffic selectors, FALSE for remote * @return list of traffic selectors */ linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local); /** - * @brief Get the time of this child_sa_t's last use (i.e. last use of any of its policies) + * Get the time of this child_sa_t's last use (i.e. last use of any of its policies) * - * @param this calling object * @param inbound query for in- or outbound usage * @param use_time the time * @return SUCCESS or FAILED @@ -243,48 +226,58 @@ struct child_sa_t { status_t (*get_use_time) (child_sa_t *this, bool inbound, time_t *use_time); /** - * @brief Get the state of the CHILD_SA. - * - * @param this calling object + * Get the state of the CHILD_SA. */ child_sa_state_t (*get_state) (child_sa_t *this); /** - * @brief Set the state of the CHILD_SA. + * Set the state of the CHILD_SA. * - * @param this calling object + * @param state state to set on CHILD_SA */ void (*set_state) (child_sa_t *this, child_sa_state_t state); /** - * @brief Get the config used to set up this child sa. + * Get the config used to set up this child sa. * - * @param this calling object * @return child_cfg */ child_cfg_t* (*get_config) (child_sa_t *this); /** - * @brief Set the virtual IP used received from IRAS. + * Set the virtual IP used received from IRAS. * * To allow proper setup of firewall rules, the virtual IP is required * for filtering. * - * @param this calling object * @param ip own virtual IP */ void (*set_virtual_ip) (child_sa_t *this, host_t *ip); /** - * @brief Destroys a child_sa. - * - * @param this calling object + * Activate IPComp by setting the transform ID and CPI values. + * + * @param ipcomp the IPComp transform to use + * @param other_cpi other Compression Parameter Index + */ + void (*activate_ipcomp) (child_sa_t *this, ipcomp_transform_t ipcomp, + u_int16_t other_cpi); + + /** + * Returns the Compression Parameter Index (CPI) allocated from the kernel. + * + * @return allocated CPI + */ + u_int16_t (*get_my_cpi) (child_sa_t *this); + + /** + * Destroys a child_sa. */ void (*destroy) (child_sa_t *this); }; /** - * @brief Constructor to create a new child_sa_t. + * Constructor to create a new child_sa_t. * * @param me own address * @param other remote address @@ -294,11 +287,9 @@ struct child_sa_t { * @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise * @param encap TRUE to enable UDP encapsulation (NAT traversal) * @return child_sa_t object - * - * @ingroup sa */ child_sa_t * child_sa_create(host_t *me, host_t *other, identification_t *my_id, identification_t* other_id, child_cfg_t *config, u_int32_t reqid, bool encap); -#endif /*CHILD_SA_H_*/ +#endif /*CHILD_SA_H_ @} */ diff --git a/src/charon/sa/connect_manager.c b/src/charon/sa/connect_manager.c index 06755fa9c..19ceea666 100644 --- a/src/charon/sa/connect_manager.c +++ b/src/charon/sa/connect_manager.c @@ -1,12 +1,5 @@ -/** - * @file connect_manager.c - * - * @brief Implementation of connect_manager_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,6 +11,8 @@ * 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. + * + * $Id: connect_manager.c 3792 2008-04-10 12:51:04Z tobias $ */ #include "connect_manager.h" @@ -34,13 +29,20 @@ #include <encoding/payloads/endpoint_notify.h> /* base timeout - * the sending interval is P2P_INTERVAL * active checklists (N) - * retransmission timeout is P2P_INTERVAL * N * checks in waiting state (NW) */ -#define P2P_INTERVAL 20 /* ms */ -/* min retransmission timeout (RTO is P2P_INTERVAL * N * checks in waiting state) */ -#define P2P_RTO_MIN 100 /* ms */ -/* max number of retransmissions (+ the initial check) */ -#define P2P_MAX_RETRANS 2 + * the check interval is ME_INTERVAL */ +#define ME_INTERVAL 25 /* ms */ +/* retransmission timeout is first ME_INTERVAL for ME_BOOST retransmissions + * then gets reduced to ME_INTERVAL * ME_RETRANS_BASE ^ (sent retransmissions - ME_BOOST). */ +/* number of initial retransmissions sent in short interval */ +#define ME_BOOST 2 +/* base for retransmissions */ +#define ME_RETRANS_BASE 1.8 +/* max number of retransmissions */ +#define ME_MAX_RETRANS 13 + +/* time to wait before the initiator finishes the connectivity checks after + * the first check has succeeded */ +#define ME_WAIT_TO_FINISH 1000 /* ms */ typedef struct private_connect_manager_t private_connect_manager_t; @@ -70,7 +72,7 @@ struct private_connect_manager_t { linked_list_t *initiated; /** - * Linked list with checklists (hash table with session ID as key would be better). + * Linked list with checklists (hash table with connect ID as key would be better). */ linked_list_t *checklists; }; @@ -180,8 +182,8 @@ struct check_list_t { linked_list_t *endpoints; } responder; - /** session id */ - chunk_t session_id; + /** connect id */ + chunk_t connect_id; /** list of endpoint pairs */ linked_list_t *pairs; @@ -195,6 +197,12 @@ struct check_list_t { /** TRUE if this is the initiator */ bool is_initiator; + /** TRUE if the initiator is finishing the checks */ + bool is_finishing; + + /** the current sender job */ + job_t *sender; + }; /** @@ -205,7 +213,7 @@ static void check_list_destroy(check_list_t *this) DESTROY_IF(this->initiator.id); DESTROY_IF(this->responder.id); - chunk_free(&this->session_id); + chunk_free(&this->connect_id); chunk_free(&this->initiator.key); chunk_free(&this->responder.key); @@ -223,12 +231,12 @@ static void check_list_destroy(check_list_t *this) * Creates a new checklist */ static check_list_t *check_list_create(identification_t *initiator, identification_t *responder, - chunk_t session_id, chunk_t initiator_key, linked_list_t *initiator_endpoints, + chunk_t connect_id, chunk_t initiator_key, linked_list_t *initiator_endpoints, bool is_initiator) { check_list_t *this = malloc_thing(check_list_t); - this->session_id = chunk_clone(session_id); + this->connect_id = chunk_clone(connect_id); this->initiator.id = initiator->clone(initiator); this->initiator.key = chunk_clone(initiator_key); @@ -242,43 +250,7 @@ static check_list_t *check_list_create(identification_t *initiator, identificati this->triggered = linked_list_create(); this->state = CHECK_NONE; this->is_initiator = is_initiator; - - return this; -} - - -typedef struct waiting_sa_t waiting_sa_t; - -/** - * For an initiator, the data stored about a waiting mediated sa - */ -struct waiting_sa_t { - /** ike sa id */ - ike_sa_id_t *ike_sa_id; - - /** list of child_cfg_t */ - linked_list_t *childs; -}; - -/** - * Destroys a queued mediated sa - */ -static void waiting_sa_destroy(waiting_sa_t *this) -{ - DESTROY_IF(this->ike_sa_id); - this->childs->destroy_offset(this->childs, offsetof(child_cfg_t, destroy)); - free(this); -} - -/** - * Creates a new mediated sa object - */ -static waiting_sa_t *waiting_sa_create(ike_sa_id_t *ike_sa_id) -{ - waiting_sa_t *this = malloc_thing(waiting_sa_t); - - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - this->childs = linked_list_create(); + this->is_finishing = FALSE; return this; } @@ -306,7 +278,7 @@ static void initiated_destroy(initiated_t *this) { DESTROY_IF(this->id); DESTROY_IF(this->peer_id); - this->mediated->destroy_function(this->mediated, (void*)waiting_sa_destroy); + this->mediated->destroy_offset(this->mediated, offsetof(ike_sa_id_t, destroy)); free(this); } @@ -340,8 +312,8 @@ struct check_t { /** destination of the connectivity check */ host_t *dst; - /** session id */ - chunk_t session_id; + /** connect id */ + chunk_t connect_id; /** endpoint */ endpoint_notify_t *endpoint; @@ -349,8 +321,8 @@ struct check_t { /** raw endpoint payload (to verify the signature) */ chunk_t endpoint_raw; - /** cookie */ - chunk_t cookie; + /** connect auth */ + chunk_t auth; }; /** @@ -358,9 +330,11 @@ struct check_t { */ static void check_destroy(check_t *this) { - chunk_free(&this->session_id); + chunk_free(&this->connect_id); chunk_free(&this->endpoint_raw); - chunk_free(&this->cookie); + chunk_free(&this->auth); + DESTROY_IF(this->src); + DESTROY_IF(this->dst); DESTROY_IF(this->endpoint); free(this); } @@ -372,9 +346,11 @@ static check_t *check_create() { check_t *this = malloc_thing(check_t); - this->session_id = chunk_empty; - this->cookie = chunk_empty; + this->connect_id = chunk_empty; + this->auth = chunk_empty; this->endpoint_raw = chunk_empty; + this->src = NULL; + this->dst = NULL; this->endpoint = NULL; this->mid = 0; @@ -382,76 +358,52 @@ static check_t *check_create() return this; } -typedef struct sender_data_t sender_data_t; +typedef struct callback_data_t callback_data_t; /** - * Data required by the sender + * Data required by several callback jobs used in this file */ -struct sender_data_t { +struct callback_data_t { /** connect manager */ private_connect_manager_t *connect_manager; - /** session id */ - chunk_t session_id; + /** connect id */ + chunk_t connect_id; + + /** message (pair) id */ + u_int32_t mid; }; /** - * Destroys a sender data object + * Destroys a callback data object */ -static void sender_data_destroy(sender_data_t *this) +static void callback_data_destroy(callback_data_t *this) { - chunk_free(&this->session_id); + chunk_free(&this->connect_id); free(this); } /** - * Creates a new sender data object + * Creates a new callback data object */ -static sender_data_t *sender_data_create(private_connect_manager_t *connect_manager, chunk_t session_id) +static callback_data_t *callback_data_create(private_connect_manager_t *connect_manager, + chunk_t connect_id) { - sender_data_t *this = malloc_thing(sender_data_t); + callback_data_t *this = malloc_thing(callback_data_t); this->connect_manager = connect_manager; - this->session_id = session_id; + this->connect_id = chunk_clone(connect_id); + this->mid = 0; return this; } -typedef struct retransmit_data_t retransmit_data_t; - -/** - * Data required by the retransmission job - */ -struct retransmit_data_t { - /** connect manager */ - private_connect_manager_t *connect_manager; - - /** session id */ - chunk_t session_id; - - /** message (pair) id */ - u_int32_t mid; -}; - -/** - * Destroys a retransmission data object - */ -static void retransmit_data_destroy(retransmit_data_t *this) -{ - chunk_free(&this->session_id); - free(this); -} - /** * Creates a new retransmission data object */ -static retransmit_data_t *retransmit_data_create(private_connect_manager_t *connect_manager, - chunk_t session_id, u_int32_t mid) +static callback_data_t *retransmit_data_create(private_connect_manager_t *connect_manager, + chunk_t connect_id, u_int32_t mid) { - retransmit_data_t *this = malloc_thing(retransmit_data_t); - - this->connect_manager = connect_manager; - this->session_id = session_id; + callback_data_t *this = callback_data_create(connect_manager, connect_id); this->mid = mid; - return this; } @@ -529,34 +481,19 @@ static void remove_initiated(private_connect_manager_t *this, initiated_t *initi } /** - * Finds a waiting sa + * Find the checklist with a specific connect ID */ -static bool match_waiting_sa(waiting_sa_t *current, ike_sa_id_t *ike_sa_id) +static bool match_checklist_by_id(check_list_t *current, chunk_t *connect_id) { - return ike_sa_id->equals(ike_sa_id, current->ike_sa_id); -} - -static status_t get_waiting_sa(initiated_t *initiated, ike_sa_id_t *ike_sa_id, waiting_sa_t **waiting_sa) -{ - return initiated->mediated->find_first(initiated->mediated, - (linked_list_match_t)match_waiting_sa, - (void**)waiting_sa, ike_sa_id); -} - -/** - * Find the checklist with a specific session ID - */ -static bool match_checklist_by_id(check_list_t *current, chunk_t *session_id) -{ - return chunk_equals(*session_id, current->session_id); + return chunk_equals(*connect_id, current->connect_id); } static status_t get_checklist_by_id(private_connect_manager_t *this, - chunk_t session_id, check_list_t **check_list) + chunk_t connect_id, check_list_t **check_list) { return this->checklists->find_first(this->checklists, (linked_list_match_t)match_checklist_by_id, - (void**)check_list, &session_id); + (void**)check_list, &connect_id); } /** @@ -595,51 +532,6 @@ static status_t endpoints_contain(linked_list_t *endpoints, host_t *host, endpoi } /** - * Updates the state of the whole checklist - */ -static void update_checklist_state(check_list_t *checklist) -{ - iterator_t *iterator; - endpoint_pair_t *current; - bool in_progress = FALSE, succeeded = FALSE; - - iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - switch(current->state) - { - case CHECK_WAITING: - /* at least one is still waiting -> checklist remains - * in waiting state */ - iterator->destroy(iterator); - return; - case CHECK_IN_PROGRESS: - in_progress = TRUE; - break; - case CHECK_SUCCEEDED: - succeeded = TRUE; - break; - default: - break; - } - } - iterator->destroy(iterator); - - if (in_progress) - { - checklist->state = CHECK_IN_PROGRESS; - } - else if (succeeded) - { - checklist->state = CHECK_SUCCEEDED; - } - else - { - checklist->state = CHECK_FAILED; - } -} - -/** * Inserts an endpoint pair into the list of pairs ordered by priority (high to low) */ static void insert_pair_by_priority(linked_list_t *pairs, endpoint_pair_t *pair) @@ -681,14 +573,14 @@ static status_t get_pair_by_hosts(linked_list_t *pairs, host_t *local, host_t *r (void**)pair, local, remote); } -/** - * Searches for a pair with a specific id - */ static bool match_pair_by_id(endpoint_pair_t *current, u_int32_t *id) { return current->id == *id; } +/** + * Searches for a pair with a specific id + */ static status_t get_pair_by_id(check_list_t *checklist, u_int32_t id, endpoint_pair_t **pair) { return checklist->pairs->find_first(checklist->pairs, @@ -696,14 +588,14 @@ static status_t get_pair_by_id(check_list_t *checklist, u_int32_t id, endpoint_p (void**)pair, &id); } -/** - * Returns the best pair of state CHECK_SUCCEEDED from a checklist. - */ static bool match_succeeded_pair(endpoint_pair_t *current) { return current->state == CHECK_SUCCEEDED; } +/** + * Returns the best pair of state CHECK_SUCCEEDED from a checklist. + */ static status_t get_best_valid_pair(check_list_t *checklist, endpoint_pair_t **pair) { return checklist->pairs->find_first(checklist->pairs, @@ -711,14 +603,14 @@ static status_t get_best_valid_pair(check_list_t *checklist, endpoint_pair_t **p (void**)pair); } -/** - * Returns and *removes* the first triggered pair in state CHECK_WAITING. - */ static bool match_waiting_pair(endpoint_pair_t *current) { return current->state == CHECK_WAITING; } +/** + * Returns and *removes* the first triggered pair in state CHECK_WAITING. + */ static status_t get_triggered_pair(check_list_t *checklist, endpoint_pair_t **pair) { iterator_t *iterator; @@ -746,6 +638,24 @@ static status_t get_triggered_pair(check_list_t *checklist, endpoint_pair_t **pa } /** + * Prints all the pairs on a checklist + */ +static void print_checklist(check_list_t *checklist) +{ + iterator_t *iterator; + endpoint_pair_t *current; + + DBG1(DBG_IKE, "pairs on checklist %#B:", &checklist->connect_id); + iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE); + while (iterator->iterate(iterator, (void**)¤t)) + { + DBG1(DBG_IKE, " * %#H - %#H (%d)", current->local, current->remote, + current->priority); + } + iterator->destroy(iterator); +} + +/** * Prunes identical pairs with lower priority from the list * Note: this function also numbers the remaining pairs serially */ @@ -775,7 +685,7 @@ static void prune_pairs(linked_list_t *pairs) * order, and we iterate the list from the beginning, we are * sure that the priority of 'other' is lower than that of * 'current', remove it */ - DBG1(DBG_IKE, "pruning endpoint pair %H - %H with priority %d", + DBG1(DBG_IKE, "pruning endpoint pair %#H - %#H with priority %d", other->local, other->remote, other->priority); search->remove(search); endpoint_pair_destroy(other); @@ -792,6 +702,7 @@ static void prune_pairs(linked_list_t *pairs) */ static void build_pairs(check_list_t *checklist) { + /* FIXME: limit endpoints and pairs */ iterator_t *iterator_i, *iterator_r; endpoint_notify_t *initiator, *responder; @@ -812,6 +723,8 @@ static void build_pairs(check_list_t *checklist) iterator_r->destroy(iterator_r); } iterator_i->destroy(iterator_i); + + print_checklist(checklist); prune_pairs(checklist->pairs); } @@ -838,45 +751,45 @@ static status_t process_payloads(message_t *message, check_t *check) switch (notify->get_notify_type(notify)) { - case P2P_ENDPOINT: + case ME_ENDPOINT: { if (check->endpoint) { - DBG1(DBG_IKE, "connectivity check contains multiple P2P_ENDPOINT notifies"); + DBG1(DBG_IKE, "connectivity check contains multiple ME_ENDPOINT notifies"); break; } endpoint_notify_t *endpoint = endpoint_notify_create_from_payload(notify); if (!endpoint) { - DBG1(DBG_IKE, "received invalid P2P_ENDPOINT notify"); + DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify"); break; } check->endpoint = endpoint; check->endpoint_raw = chunk_clone(notify->get_notification_data(notify)); - DBG2(DBG_IKE, "received P2P_ENDPOINT notify"); + DBG2(DBG_IKE, "received ME_ENDPOINT notify"); break; } - case P2P_SESSIONID: + case ME_CONNECTID: { - if (check->session_id.ptr) + if (check->connect_id.ptr) { - DBG1(DBG_IKE, "connectivity check contains multiple P2P_SESSIONID notifies"); + DBG1(DBG_IKE, "connectivity check contains multiple ME_CONNECTID notifies"); break; } - check->session_id = chunk_clone(notify->get_notification_data(notify)); - DBG3(DBG_IKE, "received p2p_sessionid %B", &check->session_id); + check->connect_id = chunk_clone(notify->get_notification_data(notify)); + DBG2(DBG_IKE, "received ME_CONNECTID %#B", &check->connect_id); break; } - case COOKIE: + case ME_CONNECTAUTH: { - if (check->cookie.ptr) + if (check->auth.ptr) { - DBG1(DBG_IKE, "connectivity check contains multiple COOKIE notifies"); + DBG1(DBG_IKE, "connectivity check contains multiple ME_CONNECTAUTH notifies"); break; } - check->cookie = chunk_clone(notify->get_notification_data(notify)); - DBG3(DBG_IKE, "received cookie %B", &check->cookie); + check->auth = chunk_clone(notify->get_notification_data(notify)); + DBG2(DBG_IKE, "received ME_CONNECTAUTH %#B", &check->auth); break; } default: @@ -885,7 +798,7 @@ static status_t process_payloads(message_t *message, check_t *check) } iterator->destroy(iterator); - if (!check->session_id.ptr || !check->endpoint || !check->cookie.ptr) + if (!check->connect_id.ptr || !check->endpoint || !check->auth.ptr) { DBG1(DBG_IKE, "at least one payload was missing from the connectivity check"); return FAILED; @@ -900,42 +813,129 @@ static status_t process_payloads(message_t *message, check_t *check) static chunk_t build_signature(private_connect_manager_t *this, check_list_t *checklist, check_t *check, bool outbound) { + u_int32_t mid; chunk_t mid_chunk, key_chunk, sig_chunk; chunk_t sig_hash; - mid_chunk = chunk_from_thing(check->mid); + mid = htonl(check->mid); + mid_chunk = chunk_from_thing(mid); key_chunk = (checklist->is_initiator && outbound) || (!checklist->is_initiator && !outbound) ? checklist->initiator.key : checklist->responder.key; - /* signature = SHA1( MID | P2P_SESSIONID | P2P_ENDPOINT | P2P_SESSIONKEY ) */ - sig_chunk = chunk_cat("cccc", mid_chunk, check->session_id, check->endpoint_raw, key_chunk); + /* signature = SHA1( MID | ME_CONNECTID | ME_ENDPOINT | ME_CONNECTKEY ) */ + sig_chunk = chunk_cat("cccc", mid_chunk, check->connect_id, check->endpoint_raw, key_chunk); this->hasher->allocate_hash(this->hasher, sig_chunk, &sig_hash); - DBG3(DBG_IKE, "sig_chunk %B", &sig_chunk); - DBG3(DBG_IKE, "sig_hash %B", &sig_hash); + DBG3(DBG_IKE, "sig_chunk %#B", &sig_chunk); + DBG3(DBG_IKE, "sig_hash %#B", &sig_hash); chunk_free(&sig_chunk); return sig_hash; } -static void queue_retransmission(private_connect_manager_t *this, chunk_t session_id, u_int32_t mid); +static void queue_retransmission(private_connect_manager_t *this, check_list_t *checklist, endpoint_pair_t *pair); static void schedule_checks(private_connect_manager_t *this, check_list_t *checklist, u_int32_t time); static void finish_checks(private_connect_manager_t *this, check_list_t *checklist); /** + * After one of the initiator's pairs has succeeded we finish the checks without + * waiting for all the timeouts + */ +static job_requeue_t initiator_finish(callback_data_t *data) +{ + private_connect_manager_t *this = data->connect_manager; + + pthread_mutex_lock(&(this->mutex)); + + check_list_t *checklist; + if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS) + { + DBG1(DBG_IKE, "checklist with id '%#B' not found, can't finish connectivity checks", + &data->connect_id); + pthread_mutex_unlock(&(this->mutex)); + return JOB_REQUEUE_NONE; + } + + finish_checks(this, checklist); + + pthread_mutex_unlock(&(this->mutex)); + + return JOB_REQUEUE_NONE; +} + +/** + * Updates the state of the whole checklist + */ +static void update_checklist_state(private_connect_manager_t *this, check_list_t *checklist) +{ + iterator_t *iterator; + endpoint_pair_t *current; + bool in_progress = FALSE, succeeded = FALSE; + + iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE); + while (iterator->iterate(iterator, (void**)¤t)) + { + switch(current->state) + { + case CHECK_WAITING: + /* at least one is still waiting -> checklist remains + * in waiting state */ + iterator->destroy(iterator); + return; + case CHECK_IN_PROGRESS: + in_progress = TRUE; + break; + case CHECK_SUCCEEDED: + succeeded = TRUE; + break; + default: + break; + } + } + iterator->destroy(iterator); + + if (checklist->is_initiator && succeeded && !checklist->is_finishing) + { + /* instead of waiting until all checks have finished (i.e. all + * retransmissions have failed) the initiator finishes the checks + * right after the first check has succeeded. to allow a probably + * better pair to succeed, we still wait a certain time */ + DBG2(DBG_IKE, "fast finishing checks for checklist '%#B'", &checklist->connect_id); + + callback_data_t *data = callback_data_create(this, checklist->connect_id); + job_t *job = (job_t*)callback_job_create((callback_job_cb_t)initiator_finish, data, (callback_job_cleanup_t)callback_data_destroy, NULL); + charon->scheduler->schedule_job(charon->scheduler, job, ME_WAIT_TO_FINISH); + checklist->is_finishing = TRUE; + } + + if (in_progress) + { + checklist->state = CHECK_IN_PROGRESS; + } + else if (succeeded) + { + checklist->state = CHECK_SUCCEEDED; + } + else + { + checklist->state = CHECK_FAILED; + } +} + +/** * This function is triggered for each sent check after a specific timeout */ -static job_requeue_t retransmit(retransmit_data_t *data) +static job_requeue_t retransmit(callback_data_t *data) { private_connect_manager_t *this = data->connect_manager; pthread_mutex_lock(&(this->mutex)); check_list_t *checklist; - if (get_checklist_by_id(this, data->session_id, &checklist) != SUCCESS) + if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS) { - DBG1(DBG_IKE, "checklist with id '%B' not found, can't retransmit connectivity check", - &data->session_id); + DBG1(DBG_IKE, "checklist with id '%#B' not found, can't retransmit connectivity check", + &data->connect_id); pthread_mutex_unlock(&(this->mutex)); return JOB_REQUEUE_NONE; } @@ -955,20 +955,20 @@ static job_requeue_t retransmit(retransmit_data_t *data) goto retransmit_end; } - if (++pair->retransmitted >= P2P_MAX_RETRANS) + if (++pair->retransmitted > ME_MAX_RETRANS) { - DBG2(DBG_IKE, "pair with id '%d' failed after %d tries", - data->mid, pair->retransmitted); + DBG2(DBG_IKE, "pair with id '%d' failed after %d retransmissions", + data->mid, ME_MAX_RETRANS); pair->state = CHECK_FAILED; goto retransmit_end; } charon->sender->send(charon->sender, pair->packet->clone(pair->packet)); - queue_retransmission(this, checklist->session_id, pair->id); + queue_retransmission(this, checklist, pair); retransmit_end: - update_checklist_state(checklist); + update_checklist_state(this, checklist); switch(checklist->state) { @@ -989,11 +989,20 @@ retransmit_end: /** * Queues a retransmission job */ -static void queue_retransmission(private_connect_manager_t *this, chunk_t session_id, u_int32_t mid) +static void queue_retransmission(private_connect_manager_t *this, check_list_t *checklist, endpoint_pair_t *pair) { - retransmit_data_t *data = retransmit_data_create(this, chunk_clone(session_id), mid); - job_t *job = (job_t*)callback_job_create((callback_job_cb_t)retransmit, data, (callback_job_cleanup_t)retransmit_data_destroy, NULL); - charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, P2P_RTO_MIN); + callback_data_t *data = retransmit_data_create(this, checklist->connect_id, pair->id); + job_t *job = (job_t*)callback_job_create((callback_job_cb_t)retransmit, data, (callback_job_cleanup_t)callback_data_destroy, NULL); + + u_int32_t retransmission = pair->retransmitted + 1; + u_int32_t rto = ME_INTERVAL; + if (retransmission > ME_BOOST) + { + rto = (u_int32_t)(ME_INTERVAL * pow(ME_RETRANS_BASE, retransmission - ME_BOOST)); + } + DBG2(DBG_IKE, "scheduling retransmission %d of pair '%d' in %dms", retransmission, pair->id, rto); + + charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, rto); } /** @@ -1009,16 +1018,21 @@ static void send_check(private_connect_manager_t *this, check_list_t *checklist, message->set_destination(message, check->dst->clone(check->dst)); message->set_source(message, check->src->clone(check->src)); - message->set_ike_sa_id(message, ike_sa_id_create(0, 0, request)); + ike_sa_id_t *ike_sa_id = ike_sa_id_create(0, 0, request); + message->set_ike_sa_id(message, ike_sa_id); + ike_sa_id->destroy(ike_sa_id); - message->add_notify(message, FALSE, P2P_SESSIONID, check->session_id); + message->add_notify(message, FALSE, ME_CONNECTID, check->connect_id); + DBG2(DBG_IKE, "send ME_CONNECTID %#B", &check->connect_id); notify_payload_t *endpoint = check->endpoint->build_notify(check->endpoint); check->endpoint_raw = chunk_clone(endpoint->get_notification_data(endpoint)); message->add_payload(message, (payload_t*)endpoint); + DBG2(DBG_IKE, "send ME_ENDPOINT notify"); - check->cookie = build_signature(this, checklist, check, TRUE); - message->add_notify(message, FALSE, COOKIE, check->cookie); + check->auth = build_signature(this, checklist, check, TRUE); + message->add_notify(message, FALSE, ME_CONNECTAUTH, check->auth); + DBG2(DBG_IKE, "send ME_CONNECTAUTH %#B", &check->auth); packet_t *packet; if (message->generate(message, NULL, NULL, &packet) == SUCCESS) @@ -1029,42 +1043,55 @@ static void send_check(private_connect_manager_t *this, check_list_t *checklist, { DESTROY_IF(pair->packet); pair->packet = packet; - queue_retransmission(this, checklist->session_id, pair->id); + pair->retransmitted = 0; + queue_retransmission(this, checklist, pair); } else { packet->destroy(packet); } } + message->destroy(message); } /** * Queues a triggered check */ -static void queue_triggered_check(check_list_t *checklist, endpoint_pair_t *pair) +static void queue_triggered_check(private_connect_manager_t *this, + check_list_t *checklist, endpoint_pair_t *pair) { + DBG2(DBG_IKE, "queueing triggered check for pair '%d'", pair->id); pair->state = CHECK_WAITING; checklist->triggered->insert_last(checklist->triggered, pair); + + if (!checklist->sender) + { + /* if the sender is not running we restart it */ + schedule_checks(this, checklist, ME_INTERVAL); + } } /** * This function is triggered for each checklist at a specific interval */ -static job_requeue_t sender(sender_data_t *data) +static job_requeue_t sender(callback_data_t *data) { private_connect_manager_t *this = data->connect_manager; pthread_mutex_lock(&(this->mutex)); - + check_list_t *checklist; - if (get_checklist_by_id(this, data->session_id, &checklist) != SUCCESS) + if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS) { - DBG1(DBG_IKE, "checklist with id '%B' not found, can't send connectivity check", - &data->session_id); + DBG1(DBG_IKE, "checklist with id '%#B' not found, can't send connectivity check", + &data->connect_id); pthread_mutex_unlock(&(this->mutex)); return JOB_REQUEUE_NONE; } + /* reset the sender */ + checklist->sender = NULL; + endpoint_pair_t *pair; if (get_triggered_pair(checklist, &pair) != SUCCESS) { @@ -1087,7 +1114,7 @@ static job_requeue_t sender(sender_data_t *data) check->mid = pair->id; check->src = pair->local->clone(pair->local); check->dst = pair->remote->clone(pair->remote); - check->session_id = chunk_clone(checklist->session_id); + check->connect_id = chunk_clone(checklist->connect_id); check->endpoint = endpoint_notify_create(); pair->state = CHECK_IN_PROGRESS; @@ -1097,8 +1124,7 @@ static job_requeue_t sender(sender_data_t *data) check_destroy(check); /* schedule this job again */ - u_int32_t N = this->checklists->get_count(this->checklists); - schedule_checks(this, checklist, P2P_INTERVAL * N); + schedule_checks(this, checklist, ME_INTERVAL); pthread_mutex_unlock(&(this->mutex)); @@ -1111,10 +1137,9 @@ static job_requeue_t sender(sender_data_t *data) */ static void schedule_checks(private_connect_manager_t *this, check_list_t *checklist, u_int32_t time) { - chunk_t session_id = chunk_clone(checklist->session_id); - sender_data_t *data = sender_data_create(this, session_id); - job_t *job = (job_t*)callback_job_create((callback_job_cb_t)sender, data, (callback_job_cleanup_t)sender_data_destroy, NULL); - charon->scheduler->schedule_job(charon->scheduler, job, time); + callback_data_t *data = callback_data_create(this, checklist->connect_id); + checklist->sender = (job_t*)callback_job_create((callback_job_cb_t)sender, data, (callback_job_cleanup_t)callback_data_destroy, NULL); + charon->scheduler->schedule_job(charon->scheduler, checklist->sender, time); } /** @@ -1128,12 +1153,12 @@ static job_requeue_t initiate_mediated(initiate_data_t *data) endpoint_pair_t *pair; if (get_best_valid_pair(checklist, &pair) == SUCCESS) { - waiting_sa_t *waiting_sa; + ike_sa_id_t *waiting_sa; iterator_t *iterator = initiated->mediated->create_iterator(initiated->mediated, TRUE); while (iterator->iterate(iterator, (void**)&waiting_sa)) { - ike_sa_t *sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, waiting_sa->ike_sa_id); - if (sa->initiate_mediated(sa, pair->local, pair->remote, waiting_sa->childs) != SUCCESS) + ike_sa_t *sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, waiting_sa); + if (sa->initiate_mediated(sa, pair->local, pair->remote, checklist->connect_id) != SUCCESS) { SIG(IKE_UP_FAILED, "establishing the mediated connection failed"); charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa); @@ -1175,11 +1200,6 @@ static void finish_checks(private_connect_manager_t *this, check_list_t *checkli "and '%D'", checklist->initiator.id, checklist->responder.id); } } - - /* remove_checklist(this, checklist); - * check_list_destroy(checklist); - * FIXME: we should do this ^^^ after a specific timeout on the - * responder side */ } /** @@ -1212,7 +1232,7 @@ static void process_response(private_connect_manager_t *this, check_t *check, local_endpoints->insert_last(local_endpoints, local_endpoint); } - update_checklist_state(checklist); + update_checklist_state(this, checklist); switch(checklist->state) { @@ -1253,12 +1273,12 @@ static void process_request(private_connect_manager_t *this, check_t *check, { case CHECK_IN_PROGRESS: /* prevent retransmissions */ - pair->retransmitted = P2P_MAX_RETRANS; + pair->retransmitted = ME_MAX_RETRANS; /* FIXME: we should wait to the next rto to send the triggered check * fall-through */ case CHECK_WAITING: case CHECK_FAILED: - queue_triggered_check(checklist, pair); + queue_triggered_check(this, checklist, pair); break; case CHECK_SUCCEEDED: default: @@ -1277,7 +1297,7 @@ static void process_request(private_connect_manager_t *this, check_t *check, insert_pair_by_priority(checklist->pairs, pair); - queue_triggered_check(checklist, pair); + queue_triggered_check(this, checklist, pair); local_endpoint->destroy(local_endpoint); } @@ -1288,7 +1308,7 @@ static void process_request(private_connect_manager_t *this, check_t *check, response->mid = check->mid; response->src = check->dst->clone(check->dst); response->dst = check->src->clone(check->src); - response->session_id = chunk_clone(check->session_id); + response->connect_id = chunk_clone(check->connect_id); response->endpoint = peer_reflexive; send_check(this, checklist, response, pair, FALSE); @@ -1313,7 +1333,9 @@ static void process_check(private_connect_manager_t *this, message_t *message) check_t *check = check_create(); check->mid = message->get_message_id(message); check->src = message->get_source(message); + check->src = check->src->clone(check->src); check->dst = message->get_destination(message); + check->dst = check->dst->clone(check->dst); if (process_payloads(message, check) != SUCCESS) { @@ -1326,17 +1348,17 @@ static void process_check(private_connect_manager_t *this, message_t *message) pthread_mutex_lock(&(this->mutex)); check_list_t *checklist; - if (get_checklist_by_id(this, check->session_id, &checklist) != SUCCESS) + if (get_checklist_by_id(this, check->connect_id, &checklist) != SUCCESS) { - DBG1(DBG_IKE, "checklist with id '%B' not found", - &check->session_id); + DBG1(DBG_IKE, "checklist with id '%#B' not found", + &check->connect_id); check_destroy(check); pthread_mutex_unlock(&(this->mutex)); return; } chunk_t sig = build_signature(this, checklist, check, FALSE); - if (!chunk_equals(sig, check->cookie)) + if (!chunk_equals(sig, check->auth)) { DBG1(DBG_IKE, "connectivity check verification failed"); check_destroy(check); @@ -1365,7 +1387,7 @@ static void process_check(private_connect_manager_t *this, message_t *message) */ static bool check_and_register(private_connect_manager_t *this, identification_t *id, identification_t *peer_id, - ike_sa_id_t *mediated_sa, child_cfg_t *child) + ike_sa_id_t *mediated_sa) { initiated_t *initiated; bool already_there = TRUE; @@ -1380,16 +1402,12 @@ static bool check_and_register(private_connect_manager_t *this, already_there = FALSE; } - waiting_sa_t *waiting_sa; - if (get_waiting_sa(initiated, mediated_sa, &waiting_sa) != SUCCESS) + if (initiated->mediated->find_first(initiated->mediated, + (linked_list_match_t)mediated_sa->equals, NULL, mediated_sa) != SUCCESS) { - waiting_sa = waiting_sa_create(mediated_sa); - initiated->mediated->insert_last(initiated->mediated, waiting_sa); + initiated->mediated->insert_last(initiated->mediated, mediated_sa->clone(mediated_sa)); } - child->get_ref(child); - waiting_sa->childs->insert_last(waiting_sa->childs, child); - pthread_mutex_unlock(&(this->mutex)); return already_there; @@ -1412,14 +1430,14 @@ static void check_and_initiate(private_connect_manager_t *this, ike_sa_id_t *med return; } - waiting_sa_t *waiting_sa; + ike_sa_id_t *waiting_sa; iterator_t *iterator = initiated->mediated->create_iterator(initiated->mediated, TRUE); while (iterator->iterate(iterator, (void**)&waiting_sa)) { - job_t *job = (job_t*)reinitiate_mediation_job_create(mediation_sa, - waiting_sa->ike_sa_id); + job_t *job = (job_t*)reinitiate_mediation_job_create(mediation_sa, waiting_sa); charon->processor->queue_job(charon->processor, job); } + iterator->destroy(iterator); pthread_mutex_unlock(&(this->mutex)); } @@ -1429,21 +1447,21 @@ static void check_and_initiate(private_connect_manager_t *this, ike_sa_id_t *med */ static status_t set_initiator_data(private_connect_manager_t *this, identification_t *initiator, identification_t *responder, - chunk_t session_id, chunk_t key, linked_list_t *endpoints, bool is_initiator) + chunk_t connect_id, chunk_t key, linked_list_t *endpoints, bool is_initiator) { check_list_t *checklist; pthread_mutex_lock(&(this->mutex)); - if (get_checklist_by_id(this, session_id, NULL) == SUCCESS) + if (get_checklist_by_id(this, connect_id, NULL) == SUCCESS) { - DBG1(DBG_IKE, "checklist with id '%B' already exists, aborting", - &session_id); + DBG1(DBG_IKE, "checklist with id '%#B' already exists, aborting", + &connect_id); pthread_mutex_unlock(&(this->mutex)); return FAILED; } - checklist = check_list_create(initiator, responder, session_id, key, endpoints, is_initiator); + checklist = check_list_create(initiator, responder, connect_id, key, endpoints, is_initiator); this->checklists->insert_last(this->checklists, checklist); pthread_mutex_unlock(&(this->mutex)); @@ -1455,16 +1473,16 @@ static status_t set_initiator_data(private_connect_manager_t *this, * Implementation of connect_manager_t.set_responder_data. */ static status_t set_responder_data(private_connect_manager_t *this, - chunk_t session_id, chunk_t key, linked_list_t *endpoints) + chunk_t connect_id, chunk_t key, linked_list_t *endpoints) { check_list_t *checklist; pthread_mutex_lock(&(this->mutex)); - if (get_checklist_by_id(this, session_id, &checklist) != SUCCESS) + if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS) { - DBG1(DBG_IKE, "checklist with id '%B' not found", - &session_id); + DBG1(DBG_IKE, "checklist with id '%#B' not found", + &connect_id); pthread_mutex_unlock(&(this->mutex)); return NOT_FOUND; } @@ -1484,6 +1502,33 @@ static status_t set_responder_data(private_connect_manager_t *this, } /** + * Implementation of connect_manager_t.stop_checks. + */ +static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id) +{ + check_list_t *checklist; + + pthread_mutex_lock(&(this->mutex)); + + if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS) + { + DBG1(DBG_IKE, "checklist with id '%#B' not found", + &connect_id); + pthread_mutex_unlock(&(this->mutex)); + return NOT_FOUND; + } + + DBG1(DBG_IKE, "removing checklist with id '%#B'", &connect_id); + + remove_checklist(this, checklist); + check_list_destroy(checklist); + + pthread_mutex_unlock(&(this->mutex)); + + return SUCCESS; +} + +/** * Implementation of connect_manager_t.destroy. */ static void destroy(private_connect_manager_t *this) @@ -1507,13 +1552,21 @@ connect_manager_t *connect_manager_create() private_connect_manager_t *this = malloc_thing(private_connect_manager_t); this->public.destroy = (void(*)(connect_manager_t*))destroy; - this->public.check_and_register = (bool(*)(connect_manager_t*,identification_t*,identification_t*,ike_sa_id_t*,child_cfg_t*))check_and_register; + this->public.check_and_register = (bool(*)(connect_manager_t*,identification_t*,identification_t*,ike_sa_id_t*))check_and_register; this->public.check_and_initiate = (void(*)(connect_manager_t*,ike_sa_id_t*,identification_t*,identification_t*))check_and_initiate; this->public.set_initiator_data = (status_t(*)(connect_manager_t*,identification_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))set_initiator_data; this->public.set_responder_data = (status_t(*)(connect_manager_t*,chunk_t,chunk_t,linked_list_t*))set_responder_data; this->public.process_check = (void(*)(connect_manager_t*,message_t*))process_check; + this->public.stop_checks = (status_t(*)(connect_manager_t*,chunk_t))stop_checks; + + this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (this->hasher == NULL) + { + DBG1(DBG_IKE, "unable to create connect manager, SHA1 not supported"); + free(this); + return NULL; + } - this->hasher = hasher_create(HASH_SHA1); this->checklists = linked_list_create(); this->initiated = linked_list_create(); diff --git a/src/charon/sa/connect_manager.h b/src/charon/sa/connect_manager.h index 2f3e9109b..38d8e7a49 100644 --- a/src/charon/sa/connect_manager.h +++ b/src/charon/sa/connect_manager.h @@ -1,12 +1,5 @@ -/** - * @file connect_manager.h - * - * @brief Interface of connect_manager_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,6 +11,13 @@ * 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. + * + * $Id: connect_manager.h 3792 2008-04-10 12:51:04Z tobias $ + */ + +/** + * @defgroup connect_manager connect_manager + * @{ @ingroup sa */ #ifndef CONNECT_MANAGER_H_ @@ -26,43 +26,33 @@ typedef struct connect_manager_t connect_manager_t; #include <encoding/message.h> -#include <config/child_cfg.h> #include <sa/ike_sa_id.h> #include <utils/identification.h> /** - * @brief The connection manager is responsible for establishing a direct + * The connection manager is responsible for establishing a direct * connection with another peer. - * - * @b Constructors: - * - connect_manager_create() - * - * @ingroup sa */ struct connect_manager_t { /** - * @brief Checks if a there is already a mediated connection registered + * Checks if a there is already a mediated connection registered * between two peers. * - * @param this the manager object * @param id my id * @param peer_id the other peer's id * @param mediated_sa the IKE_SA ID of the mediated connection - * @param child the CHILD_SA config of the mediated connection * @returns * - TRUE, if there was already a mediated connection registered * - FALSE, otherwise */ bool (*check_and_register) (connect_manager_t *this, - identification_t *id, identification_t *peer_id, - ike_sa_id_t *mediated_sa, child_cfg_t *child); + identification_t *id, identification_t *peer_id, ike_sa_id_t *mediated_sa); /** - * @brief Checks if there are waiting connections with a specific peer. + * Checks if there are waiting connections with a specific peer. * If so, reinitiate them. * - * @param this the manager object * @param id my id * @param peer_id the other peer's id */ @@ -70,29 +60,26 @@ struct connect_manager_t { identification_t *id, identification_t *peer_id); /** - * @brief Creates a checklist and sets the initiator's data. + * Creates a checklist and sets the initiator's data. * - * @param this the manager object * @param initiator ID of the initiator * @param responder ID of the responder - * @param session_id the session ID provided by the initiator + * @param connect_id the connect ID provided by the initiator * @param key the initiator's key * @param endpoints the initiator's endpoints * @param is_initiator TRUE, if the caller of this method is the initiator * FALSE, otherwise - * @returns - * SUCCESS + * @returns SUCCESS */ status_t (*set_initiator_data) (connect_manager_t *this, identification_t *initiator, identification_t *responder, - chunk_t session_id, chunk_t key, linked_list_t *endpoints, bool is_initiator); + chunk_t connect_id, chunk_t key, linked_list_t *endpoints, bool is_initiator); /** - * @brief Updates a checklist and sets the responder's data. The checklist's + * Updates a checklist and sets the responder's data. The checklist's * state is advanced to WAITING which means that checks will be sent. * - * @param this the manager object - * @param session_id the session ID + * @param connect_id the connect ID * @param chunk_t the responder's key * @param endpoints the responder's endpoints * @returns @@ -100,32 +87,37 @@ struct connect_manager_t { * - SUCCESS, otherwise */ status_t (*set_responder_data) (connect_manager_t *this, - chunk_t session_id, chunk_t key, linked_list_t *endpoints); + chunk_t connect_id, chunk_t key, linked_list_t *endpoints); + /** + * Stops checks for a checklist. Used after the responder received an IKE_SA_INIT + * request which contains a ME_CONNECTID payload. + * + * @param connect_id the connect ID + * @returns + * - NOT_FOUND, if the checklist has not been found + * - SUCCESS, otherwise + */ + status_t (*stop_checks) (connect_manager_t *this, chunk_t connect_id); /** - * @brief Processes a connectivity check + * Processes a connectivity check * - * @param this the manager object * @param message the received message */ void (*process_check) (connect_manager_t *this, message_t *message); /** - * @brief Destroys the manager with all data. - * - * @param this the manager object + * Destroys the manager with all data. */ void (*destroy) (connect_manager_t *this); }; /** - * @brief Create a manager. + * Create a manager. * * @returns connect_manager_t object - * - * @ingroup sa */ connect_manager_t *connect_manager_create(void); -#endif /*CONNECT_MANAGER_H_*/ +#endif /*CONNECT_MANAGER_H_ @} */ diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 93aa08965..384226380 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -1,12 +1,5 @@ -/** - * @file ike_sa.c - * - * @brief Implementation of ike_sa_t. - * - */ - /* - * Copyright (C) 2006-2007 Tobias Brunner + * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -21,6 +14,8 @@ * 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. + * + * $Id: ike_sa.c 4106 2008-06-25 11:40:50Z martin $ */ #include <sys/time.h> @@ -53,7 +48,8 @@ #include <sa/tasks/ike_auth.h> #include <sa/tasks/ike_auth_lifetime.h> #include <sa/tasks/ike_config.h> -#include <sa/tasks/ike_cert.h> +#include <sa/tasks/ike_cert_pre.h> +#include <sa/tasks/ike_cert_post.h> #include <sa/tasks/ike_rekey.h> #include <sa/tasks/ike_reauth.h> #include <sa/tasks/ike_delete.h> @@ -67,8 +63,8 @@ #include <processing/jobs/send_keepalive_job.h> #include <processing/jobs/rekey_ike_sa_job.h> -#ifdef P2P -#include <sa/tasks/ike_p2p.h> +#ifdef ME +#include <sa/tasks/ike_me.h> #include <processing/jobs/initiate_mediation_job.h> #endif @@ -122,6 +118,16 @@ struct private_ike_sa_t { peer_cfg_t *peer_cfg; /** + * associated authentication/authorization info for local peer + */ + auth_info_t *my_auth; + + /** + * associated authentication/authorization info for remote peer + */ + auth_info_t *other_auth; + + /** * Juggles tasks to process messages */ task_manager_t *task_manager; @@ -136,12 +142,22 @@ struct private_ike_sa_t { */ host_t *other_host; -#ifdef P2P +#ifdef ME + /** + * Are we mediation server + */ + bool is_mediation_server; + /** * Server reflexive host */ host_t *server_reflexive_host; -#endif /* P2P */ + + /** + * Connect ID + */ + chunk_t connect_id; +#endif /* ME */ /** * Identification used for us @@ -154,11 +170,6 @@ struct private_ike_sa_t { identification_t *other_id; /** - * CA that issued the certificate of other - */ - ca_info_t *other_ca; - - /** * set of extensions the peer supports */ ike_extension_t extensions; @@ -174,6 +185,11 @@ struct private_ike_sa_t { linked_list_t *child_sas; /** + * String describing the selected IKE proposal + */ + char *selected_proposal; + + /** * crypter for inbound traffic */ crypter_t *crypter_in; @@ -390,6 +406,7 @@ static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this) */ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) { + DESTROY_IF(this->peer_cfg); peer_cfg->get_ref(peer_cfg); this->peer_cfg = peer_cfg; @@ -398,18 +415,6 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); this->ike_cfg->get_ref(this->ike_cfg); } - - /* apply values, so we are ready to initate/acquire */ - if (this->my_host->is_anyaddr(this->my_host)) - { - host_t *me = this->ike_cfg->get_my_host(this->ike_cfg); - set_my_host(this, me->clone(me)); - } - if (this->other_host->is_anyaddr(this->other_host)) - { - host_t *other = this->ike_cfg->get_other_host(this->ike_cfg); - set_other_host(this, other->clone(other)); - } /* apply IDs if they are not already set */ if (this->my_id->contains_wildcards(this->my_id)) { @@ -426,6 +431,22 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) } /** + * Implementation of ike_sa_t.get_my_auth. + */ +static auth_info_t* get_my_auth(private_ike_sa_t *this) +{ + return this->my_auth; +} + +/** + * Implementation of ike_sa_t.get_other_auth. + */ +static auth_info_t* get_other_auth(private_ike_sa_t *this) +{ + return this->other_auth; +} + +/** * Implementation of ike_sa_t.send_keepalive */ static void send_keepalive(private_ike_sa_t *this) @@ -480,6 +501,15 @@ static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg) ike_cfg->get_ref(ike_cfg); this->ike_cfg = ike_cfg; } + +/** + * Implementation of ike_sa_t.is_ike_initiator + */ +static bool is_ike_initiator(private_ike_sa_t *this) +{ + return this->ike_initiator; +} + /** * Implementation of ike_sa_t.enable_extension. */ @@ -562,7 +592,7 @@ static status_t send_dpd(private_ike_sa_t *this) send_dpd_job_t *job; time_t diff, delay; - delay = this->peer_cfg->get_dpd_delay(this->peer_cfg); + delay = this->peer_cfg->get_dpd(this->peer_cfg); if (delay == 0) { @@ -907,7 +937,17 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request, response->destroy(response); } -#ifdef P2P +#ifdef ME +/** + * Implementation of ike_sa_t.act_as_mediation_server. + */ +static void act_as_mediation_server(private_ike_sa_t *this) +{ + charon->mediation_manager->update_sa_id(charon->mediation_manager, + this->other_id, this->ike_sa_id); + this->is_mediation_server = TRUE; +} + /** * Implementation of ike_sa_t.get_server_reflexive_host. */ @@ -926,13 +966,21 @@ static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host) } /** + * Implementation of ike_sa_t.get_connect_id. + */ +static chunk_t get_connect_id(private_ike_sa_t *this) +{ + return this->connect_id; +} + +/** * Implementation of ike_sa_t.respond */ static status_t respond(private_ike_sa_t *this, identification_t *peer_id, - chunk_t session_id) + chunk_t connect_id) { - ike_p2p_t *task = ike_p2p_create(&this->public, TRUE); - task->respond(task, peer_id, session_id); + ike_me_t *task = ike_me_create(&this->public, TRUE); + task->respond(task, peer_id, connect_id); this->task_manager->queue_task(this->task_manager, (task_t*)task); return this->task_manager->initiate(this->task_manager); } @@ -942,7 +990,7 @@ static status_t respond(private_ike_sa_t *this, identification_t *peer_id, */ static status_t callback(private_ike_sa_t *this, identification_t *peer_id) { - ike_p2p_t *task = ike_p2p_create(&this->public, TRUE); + ike_me_t *task = ike_me_create(&this->public, TRUE); task->callback(task, peer_id); this->task_manager->queue_task(this->task_manager, (task_t*)task); return this->task_manager->initiate(this->task_manager); @@ -952,10 +1000,10 @@ static status_t callback(private_ike_sa_t *this, identification_t *peer_id) * Implementation of ike_sa_t.relay */ static status_t relay(private_ike_sa_t *this, identification_t *requester, - chunk_t session_id, chunk_t session_key, linked_list_t *endpoints, bool response) + chunk_t connect_id, chunk_t connect_key, linked_list_t *endpoints, bool response) { - ike_p2p_t *task = ike_p2p_create(&this->public, TRUE); - task->relay(task, requester, session_id, session_key, endpoints, response); + ike_me_t *task = ike_me_create(&this->public, TRUE); + task->relay(task, requester, connect_id, connect_key, endpoints, response); this->task_manager->queue_task(this->task_manager, (task_t*)task); return this->task_manager->initiate(this->task_manager); } @@ -965,7 +1013,7 @@ static status_t relay(private_ike_sa_t *this, identification_t *requester, */ static status_t initiate_mediation(private_ike_sa_t *this, peer_cfg_t *mediated_cfg) { - ike_p2p_t *task = ike_p2p_create(&this->public, TRUE); + ike_me_t *task = ike_me_create(&this->public, TRUE); task->connect(task, mediated_cfg->get_peer_id(mediated_cfg)); this->task_manager->queue_task(this->task_manager, (task_t*)task); return this->task_manager->initiate(this->task_manager); @@ -975,37 +1023,54 @@ static status_t initiate_mediation(private_ike_sa_t *this, peer_cfg_t *mediated_ * Implementation of ike_sa_t.initiate_mediated */ static status_t initiate_mediated(private_ike_sa_t *this, host_t *me, host_t *other, - linked_list_t *childs) + chunk_t connect_id) { - this->my_host = me->clone(me); - this->other_host = other->clone(other); + set_my_host(this, me->clone(me)); + set_other_host(this, other->clone(other)); + chunk_free(&this->connect_id); + this->connect_id = chunk_clone(connect_id); - task_t *task; - child_cfg_t *child_cfg; - iterator_t *iterator = childs->create_iterator(childs, TRUE); - while (iterator->iterate(iterator, (void**)&child_cfg)) + return this->task_manager->initiate(this->task_manager); +} +#endif /* ME */ + +/** + * Resolve DNS host in configuration + */ +static void resolve_hosts(private_ike_sa_t *this) +{ + host_t *host; + + host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg), 0, + IKEV2_UDP_PORT); + if (host) { - task = (task_t*)child_create_create(&this->public, child_cfg); - this->task_manager->queue_task(this->task_manager, task); + set_my_host(this, host); + } + host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg), + this->my_host->get_family(this->my_host), + IKEV2_UDP_PORT); + if (host) + { + set_other_host(this, host); } - iterator->destroy(iterator); - return this->task_manager->initiate(this->task_manager); } -#endif /* P2P */ /** - * Implementation of ike_sa_t.initiate. + * Initiates a CHILD_SA using the appropriate reqid */ -static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg) +static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid) { task_t *task; if (this->state == IKE_CREATED) { + resolve_hosts(this); + if (this->other_host->is_anyaddr(this->other_host) -#ifdef P2P +#ifdef ME && !this->peer_cfg->get_mediated_by(this->peer_cfg) -#endif /* P2P */ +#endif /* ME */ ) { child_cfg->destroy(child_cfg); @@ -1020,10 +1085,12 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg) this->task_manager->queue_task(this->task_manager, task); task = (task_t*)ike_natd_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_cert_create(&this->public, TRUE); + task = (task_t*)ike_cert_pre_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); task = (task_t*)ike_auth_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); + task = (task_t*)ike_cert_post_create(&this->public, TRUE); + this->task_manager->queue_task(this->task_manager, task); task = (task_t*)ike_config_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); task = (task_t*)ike_auth_lifetime_create(&this->public, TRUE); @@ -1033,50 +1100,65 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg) task = (task_t*)ike_mobike_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); } -#ifdef P2P - task = (task_t*)ike_p2p_create(&this->public, TRUE); +#ifdef ME + task = (task_t*)ike_me_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, task); -#endif /* P2P */ +#endif /* ME */ } -#ifdef P2P - if (this->peer_cfg->get_mediated_by(this->peer_cfg)) - { - /* mediated connection, initiate mediation process */ - job_t *job = (job_t*)initiate_mediation_job_create(this->ike_sa_id, child_cfg); - child_cfg->destroy(child_cfg); - charon->processor->queue_job(charon->processor, job); - return SUCCESS; - } - else if (this->peer_cfg->is_mediation(this->peer_cfg)) +#ifdef ME + if (this->peer_cfg->is_mediation(this->peer_cfg)) { + /* mediation connection */ if (this->state == IKE_ESTABLISHED) { /* FIXME: we should try to find a better solution to this */ SIG(CHILD_UP_SUCCESS, "mediation connection is already up and running"); } + DESTROY_IF(child_cfg); } else -#endif /* P2P */ +#endif /* ME */ { /* normal IKE_SA with CHILD_SA */ task = (task_t*)child_create_create(&this->public, child_cfg); child_cfg->destroy(child_cfg); + if (reqid) + { + child_create_t *child_create = (child_create_t*)task; + child_create->use_reqid(child_create, reqid); + } this->task_manager->queue_task(this->task_manager, task); + +#ifdef ME + if (this->peer_cfg->get_mediated_by(this->peer_cfg)) + { + /* mediated connection, initiate mediation process */ + job_t *job = (job_t*)initiate_mediation_job_create(this->ike_sa_id); + charon->processor->queue_job(charon->processor, job); + return SUCCESS; + } +#endif /* ME */ } return this->task_manager->initiate(this->task_manager); } /** + * Implementation of ike_sa_t.initiate. + */ +static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg) +{ + return initiate_with_reqid(this, child_cfg, 0); +} + +/** * Implementation of ike_sa_t.acquire. */ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) -{ /* FIXME: P2P-NAT-T */ +{ child_cfg_t *child_cfg; iterator_t *iterator; child_sa_t *current, *child_sa = NULL; - task_t *task; - child_create_t *child_create; if (this->state == IKE_DELETING) { @@ -1105,34 +1187,10 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) return FAILED; } - - if (this->state == IKE_CREATED) - { - task = (task_t*)ike_init_create(&this->public, TRUE, NULL); - this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_natd_create(&this->public, TRUE); - this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_cert_create(&this->public, TRUE); - this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_auth_create(&this->public, TRUE); - this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_config_create(&this->public, TRUE); - this->task_manager->queue_task(this->task_manager, task); - task = (task_t*)ike_auth_lifetime_create(&this->public, TRUE); - this->task_manager->queue_task(this->task_manager, task); - if (this->peer_cfg->use_mobike(this->peer_cfg)) - { - task = (task_t*)ike_mobike_create(&this->public, TRUE); - this->task_manager->queue_task(this->task_manager, task); - } - } - child_cfg = child_sa->get_config(child_sa); - child_create = child_create_create(&this->public, child_cfg); - child_create->use_reqid(child_create, reqid); - this->task_manager->queue_task(this->task_manager, (task_t*)child_create); + child_cfg->get_ref(child_cfg); - return this->task_manager->initiate(this->task_manager); + return initiate_with_reqid(this, child_cfg, reqid); } /** @@ -1175,10 +1233,12 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg) default: break; } + + resolve_hosts(this); /* install kernel policies */ child_sa = child_sa_create(this->my_host, this->other_host, this->my_id, - this->other_id, child_cfg, FALSE, 0); + this->other_id, child_cfg, 0, FALSE); me = this->my_host; if (this->my_virtual_ip) { @@ -1394,145 +1454,6 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) } /** - * Implementation of ike_sa_t.retransmit. - */ -static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) -{ /* FIXME: P2P-NAT-T */ - this->time.outbound = time(NULL); - if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) - { - child_cfg_t *child_cfg; - child_sa_t* child_sa; - linked_list_t *to_route, *to_restart; - iterator_t *iterator; - - /* send a proper signal to brief interested bus listeners */ - switch (this->state) - { - case IKE_CONNECTING: - { - /* retry IKE_SA_INIT if we have multiple keyingtries */ - u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg); - this->keyingtry++; - if (tries == 0 || tries > this->keyingtry) - { - SIG(IKE_UP_FAILED, "peer not responding, trying again " - "(%d/%d) in background ", this->keyingtry + 1, tries); - reset(this); - return this->task_manager->initiate(this->task_manager); - } - SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding"); - break; - } - case IKE_REKEYING: - SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding"); - break; - case IKE_DELETING: - SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding"); - break; - default: - break; - } - - /* summarize how we have to handle each child */ - to_route = linked_list_create(); - to_restart = linked_list_create(); - iterator = this->child_sas->create_iterator(this->child_sas, TRUE); - while (iterator->iterate(iterator, (void**)&child_sa)) - { - child_cfg = child_sa->get_config(child_sa); - - if (child_sa->get_state(child_sa) == CHILD_ROUTED) - { - /* reroute routed CHILD_SAs */ - to_route->insert_last(to_route, child_cfg); - } - else - { - /* use DPD action for established CHILD_SAs */ - switch (this->peer_cfg->get_dpd_action(this->peer_cfg)) - { - case DPD_ROUTE: - to_route->insert_last(to_route, child_cfg); - break; - case DPD_RESTART: - to_restart->insert_last(to_restart, child_cfg); - break; - default: - break; - } - } - } - iterator->destroy(iterator); - - /* create a new IKE_SA if we have to route or to restart */ - if (to_route->get_count(to_route) || to_restart->get_count(to_restart)) - { - private_ike_sa_t *new; - task_t *task; - - new = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new( - charon->ike_sa_manager, TRUE); - - set_peer_cfg(new, this->peer_cfg); - /* use actual used host, not the wildcarded one in config */ - new->other_host->destroy(new->other_host); - new->other_host = this->other_host->clone(this->other_host); - /* reset port to 500, but only if peer is not NATed */ - if (!has_condition(this, COND_NAT_THERE)) - { - new->other_host->set_port(new->other_host, IKEV2_UDP_PORT); - } - /* take over virtual ip, as we need it for a proper route */ - if (this->my_virtual_ip) - { - set_virtual_ip(new, TRUE, this->my_virtual_ip); - } - - /* install routes */ - while (to_route->remove_last(to_route, (void**)&child_cfg) == SUCCESS) - { - route(new, child_cfg); - } - - /* restart children */ - if (to_restart->get_count(to_restart)) - { - task = (task_t*)ike_init_create(&new->public, TRUE, NULL); - new->task_manager->queue_task(new->task_manager, task); - task = (task_t*)ike_natd_create(&new->public, TRUE); - new->task_manager->queue_task(new->task_manager, task); - task = (task_t*)ike_cert_create(&new->public, TRUE); - new->task_manager->queue_task(new->task_manager, task); - task = (task_t*)ike_config_create(&new->public, TRUE); - new->task_manager->queue_task(new->task_manager, task); - task = (task_t*)ike_auth_create(&new->public, TRUE); - new->task_manager->queue_task(new->task_manager, task); - - while (to_restart->remove_last(to_restart, (void**)&child_cfg) == SUCCESS) - { - task = (task_t*)child_create_create(&new->public, child_cfg); - new->task_manager->queue_task(new->task_manager, task); - } - task = (task_t*)ike_auth_lifetime_create(&new->public, TRUE); - new->task_manager->queue_task(new->task_manager, task); - if (this->peer_cfg->use_mobike(this->peer_cfg)) - { - task = (task_t*)ike_mobike_create(&new->public, TRUE); - new->task_manager->queue_task(new->task_manager, task); - } - new->task_manager->initiate(new->task_manager); - } - charon->ike_sa_manager->checkin(charon->ike_sa_manager, &new->public); - } - to_route->destroy(to_route); - to_restart->destroy(to_restart); - return DESTROY_ME; - } - return SUCCESS; -} - -/** * Implementation of ike_sa_t.get_prf. */ static prf_t *get_prf(private_ike_sa_t *this) @@ -1607,22 +1528,6 @@ static void set_other_id(private_ike_sa_t *this, identification_t *other) } /** - * Implementation of ike_sa_t.get_other_ca. - */ -static ca_info_t* get_other_ca(private_ike_sa_t *this) -{ - return this->other_ca; -} - -/** - * Implementation of ike_sa_t.set_other_ca. - */ -static void set_other_ca(private_ike_sa_t *this, ca_info_t *other_ca) -{ - this->other_ca = other_ca; -} - -/** * Implementation of ike_sa_t.derive_keys. */ static status_t derive_keys(private_ike_sa_t *this, @@ -1631,9 +1536,8 @@ static status_t derive_keys(private_ike_sa_t *this, bool initiator, prf_t *child_prf, prf_t *old_prf) { prf_plus_t *prf_plus; - chunk_t skeyseed, key, nonces, prf_plus_seed; - algorithm_t *algo; - size_t key_size; + chunk_t skeyseed, key, full_nonce, fixed_nonce, prf_plus_seed; + u_int16_t alg, key_size; crypter_t *crypter_i, *crypter_r; signer_t *signer_i, *signer_r; u_int8_t spi_i_buf[sizeof(u_int64_t)], spi_r_buf[sizeof(u_int64_t)]; @@ -1641,24 +1545,42 @@ static status_t derive_keys(private_ike_sa_t *this, chunk_t spi_r = chunk_from_buf(spi_r_buf); /* Create SAs general purpose PRF first, we may use it here */ - if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo)) + if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL)) { - DBG1(DBG_IKE, "key derivation failed: no PSEUDO_RANDOM_FUNCTION");; + DBG1(DBG_IKE, "no %N selected", + transform_type_names, PSEUDO_RANDOM_FUNCTION); return FAILED; } - this->prf = prf_create(algo->algorithm); + this->prf = lib->crypto->create_prf(lib->crypto, alg); if (this->prf == NULL) { - DBG1(DBG_IKE, "key derivation failed: PSEUDO_RANDOM_FUNCTION " - "%N not supported!", pseudo_random_function_names, algo->algorithm); + DBG1(DBG_IKE, "%N %N not supported!", + transform_type_names, PSEUDO_RANDOM_FUNCTION, + pseudo_random_function_names, alg); return FAILED; } - DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret); - nonces = chunk_cat("cc", nonce_i, nonce_r); + /* full nonce is used as seed for PRF+ ... */ + full_nonce = chunk_cat("cc", nonce_i, nonce_r); + /* but the PRF may need a fixed key which only uses the first bytes of + * the nonces. */ + switch (alg) + { + case PRF_AES128_XCBC: + /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does + * not and therefore fixed key semantics apply to XCBC for key + * derivation. */ + nonce_i.len = min(nonce_i.len, this->prf->get_key_size(this->prf)/2); + nonce_r.len = min(nonce_r.len, this->prf->get_key_size(this->prf)/2); + break; + default: + /* all other algorithms use variable key length, full nonce */ + break; + } + fixed_nonce = chunk_cat("cc", nonce_i, nonce_r); *((u_int64_t*)spi_i.ptr) = this->ike_sa_id->get_initiator_spi(this->ike_sa_id); *((u_int64_t*)spi_r.ptr) = this->ike_sa_id->get_responder_spi(this->ike_sa_id); - prf_plus_seed = chunk_cat("ccc", nonces, spi_i, spi_r); + prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r); /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr) * @@ -1667,7 +1589,7 @@ static status_t derive_keys(private_ike_sa_t *this, if (child_prf == NULL) /* not rekeying */ { /* SKEYSEED = prf(Ni | Nr, g^ir) */ - this->prf->set_key(this->prf, nonces); + this->prf->set_key(this->prf, fixed_nonce); this->prf->allocate_bytes(this->prf, secret, &skeyseed); DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); this->prf->set_key(this->prf, skeyseed); @@ -1679,7 +1601,7 @@ static status_t derive_keys(private_ike_sa_t *this, { /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr) * use OLD SAs PRF functions for both prf_plus and prf */ - secret = chunk_cat("mc", secret, nonces); + secret = chunk_cat("mc", secret, full_nonce); child_prf->allocate_bytes(child_prf, secret, &skeyseed); DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed); old_prf->set_key(old_prf, skeyseed); @@ -1687,14 +1609,15 @@ static status_t derive_keys(private_ike_sa_t *this, chunk_free(&secret); prf_plus = prf_plus_create(old_prf, prf_plus_seed); } - chunk_free(&nonces); + chunk_free(&full_nonce); + chunk_free(&fixed_nonce); chunk_free(&prf_plus_seed); /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */ /* SK_d is used for generating CHILD_SA key mat => child_prf */ - proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); - this->child_prf = prf_create(algo->algorithm); + proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL); + this->child_prf = lib->crypto->create_prf(lib->crypto, alg); key_size = this->child_prf->get_key_size(this->child_prf); prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_d secret %B", &key); @@ -1702,17 +1625,20 @@ static status_t derive_keys(private_ike_sa_t *this, chunk_free(&key); /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */ - if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo)) + if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)) { - DBG1(DBG_IKE, "key derivation failed: no INTEGRITY_ALGORITHM"); + DBG1(DBG_IKE, "no %N selected", + transform_type_names, INTEGRITY_ALGORITHM); return FAILED; } - signer_i = signer_create(algo->algorithm); - signer_r = signer_create(algo->algorithm); + signer_i = lib->crypto->create_signer(lib->crypto, alg); + signer_r = lib->crypto->create_signer(lib->crypto, alg); if (signer_i == NULL || signer_r == NULL) { - DBG1(DBG_IKE, "key derivation failed: INTEGRITY_ALGORITHM " - "%N not supported!", integrity_algorithm_names ,algo->algorithm); + DBG1(DBG_IKE, "%N %N not supported!", + transform_type_names, INTEGRITY_ALGORITHM, + integrity_algorithm_names ,alg); + prf_plus->destroy(prf_plus); return FAILED; } key_size = signer_i->get_key_size(signer_i); @@ -1739,18 +1665,21 @@ static status_t derive_keys(private_ike_sa_t *this, } /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */ - if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo)) + if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size)) { - DBG1(DBG_IKE, "key derivation failed: no ENCRYPTION_ALGORITHM"); + DBG1(DBG_IKE, "no %N selected", + transform_type_names, ENCRYPTION_ALGORITHM); + prf_plus->destroy(prf_plus); return FAILED; } - crypter_i = crypter_create(algo->algorithm, algo->key_size / 8); - crypter_r = crypter_create(algo->algorithm, algo->key_size / 8); + crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8); + crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8); if (crypter_i == NULL || crypter_r == NULL) { - DBG1(DBG_IKE, "key derivation failed: ENCRYPTION_ALGORITHM " - "%N (key size %d) not supported!", - encryption_algorithm_names, algo->algorithm, algo->key_size); + DBG1(DBG_IKE, "%N %N (key size %d) not supported!", + transform_type_names, ENCRYPTION_ALGORITHM, + encryption_algorithm_names, alg, key_size); + prf_plus->destroy(prf_plus); return FAILED; } key_size = crypter_i->get_key_size(crypter_i); @@ -1806,6 +1735,23 @@ static status_t derive_keys(private_ike_sa_t *this, } /** + * Implementation of ike_sa_t.get_proposal. + */ +static char* get_proposal(private_ike_sa_t *this) +{ + return this->selected_proposal; +} + +/** + * Implementation of ike_sa_t.set_proposal. + */ +static void set_proposal(private_ike_sa_t *this, char *proposal) +{ + free(this->selected_proposal); + this->selected_proposal = strdup(proposal); +} + +/** * Implementation of ike_sa_t.add_child_sa. */ static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa) @@ -1944,9 +1890,9 @@ static status_t rekey(private_ike_sa_t *this) } /** - * Implementation of ike_sa_t.reestablish + * Implementation of ike_sa_t.reauth */ -static status_t reestablish(private_ike_sa_t *this) +static status_t reauth(private_ike_sa_t *this) { task_t *task; @@ -1957,7 +1903,12 @@ static status_t reestablish(private_ike_sa_t *this) { DBG1(DBG_IKE, "initiator did not reauthenticate as requested"); if (this->other_virtual_ip != NULL || - has_condition(this, COND_EAP_AUTHENTICATED)) + has_condition(this, COND_EAP_AUTHENTICATED) +#ifdef ME + /* if we are mediation server we too cannot reauth the IKE_SA */ + || this->is_mediation_server +#endif /* ME */ + ) { time_t now = time(NULL); @@ -1976,6 +1927,176 @@ static status_t reestablish(private_ike_sa_t *this) } /** + * Implementation of ike_sa_t.reestablish + */ +static status_t reestablish(private_ike_sa_t *this) +{ + ike_sa_t *new; + host_t *host; + action_t action; + iterator_t *iterator; + child_sa_t *child_sa; + child_cfg_t *child_cfg; + bool required = FALSE; + status_t status = FAILED; + + /* check if we have children to keep up at all*/ + iterator = create_child_sa_iterator(this); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + child_cfg = child_sa->get_config(child_sa); + if (this->state == IKE_DELETING) + { + action = child_cfg->get_close_action(child_cfg); + } + else + { + action = child_cfg->get_dpd_action(child_cfg); + } + switch (action) + { + case ACTION_RESTART: + case ACTION_ROUTE: + required = TRUE; + default: + break; + } + } + iterator->destroy(iterator); +#ifdef ME + /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */ + if (this->peer_cfg->is_mediation(this->peer_cfg)) + { + required = TRUE; + } +#endif /* ME */ + if (!required) + { + return FAILED; + } + + /* check if we are able to reestablish this IKE_SA */ + if (!this->ike_initiator && + (this->other_virtual_ip != NULL || + has_condition(this, COND_EAP_AUTHENTICATED) +#ifdef ME + || this->is_mediation_server +#endif /* ME */ + )) + { + DBG1(DBG_IKE, "unable to reestablish IKE_SA due asymetric setup"); + return FAILED; + } + + new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE); + new->set_peer_cfg(new, this->peer_cfg); + host = this->other_host; + new->set_other_host(new, host->clone(host)); + host = this->my_host; + new->set_my_host(new, host->clone(host)); + /* if we already have a virtual IP, we reuse it */ + host = this->my_virtual_ip; + if (host) + { + new->set_virtual_ip(new, TRUE, host); + } + +#ifdef ME + if (this->peer_cfg->is_mediation(this->peer_cfg)) + { + status = new->initiate(new, NULL); + } + else +#endif /* ME */ + { + iterator = create_child_sa_iterator(this); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + child_cfg = child_sa->get_config(child_sa); + if (this->state == IKE_DELETING) + { + action = child_cfg->get_close_action(child_cfg); + } + else + { + action = child_cfg->get_dpd_action(child_cfg); + } + switch (action) + { + case ACTION_RESTART: + DBG1(DBG_IKE, "restarting CHILD_SA %s", + child_cfg->get_name(child_cfg)); + child_cfg->get_ref(child_cfg); + status = new->initiate(new, child_cfg); + break; + case ACTION_ROUTE: + status = new->route(new, child_cfg); + break; + default: + continue; + } + if (status == DESTROY_ME) + { + break; + } + } + iterator->destroy(iterator); + } + + if (status == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new); + return FAILED; + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, new); + return SUCCESS; + } +} + +/** + * Implementation of ike_sa_t.retransmit. + */ +static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) +{ + this->time.outbound = time(NULL); + if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) + { + /* send a proper signal to brief interested bus listeners */ + switch (this->state) + { + case IKE_CONNECTING: + { + /* retry IKE_SA_INIT if we have multiple keyingtries */ + u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg); + this->keyingtry++; + if (tries == 0 || tries > this->keyingtry) + { + SIG(IKE_UP_FAILED, "peer not responding, trying again " + "(%d/%d) in background ", this->keyingtry + 1, tries); + reset(this); + return this->task_manager->initiate(this->task_manager); + } + SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding"); + break; + } + case IKE_DELETING: + SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding"); + break; + case IKE_REKEYING: + SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding"); + /* FALL */ + default: + reestablish(this); + break; + } + return DESTROY_ME; + } + return SUCCESS; +} + +/** * Implementation of ike_sa_t.set_auth_lifetime. */ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime) @@ -2009,6 +2130,14 @@ static status_t roam(private_ike_sa_t *this, bool address) host_t *me, *other; ike_mobike_t *mobike; + switch (this->state) + { + case IKE_CREATED: + case IKE_DELETING: + return SUCCESS; + default: + break; + } /* responder just updates the peer about changed address config */ if (!this->ike_sa_id->is_initiator(this->ike_sa_id)) { @@ -2048,9 +2177,9 @@ static status_t roam(private_ike_sa_t *this, bool address) this->task_manager->queue_task(this->task_manager, (task_t*)mobike); return this->task_manager->initiate(this->task_manager); } - DBG1(DBG_IKE, "reestablishing IKE_SA due address change"); - /* ... reestablish if not */ - return reestablish(this); + DBG1(DBG_IKE, "reauthenticating IKE_SA due address change"); + /* ... reauth if not */ + return reauth(this); } /** @@ -2097,6 +2226,18 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) { send_keepalive(this); } + +#ifdef ME + if (other->is_mediation_server) + { + act_as_mediation_server(this); + } + else if (other->server_reflexive_host) + { + this->server_reflexive_host = other->server_reflexive_host->clone( + other->server_reflexive_host); + } +#endif /* ME */ /* adopt all children */ while (other->child_sas->remove_last(other->child_sas, @@ -2270,6 +2411,8 @@ static void destroy(private_ike_sa_t *this) { this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy)); + this->task_manager->destroy(this->task_manager); + DESTROY_IF(this->crypter_in); DESTROY_IF(this->crypter_out); DESTROY_IF(this->signer_in); @@ -2278,6 +2421,7 @@ static void destroy(private_ike_sa_t *this) DESTROY_IF(this->child_prf); chunk_free(&this->skp_verify); chunk_free(&this->skp_build); + free(this->selected_proposal); if (this->my_virtual_ip) { @@ -2285,22 +2429,30 @@ static void destroy(private_ike_sa_t *this) this->my_virtual_ip); this->my_virtual_ip->destroy(this->my_virtual_ip); } - DESTROY_IF(this->other_virtual_ip); + if (this->other_virtual_ip) + { + if (this->peer_cfg && this->peer_cfg->get_pool(this->peer_cfg)) + { + charon->attributes->release_address(charon->attributes, + this->peer_cfg->get_pool(this->peer_cfg), + this->other_virtual_ip); + } + this->other_virtual_ip->destroy(this->other_virtual_ip); + } remove_dns_servers(this); this->dns_servers->destroy_offset(this->dns_servers, offsetof(host_t, destroy)); this->additional_addresses->destroy_offset(this->additional_addresses, offsetof(host_t, destroy)); -#ifdef P2P - if (this->peer_cfg && this->peer_cfg->is_mediation(this->peer_cfg) && - !this->ike_sa_id->is_initiator(this->ike_sa_id)) +#ifdef ME + if (this->is_mediation_server) { - /* mediation server */ charon->mediation_manager->remove(charon->mediation_manager, this->ike_sa_id); } DESTROY_IF(this->server_reflexive_host); -#endif /* P2P */ + chunk_free(&this->connect_id); +#endif /* ME */ DESTROY_IF(this->my_host); DESTROY_IF(this->other_host); @@ -2309,9 +2461,10 @@ static void destroy(private_ike_sa_t *this) DESTROY_IF(this->ike_cfg); DESTROY_IF(this->peer_cfg); + DESTROY_IF(this->my_auth); + DESTROY_IF(this->other_auth); this->ike_sa_id->destroy(this->ike_sa_id); - this->task_manager->destroy(this->task_manager); free(this); } @@ -2337,6 +2490,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.set_ike_cfg = (void (*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg; this->public.get_peer_cfg = (peer_cfg_t* (*)(ike_sa_t*))get_peer_cfg; this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg; + this->public.get_my_auth = (auth_info_t*(*)(ike_sa_t*))get_my_auth; + this->public.get_other_auth = (auth_info_t*(*)(ike_sa_t*))get_other_auth; this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id; this->public.get_my_host = (host_t* (*)(ike_sa_t*)) get_my_host; this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host; @@ -2347,14 +2502,13 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id; this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id; this->public.set_other_id = (void (*)(ike_sa_t*,identification_t*)) set_other_id; - this->public.get_other_ca = (ca_info_t* (*)(ike_sa_t*)) get_other_ca; - this->public.set_other_ca = (void (*)(ike_sa_t*,ca_info_t*)) set_other_ca; this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension; this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension; this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition; this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition; this->public.set_pending_updates = (void(*)(ike_sa_t*, u_int32_t updates))set_pending_updates; this->public.get_pending_updates = (u_int32_t(*)(ike_sa_t*))get_pending_updates; + this->public.is_ike_initiator = (bool (*)(ike_sa_t*))is_ike_initiator; this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator; this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address; this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit; @@ -2367,6 +2521,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.get_skp_verify = (chunk_t (*)(ike_sa_t *)) get_skp_verify; this->public.get_skp_build = (chunk_t (*)(ike_sa_t *)) get_skp_build; this->public.derive_keys = (status_t (*)(ike_sa_t *,proposal_t*,chunk_t,chunk_t,chunk_t,bool,prf_t*,prf_t*)) derive_keys; + this->public.get_proposal = (char* (*)(ike_sa_t*)) get_proposal; + this->public.set_proposal = (void (*)(ike_sa_t*,char*)) set_proposal; this->public.add_child_sa = (void (*)(ike_sa_t*,child_sa_t*)) add_child_sa; this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa; this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator; @@ -2374,6 +2530,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa; this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa; this->public.rekey = (status_t (*)(ike_sa_t*))rekey; + this->public.reauth = (status_t (*)(ike_sa_t*))reauth; this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish; this->public.set_auth_lifetime = (void(*)(ike_sa_t*, u_int32_t lifetime))set_auth_lifetime; this->public.roam = (status_t(*)(ike_sa_t*,bool))roam; @@ -2384,26 +2541,28 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip; this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip; this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server; -#ifdef P2P +#ifdef ME + this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server; this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host; this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host; + this->public.get_connect_id = (chunk_t (*)(ike_sa_t*)) get_connect_id; this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation; - this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,linked_list_t*)) initiate_mediated; + this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,chunk_t)) initiate_mediated; this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay; this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback; this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond; -#endif /* P2P */ +#endif /* ME */ /* initialize private fields */ this->ike_sa_id = ike_sa_id->clone(ike_sa_id); this->child_sas = linked_list_create(); - this->my_host = host_create_any(AF_INET); - this->other_host = host_create_any(AF_INET); + this->my_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT); + this->other_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT); this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty); this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty); - this->other_ca = NULL; this->extensions = 0; this->conditions = 0; + this->selected_proposal = NULL; this->crypter_in = NULL; this->crypter_out = NULL; this->signer_in = NULL; @@ -2420,6 +2579,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->time.delete = 0; this->ike_cfg = NULL; this->peer_cfg = NULL; + this->my_auth = auth_info_create(); + this->other_auth = auth_info_create(); this->task_manager = task_manager_create(&this->public); this->unique_id = ++unique_id; this->my_virtual_ip = NULL; @@ -2429,9 +2590,11 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->pending_updates = 0; this->keyingtry = 0; this->ike_initiator = FALSE; -#ifdef P2P +#ifdef ME + this->is_mediation_server = FALSE; this->server_reflexive_host = NULL; -#endif /* P2P */ + this->connect_id = chunk_empty; +#endif /* ME */ return &this->public; } diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index 975447d9c..0935f5d6b 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -1,12 +1,5 @@ -/** - * @file ike_sa.h - * - * @brief Interface of ike_sa_t. - * - */ - /* - * Copyright (C) 2006-2007 Tobias Brunner + * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -21,6 +14,13 @@ * 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. + * + * $Id: ike_sa.h 4086 2008-06-22 11:24:33Z andreas $ + */ + +/** + * @defgroup ike_sa ike_sa + * @{ @ingroup sa */ #ifndef IKE_SA_H_ @@ -38,44 +38,35 @@ typedef struct ike_sa_t ike_sa_t; #include <sa/ike_sa_id.h> #include <sa/child_sa.h> #include <sa/tasks/task.h> -#include <utils/randomizer.h> #include <crypto/prfs/prf.h> #include <crypto/crypters/crypter.h> #include <crypto/signers/signer.h> -#include <crypto/ca.h> #include <config/peer_cfg.h> #include <config/ike_cfg.h> +#include <credentials/auth_info.h> /** * Timeout in milliseconds after that a half open IKE_SA gets deleted. - * - * @ingroup sa */ #define HALF_OPEN_IKE_SA_TIMEOUT 30000 /** * Interval to send keepalives when NATed, in seconds. - * - * @ingroup sa */ #define KEEPALIVE_INTERVAL 20 /** * After which time rekeying should be retried if it failed, in seconds. - * - * @ingroup sa */ #define RETRY_INTERVAL 30 /** * Jitter to subtract from RETRY_INTERVAL to randomize rekey retry. - * - * @ingroup sa */ #define RETRY_JITTER 20 /** - * @brief Extensions (or optional features) the peer supports + * Extensions (or optional features) the peer supports */ enum ike_extension_t { @@ -88,10 +79,15 @@ enum ike_extension_t { * peer supports MOBIKE (RFC4555) */ EXT_MOBIKE = (1<<1), + + /** + * peer supports HTTP cert lookups as specified in RFC4306 + */ + EXT_HASH_AND_URL = (1<<2), }; /** - * @brief Conditions of an IKE_SA, change during its lifetime + * Conditions of an IKE_SA, change during its lifetime */ enum ike_condition_t { @@ -119,6 +115,11 @@ enum ike_condition_t { * peer has ben authenticated using EAP */ COND_EAP_AUTHENTICATED = (1<<4), + + /** + * received a certificate request from the peer + */ + COND_CERTREQ_SEEN = (1<<5), }; /** @@ -138,7 +139,7 @@ enum statistic_t { }; /** - * @brief State of an IKE_SA. + * State of an IKE_SA. * * An IKE_SA passes various states in its lifetime. A newly created * SA is in the state CREATED. @@ -173,8 +174,6 @@ enum statistic_t { X / \ @endverbatim - * - * @ingroup sa */ enum ike_sa_state_t { @@ -210,365 +209,342 @@ enum ike_sa_state_t { extern enum_name_t *ike_sa_state_names; /** - * @brief Class ike_sa_t representing an IKE_SA. + * Class ike_sa_t representing an IKE_SA. * * An IKE_SA contains crypto information related to a connection * with a peer. It contains multiple IPsec CHILD_SA, for which * it is responsible. All traffic is handled by an IKE_SA, using * the task manager and its tasks. - * - * @b Constructors: - * - ike_sa_create() - * - * @ingroup sa */ struct ike_sa_t { /** - * @brief Get the id of the SA. + * Get the id of the SA. * * Returned ike_sa_id_t object is not getting cloned! * - * @param this calling object * @return ike_sa's ike_sa_id_t */ ike_sa_id_t* (*get_id) (ike_sa_t *this); /** - * @brief Get the numerical ID uniquely defining this IKE_SA. + * Get the numerical ID uniquely defining this IKE_SA. * - * @param this calling object * @return unique ID */ u_int32_t (*get_unique_id) (ike_sa_t *this); /** - * @brief Get the state of the IKE_SA. + * Get the state of the IKE_SA. * - * @param this calling object * @return state of the IKE_SA */ ike_sa_state_t (*get_state) (ike_sa_t *this); /** - * @brief Set the state of the IKE_SA. + * Set the state of the IKE_SA. * - * @param this calling object * @param state state to set for the IKE_SA */ void (*set_state) (ike_sa_t *this, ike_sa_state_t ike_sa); /** - * @brief Get the name of the connection this IKE_SA uses. + * Get the name of the connection this IKE_SA uses. * - * @param this calling object * @return name */ char* (*get_name) (ike_sa_t *this); /** - * @brief Get statistic values from the IKE_SA. + * Get statistic values from the IKE_SA. * - * @param this calling object * @param kind kind of requested value * @return value as integer */ u_int32_t (*get_statistic)(ike_sa_t *this, statistic_t kind); /** - * @brief Get the own host address. + * Get the own host address. * - * @param this calling object * @return host address */ host_t* (*get_my_host) (ike_sa_t *this); /** - * @brief Set the own host address. + * Set the own host address. * - * @param this calling object * @param me host address */ void (*set_my_host) (ike_sa_t *this, host_t *me); /** - * @brief Get the other peers host address. + * Get the other peers host address. * - * @param this calling object * @return host address */ host_t* (*get_other_host) (ike_sa_t *this); /** - * @brief Set the others host address. + * Set the others host address. * - * @param this calling object * @param other host address */ void (*set_other_host) (ike_sa_t *this, host_t *other); /** - * @brief Update the IKE_SAs host. + * Update the IKE_SAs host. * * Hosts may be NULL to use current host. * - * @param this calling object * @param me new local host address, or NULL * @param other new remote host address, or NULL */ void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other); /** - * @brief Get the own identification. + * Get the own identification. * - * @param this calling object * @return identification */ identification_t* (*get_my_id) (ike_sa_t *this); /** - * @brief Set the own identification. + * Set the own identification. * - * @param this calling object * @param me identification */ void (*set_my_id) (ike_sa_t *this, identification_t *me); /** - * @brief Get the other peer's identification. + * Get the other peer's identification. * - * @param this calling object * @return identification */ identification_t* (*get_other_id) (ike_sa_t *this); /** - * @brief Set the other peer's identification. + * Set the other peer's identification. * - * @param this calling object * @param other identification */ void (*set_other_id) (ike_sa_t *this, identification_t *other); /** - * @brief Get the other peer's certification authority + * Get the config used to setup this IKE_SA. * - * @param this calling object - * @return ca_info_t record of other ca - */ - ca_info_t* (*get_other_ca) (ike_sa_t *this); - - /** - * @brief Set the other peer's certification authority - * - * @param this calling object - * @param other_ca ca_info_t record of other ca - */ - void (*set_other_ca) (ike_sa_t *this, ca_info_t *other_ca); - - /** - * @brief Get the config used to setup this IKE_SA. - * - * @param this calling object * @return ike_config */ ike_cfg_t* (*get_ike_cfg) (ike_sa_t *this); /** - * @brief Set the config to setup this IKE_SA. + * Set the config to setup this IKE_SA. * - * @param this calling object * @param config ike_config to use */ void (*set_ike_cfg) (ike_sa_t *this, ike_cfg_t* config); /** - * @brief Get the peer config used by this IKE_SA. + * Get the peer config used by this IKE_SA. * - * @param this calling object * @return peer_config */ peer_cfg_t* (*get_peer_cfg) (ike_sa_t *this); /** - * @brief Set the peer config to use with this IKE_SA. + * Set the peer config to use with this IKE_SA. * - * @param this calling object * @param config peer_config to use */ void (*set_peer_cfg) (ike_sa_t *this, peer_cfg_t *config); /** - * @brief Add an additional address for the peer. + * Get authentication/authorization info for local peer. + * + * @return auth_info for me + */ + auth_info_t* (*get_my_auth)(ike_sa_t *this); + + /** + * Get authentication/authorization info for remote peer. + * + * @return auth_info for me + */ + auth_info_t* (*get_other_auth)(ike_sa_t *this); + + /** + * Add an additional address for the peer. * * In MOBIKE, a peer may transmit additional addresses where it is * reachable. These are stored in the IKE_SA. * The own list of addresses is not stored, they are queried from * the kernel when required. * - * @param this calling object * @param host host to add to list */ void (*add_additional_address)(ike_sa_t *this, host_t *host); /** - * @brief Create an iterator over all additional addresses of the peer. + * Create an iterator over all additional addresses of the peer. * - * @param this calling object * @return iterator over addresses */ iterator_t* (*create_additional_address_iterator)(ike_sa_t *this); /** - * @brief Enable an extension the peer supports. + * Enable an extension the peer supports. * * If support for an IKE extension is detected, this method is called * to enable that extension and behave accordingly. * - * @param this calling object * @param extension extension to enable */ void (*enable_extension)(ike_sa_t *this, ike_extension_t extension); /** - * @brief Check if the peer supports an extension. + * Check if the peer supports an extension. * - * @param this calling object * @param extension extension to check for support * @return TRUE if peer supports it, FALSE otherwise */ bool (*supports_extension)(ike_sa_t *this, ike_extension_t extension); /** - * @brief Enable/disable a condition flag for this IKE_SA. + * Enable/disable a condition flag for this IKE_SA. * - * @param this calling object * @param condition condition to enable/disable * @param enable TRUE to enable condition, FALSE to disable */ void (*set_condition) (ike_sa_t *this, ike_condition_t condition, bool enable); /** - * @brief Check if a condition flag is set. + * Check if a condition flag is set. * - * @param this calling object * @param condition condition to check * @return TRUE if condition flag set, FALSE otherwise */ bool (*has_condition) (ike_sa_t *this, ike_condition_t condition); /** - * @brief Get the number of queued MOBIKE address updates. + * Get the number of queued MOBIKE address updates. * - * @param this calling object * @return number of pending updates */ u_int32_t (*get_pending_updates)(ike_sa_t *this); /** - * @brief Set the number of queued MOBIKE address updates. + * Set the number of queued MOBIKE address updates. * - * @param this calling object * @param updates number of pending updates */ void (*set_pending_updates)(ike_sa_t *this, u_int32_t updates); + + /** + * Check if we are the original initiator of this IKE_SA (rekeying does not + * change this flag). + */ + bool (*is_ike_initiator)(ike_sa_t *this); + -#ifdef P2P +#ifdef ME /** - * @brief Get the server reflexive host. + * Activate mediation server functionality for this IKE_SA. + */ + void (*act_as_mediation_server) (ike_sa_t *this); + + /** + * Get the server reflexive host. * - * @param this calling object * @return server reflexive host */ host_t* (*get_server_reflexive_host) (ike_sa_t *this); /** - * @brief Set the server reflexive host. + * Set the server reflexive host. * - * @param this calling object * @param host server reflexive host */ void (*set_server_reflexive_host) (ike_sa_t *this, host_t *host); /** - * @brief Initiate the mediation of a mediated connection (i.e. initiate a - * P2P_CONNECT exchange). + * Get the connect ID. + * + * @return connect ID + */ + chunk_t (*get_connect_id) (ike_sa_t *this); + + /** + * Initiate the mediation of a mediated connection (i.e. initiate a + * ME_CONNECT exchange). * - * @param this calling object * @param mediated_cfg peer_cfg of the mediated connection * @return - * - SUCCESS if initialization started - * - DESTROY_ME if initialization failed + * - SUCCESS if initialization started + * - DESTROY_ME if initialization failed */ status_t (*initiate_mediation) (ike_sa_t *this, peer_cfg_t *mediated_cfg); /** - * @brief Initiate the mediated connection + * Initiate the mediated connection * - * @param this calling object * @param me local endpoint (gets cloned) * @param other remote endpoint (gets cloned) - * @param childs linked list of child_cfg_t of CHILD_SAs (gets cloned) + * @param connect_id connect ID (gets cloned) * @return - * - SUCCESS if initialization started - * - DESTROY_ME if initialization failed + * - SUCCESS if initialization started + * - DESTROY_ME if initialization failed */ status_t (*initiate_mediated) (ike_sa_t *this, host_t *me, host_t *other, - linked_list_t *childs); + chunk_t connect_id); /** - * @brief Relay data from one peer to another (i.e. initiate a - * P2P_CONNECT exchange). + * Relay data from one peer to another (i.e. initiate a + * ME_CONNECT exchange). * * Data is cloned. * - * @param this calling object * @param requester ID of the requesting peer - * @param session_id data of the P2P_SESSIONID payload - * @param session_key data of the P2P_SESSIONKEY payload + * @param connect_id data of the ME_CONNECTID payload + * @param connect_key data of the ME_CONNECTKEY payload * @param endpoints endpoints * @param response TRUE if this is a response * @return - * - SUCCESS if relay started - * - DESTROY_ME if relay failed + * - SUCCESS if relay started + * - DESTROY_ME if relay failed */ - status_t (*relay) (ike_sa_t *this, identification_t *requester, chunk_t session_id, - chunk_t session_key, linked_list_t *endpoints, bool response); + status_t (*relay) (ike_sa_t *this, identification_t *requester, chunk_t connect_id, + chunk_t connect_key, linked_list_t *endpoints, bool response); /** - * @brief Send a callback to a peer. + * Send a callback to a peer. * * Data is cloned. * - * @param this calling object * @param peer_id ID of the other peer * @return - * - SUCCESS if response started - * - DESTROY_ME if response failed + * - SUCCESS if response started + * - DESTROY_ME if response failed */ status_t (*callback) (ike_sa_t *this, identification_t *peer_id); /** - * @brief Respond to a P2P_CONNECT request. + * Respond to a ME_CONNECT request. * * Data is cloned. * - * @param this calling object * @param peer_id ID of the other peer - * @param session_id the session ID supplied by the initiator + * @param connect_id the connect ID supplied by the initiator * @return - * - SUCCESS if response started - * - DESTROY_ME if response failed + * - SUCCESS if response started + * - DESTROY_ME if response failed */ - status_t (*respond) (ike_sa_t *this, identification_t *peer_id, chunk_t session_id); -#endif /* P2P */ + status_t (*respond) (ike_sa_t *this, identification_t *peer_id, chunk_t connect_id); +#endif /* ME */ /** - * @brief Initiate a new connection. + * Initiate a new connection. * * The configs are owned by the IKE_SA after the call. * - * @param this calling object * @param child_cfg child config to create CHILD from * @return * - SUCCESS if initialization started @@ -577,12 +553,11 @@ struct ike_sa_t { status_t (*initiate) (ike_sa_t *this, child_cfg_t *child_cfg); /** - * @brief Route a policy in the kernel. + * Route a policy in the kernel. * * Installs the policies in the kernel. If traffic matches, * the kernel requests connection setup from the IKE_SA via acquire(). * - * @param this calling object * @param child_cfg child config to route * @return * - SUCCESS if routed successfully @@ -591,9 +566,8 @@ struct ike_sa_t { status_t (*route) (ike_sa_t *this, child_cfg_t *child_cfg); /** - * @brief Unroute a policy in the kernel previously routed. + * Unroute a policy in the kernel previously routed. * - * @param this calling object * @param reqid reqid of CHILD_SA to unroute * @return * - SUCCESS if route removed @@ -603,12 +577,11 @@ struct ike_sa_t { status_t (*unroute) (ike_sa_t *this, u_int32_t reqid); /** - * @brief Acquire connection setup for an installed kernel policy. + * Acquire connection setup for an installed kernel policy. * * If an installed policy raises an acquire, the kernel calls * this function to establish the CHILD_SA (and maybe the IKE_SA). * - * @param this calling object * @param reqid reqid of the CHILD_SA the policy belongs to. * @return * - SUCCESS if initialization started @@ -617,13 +590,12 @@ struct ike_sa_t { status_t (*acquire) (ike_sa_t *this, u_int32_t reqid); /** - * @brief Initiates the deletion of an IKE_SA. + * Initiates the deletion of an IKE_SA. * * Sends a delete message to the remote peer and waits for * its response. If the response comes in, or a timeout occurs, * the IKE SA gets deleted. * - * @param this calling object * @return * - SUCCESS if deletion is initialized * - INVALID_STATE, if the IKE_SA is not in @@ -633,7 +605,7 @@ struct ike_sa_t { status_t (*delete) (ike_sa_t *this); /** - * @brief Update IKE_SAs after network interfaces have changed. + * Update IKE_SAs after network interfaces have changed. * * Whenever the network interface configuration changes, the kernel * interface calls roam() on each IKE_SA. The IKE_SA then checks if @@ -641,21 +613,19 @@ struct ike_sa_t { * If MOBIKE is supported, addresses are updated; If not, the tunnel is * restarted. * - * @param this calling object * @param address TRUE if address list changed, FALSE otherwise * @return SUCCESS, FAILED, DESTROY_ME */ status_t (*roam)(ike_sa_t *this, bool address); /** - * @brief Processes a incoming IKEv2-Message. + * Processes a incoming IKEv2-Message. * * Message processing may fail. If a critical failure occurs, * process_message() return DESTROY_ME. Then the caller must * destroy the IKE_SA immediatly, as it is unusable. * - * @param this calling object - * @param message message to process + * @param message message to process * @return * - SUCCESS * - FAILED @@ -664,12 +634,11 @@ struct ike_sa_t { status_t (*process_message) (ike_sa_t *this, message_t *message); /** - * @brief Generate a IKE message to send it to the peer. + * Generate a IKE message to send it to the peer. * * This method generates all payloads in the message and encrypts/signs * the packet. * - * @param this calling object * @param message message to generate * @param packet generated output packet * @return @@ -681,9 +650,8 @@ struct ike_sa_t { packet_t **packet); /** - * @brief Retransmits a request. + * Retransmits a request. * - * @param this calling object * @param message_id ID of the request to retransmit * @return * - SUCCESS @@ -692,13 +660,12 @@ struct ike_sa_t { status_t (*retransmit) (ike_sa_t *this, u_int32_t message_id); /** - * @brief Sends a DPD request to the peer. + * Sends a DPD request to the peer. * * To check if a peer is still alive, periodic * empty INFORMATIONAL messages are sent if no * other traffic was received. * - * @param this calling object * @return * - SUCCESS * - DESTROY_ME, if peer did not respond @@ -706,19 +673,17 @@ struct ike_sa_t { status_t (*send_dpd) (ike_sa_t *this); /** - * @brief Sends a keep alive packet. + * Sends a keep alive packet. * * To refresh NAT tables in a NAT router * between the peers, periodic empty * UDP packets are sent if no other traffic * was sent. - * - * @param this calling object */ void (*send_keepalive) (ike_sa_t *this); /** - * @brief Derive all keys and create the transforms for IKE communication. + * Derive all keys and create the transforms for IKE communication. * * Keys are derived using the diffie hellman secret, nonces and internal * stored SPIs. @@ -726,7 +691,6 @@ struct ike_sa_t { * existing IKE_SA (rekeying). The SK_d key from the old IKE_SA * is included in the derivation process. * - * @param this calling object * @param proposal proposal which contains algorithms to use * @param secret secret derived from DH exchange, gets freed * @param nonce_i initiators nonce @@ -740,49 +704,58 @@ struct ike_sa_t { bool initiator, prf_t *child_prf, prf_t *old_prf); /** - * @brief Get a multi purpose prf for the negotiated PRF function. + * Get the selected IKE proposal string + * + * @return string describing the selected IKE proposal + */ + char* (*get_proposal)(ike_sa_t *this); + + /** + * Set the selected IKE proposal string for status information purposes + * (the "%P" printf format handler is used) + * + * @param proposal string describing the selected IKE proposal + */ + void (*set_proposal)(ike_sa_t *this, char *proposal); + + /** + * Get a multi purpose prf for the negotiated PRF function. * - * @param this calling object * @return pointer to prf_t object */ prf_t *(*get_prf) (ike_sa_t *this); /** - * @brief Get the prf-object, which is used to derive keys for child SAs. + * Get the prf-object, which is used to derive keys for child SAs. * - * @param this calling object * @return pointer to prf_t object */ prf_t *(*get_child_prf) (ike_sa_t *this); /** - * @brief Get the key to build outgoing authentication data. + * Get the key to build outgoing authentication data. * - * @param this calling object * @return pointer to prf_t object */ chunk_t (*get_skp_build) (ike_sa_t *this); /** - * @brief Get the key to verify incoming authentication data. + * Get the key to verify incoming authentication data. * - * @param this calling object * @return pointer to prf_t object */ chunk_t (*get_skp_verify) (ike_sa_t *this); /** - * @brief Associates a child SA to this IKE SA + * Associates a child SA to this IKE SA * - * @param this calling object * @param child_sa child_sa to add */ void (*add_child_sa) (ike_sa_t *this, child_sa_t *child_sa); /** - * @brief Get a CHILD_SA identified by protocol and SPI. + * Get a CHILD_SA identified by protocol and SPI. * - * @param this calling object * @param protocol protocol of the SA * @param spi SPI of the CHILD_SA * @param inbound TRUE if SPI is inbound, FALSE if outbound @@ -792,19 +765,17 @@ struct ike_sa_t { u_int32_t spi, bool inbound); /** - * @brief Create an iterator over all CHILD_SAs. + * Create an iterator over all CHILD_SAs. * - * @param this calling object * @return iterator */ iterator_t* (*create_child_sa_iterator) (ike_sa_t *this); /** - * @brief Rekey the CHILD SA with the specified reqid. + * Rekey the CHILD SA with the specified reqid. * * Looks for a CHILD SA owned by this IKE_SA, and start the rekeing. * - * @param this calling object * @param protocol protocol of the SA * @param spi inbound SPI of the CHILD_SA * @return @@ -814,13 +785,12 @@ struct ike_sa_t { status_t (*rekey_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi); /** - * @brief Close the CHILD SA with the specified protocol/SPI. + * Close the CHILD SA with the specified protocol/SPI. * * Looks for a CHILD SA owned by this IKE_SA, deletes it and * notify's the remote peer about the delete. The associated * states and policies in the kernel get deleted, if they exist. * - * @param this calling object * @param protocol protocol of the SA * @param spi inbound SPI of the CHILD_SA * @return @@ -830,11 +800,10 @@ struct ike_sa_t { status_t (*delete_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi); /** - * @brief Destroy a CHILD SA with the specified protocol/SPI. + * Destroy a CHILD SA with the specified protocol/SPI. * * Looks for a CHILD SA owned by this IKE_SA and destroys it. * - * @param this calling object * @param protocol protocol of the SA * @param spi inbound SPI of the CHILD_SA * @return @@ -844,99 +813,98 @@ struct ike_sa_t { status_t (*destroy_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi); /** - * @brief Rekey the IKE_SA. + * Rekey the IKE_SA. * * Sets up a new IKE_SA, moves all CHILDs to it and deletes this IKE_SA. * - * @param this calling object * @return - SUCCESS, if IKE_SA rekeying initiated */ status_t (*rekey) (ike_sa_t *this); /** - * @brief Restablish the IKE_SA. + * Reauthenticate the IKE_SA. * * Create a completely new IKE_SA with authentication, recreates all children * within the IKE_SA, closes this IKE_SA. * - * @param this calling object + * @return DESTROY_ME to destroy the IKE_SA + */ + status_t (*reauth) (ike_sa_t *this); + + /** + * Restablish the IKE_SA. + * + * Reestablish an IKE_SA after it has been closed. + * * @return DESTROY_ME to destroy the IKE_SA */ status_t (*reestablish) (ike_sa_t *this); /** - * @brief Set the lifetime limit received from a AUTH_LIFETIME notify. + * Set the lifetime limit received from a AUTH_LIFETIME notify. * - * @param this calling object * @param lifetime lifetime in seconds */ void (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime); /** - * @brief Set the virtual IP to use for this IKE_SA and its children. + * Set the virtual IP to use for this IKE_SA and its children. * * The virtual IP is assigned per IKE_SA, not per CHILD_SA. It has the same * lifetime as the IKE_SA. * - * @param this calling object + * @param local TRUE to set local address, FALSE for remote + * @param ip IP to set as virtual IP */ void (*set_virtual_ip) (ike_sa_t *this, bool local, host_t *ip); /** - * @brief Get the virtual IP configured. + * Get the virtual IP configured. * - * @param this calling object * @param local TRUE to get local virtual IP, FALSE for remote + * @return host_t *virtual IP */ host_t* (*get_virtual_ip) (ike_sa_t *this, bool local); /** - * @brief Add a DNS server to the system. + * Add a DNS server to the system. * * An IRAS may send a DNS server. To use it, it is installed on the * system. The DNS entry has a lifetime until the IKE_SA gets closed. * - * @param this calling object * @param dns DNS server to install on the system */ void (*add_dns_server) (ike_sa_t *this, host_t *dns); /** - * @brief Inherit all attributes of other to this after rekeying. + * Inherit all attributes of other to this after rekeying. * * When rekeying is completed, all CHILD_SAs, the virtual IP and all * outstanding tasks are moved from other to this. * As this call may initiate inherited tasks, a status is returned. * - * @param this calling object * @param other other task to inherit from * @return DESTROY_ME if initiation of inherited task failed */ status_t (*inherit) (ike_sa_t *this, ike_sa_t *other); /** - * @brief Reset the IKE_SA, useable when initiating fails - * - * @param this calling object + * Reset the IKE_SA, useable when initiating fails */ void (*reset) (ike_sa_t *this); /** - * @brief Destroys a ike_sa_t object. - * - * @param this calling object + * Destroys a ike_sa_t object. */ void (*destroy) (ike_sa_t *this); }; /** - * @brief Creates an ike_sa_t object with a specific ID. + * Creates an ike_sa_t object with a specific ID. * * @param ike_sa_id ike_sa_id_t object to associate with new IKE_SA * @return ike_sa_t object - * - * @ingroup sa */ ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id); -#endif /* IKE_SA_H_ */ +#endif /* IKE_SA_H_ @} */ diff --git a/src/charon/sa/ike_sa_id.c b/src/charon/sa/ike_sa_id.c index a838c0b8a..e012d5944 100644 --- a/src/charon/sa/ike_sa_id.c +++ b/src/charon/sa/ike_sa_id.c @@ -1,10 +1,3 @@ -/** - * @file ike_sa_id.c - * - * @brief Implementation of ike_sa_id_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,9 +12,10 @@ * 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. + * + * $Id: ike_sa_id.c 3589 2008-03-13 14:14:44Z martin $ */ - #include "ike_sa_id.h" #include <stdio.h> diff --git a/src/charon/sa/ike_sa_id.h b/src/charon/sa/ike_sa_id.h index 0606b7222..652c968b6 100644 --- a/src/charon/sa/ike_sa_id.h +++ b/src/charon/sa/ike_sa_id.h @@ -1,10 +1,3 @@ -/** - * @file ike_sa_id.h - * - * @brief Interface of ike_sa_id_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,8 +12,14 @@ * 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. + * + * $Id: ike_sa_id.h 3589 2008-03-13 14:14:44Z martin $ */ +/** + * @defgroup ike_sa_id ike_sa_id + * @{ @ingroup sa + */ #ifndef IKE_SA_ID_H_ #define IKE_SA_ID_H_ @@ -29,119 +28,101 @@ typedef struct ike_sa_id_t ike_sa_id_t; #include <library.h> - /** - * @brief An object of type ike_sa_id_t is used to identify an IKE_SA. + * An object of type ike_sa_id_t is used to identify an IKE_SA. * * An IKE_SA is identified by its initiator and responder spi's. * Additionaly it contains the role of the actual running IKEv2-Daemon * for the specific IKE_SA (original initiator or responder). - * - * @b Constructors: - * - ike_sa_id_create() - * - * @ingroup sa */ struct ike_sa_id_t { /** - * @brief Set the SPI of the responder. + * Set the SPI of the responder. * * This function is called when a request or reply of a IKE_SA_INIT is received. * - * @param this calling object * @param responder_spi SPI of responder to set */ void (*set_responder_spi) (ike_sa_id_t *this, u_int64_t responder_spi); /** - * @brief Set the SPI of the initiator. + * Set the SPI of the initiator. * - * @param this calling object * @param initiator_spi SPI to set */ void (*set_initiator_spi) (ike_sa_id_t *this, u_int64_t initiator_spi); /** - * @brief Get the initiator SPI. + * Get the initiator SPI. * - * @param this calling object * @return SPI of the initiator */ u_int64_t (*get_initiator_spi) (ike_sa_id_t *this); /** - * @brief Get the responder SPI. + * Get the responder SPI. * - * @param this calling object * @return SPI of the responder */ u_int64_t (*get_responder_spi) (ike_sa_id_t *this); /** - * @brief Check if two ike_sa_id_t objects are equal. + * Check if two ike_sa_id_t objects are equal. * * Two ike_sa_id_t objects are equal if both SPI values and the role matches. * - * @param this calling object * @param other ike_sa_id_t object to check if equal * @return TRUE if given ike_sa_id_t are equal, FALSE otherwise */ bool (*equals) (ike_sa_id_t *this, ike_sa_id_t *other); /** - * @brief Replace all values of a given ike_sa_id_t object with values. + * Replace all values of a given ike_sa_id_t object with values. * from another ike_sa_id_t object. * * After calling this function, both objects are equal. * - * @param this calling object * @param other ike_sa_id_t object from which values will be taken */ void (*replace_values) (ike_sa_id_t *this, ike_sa_id_t *other); /** - * @brief Get the initiator flag. + * Get the initiator flag. * - * @param this calling object * @return TRUE if we are the original initator */ bool (*is_initiator) (ike_sa_id_t *this); /** - * @brief Switche the original initiator flag. + * Switche the original initiator flag. * - * @param this calling object * @return TRUE if we are the original initator after switch, FALSE otherwise */ bool (*switch_initiator) (ike_sa_id_t *this); /** - * @brief Clones a given ike_sa_id_t object. + * Clones a given ike_sa_id_t object. * - * @param this calling object * @return cloned ike_sa_id_t object */ ike_sa_id_t *(*clone) (ike_sa_id_t *this); /** - * @brief Destroys an ike_sa_id_t object. - * - * @param this calling object + * Destroys an ike_sa_id_t object. */ void (*destroy) (ike_sa_id_t *this); }; /** - * @brief Creates an ike_sa_id_t object with specific SPI's and defined role. + * Creates an ike_sa_id_t object with specific SPI's and defined role. * * @param initiator_spi initiators SPI * @param responder_spi responders SPI * @param is_initiaor TRUE if we are the original initiator * @return ike_sa_id_t object - * - * @ingroup sa */ -ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, bool is_initiaor); +ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi, + bool is_initiaor); -#endif /*IKE_SA_ID_H_*/ +#endif /*IKE_SA_ID_H_ @} */ diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index 5e7f78af0..9c1b2d413 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -1,10 +1,3 @@ -/** - * @file ike_sa_manager.c - * - * @brief Implementation of ike_sa_mananger_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: ike_sa_manager.c 4044 2008-06-06 15:05:54Z martin $ */ #include <pthread.h> @@ -30,6 +25,7 @@ #include <sa/ike_sa_id.h> #include <bus/bus.h> #include <utils/linked_list.h> +#include <crypto/hashers/hasher.h> typedef struct entry_t entry_t; @@ -79,6 +75,11 @@ struct entry_t { chunk_t init_hash; /** + * remote host address, required for DoS detection + */ + host_t *other; + + /** * message ID currently processing, if any */ u_int32_t message_id; @@ -93,6 +94,7 @@ static status_t entry_destroy(entry_t *this) this->ike_sa->destroy(this->ike_sa); this->ike_sa_id->destroy(this->ike_sa_id); chunk_free(&this->init_hash); + DESTROY_IF(this->other); free(this); return SUCCESS; } @@ -113,6 +115,7 @@ static entry_t *entry_create(ike_sa_id_t *ike_sa_id) this->driveout_waiting_threads = FALSE; this->message_id = -1; this->init_hash = chunk_empty; + this->other = NULL; /* ike_sa_id is always cloned */ this->ike_sa_id = ike_sa_id->clone(ike_sa_id); @@ -146,9 +149,9 @@ struct private_ike_sa_manager_t { linked_list_t *ike_sa_list; /** - * A randomizer, to get random SPIs for our side + * RNG to get random SPIs for our side */ - randomizer_t *randomizer; + rng_t *rng; /** * SHA1 hasher for IKE_SA_INIT retransmit detection @@ -159,20 +162,20 @@ struct private_ike_sa_manager_t { /** * Implementation of private_ike_sa_manager_t.get_entry_by_id. */ -static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, entry_t **entry) +static status_t get_entry_by_id(private_ike_sa_manager_t *this, + ike_sa_id_t *ike_sa_id, entry_t **entry) { - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; + enumerator_t *enumerator; entry_t *current; status_t status; - /* create iterator over list of ike_sa's */ - iterator = list->create_iterator(list, TRUE); + /* create enumerator over list of ike_sa's */ + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); /* default status */ status = NOT_FOUND; - while (iterator->iterate(iterator, (void**)¤t)) + while (enumerator->enumerate(enumerator, ¤t)) { if (current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id)) { @@ -198,26 +201,26 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return status; } /** * Implementation of private_ike_sa_manager_t.get_entry_by_sa. */ -static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa, entry_t **entry) +static status_t get_entry_by_sa(private_ike_sa_manager_t *this, + ike_sa_t *ike_sa, entry_t **entry) { - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; + enumerator_t *enumerator; entry_t *current; status_t status; - iterator = list->create_iterator(list, TRUE); + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); /* default status */ status = NOT_FOUND; - while (iterator->iterate(iterator, (void**)¤t)) + while (enumerator->enumerate(enumerator, ¤t)) { /* only pointers are compared */ if (current->ike_sa == ike_sa) @@ -228,7 +231,7 @@ static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return status; } @@ -238,16 +241,15 @@ static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa */ static status_t delete_entry(private_ike_sa_manager_t *this, entry_t *entry) { - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; + enumerator_t *enumerator; entry_t *current; status_t status; - iterator = list->create_iterator(list, TRUE); + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); status = NOT_FOUND; - while (iterator->iterate(iterator, (void**)¤t)) + while (enumerator->enumerate(enumerator, ¤t)) { if (current == entry) { @@ -263,13 +265,13 @@ static status_t delete_entry(private_ike_sa_manager_t *this, entry_t *entry) } DBG2(DBG_MGR, "found entry by pointer, deleting it"); - iterator->remove(iterator); + this->ike_sa_list->remove_at(this->ike_sa_list, enumerator); entry_destroy(entry); status = SUCCESS; break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return status; } @@ -309,8 +311,7 @@ static u_int64_t get_next_spi(private_ike_sa_manager_t *this) { u_int64_t spi; - this->randomizer->get_pseudo_random_bytes(this->randomizer, sizeof(spi), - (u_int8_t*)&spi); + this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi); return spi; } @@ -386,7 +387,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, message->get_exchange_type(message) == IKE_SA_INIT) { /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */ - iterator_t *iterator; + enumerator_t *enumerator; chunk_t data, hash; data = message->get_packet_data(message); @@ -394,14 +395,14 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, chunk_free(&data); pthread_mutex_lock(&this->mutex); - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { if (chunk_equals(hash, entry->init_hash)) { if (entry->message_id == 0) { - iterator->destroy(iterator); + enumerator->destroy(enumerator); pthread_mutex_unlock(&this->mutex); chunk_free(&hash); id->destroy(id); @@ -418,7 +419,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); pthread_mutex_unlock(&this->mutex); if (ike_sa == NULL) @@ -488,7 +489,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, peer_cfg_t *peer_cfg) { - iterator_t *iterator; + enumerator_t *enumerator; entry_t *entry; ike_sa_t *ike_sa = NULL; identification_t *my_id, *other_id; @@ -496,65 +497,70 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, ike_cfg_t *ike_cfg; ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - my_host = ike_cfg->get_my_host(ike_cfg); - other_host = ike_cfg->get_other_host(ike_cfg); my_id = peer_cfg->get_my_id(peer_cfg); other_id = peer_cfg->get_other_id(peer_cfg); + my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0); + other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0); pthread_mutex_lock(&(this->mutex)); - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) + if (my_host && other_host) { - identification_t *found_my_id, *found_other_id; - host_t *found_my_host, *found_other_host; - int wc; - - if (!wait_for_entry(this, entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { - continue; - } + identification_t *found_my_id, *found_other_id; + host_t *found_my_host, *found_other_host; - if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING) - { - /* skip IKE_SA which are not useable */ - continue; - } + if (!wait_for_entry(this, entry)) + { + continue; + } - found_my_id = entry->ike_sa->get_my_id(entry->ike_sa); - found_other_id = entry->ike_sa->get_other_id(entry->ike_sa); - found_my_host = entry->ike_sa->get_my_host(entry->ike_sa); - found_other_host = entry->ike_sa->get_other_host(entry->ike_sa); + if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING) + { + /* skip IKE_SA which are not useable */ + continue; + } - if (found_my_id->get_type(found_my_id) == ID_ANY && - found_other_id->get_type(found_other_id) == ID_ANY) - { - /* IKE_SA has no IDs yet, so we can't use it */ - continue; - } - DBG2(DBG_MGR, "candidate IKE_SA for \n\t%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]", - my_host, my_id, other_host, other_id, - found_my_host, found_my_id, found_other_host, found_other_id); - /* compare ID and hosts. Supplied ID may contain wildcards, and IP - * may be %any. */ - if ((my_host->is_anyaddr(my_host) || - my_host->ip_equals(my_host, found_my_host)) && - (other_host->is_anyaddr(other_host) || - other_host->ip_equals(other_host, found_other_host)) && - found_my_id->matches(found_my_id, my_id, &wc) && - found_other_id->matches(found_other_id, other_id, &wc) && - streq(peer_cfg->get_name(peer_cfg), - entry->ike_sa->get_name(entry->ike_sa))) - { - /* looks good, we take this one */ - DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]", - my_host, my_id, other_host, other_id); - entry->checked_out = TRUE; - ike_sa = entry->ike_sa; - break; + found_my_id = entry->ike_sa->get_my_id(entry->ike_sa); + found_other_id = entry->ike_sa->get_other_id(entry->ike_sa); + found_my_host = entry->ike_sa->get_my_host(entry->ike_sa); + found_other_host = entry->ike_sa->get_other_host(entry->ike_sa); + + if (found_my_id->get_type(found_my_id) == ID_ANY && + found_other_id->get_type(found_other_id) == ID_ANY) + { + /* IKE_SA has no IDs yet, so we can't use it */ + continue; + } + DBG2(DBG_MGR, "candidate IKE_SA for \n\t" + "%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]", + my_host, my_id, other_host, other_id, + found_my_host, found_my_id, found_other_host, found_other_id); + /* compare ID and hosts. Supplied ID may contain wildcards, and IP + * may be %any. */ + if ((my_host->is_anyaddr(my_host) || + my_host->ip_equals(my_host, found_my_host)) && + (other_host->is_anyaddr(other_host) || + other_host->ip_equals(other_host, found_other_host)) && + found_my_id->matches(found_my_id, my_id) && + found_other_id->matches(found_other_id, other_id) && + streq(peer_cfg->get_name(peer_cfg), + entry->ike_sa->get_name(entry->ike_sa))) + { + /* looks good, we take this one */ + DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]", + my_host, my_id, other_host, other_id); + entry->checked_out = TRUE; + ike_sa = entry->ike_sa; + break; + } } + enumerator->destroy(enumerator); } - iterator->destroy(iterator); + DESTROY_IF(my_host); + DESTROY_IF(other_host); if (!ike_sa) { @@ -589,15 +595,16 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id, bool child) { - iterator_t *iterator, *children; + enumerator_t *enumerator; + iterator_t *children; entry_t *entry; ike_sa_t *ike_sa = NULL; child_sa_t *child_sa; pthread_mutex_lock(&(this->mutex)); - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { if (wait_for_entry(this, entry)) { @@ -630,7 +637,7 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id, } } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); pthread_mutex_unlock(&(this->mutex)); charon->bus->set_sa(charon->bus, ike_sa); @@ -643,15 +650,16 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id, static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name, bool child) { - iterator_t *iterator, *children; + enumerator_t *enumerator; + iterator_t *children; entry_t *entry; ike_sa_t *ike_sa = NULL; child_sa_t *child_sa; pthread_mutex_lock(&(this->mutex)); - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { if (wait_for_entry(this, entry)) { @@ -684,39 +692,82 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name, } } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); pthread_mutex_unlock(&(this->mutex)); charon->bus->set_sa(charon->bus, ike_sa); return ike_sa; } + +/** + * Implementation of ike_sa_manager_t.checkout_duplicate. + */ +static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this, + ike_sa_t *ike_sa) +{ + enumerator_t *enumerator; + entry_t *entry; + ike_sa_t *duplicate = NULL; + identification_t *me, *other; + + me = ike_sa->get_my_id(ike_sa); + other = ike_sa->get_other_id(ike_sa); + + pthread_mutex_lock(&this->mutex); + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->ike_sa == ike_sa) + { /* self is not a duplicate */ + continue; + } + if (wait_for_entry(this, entry)) + { + if (me->equals(me, entry->ike_sa->get_my_id(entry->ike_sa)) && + other->equals(other, entry->ike_sa->get_other_id(entry->ike_sa))) + { + duplicate = entry->ike_sa; + entry->checked_out = TRUE; + break; + } + } + } + enumerator->destroy(enumerator); + pthread_mutex_unlock(&this->mutex); + return duplicate; +} + +/** + * enumerator cleanup function + */ +static void enumerator_unlock(private_ike_sa_manager_t *this) +{ + pthread_mutex_unlock(&this->mutex); +} /** - * Iterator hook for iterate, gets ike_sas instead of entries + * enumerator filter function */ -static hook_result_t iterator_hook(private_ike_sa_manager_t* this, entry_t *in, - ike_sa_t **out) +static bool enumerator_filter(private_ike_sa_manager_t *this, + entry_t **in, ike_sa_t **out) { - /* check out entry */ - if (wait_for_entry(this, in)) + if (wait_for_entry(this, *in)) { - *out = in->ike_sa; - return HOOK_NEXT; + *out = (*in)->ike_sa; + return TRUE; } - return HOOK_SKIP; + return FALSE; } /** * Implementation of ike_sa_manager_t.create_iterator. */ -static iterator_t *create_iterator(private_ike_sa_manager_t* this) +static enumerator_t *create_enumerator(private_ike_sa_manager_t* this) { - iterator_t *iterator = this->ike_sa_list->create_iterator_locked( - this->ike_sa_list, &this->mutex); - - /* register hook to iterator over ike_sas, not entries */ - iterator->set_iterator_hook(iterator, (iterator_hook_t*)iterator_hook, this); - return iterator; + pthread_mutex_lock(&this->mutex); + return enumerator_create_filter( + this->ike_sa_list->create_enumerator(this->ike_sa_list), + (void*)enumerator_filter, this, (void*)enumerator_unlock); } /** @@ -732,6 +783,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) status_t retval; entry_t *entry; ike_sa_id_t *ike_sa_id; + host_t *other; ike_sa_id = ike_sa->get_id(ike_sa); @@ -747,6 +799,13 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) /* signal waiting threads */ entry->checked_out = FALSE; entry->message_id = -1; + /* apply remote address for DoS detection */ + other = ike_sa->get_other_host(ike_sa); + if (!entry->other || !other->equals(other, entry->other)) + { + DESTROY_IF(entry->other); + entry->other = other->clone(other); + } DBG2(DBG_MGR, "check-in of IKE_SA successful."); pthread_cond_signal(&(entry->condvar)); retval = SUCCESS; @@ -783,6 +842,7 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik ike_sa_id = ike_sa->get_id(ike_sa); DBG2(DBG_MGR, "checkin and destroy IKE_SA"); + charon->bus->set_sa(charon->bus, NULL); pthread_mutex_lock(&(this->mutex)); @@ -803,7 +863,6 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik } pthread_mutex_unlock(&(this->mutex)); - charon->bus->set_sa(charon->bus, ike_sa); return retval; } @@ -812,23 +871,22 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik */ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip) { - iterator_t *iterator; + enumerator_t *enumerator; entry_t *entry; int count = 0; pthread_mutex_lock(&(this->mutex)); - iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { /* we check if we have a responder CONNECTING IKE_SA without checkout */ if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) && entry->ike_sa->get_state(entry->ike_sa) == IKE_CONNECTING) { - /* if we have a host, we have wait until no other uses the IKE_SA */ + /* if we have a host, count only matching IKE_SAs */ if (ip) { - if (wait_for_entry(this, entry) && ip->ip_equals(ip, - entry->ike_sa->get_other_host(entry->ike_sa))) + if (entry->other && ip->ip_equals(ip, entry->other)) { count++; } @@ -839,37 +897,37 @@ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip) } } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); pthread_mutex_unlock(&(this->mutex)); return count; } /** - * Implementation of ike_sa_manager_t.destroy. + * Implementation of ike_sa_manager_t.flush. */ -static void destroy(private_ike_sa_manager_t *this) +static void flush(private_ike_sa_manager_t *this) { /* destroy all list entries */ - linked_list_t *list = this->ike_sa_list; - iterator_t *iterator; + enumerator_t *enumerator; entry_t *entry; pthread_mutex_lock(&(this->mutex)); DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's"); /* Step 1: drive out all waiting threads */ DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's"); - iterator = list->create_iterator(list, TRUE); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { /* do not accept new threads, drive out waiting threads */ entry->driveout_new_threads = TRUE; entry->driveout_waiting_threads = TRUE; } + enumerator->destroy(enumerator); DBG2(DBG_MGR, "wait for all threads to leave IKE_SA's"); /* Step 2: wait until all are gone */ - iterator->reset(iterator); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { while (entry->waiting_threads) { @@ -879,21 +937,33 @@ static void destroy(private_ike_sa_manager_t *this) pthread_cond_wait(&(entry->condvar), &(this->mutex)); } } + enumerator->destroy(enumerator); DBG2(DBG_MGR, "delete all IKE_SA's"); /* Step 3: initiate deletion of all IKE_SAs */ - iterator->reset(iterator); - while (iterator->iterate(iterator, (void**)&entry)) + enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); + while (enumerator->enumerate(enumerator, &entry)) { entry->ike_sa->delete(entry->ike_sa); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); DBG2(DBG_MGR, "destroy all entries"); /* Step 4: destroy all entries */ - list->destroy_function(list, (void*)entry_destroy); + while (this->ike_sa_list->remove_last(this->ike_sa_list, + (void**)&entry) == SUCCESS) + { + entry_destroy(entry); + } pthread_mutex_unlock(&(this->mutex)); - - this->randomizer->destroy(this->randomizer); +} + +/** + * Implementation of ike_sa_manager_t.destroy. + */ +static void destroy(private_ike_sa_manager_t *this) +{ + this->ike_sa_list->destroy(this->ike_sa_list); + this->rng->destroy(this->rng); this->hasher->destroy(this->hasher); free(this); @@ -907,6 +977,7 @@ ike_sa_manager_t *ike_sa_manager_create() private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t); /* assign public functions */ + this->public.flush = (void(*)(ike_sa_manager_t*))flush; this->public.destroy = (void(*)(ike_sa_manager_t*))destroy; this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout; this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new; @@ -914,16 +985,30 @@ ike_sa_manager_t *ike_sa_manager_create() this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config; this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id; this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name; - this->public.create_iterator = (iterator_t*(*)(ike_sa_manager_t*))create_iterator; + this->public.checkout_duplicate = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))checkout_duplicate; + this->public.create_enumerator = (enumerator_t*(*)(ike_sa_manager_t*))create_enumerator; this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin; this->public.checkin_and_destroy = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy; this->public.get_half_open_count = (int(*)(ike_sa_manager_t*,host_t*))get_half_open_count; /* initialize private variables */ + this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED); + if (this->hasher == NULL) + { + DBG1(DBG_MGR, "manager initialization failed, no hasher supported"); + free(this); + return NULL; + } + this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (this->rng == NULL) + { + DBG1(DBG_MGR, "manager initialization failed, no RNG supported"); + this->hasher->destroy(this->hasher); + free(this); + return NULL; + } this->ike_sa_list = linked_list_create(); pthread_mutex_init(&this->mutex, NULL); - this->randomizer = randomizer_create(); - this->hasher = hasher_create(HASH_SHA1); - return &this->public; } + diff --git a/src/charon/sa/ike_sa_manager.h b/src/charon/sa/ike_sa_manager.h index a73a106ba..04b6d96c2 100644 --- a/src/charon/sa/ike_sa_manager.h +++ b/src/charon/sa/ike_sa_manager.h @@ -1,10 +1,3 @@ -/** - * @file ike_sa_manager.h - * - * @brief Interface of ike_sa_manager_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * 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. + * + * $Id: ike_sa_manager.h 3819 2008-04-17 10:46:25Z martin $ + */ + +/** + * @defgroup ike_sa_manager ike_sa_manager + * @{ @ingroup sa */ #ifndef IKE_SA_MANAGER_H_ @@ -32,7 +32,7 @@ typedef struct ike_sa_manager_t ike_sa_manager_t; #include <config/peer_cfg.h> /** - * @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's. + * The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's. * * To avoid access from multiple threads, IKE_SAs must be checked out from * the manager, and checked in after usage. @@ -42,18 +42,12 @@ typedef struct ike_sa_manager_t ike_sa_manager_t; * This could be done by comparing thread-ids via pthread_self()... * * @todo Managing of ike_sa_t objects in a hash table instead of linked list. - * - * @b Constructors: - * - ike_sa_manager_create() - * - * @ingroup sa */ struct ike_sa_manager_t { /** - * @brief Checkout an existing IKE_SA. + * Checkout an existing IKE_SA. * - * @param this the manager object * @param ike_sa_id the SA identifier, will be updated * @returns * - checked out IKE_SA if found @@ -62,16 +56,15 @@ struct ike_sa_manager_t { ike_sa_t* (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id); /** - * @brief Create and check out a new IKE_SA. + * Create and check out a new IKE_SA. * - * @param this the manager object * @param initiator TRUE for initiator, FALSE otherwise * @returns created andchecked out IKE_SA */ ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, bool initiator); /** - * @brief Checkout an IKE_SA by a message. + * Checkout an IKE_SA by a message. * * In some situations, it is necessary that the manager knows the * message to use for the checkout. This has the folloing reasons: @@ -86,7 +79,6 @@ struct ike_sa_manager_t { * If processing the message does not make sense (for the reasons above), * NULL is returned. * - * @param this the manager object * @param ike_sa_id the SA identifier, will be updated * @returns * - checked out/created IKE_SA @@ -95,7 +87,7 @@ struct ike_sa_manager_t { ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message); /** - * @brief Checkout an IKE_SA for initiation by a peer_config. + * Checkout an IKE_SA for initiation by a peer_config. * * To initiate, a CHILD_SA may be established within an existing IKE_SA. * This call checks for an existing IKE_SA by comparing the configuration. @@ -104,7 +96,6 @@ struct ike_sa_manager_t { * If no IKE_SA is found, a new one is created. This is also the case when * the found IKE_SA is in the DELETING state. * - * @param this the manager object * @param peer_cfg configuration used to find an existing IKE_SA * @return checked out/created IKE_SA */ @@ -112,14 +103,21 @@ struct ike_sa_manager_t { peer_cfg_t *peer_cfg); /** - * @brief Check out an IKE_SA a unique ID. + * Check out a duplicate if ike_sa to do uniqueness tests. + * + * @param ike_sa ike_sa to get a duplicate from + * @return checked out duplicate + */ + ike_sa_t* (*checkout_duplicate)(ike_sa_manager_t *this, ike_sa_t *ike_sa); + + /** + * Check out an IKE_SA a unique ID. * * Every IKE_SA and every CHILD_SA is uniquely identified by an ID. * These checkout function uses, depending * on the child parameter, the unique ID of the IKE_SA or the reqid * of one of a IKE_SAs CHILD_SA. * - * @param this the manager object * @param id unique ID of the object * @param child TRUE to use CHILD, FALSE to use IKE_SA * @return @@ -130,12 +128,11 @@ struct ike_sa_manager_t { bool child); /** - * @brief Check out an IKE_SA by the policy/connection name. + * Check out an IKE_SA by the policy/connection name. * * Check out the IKE_SA by the connections name or by a CHILD_SAs policy * name. * - * @param this the manager object * @param name name of the connection/policy * @param child TRUE to use policy name, FALSE to use conn name * @return @@ -146,24 +143,21 @@ struct ike_sa_manager_t { bool child); /** - * @brief Create an iterator over all stored IKE_SAs. + * Create an enumerator over all stored IKE_SAs. * - * The avoid synchronization issues, the iterator locks access + * The avoid synchronization issues, the enumerator locks access * to the manager exclusively, until it gets destroyed. - * This iterator is for reading only! Writing will corrupt the manager. * - * @param this the manager object - * @return iterator over all IKE_SAs. + * @return enumerator over all IKE_SAs. */ - iterator_t *(*create_iterator) (ike_sa_manager_t* this); + enumerator_t *(*create_enumerator) (ike_sa_manager_t* this); /** - * @brief Checkin the SA after usage. + * Checkin the SA after usage. * * @warning the SA pointer MUST NOT be used after checkin! * The SA must be checked out again! * - * @param this the manager object * @param ike_sa_id the SA identifier, will be updated * @param ike_sa checked out SA * @returns @@ -173,7 +167,7 @@ struct ike_sa_manager_t { status_t (*checkin) (ike_sa_manager_t* this, ike_sa_t *ike_sa); /** - * @brief Destroy a checked out SA. + * Destroy a checked out SA. * * The IKE SA is destroyed without notification of the remote peer. * Use this only if the other peer doesn't respond or behaves not @@ -182,7 +176,6 @@ struct ike_sa_manager_t { * so this can be called if the SA is in a "unclean" state, without the * risk that another thread can get the SA. * - * @param this the manager object * @param ike_sa SA to delete * @returns * - SUCCESS if found @@ -191,7 +184,7 @@ struct ike_sa_manager_t { status_t (*checkin_and_destroy) (ike_sa_manager_t* this, ike_sa_t *ike_sa); /** - * @brief Get the number of IKE_SAs which are in the connecting state. + * Get the number of IKE_SAs which are in the connecting state. * * To prevent the server from resource exhaustion, cookies and other * mechanisms are used. The number of half open IKE_SAs is a good @@ -200,29 +193,31 @@ struct ike_sa_manager_t { * from this IP are counted. * Only SAs for which we are the responder are counted. * - * @param this the manager object * @param ip NULL for all, IP for half open IKE_SAs with IP * @return number of half open IKE_SAs */ int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip); /** - * @brief Destroys the manager with all associated SAs. + * Delete all existing IKE_SAs and destroy them immediately. * * Threads will be driven out, so all SAs can be deleted cleanly. - * - * @param this the manager object + */ + void (*flush)(ike_sa_manager_t *this); + + /** + * Destroys the manager with all associated SAs. + * + * A call to flush() is required before calling destroy. */ void (*destroy) (ike_sa_manager_t *this); }; /** - * @brief Create a manager. - * - * @returns ike_sa_manager_t object + * Create a manager. * - * @ingroup sa + * @returns ike_sa_manager_t object, NULL if initialization fails */ ike_sa_manager_t *ike_sa_manager_create(void); -#endif /*IKE_SA_MANAGER_H_*/ +#endif /*IKE_SA_MANAGER_H_ @} */ diff --git a/src/charon/sa/mediation_manager.c b/src/charon/sa/mediation_manager.c index f6137304d..d15f4c100 100644 --- a/src/charon/sa/mediation_manager.c +++ b/src/charon/sa/mediation_manager.c @@ -1,10 +1,3 @@ -/** - * @file mediation_manager.c - * - * @brief Implementation of mediation_manager_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: mediation_manager.c 3773 2008-04-07 09:36:52Z tobias $ */ #include "mediation_manager.h" @@ -246,6 +241,7 @@ static void update_sa_id(private_mediation_manager_t *this, identification_t *pe { job_t *job = (job_t*)mediation_callback_job_create(requester, peer_id); charon->processor->queue_job(charon->processor, job); + requester->destroy(requester); } pthread_mutex_unlock(&(this->mutex)); diff --git a/src/charon/sa/mediation_manager.h b/src/charon/sa/mediation_manager.h index 74acc4d41..d21c93244 100644 --- a/src/charon/sa/mediation_manager.h +++ b/src/charon/sa/mediation_manager.h @@ -1,10 +1,3 @@ -/** - * @file mediation_manager.h - * - * @brief Interface of mediation_manager_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: mediation_manager.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup mediation_manager mediation_manager + * @{ @ingroup sa */ #ifndef MEDIATION_MANAGER_H_ @@ -29,29 +29,22 @@ typedef struct mediation_manager_t mediation_manager_t; #include <utils/identification.h> /** - * @brief The mediation manager is responsible for managing currently online + * The mediation manager is responsible for managing currently online * peers and registered requests for offline peers on the mediation server. - * - * @b Constructors: - * - mediation_manager_create() - * - * @ingroup sa */ struct mediation_manager_t { /** - * @brief Remove the IKE_SA of a peer. + * Remove the IKE_SA of a peer. * - * @param this the manager object * @param ike_sa_id the IKE_SA ID of the peer's SA */ void (*remove) (mediation_manager_t* this, ike_sa_id_t *ike_sa_id); /** - * @brief Update the ike_sa_id that is assigned to a peer's ID. If the peer + * Update the ike_sa_id that is assigned to a peer's ID. If the peer * is new, it gets a new record assigned. * - * @param this the manager object * @param peer_id the peer's ID * @param ike_sa_id the IKE_SA ID of the peer's SA */ @@ -59,9 +52,8 @@ struct mediation_manager_t { ike_sa_id_t *ike_sa_id); /** - * @brief Checks if a specific peer is online. + * Checks if a specific peer is online. * - * @param this the manager object * @param peer_id the peer's ID * @returns * - IKE_SA ID of the peer's SA. @@ -71,10 +63,9 @@ struct mediation_manager_t { identification_t *peer_id); /** - * @brief Checks if a specific peer is online and registers the requesting + * Checks if a specific peer is online and registers the requesting * peer if it is not. * - * @param this the manager object * @param peer_id the peer's ID * @param requester the requesters ID * @returns @@ -85,20 +76,16 @@ struct mediation_manager_t { identification_t *peer_id, identification_t *requester); /** - * @brief Destroys the manager with all data. - * - * @param this the manager object + * Destroys the manager with all data. */ void (*destroy) (mediation_manager_t *this); }; /** - * @brief Create a manager. + * Create a manager. * * @returns mediation_manager_t object - * - * @ingroup sa */ mediation_manager_t *mediation_manager_create(void); -#endif /*MEDIATION_MANAGER_H_*/ +#endif /*MEDIATION_MANAGER_H_ @} */ diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c index 89f527aba..e453fff00 100644 --- a/src/charon/sa/task_manager.c +++ b/src/charon/sa/task_manager.c @@ -1,10 +1,3 @@ -/** - * @file task_manager.c - * - * @brief Implementation of task_manager_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2007 Martin Willi @@ -19,6 +12,8 @@ * 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. + * + * $Id: task_manager.c 3666 2008-03-26 18:40:19Z tobias $ */ #include "task_manager.h" @@ -31,7 +26,8 @@ #include <sa/tasks/ike_mobike.h> #include <sa/tasks/ike_auth.h> #include <sa/tasks/ike_auth_lifetime.h> -#include <sa/tasks/ike_cert.h> +#include <sa/tasks/ike_cert_pre.h> +#include <sa/tasks/ike_cert_post.h> #include <sa/tasks/ike_rekey.h> #include <sa/tasks/ike_delete.h> #include <sa/tasks/ike_config.h> @@ -42,8 +38,8 @@ #include <encoding/payloads/delete_payload.h> #include <processing/jobs/retransmit_job.h> -#ifdef P2P -#include <sa/tasks/ike_p2p.h> +#ifdef ME +#include <sa/tasks/ike_me.h> #endif typedef struct exchange_t exchange_t; @@ -328,15 +324,16 @@ static status_t build_request(private_task_manager_t *this) this->initiating.mid = 0; exchange = IKE_SA_INIT; activate_task(this, IKE_NATD); - activate_task(this, IKE_CERT); -#ifdef P2P + activate_task(this, IKE_CERT_PRE); +#ifdef ME /* this task has to be activated before the IKE_AUTHENTICATE * task, because that task pregenerates the packet after * which no payloads can be added to the message anymore. */ - activate_task(this, IKE_P2P); -#endif /* P2P */ + activate_task(this, IKE_ME); +#endif /* ME */ activate_task(this, IKE_AUTHENTICATE); + activate_task(this, IKE_CERT_POST); activate_task(this, IKE_CONFIG); activate_task(this, CHILD_CREATE); activate_task(this, IKE_AUTH_LIFETIME); @@ -384,13 +381,13 @@ static status_t build_request(private_task_manager_t *this) exchange = INFORMATIONAL; break; } -#ifdef P2P - if (activate_task(this, IKE_P2P)) +#ifdef ME + if (activate_task(this, IKE_ME)) { - exchange = P2P_CONNECT; + exchange = ME_CONNECT; break; } -#endif /* P2P */ +#endif /* ME */ case IKE_REKEYING: if (activate_task(this, IKE_DELETE)) { @@ -687,14 +684,16 @@ static status_t process_request(private_task_manager_t *this, this->passive_tasks->insert_last(this->passive_tasks, task); task = (task_t*)ike_natd_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); - task = (task_t*)ike_cert_create(this->ike_sa, FALSE); + task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); -#ifdef P2P - task = (task_t*)ike_p2p_create(this->ike_sa, FALSE); +#ifdef ME + task = (task_t*)ike_me_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); -#endif /* P2P */ +#endif /* ME */ task = (task_t*)ike_auth_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); + task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE); + this->passive_tasks->insert_last(this->passive_tasks, task); task = (task_t*)ike_config_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); task = (task_t*)child_create_create(this->ike_sa, NULL); @@ -818,13 +817,13 @@ static status_t process_request(private_task_manager_t *this, this->passive_tasks->insert_last(this->passive_tasks, task); break; } -#ifdef P2P - case P2P_CONNECT: +#ifdef ME + case ME_CONNECT: { - task = (task_t*)ike_p2p_create(this->ike_sa, FALSE); + task = (task_t*)ike_me_create(this->ike_sa, FALSE); this->passive_tasks->insert_last(this->passive_tasks, task); } -#endif /* P2P */ +#endif /* ME */ default: break; } diff --git a/src/charon/sa/task_manager.h b/src/charon/sa/task_manager.h index 38c63c1a9..6243ac888 100644 --- a/src/charon/sa/task_manager.h +++ b/src/charon/sa/task_manager.h @@ -1,10 +1,3 @@ -/** - * @file task_manager.h - * - * @brief Interface of task_manager_t. - * - */ - /* * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: task_manager.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup task_manager task_manager + * @{ @ingroup sa */ #ifndef TASK_MANAGER_H_ @@ -32,42 +32,32 @@ typedef struct task_manager_t task_manager_t; /** * First retransmit timeout in milliseconds. - * - * @ingroup sa */ #define RETRANSMIT_TIMEOUT 4000 /** * Base which is raised to the power of the retransmission try. - * - * @ingroup sa */ #define RETRANSMIT_BASE 1.8 /** * Number of retransmits done before giving up. - * - * @ingroup sa */ #define RETRANSMIT_TRIES 5 /** * Interval for mobike routability checks in ms. - * - * @ingroup sa */ #define ROUTEABILITY_CHECK_INTERVAL 2500 /** * Number of routability checks before giving up - * - * @ingroup sa */ #define ROUTEABILITY_CHECK_TRIES 10 /** - * @brief The task manager, juggles task and handles message exchanges. + * The task manager, juggles task and handles message exchanges. * * On incoming requests, the task manager creates new tasks on demand and * juggles the request through all available tasks. Each task inspects the @@ -97,18 +87,12 @@ typedef struct task_manager_t task_manager_t; @endberbatim * The peer is considered dead after 2min 45s when no reply comes in. - * - * @b Constructors: - * - task_manager_create() - * - * @ingroup sa */ struct task_manager_t { /** - * @brief Process an incoming message. + * Process an incoming message. * - * @param this calling object * @param message message to add payloads to * @return * - DESTROY_ME if IKE_SA must be closed @@ -117,28 +101,24 @@ struct task_manager_t { status_t (*process_message) (task_manager_t *this, message_t *message); /** - * @brief Initiate an exchange with the currently queued tasks. - * - * @param this calling object + * Initiate an exchange with the currently queued tasks. */ status_t (*initiate) (task_manager_t *this); /** - * @brief Queue a task in the manager. + * Queue a task in the manager. * - * @param this calling object * @param task task to queue */ void (*queue_task) (task_manager_t *this, task_t *task); /** - * @brief Retransmit a request if it hasn't been acknowledged yet. + * Retransmit a request if it hasn't been acknowledged yet. * * A return value of INVALID_STATE means that the message was already * acknowledged and has not to be retransmitted. A return value of SUCCESS * means retransmission was required and the message has been resent. * - * @param this calling object * @param message_id ID of the message to retransmit * @return * - INVALID_STATE if retransmission not required @@ -147,52 +127,45 @@ struct task_manager_t { status_t (*retransmit) (task_manager_t *this, u_int32_t message_id); /** - * @brief Migrate all tasks from other to this. + * Migrate all tasks from other to this. * * To rekey or reestablish an IKE_SA completely, all queued or active * tasks should get migrated to the new IKE_SA. * - * @param this manager which gets all tasks * @param other manager which gives away its tasks */ void (*adopt_tasks) (task_manager_t *this, task_manager_t *other); /** - * @brief Reset message ID counters of the task manager. + * Reset message ID counters of the task manager. * * The IKEv2 protocol requires to restart exchanges with message IDs * reset to zero (INVALID_KE_PAYLOAD, COOKIES, ...). The reset() method * resets the message IDs and resets all active tasks using the migrate() * method. * - * @param this calling object * @param other manager which gives away its tasks */ void (*reset) (task_manager_t *this); /** - * @brief Check if we are currently waiting for a reply. + * Check if we are currently waiting for a reply. * - * @param this calling object * @return TRUE if we are waiting, FALSE otherwise */ bool (*busy) (task_manager_t *this); /** - * @brief Destroy the task_manager_t. - * - * @param this calling object + * Destroy the task_manager_t. */ void (*destroy) (task_manager_t *this); }; /** - * @brief Create an instance of the task manager. + * Create an instance of the task manager. * * @param ike_sa IKE_SA to manage. - * - * @ingroup sa */ task_manager_t *task_manager_create(ike_sa_t *ike_sa); -#endif /* TASK_MANAGER_H_ */ +#endif /* TASK_MANAGER_H_ @} */ diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index 3947a84d1..4638da03e 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -1,11 +1,5 @@ -/** - * @file child_create.c - * - * @brief Implementation of the child_create task. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -19,6 +13,8 @@ * 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. + * + * $Id: child_create.c 3920 2008-05-08 16:19:11Z tobias $ */ #include "child_create.h" @@ -105,6 +101,21 @@ struct private_child_create_t { mode_t mode; /** + * IPComp transform to use + */ + ipcomp_transform_t ipcomp; + + /** + * IPComp transform proposed or accepted by the other peer + */ + ipcomp_transform_t ipcomp_received; + + /** + * Other Compression Parameter Index (CPI) + */ + u_int16_t other_cpi; + + /** * reqid to use if we are rekeying */ u_int32_t reqid; @@ -141,17 +152,16 @@ static status_t get_nonce(message_t *message, chunk_t *nonce) */ static status_t generate_nonce(chunk_t *nonce) { - status_t status; - randomizer_t *randomizer = randomizer_create(); + rng_t *rng; - status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, - nonce); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { - DBG1(DBG_IKE, "error generating random nonce value"); + DBG1(DBG_IKE, "error generating nonce value, no RNG found"); return FAILED; } + rng->allocate_bytes(rng, NONCE_SIZE, nonce); + rng->destroy(rng); return SUCCESS; } @@ -227,11 +237,11 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) if (!this->proposal->has_dh_group(this->proposal, this->dh_group)) { - algorithm_t *algo; + u_int16_t group; + if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, - &algo)) + &group, NULL)) { - u_int16_t group = algo->algorithm; SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N", diffie_hellman_group_names, this->dh_group, diffie_hellman_group_names, group); @@ -332,6 +342,12 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) } prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); + if (this->ipcomp != IPCOMP_NONE) + { + this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp, + this->other_cpi); + } + if (this->initiator) { status = this->child_sa->update(this->child_sa, this->proposal, @@ -422,6 +438,36 @@ static void build_payloads(private_child_create_t *this, message_t *message) } /** + * Adds an IPCOMP_SUPPORTED notify to the message, if possible + */ +static void build_ipcomp_supported_notify(private_child_create_t *this, message_t *message) +{ + if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) + { + DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, IPComp is disabled"); + this->ipcomp = IPCOMP_NONE; + return; + } + + u_int16_t cpi = this->child_sa->get_my_cpi(this->child_sa); + if (cpi) + { + chunk_t cpi_chunk, tid_chunk, data; + u_int8_t tid = this->ipcomp; + cpi_chunk = chunk_from_thing(cpi); + tid_chunk = chunk_from_thing(tid); + data = chunk_cat("cc", cpi_chunk, tid_chunk); + message->add_notify(message, FALSE, IPCOMP_SUPPORTED, data); + chunk_free(&data); + } + else + { + DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp is disabled"); + this->ipcomp = IPCOMP_NONE; + } +} + +/** * Read payloads from message */ static void process_payloads(private_child_create_t *this, message_t *message) @@ -450,7 +496,7 @@ static void process_payloads(private_child_create_t *this, message_t *message) if (!this->initiator) { this->dh_group = ke_payload->get_dh_group_number(ke_payload); - this->dh = diffie_hellman_create(this->dh_group); + this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); } if (this->dh) { @@ -476,6 +522,25 @@ static void process_payloads(private_child_create_t *this, message_t *message) case USE_BEET_MODE: this->mode = MODE_BEET; break; + case IPCOMP_SUPPORTED: + { + chunk_t data = notify_payload->get_notification_data(notify_payload); + u_int16_t cpi = *(u_int16_t*)data.ptr; + ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2)); + switch(ipcomp) + { + case IPCOMP_DEFLATE: + this->other_cpi = cpi; + this->ipcomp_received = ipcomp; + break; + case IPCOMP_LZS: + case IPCOMP_LZJH: + default: + DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform" + " ID we don't support %N", ipcomp_transform_names, ipcomp); + break; + } + } default: break; } @@ -540,11 +605,10 @@ static status_t build_i(private_child_create_t *this, message_t *message) if (!this->reqid) { peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - vip = peer_cfg->get_my_virtual_ip(peer_cfg); + vip = peer_cfg->get_virtual_ip(peer_cfg); if (vip) { propose_all = TRUE; - vip->destroy(vip); } } @@ -580,7 +644,13 @@ static status_t build_i(private_child_create_t *this, message_t *message) if (this->dh_group != MODP_NONE) { - this->dh = diffie_hellman_create(this->dh_group); + this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); + } + + if (this->config->use_ipcomp(this->config)) { + /* IPCOMP_DEFLATE is the only transform we support at the moment */ + this->ipcomp = IPCOMP_DEFLATE; + build_ipcomp_supported_notify(this, message); } build_payloads(this, message); @@ -700,6 +770,16 @@ static status_t build_r(private_child_create_t *this, message_t *message) this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid, this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); + if (this->config->use_ipcomp(this->config) && this->ipcomp_received != IPCOMP_NONE) + { + this->ipcomp = this->ipcomp_received; + build_ipcomp_supported_notify(this, message); + } + else if (this->ipcomp_received != IPCOMP_NONE) + { + DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify but IPComp is disabled, ignoring"); + } + switch (select_and_install(this, no_dh)) { case SUCCESS: @@ -806,6 +886,25 @@ static status_t process_i(private_child_create_t *this, message_t *message) process_payloads(this, message); + if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE) + { + SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify but we did not " + "send one previously, no CHILD_SA built"); + return SUCCESS; + } + else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE) + { + DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, " + "IPComp is disabled"); + this->ipcomp = IPCOMP_NONE; + } + else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received) + { + SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify for a transform " + "we did not propose, no CHILD_SA built"); + return SUCCESS; + } + if (select_and_install(this, no_dh) == SUCCESS) { SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully", @@ -884,6 +983,9 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa) this->dh = NULL; this->child_sa = NULL; this->mode = MODE_TUNNEL; + this->ipcomp = IPCOMP_NONE; + this->ipcomp_received = IPCOMP_NONE; + this->other_cpi = 0; this->reqid = 0; this->established = FALSE; } @@ -957,6 +1059,9 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config) this->dh_group = MODP_NONE; this->child_sa = NULL; this->mode = MODE_TUNNEL; + this->ipcomp = IPCOMP_NONE; + this->ipcomp_received = IPCOMP_NONE; + this->other_cpi = 0; this->reqid = 0; this->established = FALSE; diff --git a/src/charon/sa/tasks/child_create.h b/src/charon/sa/tasks/child_create.h index 9f4815215..cee37121e 100644 --- a/src/charon/sa/tasks/child_create.h +++ b/src/charon/sa/tasks/child_create.h @@ -1,10 +1,3 @@ -/** - * @file child_create.h - * - * @brief Interface child_create_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: child_create.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup child_create child_create + * @{ @ingroup tasks */ #ifndef CHILD_CREATE_H_ @@ -31,15 +31,10 @@ typedef struct child_create_t child_create_t; #include <config/child_cfg.h> /** - * @brief Task of type CHILD_CREATE, established a new CHILD_SA. + * Task of type CHILD_CREATE, established a new CHILD_SA. * * This task may be included in the IKE_AUTH message or in a separate * CREATE_CHILD_SA exchange. - * - * @b Constructors: - * - child_create_create() - * - * @ingroup tasks */ struct child_create_t { @@ -49,35 +44,32 @@ struct child_create_t { task_t task; /** - * @brief Use a specific reqid for the CHILD_SA. + * Use a specific reqid for the CHILD_SA. * * When this task is used for rekeying, the same reqid is used * for the new CHILD_SA. * - * @param this calling object * @param reqid reqid to use */ void (*use_reqid) (child_create_t *this, u_int32_t reqid); /** - * @brief Get the lower of the two nonces, used for rekey collisions. + * Get the lower of the two nonces, used for rekey collisions. * - * @param this calling object * @return lower nonce */ chunk_t (*get_lower_nonce) (child_create_t *this); /** - * @brief Get the CHILD_SA established/establishing by this task. + * Get the CHILD_SA established/establishing by this task. * - * @param this calling object * @return child_sa */ child_sa_t* (*get_child) (child_create_t *this); }; /** - * @brief Create a new child_create task. + * Create a new child_create task. * * @param ike_sa IKE_SA this task works for * @param config child_cfg if task initiator, NULL if responder @@ -85,4 +77,4 @@ struct child_create_t { */ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config); -#endif /* CHILD_CREATE_H_ */ +#endif /* CHILD_CREATE_H_ @} */ diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c index d0b34a276..4156f9704 100644 --- a/src/charon/sa/tasks/child_delete.c +++ b/src/charon/sa/tasks/child_delete.c @@ -1,10 +1,3 @@ -/** - * @file child_delete.c - * - * @brief Implementation of the child_delete task. - * - */ - /* * Copyright (C) 2006-2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: child_delete.c 3802 2008-04-14 08:17:18Z martin $ */ #include "child_delete.h" @@ -157,23 +152,48 @@ static void process_payloads(private_child_delete_t *this, message_t *message) } /** - * destroy the children listed in this->child_sas + * destroy the children listed in this->child_sas, reestablish by policy */ -static void destroy_children(private_child_delete_t *this) +static status_t destroy_and_reestablish(private_child_delete_t *this) { iterator_t *iterator; child_sa_t *child_sa; + child_cfg_t *child_cfg; protocol_id_t protocol; u_int32_t spi; + status_t status = SUCCESS; iterator = this->child_sas->create_iterator(this->child_sas, TRUE); while (iterator->iterate(iterator, (void**)&child_sa)) { spi = child_sa->get_spi(child_sa, TRUE); protocol = child_sa->get_protocol(child_sa); + child_cfg = child_sa->get_config(child_sa); + child_cfg->get_ref(child_cfg); this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi); + if (!this->initiator) + { /* enforce child_cfg policy if deleted passively */ + switch (child_cfg->get_close_action(child_cfg)) + { + case ACTION_RESTART: + child_cfg->get_ref(child_cfg); + status = this->ike_sa->initiate(this->ike_sa, child_cfg); + break; + case ACTION_ROUTE: + status = this->ike_sa->route(this->ike_sa, child_cfg); + break; + default: + break; + } + } + child_cfg->destroy(child_cfg); + if (status != SUCCESS) + { + break; + } } iterator->destroy(iterator); + return status; } /** @@ -214,9 +234,8 @@ static status_t process_i(private_child_delete_t *this, message_t *message) this->child_sas = linked_list_create(); process_payloads(this, message); - destroy_children(this); SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed"); - return SUCCESS; + return destroy_and_reestablish(this); } /** @@ -239,9 +258,8 @@ static status_t build_r(private_child_delete_t *this, message_t *message) { build_payloads(this, message); } - destroy_children(this); SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed"); - return SUCCESS; + return destroy_and_reestablish(this); } /** diff --git a/src/charon/sa/tasks/child_delete.h b/src/charon/sa/tasks/child_delete.h index a7e676a50..c304ea9d8 100644 --- a/src/charon/sa/tasks/child_delete.h +++ b/src/charon/sa/tasks/child_delete.h @@ -1,10 +1,3 @@ -/** - * @file child_delete.h - * - * @brief Interface child_delete_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: child_delete.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup child_delete child_delete + * @{ @ingroup tasks */ #ifndef CHILD_DELETE_H_ @@ -31,12 +31,7 @@ typedef struct child_delete_t child_delete_t; #include <sa/child_sa.h> /** - * @brief Task of type child_delete, delete a CHILD_SA. - * - * @b Constructors: - * - child_delete_create() - * - * @ingroup tasks + * Task of type child_delete, delete a CHILD_SA. */ struct child_delete_t { @@ -46,16 +41,15 @@ struct child_delete_t { task_t task; /** - * @brief Get the CHILD_SA to delete by this task. + * Get the CHILD_SA to delete by this task. * - * @param this calling object * @return child_sa */ child_sa_t* (*get_child) (child_delete_t *this); }; /** - * @brief Create a new child_delete task. + * Create a new child_delete task. * * @param ike_sa IKE_SA this task works for * @param child_sa CHILD_SA to delete, or NULL as responder @@ -63,4 +57,4 @@ struct child_delete_t { */ child_delete_t *child_delete_create(ike_sa_t *ike_sa, child_sa_t *child_sa); -#endif /* CHILD_DELETE_H_ */ +#endif /* CHILD_DELETE_H_ @} */ diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c index 3667d8fad..3953951a3 100644 --- a/src/charon/sa/tasks/child_rekey.c +++ b/src/charon/sa/tasks/child_rekey.c @@ -1,10 +1,3 @@ -/** - * @file child_rekey.c - * - * @brief Implementation of the child_rekey task. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: child_rekey.c 3589 2008-03-13 14:14:44Z martin $ */ #include "child_rekey.h" diff --git a/src/charon/sa/tasks/child_rekey.h b/src/charon/sa/tasks/child_rekey.h index 3515f0c3f..b386ef3c6 100644 --- a/src/charon/sa/tasks/child_rekey.h +++ b/src/charon/sa/tasks/child_rekey.h @@ -1,10 +1,3 @@ -/** - * @file child_rekey.h - * - * @brief Interface child_rekey_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: child_rekey.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup child_rekey child_rekey + * @{ @ingroup tasks */ #ifndef CHILD_REKEY_H_ @@ -31,12 +31,7 @@ typedef struct child_rekey_t child_rekey_t; #include <sa/tasks/task.h> /** - * @brief Task of type CHILD_REKEY, rekey an established CHILD_SA. - * - * @b Constructors: - * - child_rekey_create() - * - * @ingroup tasks + * Task of type CHILD_REKEY, rekey an established CHILD_SA. */ struct child_rekey_t { @@ -46,20 +41,19 @@ struct child_rekey_t { task_t task; /** - * @brief Register a rekeying task which collides with this one + * Register a rekeying task which collides with this one * * If two peers initiate rekeying at the same time, the collision must * be handled gracefully. The task manager is aware of what exchanges * are going on and notifies the outgoing task by passing the incoming. * - * @param this task initated by us * @param other incoming task */ void (*collide)(child_rekey_t* this, task_t *other); }; /** - * @brief Create a new CHILD_REKEY task. + * Create a new CHILD_REKEY task. * * @param ike_sa IKE_SA this task works for * @param child_sa child_sa to rekey, NULL if responder @@ -67,4 +61,4 @@ struct child_rekey_t { */ child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, child_sa_t *child_sa); -#endif /* CHILD_REKEY_H_ */ +#endif /* CHILD_REKEY_H_ @} */ diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c index de88a0abe..fd5012ee6 100644 --- a/src/charon/sa/tasks/ike_auth.c +++ b/src/charon/sa/tasks/ike_auth.c @@ -1,10 +1,3 @@ -/** - * @file ike_auth.c - * - * @brief Implementation of the ike_auth task. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -18,7 +11,9 @@ * 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. + * for more details + * + * $Id: ike_auth.c 4051 2008-06-10 09:08:27Z tobias $ */ #include "ike_auth.h" @@ -94,6 +89,68 @@ struct private_ike_auth_t { }; /** + * check uniqueness and delete duplicates + */ +static bool check_uniqueness(private_ike_auth_t *this) +{ + ike_sa_t *duplicate; + unique_policy_t policy; + status_t status = SUCCESS; + peer_cfg_t *peer_cfg; + bool cancel = FALSE; + + peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); + policy = peer_cfg->get_unique_policy(peer_cfg); + if (policy == UNIQUE_NO) + { + return FALSE; + } + duplicate = charon->ike_sa_manager->checkout_duplicate( + charon->ike_sa_manager, this->ike_sa); + if (duplicate) + { + peer_cfg = duplicate->get_peer_cfg(duplicate); + if (peer_cfg && + peer_cfg->equals(peer_cfg, this->ike_sa->get_peer_cfg(this->ike_sa))) + { + switch (duplicate->get_state(duplicate)) + { + case IKE_ESTABLISHED: + case IKE_REKEYING: + switch (policy) + { + case UNIQUE_REPLACE: + DBG1(DBG_IKE, "deleting duplicate IKE_SA due " + "uniqueness policy"); + status = duplicate->delete(duplicate); + break; + case UNIQUE_KEEP: + DBG1(DBG_IKE, "cancelling IKE_SA setup due " + "uniqueness policy"); + cancel = TRUE; + break; + default: + break; + } + break; + default: + break; + } + } + if (status == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, + duplicate); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, duplicate); + } + } + return cancel; +} + +/** * build the AUTH payload */ static status_t build_auth(private_ike_auth_t *this, message_t *message) @@ -101,7 +158,7 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message) authenticator_t *auth; auth_payload_t *auth_payload; peer_cfg_t *config; - auth_method_t method; + config_auth_method_t method; status_t status; /* create own authenticator and add auth payload */ @@ -117,7 +174,7 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message) if (auth == NULL) { SIG(IKE_UP_FAILED, "configured authentication method %N not supported", - auth_method_names, method); + config_auth_method_names, method); return FAILED; } @@ -186,13 +243,13 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message) /* AUTH payload is missing, client wants to use EAP authentication */ return NOT_FOUND; } - + auth_method = auth_payload->get_auth_method(auth_payload); - auth = authenticator_create(this->ike_sa, auth_method); + auth = authenticator_create_from_auth_payload(this->ike_sa, auth_payload); if (auth == NULL) { - SIG(IKE_UP_FAILED, "authentication method %N used by %D not " + SIG(IKE_UP_FAILED, "authentication method %N used by '%D' not " "supported", auth_method_names, auth_method, this->ike_sa->get_other_id(this->ike_sa)); return NOT_SUPPORTED; @@ -231,9 +288,9 @@ static status_t process_id(private_ike_auth_t *this, message_t *message) { id = idr->get_identification(idr); req = this->ike_sa->get_other_id(this->ike_sa); - if (!id->matches(id, req, NULL)) + if (!id->matches(id, req)) { - SIG(IKE_UP_FAILED, "peer ID %D unacceptable, %D required", id, req); + SIG(IKE_UP_FAILED, "peer ID '%D' unacceptable, '%D' required", id, req); id->destroy(id); return FAILED; } @@ -321,12 +378,12 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message) if (!this->initiator) { this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H", this->ike_sa->get_name(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); + this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); return SUCCESS; } return NEED_MORE; @@ -367,12 +424,12 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message) if (this->initiator) { this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H", this->ike_sa->get_name(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); + this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); return SUCCESS; } return NEED_MORE; @@ -404,7 +461,7 @@ static status_t process_eap_i(private_ike_auth_t *this, message_t *message) return NEED_MORE; default: this->eap_payload = NULL; - SIG(IKE_UP_FAILED, "failed to authenticate against %D using EAP", + SIG(IKE_UP_FAILED, "failed to authenticate against '%D' using EAP", this->ike_sa->get_other_id(this->ike_sa)); return FAILED; } @@ -482,7 +539,7 @@ static status_t build_i(private_ike_auth_t *this, message_t *message) } config = this->ike_sa->get_peer_cfg(this->ike_sa); - if (config->get_auth_method(config) == AUTH_EAP) + if (config->get_auth_method(config) == CONF_AUTH_EAP) { this->eap_auth = eap_authenticator_create(this->ike_sa); } @@ -525,13 +582,13 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) this->eap_auth = eap_authenticator_create(this->ike_sa); break; default: - break; + return NEED_MORE; } config = charon->backends->get_peer_cfg(charon->backends, this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_other_id(this->ike_sa), - this->ike_sa->get_other_ca(this->ike_sa)); + this->ike_sa->get_other_auth(this->ike_sa)); if (config) { this->ike_sa->set_peer_cfg(this->ike_sa, config); @@ -557,10 +614,17 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) return collect_my_init_data(this, message); } + if (!this->peer_authenticated && this->eap_auth == NULL) + { + /* peer not authenticated, nor does it want to use EAP */ + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); + return FAILED; + } + config = this->ike_sa->get_peer_cfg(this->ike_sa); if (config == NULL) { - SIG(IKE_UP_FAILED, "no matching config found for %D...%D", + SIG(IKE_UP_FAILED, "no matching config found for '%D'...'%D'", this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_other_id(this->ike_sa)); message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); @@ -574,26 +638,25 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) return FAILED; } + if (check_uniqueness(this)) + { + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); + return FAILED; + } + /* use "traditional" authentication if we could authenticate peer */ if (this->peer_authenticated) { this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H", this->ike_sa->get_name(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); + this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); return SUCCESS; } - if (this->eap_auth == NULL) - { - /* peer not authenticated, nor does it want to use EAP */ - message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); - return FAILED; - } - /* initiate EAP authenitcation */ eap_type = config->get_eap_type(config, &eap_vendor); status = this->eap_auth->initiate(this->eap_auth, eap_type, @@ -618,6 +681,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) { iterator_t *iterator; payload_t *payload; + peer_cfg_t *config; + auth_info_t *auth; if (message->get_exchange_type(message) == IKE_SA_INIT) { @@ -652,8 +717,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) case AUTH_LIFETIME: /* handled in ike_auth_lifetime task */ break; - case P2P_ENDPOINT: - /* handled in ike_p2p task */ + case ME_ENDPOINT: + /* handled in ike_me task */ break; default: { @@ -664,7 +729,7 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) iterator->destroy(iterator); return FAILED; } - DBG1(DBG_IKE, "received %N notify", + DBG2(DBG_IKE, "received %N notify", notify_type_names, type); break; } @@ -687,13 +752,21 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) return process_eap_i(this, message); } + config = this->ike_sa->get_peer_cfg(this->ike_sa); + auth = this->ike_sa->get_other_auth(this->ike_sa); + if (!auth->complies(auth, config->get_auth(config))) + { + SIG(IKE_UP_FAILED, "authorization of '%D' for config %s failed", + this->ike_sa->get_other_id(this->ike_sa), config->get_name(config)); + return FAILED; + } this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %H[%D]...[%D]%H", this->ike_sa->get_name(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); + this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa)); return SUCCESS; } diff --git a/src/charon/sa/tasks/ike_auth.h b/src/charon/sa/tasks/ike_auth.h index d7326c988..15f98f312 100644 --- a/src/charon/sa/tasks/ike_auth.h +++ b/src/charon/sa/tasks/ike_auth.h @@ -1,10 +1,3 @@ -/** - * @file ike_auth.h - * - * @brief Interface ike_auth_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_auth.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_auth ike_auth + * @{ @ingroup tasks */ #ifndef IKE_AUTH_H_ @@ -30,7 +30,7 @@ typedef struct ike_auth_t ike_auth_t; #include <sa/tasks/task.h> /** - * @brief Task of type ike_auth, authenticates an IKE_SA using authenticators. + * Task of type ike_auth, authenticates an IKE_SA using authenticators. * * The ike_auth task authenticates the IKE_SA using the IKE_AUTH * exchange. It processes and build IDi and IDr payloads and also @@ -38,11 +38,6 @@ typedef struct ike_auth_t ike_auth_t; * which do the actual authentication process. If the ike_auth task is used * with EAP authentication, it stays alive over multiple exchanges until * EAP has completed. - * - * @b Constructors: - * - ike_auth_create() - * - * @ingroup tasks */ struct ike_auth_t { @@ -53,7 +48,7 @@ struct ike_auth_t { }; /** - * @brief Create a new task of type IKE_AUTHENTICATE. + * Create a new task of type IKE_AUTHENTICATE. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE if thask is the initator of an exchange @@ -61,4 +56,4 @@ struct ike_auth_t { */ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_AUTH_H_ */ +#endif /* IKE_AUTH_H_ @} */ diff --git a/src/charon/sa/tasks/ike_auth_lifetime.c b/src/charon/sa/tasks/ike_auth_lifetime.c index 9d37ec608..2d18c6a1e 100644 --- a/src/charon/sa/tasks/ike_auth_lifetime.c +++ b/src/charon/sa/tasks/ike_auth_lifetime.c @@ -1,10 +1,3 @@ -/** - * @file ike_auth_lifetime.c - * - * @brief Implementation of the ike_auth_lifetime task. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: ike_auth_lifetime.c 3589 2008-03-13 14:14:44Z martin $ */ #include "ike_auth_lifetime.h" diff --git a/src/charon/sa/tasks/ike_auth_lifetime.h b/src/charon/sa/tasks/ike_auth_lifetime.h index 500b89d39..21a3bbfdc 100644 --- a/src/charon/sa/tasks/ike_auth_lifetime.h +++ b/src/charon/sa/tasks/ike_auth_lifetime.h @@ -1,10 +1,3 @@ -/** - * @file ike_auth_lifetime.h - * - * @brief Interface ike_auth_lifetime_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_auth_lifetime.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_auth_lifetime ike_auth_lifetime + * @{ @ingroup tasks */ #ifndef IKE_AUTH_LIFETIME_H_ @@ -30,15 +30,10 @@ typedef struct ike_auth_lifetime_t ike_auth_lifetime_t; #include <sa/tasks/task.h> /** - * @brief Task of type IKE_AUTH_LIFETIME, implements RFC4478. + * Task of type IKE_AUTH_LIFETIME, implements RFC4478. * * This task exchanges lifetimes for IKE_AUTH to force a client to * reauthenticate before the responders lifetime reaches the limit. - * - * @b Constructors: - * - ike_auth_lifetime_create() - * - * @ingroup tasks */ struct ike_auth_lifetime_t { @@ -49,7 +44,7 @@ struct ike_auth_lifetime_t { }; /** - * @brief Create a new IKE_AUTH_LIFETIME task. + * Create a new IKE_AUTH_LIFETIME task. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE if taks is initiated by us @@ -57,5 +52,4 @@ struct ike_auth_lifetime_t { */ ike_auth_lifetime_t *ike_auth_lifetime_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_MOBIKE_H_ */ - +#endif /* IKE_MOBIKE_H_ @} */ diff --git a/src/charon/sa/tasks/ike_cert.c b/src/charon/sa/tasks/ike_cert.c deleted file mode 100644 index 880ed9c42..000000000 --- a/src/charon/sa/tasks/ike_cert.c +++ /dev/null @@ -1,366 +0,0 @@ -/** - * @file ike_cert.c - * - * @brief Implementation of the ike_cert task. - * - */ - -/* - * Copyright (C) 2006-2007 Martin Willi - * 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 "ike_cert.h" - -#include <daemon.h> -#include <sa/ike_sa.h> -#include <crypto/hashers/hasher.h> -#include <encoding/payloads/cert_payload.h> -#include <encoding/payloads/certreq_payload.h> - - -typedef struct private_ike_cert_t private_ike_cert_t; - -/** - * Private members of a ike_cert_t task. - */ -struct private_ike_cert_t { - - /** - * Public methods and task_t interface. - */ - ike_cert_t public; - - /** - * Assigned IKE_SA. - */ - ike_sa_t *ike_sa; - - /** - * Are we the initiator? - */ - bool initiator; - - /** - * list of CA cert hashes requested, items point to 20 byte chunk - */ - linked_list_t *cas; - - /** - * have we seen a certificate request? - */ - bool certreq_seen; -}; - -/** - * read certificate requests - */ -static void process_certreqs(private_ike_cert_t *this, message_t *message) -{ - iterator_t *iterator; - payload_t *payload; - - iterator = message->get_payload_iterator(message); - while (iterator->iterate(iterator, (void**)&payload)) - { - if (payload->get_type(payload) == CERTIFICATE_REQUEST) - { - certreq_payload_t *certreq = (certreq_payload_t*)payload; - cert_encoding_t encoding; - chunk_t keyids, keyid; - - this->certreq_seen = TRUE; - - encoding = certreq->get_cert_encoding(certreq); - if (encoding != CERT_X509_SIGNATURE) - { - DBG1(DBG_IKE, "certreq payload %N not supported - ignored", - cert_encoding_names, encoding); - continue; - } - - keyids = certreq->get_data(certreq); - - while (keyids.len >= HASH_SIZE_SHA1) - { - keyid = chunk_create(keyids.ptr, HASH_SIZE_SHA1); - keyid = chunk_clone(keyid); - this->cas->insert_last(this->cas, keyid.ptr); - keyids = chunk_skip(keyids, HASH_SIZE_SHA1); - } - } - } - iterator->destroy(iterator); -} - -/** - * import certificates - */ -static void process_certs(private_ike_cert_t *this, message_t *message) -{ - iterator_t *iterator; - payload_t *payload; - - iterator = message->get_payload_iterator(message); - while (iterator->iterate(iterator, (void**)&payload)) - { - if (payload->get_type(payload) == CERTIFICATE) - { - cert_encoding_t encoding; - x509_t *cert; - chunk_t cert_data; - bool found; - cert_payload_t *cert_payload = (cert_payload_t*)payload; - - encoding = cert_payload->get_cert_encoding(cert_payload); - if (encoding != CERT_X509_SIGNATURE) - { - DBG1(DBG_IKE, "certificate payload %N not supported - ignored", - cert_encoding_names, encoding); - continue; - } - - cert_data = cert_payload->get_data_clone(cert_payload); - cert = x509_create_from_chunk(cert_data, 0); - if (cert) - { - if (charon->credentials->verify(charon->credentials, cert, &found)) - { - DBG2(DBG_IKE, "received end entity certificate is trusted - " - "added to store"); - if (found) - { - cert->destroy(cert); - } - else - { - charon->credentials->add_end_certificate(charon->credentials, cert); - } - } - else - { - DBG1(DBG_IKE, "received end entity certificate is not trusted - " - "discarded"); - cert->destroy(cert); - } - } - else - { - DBG1(DBG_IKE, "parsing of received certificate failed - discarded"); - chunk_free(&cert_data); - } - } - } - iterator->destroy(iterator); -} - -/** - * build certificate requests - */ -static void build_certreqs(private_ike_cert_t *this, message_t *message) -{ - ike_cfg_t *ike_cfg; - peer_cfg_t *peer_cfg; - identification_t *ca; - certreq_payload_t *certreq; - - ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); - - if (ike_cfg->send_certreq(ike_cfg) != CERT_NEVER_SEND) - { - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - - if (peer_cfg) - { - ca = peer_cfg->get_other_ca(peer_cfg); - - if (ca && ca->get_type(ca) != ID_ANY) - { - certreq = certreq_payload_create_from_cacert(ca); - } - else - { - certreq = certreq_payload_create_from_cacerts(); - } - } - else - { - certreq = certreq_payload_create_from_cacerts(); - } - - if (certreq) - { - message->add_payload(message, (payload_t*)certreq); - } - } -} - -/** - * add certificates to message - */ -static void build_certs(private_ike_cert_t *this, message_t *message) -{ - peer_cfg_t *peer_cfg; - x509_t *cert; - cert_payload_t *payload; - - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - - if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == AUTH_RSA) - { - switch (peer_cfg->get_cert_policy(peer_cfg)) - { - case CERT_NEVER_SEND: - break; - case CERT_SEND_IF_ASKED: - if (!this->certreq_seen) - { - break; - } - /* FALL */ - case CERT_ALWAYS_SEND: - { - /* TODO: respect CA cert request */ - cert = charon->credentials->get_certificate(charon->credentials, - peer_cfg->get_my_id(peer_cfg)); - if (cert) - { - payload = cert_payload_create_from_x509(cert); - message->add_payload(message, (payload_t*)payload); - } - } - } - } -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t build_i(private_ike_cert_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_SA_INIT) - { - return NEED_MORE; - } - - build_certreqs(this, message); - build_certs(this, message); - - return NEED_MORE; -} - -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_cert_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_SA_INIT) - { - return NEED_MORE; - } - - process_certreqs(this, message); - process_certs(this, message); - - return NEED_MORE; -} - -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_cert_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_SA_INIT) - { - build_certreqs(this, message); - return NEED_MORE; - } - - build_certs(this, message); - - return SUCCESS; -} - -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_cert_t *this, message_t *message) -{ - if (message->get_exchange_type(message) == IKE_SA_INIT) - { - process_certreqs(this, message); - return NEED_MORE; - } - - process_certs(this, message); - return SUCCESS; -} - -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_cert_t *this) -{ - return IKE_CERT; -} - -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_cert_t *this, ike_sa_t *ike_sa) -{ - this->ike_sa = ike_sa; - - this->cas->destroy_function(this->cas, free); - this->cas = linked_list_create(); - this->certreq_seen = FALSE; -} - -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_cert_t *this) -{ - this->cas->destroy_function(this->cas, free); - free(this); -} - -/* - * Described in header. - */ -ike_cert_t *ike_cert_create(ike_sa_t *ike_sa, bool initiator) -{ - private_ike_cert_t *this = malloc_thing(private_ike_cert_t); - - this->public.task.get_type = (task_type_t(*)(task_t*))get_type; - this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; - this->public.task.destroy = (void(*)(task_t*))destroy; - - if (initiator) - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; - } - else - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; - } - - this->ike_sa = ike_sa; - this->initiator = initiator; - this->cas = linked_list_create(); - this->certreq_seen = FALSE; - - return &this->public; -} diff --git a/src/charon/sa/tasks/ike_cert_post.c b/src/charon/sa/tasks/ike_cert_post.c new file mode 100644 index 000000000..184868b28 --- /dev/null +++ b/src/charon/sa/tasks/ike_cert_post.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2006-2008 Martin Willi + * 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. + * + * $Id: ike_cert_post.c 4051 2008-06-10 09:08:27Z tobias $ + */ + +#include "ike_cert_post.h" + +#include <daemon.h> +#include <sa/ike_sa.h> +#include <encoding/payloads/cert_payload.h> +#include <encoding/payloads/certreq_payload.h> +#include <credentials/certificates/x509.h> + + +typedef struct private_ike_cert_post_t private_ike_cert_post_t; + +/** + * Private members of a ike_cert_post_t task. + */ +struct private_ike_cert_post_t { + + /** + * Public methods and task_t interface. + */ + ike_cert_post_t public; + + /** + * Assigned IKE_SA. + */ + ike_sa_t *ike_sa; + + /** + * Are we the initiator? + */ + bool initiator; +}; + +/** + * Generates the cert payload, if possible with "Hash and URL" + */ +static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certificate_t *cert) +{ + cert_payload_t *payload = NULL; + + if (this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL)) + { + /* ok, our peer sent us a HTTP_CERT_LOOKUP_SUPPORTED Notify */ + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher != NULL) + { + chunk_t hash, encoded = cert->get_encoding(cert); + enumerator_t *enumerator; + char *url; + + hasher->allocate_hash(hasher, encoded, &hash); + identification_t *id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash); + + enumerator = charon->credentials->create_cdp_enumerator(charon->credentials, CERT_X509, id); + if (enumerator->enumerate(enumerator, &url)) + { + /* if we have an URL available we send that to our peer */ + payload = cert_payload_create_from_hash_and_url(hash, url); + } + enumerator->destroy(enumerator); + + id->destroy(id); + chunk_free(&hash); + chunk_free(&encoded); + hasher->destroy(hasher); + } + else + { + DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported"); + } + } + + if (!payload) + { + /* our peer does not support "Hash and URL" or we do not have an URL + * to send to our peer, just create a normal cert payload */ + payload = cert_payload_create_from_cert(cert); + } + + return payload; +} + +/** + * add certificates to message + */ +static void build_certs(private_ike_cert_post_t *this, message_t *message) +{ + peer_cfg_t *peer_cfg; + + peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); + if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == CONF_AUTH_PUBKEY) + { + switch (peer_cfg->get_cert_policy(peer_cfg)) + { + case CERT_NEVER_SEND: + break; + case CERT_SEND_IF_ASKED: + if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN)) + { + break; + } + /* FALL */ + case CERT_ALWAYS_SEND: + { + cert_payload_t *payload; + enumerator_t *enumerator; + certificate_t *cert; + auth_info_t *auth; + auth_item_t item; + + auth = this->ike_sa->get_my_auth(this->ike_sa); + /* get subject cert first, then issuing certificates */ + if (!auth->get_item(auth, AUTHZ_SUBJECT_CERT, (void**)&cert)) + { + break; + } + payload = build_cert_payload(this, cert); + if (!payload) + { + break; + } + DBG1(DBG_IKE, "sending end entity cert \"%D\"", + cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + + enumerator = auth->create_item_enumerator(auth); + while (enumerator->enumerate(enumerator, &item, &cert)) + { + if (item == AUTHZ_IM_CERT) + { + payload = cert_payload_create_from_cert(cert); + if (payload) + { + DBG1(DBG_IKE, "sending issuer cert \"%D\"", + cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + } + } + } + enumerator->destroy(enumerator); + } + } + } +} + +/** + * Implementation of task_t.process for initiator + */ +static status_t build_i(private_ike_cert_post_t *this, message_t *message) +{ + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + return NEED_MORE; + } + build_certs(this, message); + return SUCCESS; +} + +/** + * Implementation of task_t.process for responder + */ +static status_t process_r(private_ike_cert_post_t *this, message_t *message) +{ + return NEED_MORE; +} + +/** + * Implementation of task_t.build for responder + */ +static status_t build_r(private_ike_cert_post_t *this, message_t *message) +{ + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + return NEED_MORE; + } + build_certs(this, message); + return SUCCESS; +} + +/** + * Implementation of task_t.process for initiator + */ +static status_t process_i(private_ike_cert_post_t *this, message_t *message) +{ + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + return NEED_MORE; + } + return SUCCESS; +} + +/** + * Implementation of task_t.get_type + */ +static task_type_t get_type(private_ike_cert_post_t *this) +{ + return IKE_CERT_POST; +} + +/** + * Implementation of task_t.migrate + */ +static void migrate(private_ike_cert_post_t *this, ike_sa_t *ike_sa) +{ + this->ike_sa = ike_sa; +} + +/** + * Implementation of task_t.destroy + */ +static void destroy(private_ike_cert_post_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator) +{ + private_ike_cert_post_t *this = malloc_thing(private_ike_cert_post_t); + + this->public.task.get_type = (task_type_t(*)(task_t*))get_type; + this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; + this->public.task.destroy = (void(*)(task_t*))destroy; + + if (initiator) + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; + } + else + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; + } + + this->ike_sa = ike_sa; + this->initiator = initiator; + + return &this->public; +} + diff --git a/src/charon/sa/tasks/ike_cert_post.h b/src/charon/sa/tasks/ike_cert_post.h new file mode 100644 index 000000000..78b32d67a --- /dev/null +++ b/src/charon/sa/tasks/ike_cert_post.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2008 Martin Willi + * 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. + * + * $Id: ike_cert_post.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_cert_post ike_cert_post + * @{ @ingroup tasks + */ + +#ifndef IKE_CERT_POST_H_ +#define IKE_CERT_POST_H_ + +typedef struct ike_cert_post_t ike_cert_post_t; + +#include <library.h> +#include <sa/ike_sa.h> +#include <sa/tasks/task.h> + +/** + * Task of type ike_cert_post, certificate processing after authentication. + */ +struct ike_cert_post_t { + + /** + * Implements the task_t interface + */ + task_t task; +}; + +/** + * Create a new ike_cert_post task. + * + * The initiator parameter means the original initiator, not the initiator + * of the certificate request. + * + * @param ike_sa IKE_SA this task works for + * @param initiator TRUE if thask is the original initator + * @return ike_cert_post task to handle by the task_manager + */ +ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator); + +#endif /* IKE_CERT_POST_H_ @} */ diff --git a/src/charon/sa/tasks/ike_cert_pre.c b/src/charon/sa/tasks/ike_cert_pre.c new file mode 100644 index 000000000..3568a214e --- /dev/null +++ b/src/charon/sa/tasks/ike_cert_pre.c @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2006-2007 Martin Willi + * 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. + * + * $Id: ike_cert_pre.c 3852 2008-04-18 21:27:08Z andreas $ + */ + +#include "ike_cert_pre.h" + +#include <daemon.h> +#include <sa/ike_sa.h> +#include <encoding/payloads/cert_payload.h> +#include <encoding/payloads/certreq_payload.h> +#include <credentials/certificates/x509.h> + + +typedef struct private_ike_cert_pre_t private_ike_cert_pre_t; + +/** + * Private members of a ike_cert_pre_t task. + */ +struct private_ike_cert_pre_t { + + /** + * Public methods and task_t interface. + */ + ike_cert_pre_t public; + + /** + * Assigned IKE_SA. + */ + ike_sa_t *ike_sa; + + /** + * Are we the initiator? + */ + bool initiator; + + /** + * Did we send a HTTP_CERT_LOOKUP_SUPPORTED Notify? + */ + bool http_cert_lookup_supported_sent; +}; + +/** + * read certificate requests + */ +static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) +{ + iterator_t *iterator; + payload_t *payload; + auth_info_t *auth; + bool ca_found = FALSE; + + auth = this->ike_sa->get_my_auth(this->ike_sa); + + iterator = message->get_payload_iterator(message); + while (iterator->iterate(iterator, (void**)&payload)) + { + switch(payload->get_type(payload)) + { + case CERTIFICATE_REQUEST: + { + certreq_payload_t *certreq = (certreq_payload_t*)payload; + chunk_t keyid; + enumerator_t *enumerator; + + this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE); + + if (certreq->get_cert_type(certreq) != CERT_X509) + { + DBG1(DBG_IKE, "cert payload %N not supported - ignored", + certificate_type_names, certreq->get_cert_type(certreq)); + break; + } + enumerator = certreq->create_keyid_enumerator(certreq); + while (enumerator->enumerate(enumerator, &keyid)) + { + identification_t *id; + certificate_t *cert; + + id = identification_create_from_encoding( + ID_PUBKEY_INFO_SHA1, keyid); + cert = charon->credentials->get_cert(charon->credentials, + CERT_X509, KEY_ANY, id, TRUE); + if (cert) + { + DBG1(DBG_IKE, "received cert request for \"%D\"", + cert->get_subject(cert)); + auth->add_item(auth, AUTHN_CA_CERT, cert); + cert->destroy(cert); + ca_found = TRUE; + } + else + { + DBG1(DBG_IKE, "received cert request for unknown ca " + "with keyid %D", id); + auth->add_item(auth, AUTHN_CA_CERT_KEYID, id); + } + id->destroy(id); + } + enumerator->destroy(enumerator); + break; + } + case NOTIFY: + { + notify_payload_t *notify = (notify_payload_t*)payload; + + /* we only handle one type of notify here */ + if (notify->get_notify_type(notify) == HTTP_CERT_LOOKUP_SUPPORTED) + { + this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL); + } + break; + } + default: + /* ignore other payloads here, these are handled elsewhere */ + break; + } + } + iterator->destroy(iterator); +} + +/** + * tries to extract a certificate from the cert payload or the credential + * manager (based on the hash of a "Hash and URL" encoded cert). + * Note: the returned certificate (if any) has to be destroyed + */ +static certificate_t *try_get_cert(cert_payload_t *cert_payload) +{ + certificate_t *cert = NULL; + switch (cert_payload->get_cert_encoding(cert_payload)) + { + case ENC_X509_SIGNATURE: + { + cert = cert_payload->get_cert(cert_payload); + break; + } + case ENC_X509_HASH_AND_URL: + { + identification_t *id; + chunk_t hash = cert_payload->get_hash(cert_payload); + if (!hash.ptr) + { + /* invalid "Hash and URL" data (logged elsewhere) */ + break; + } + id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash); + cert = charon->credentials->get_cert(charon->credentials, + CERT_X509, KEY_ANY, id, FALSE); + id->destroy(id); + break; + } + default: + { + break; + } + } + return cert; +} + +/** + * import certificates + */ +static void process_certs(private_ike_cert_pre_t *this, message_t *message) +{ + iterator_t *iterator; + payload_t *payload; + auth_info_t *auth; + bool first = TRUE; + + auth = this->ike_sa->get_other_auth(this->ike_sa); + + iterator = message->get_payload_iterator(message); + while (iterator->iterate(iterator, (void**)&payload)) + { + if (payload->get_type(payload) == CERTIFICATE) + { + cert_payload_t *cert_payload = (cert_payload_t*)payload; + cert_encoding_t type = cert_payload->get_cert_encoding(cert_payload); + switch (type) + { + case ENC_X509_SIGNATURE: + case ENC_X509_HASH_AND_URL: + { + if (type == ENC_X509_HASH_AND_URL && + !this->http_cert_lookup_supported_sent) + { + DBG1(DBG_IKE, "received hash-and-url encoded cert, but" + " we don't accept them, ignore"); + break; + } + + certificate_t *cert = try_get_cert(cert_payload); + + if (cert) + { + /* we've got a certificate from the payload or the cache */ + if (first) + { /* the first certificate MUST be an end entity one */ + DBG1(DBG_IKE, "received end entity cert \"%D\"", + cert->get_subject(cert)); + auth->add_item(auth, AUTHN_SUBJECT_CERT, cert); + first = FALSE; + } + else + { + DBG1(DBG_IKE, "received issuer cert \"%D\"", + cert->get_subject(cert)); + auth->add_item(auth, AUTHN_IM_CERT, cert); + } + cert->destroy(cert); + } + else if (type == ENC_X509_HASH_AND_URL) + { + /* we received a "Hash and URL" encoded certificate that + * we haven't fetched yet, we store the URL and fetch + * it later */ + char *url = cert_payload->get_url(cert_payload); + if (!url) + { + DBG1(DBG_IKE, "received invalid hash-and-url encoded" + " cert, ignore"); + break; + } + + if (first) + { /* the first certificate MUST be an end entity one */ + DBG1(DBG_IKE, "received hash-and-url for end" + " entity cert \"%s\"", url); + auth->add_item(auth, AUTHN_SUBJECT_HASH_URL, url); + first = FALSE; + } + else + { + DBG1(DBG_IKE, "received hash-and-url for issuer" + " cert \"%s\"", url); + auth->add_item(auth, AUTHN_IM_HASH_URL, url); + } + } + break; + } + case ENC_PKCS7_WRAPPED_X509: + case ENC_PGP: + case ENC_DNS_SIGNED_KEY: + case ENC_KERBEROS_TOKEN: + case ENC_CRL: + case ENC_ARL: + case ENC_SPKI: + case ENC_X509_ATTRIBUTE: + case ENC_RAW_RSA_KEY: + case ENC_X509_HASH_AND_URL_BUNDLE: + case ENC_OCSP_CONTENT: + default: + DBG1(DBG_ENC, "certificate encoding %N not supported", + cert_encoding_names, cert_payload->get_cert_encoding(cert_payload)); + } + } + } + iterator->destroy(iterator); +} + +/** + * add a certificate request to the message, building request payload if required. + */ +static void add_certreq_payload(message_t *message, certreq_payload_t **reqp, + certificate_t *cert) +{ + public_key_t *public; + certreq_payload_t *req; + + public = cert->get_public_key(cert); + if (!public) + { + return; + } + switch (cert->get_type(cert)) + { + case CERT_X509: + { + identification_t *keyid; + x509_t *x509 = (x509_t*)cert; + + if (!(x509->get_flags(x509) & X509_CA)) + { /* no CA cert, skip */ + break; + } + if (*reqp == NULL) + { + *reqp = certreq_payload_create_type(CERT_X509); + message->add_payload(message, (payload_t*)*reqp); + } + req = *reqp; + keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1); + req->add_keyid(req, keyid->get_encoding(keyid)); + DBG1(DBG_IKE, "sending cert request for \"%D\"", + cert->get_subject(cert)); + break; + } + default: + break; + } + public->destroy(public); +} + +/** + * build certificate requests + */ +static void build_certreqs(private_ike_cert_pre_t *this, message_t *message) +{ + ike_cfg_t *ike_cfg; + enumerator_t *enumerator; + certificate_t *cert; + auth_info_t *auth; + bool restricted = FALSE; + auth_item_t item; + certreq_payload_t *x509_req = NULL; + + ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa); + if (!ike_cfg->send_certreq(ike_cfg)) + { + return; + } + auth = this->ike_sa->get_other_auth(this->ike_sa); + + /* check if we require a specific CA for that peer */ + enumerator = auth->create_item_enumerator(auth); + while (enumerator->enumerate(enumerator, &item, &cert)) + { + if (item == AUTHN_CA_CERT) + { + restricted = TRUE; + add_certreq_payload(message, &x509_req, cert); + } + } + enumerator->destroy(enumerator); + + if (!restricted) + { + /* otherwise include all trusted CA certificates */ + enumerator = charon->credentials->create_cert_enumerator( + charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE); + while (enumerator->enumerate(enumerator, &cert, TRUE)) + { + add_certreq_payload(message, &x509_req, cert); + } + enumerator->destroy(enumerator); + } + + /* if we've added at least one certreq, we notify our peer that we support + * "Hash and URL" for the requested certificates */ + if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE) && + message->get_payload(message, CERTIFICATE_REQUEST)) + { + message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED, chunk_empty); + this->http_cert_lookup_supported_sent = TRUE; + } +} + +/** + * Implementation of task_t.process for initiator + */ +static status_t build_i(private_ike_cert_pre_t *this, message_t *message) +{ + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + return NEED_MORE; + } + build_certreqs(this, message); + return NEED_MORE; +} + +/** + * Implementation of task_t.process for responder + */ +static status_t process_r(private_ike_cert_pre_t *this, message_t *message) +{ + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + return NEED_MORE; + } + process_certreqs(this, message); + process_certs(this, message); + return NEED_MORE; +} + +/** + * Implementation of task_t.build for responder + */ +static status_t build_r(private_ike_cert_pre_t *this, message_t *message) +{ + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + build_certreqs(this, message); + return NEED_MORE; + } + return SUCCESS; +} + +/** + * Implementation of task_t.process for initiator + */ +static status_t process_i(private_ike_cert_pre_t *this, message_t *message) +{ + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + process_certreqs(this, message); + return NEED_MORE; + } + process_certs(this, message); + return SUCCESS; +} + +/** + * Implementation of task_t.get_type + */ +static task_type_t get_type(private_ike_cert_pre_t *this) +{ + return IKE_CERT_PRE; +} + +/** + * Implementation of task_t.migrate + */ +static void migrate(private_ike_cert_pre_t *this, ike_sa_t *ike_sa) +{ + this->ike_sa = ike_sa; +} + +/** + * Implementation of task_t.destroy + */ +static void destroy(private_ike_cert_pre_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator) +{ + private_ike_cert_pre_t *this = malloc_thing(private_ike_cert_pre_t); + + this->public.task.get_type = (task_type_t(*)(task_t*))get_type; + this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; + this->public.task.destroy = (void(*)(task_t*))destroy; + + if (initiator) + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; + } + else + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; + } + + this->ike_sa = ike_sa; + this->initiator = initiator; + this->http_cert_lookup_supported_sent = FALSE; + + return &this->public; +} diff --git a/src/charon/sa/tasks/ike_cert.h b/src/charon/sa/tasks/ike_cert_pre.h index ba0283953..d8793a8e2 100644 --- a/src/charon/sa/tasks/ike_cert.h +++ b/src/charon/sa/tasks/ike_cert_pre.h @@ -1,12 +1,5 @@ -/** - * @file ike_cert.h - * - * @brief Interface ike_cert_t. - * - */ - /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2007-2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,27 +11,28 @@ * 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. + * + * $Id: ike_cert_pre.h 3589 2008-03-13 14:14:44Z martin $ */ -#ifndef IKE_CERT_H_ -#define IKE_CERT_H_ +/** + * @defgroup ike_cert_pre ike_cert_pre + * @{ @ingroup tasks + */ -typedef struct ike_cert_t ike_cert_t; +#ifndef IKE_CERT_PRE_H_ +#define IKE_CERT_PRE_H_ + +typedef struct ike_cert_pre_t ike_cert_pre_t; #include <library.h> #include <sa/ike_sa.h> #include <sa/tasks/task.h> /** - * @brief Task of type ike_cert, exchanges certificates and - * certificate requests. - * - * @b Constructors: - * - ike_cert_create() - * - * @ingroup tasks + * Task of type ike_cert_post, certificate processing before authentication. */ -struct ike_cert_t { +struct ike_cert_pre_t { /** * Implements the task_t interface @@ -47,15 +41,15 @@ struct ike_cert_t { }; /** - * @brief Create a new ike_cert task. + * Create a new ike_cert_pre task. * * The initiator parameter means the original initiator, not the initiator * of the certificate request. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE if thask is the original initator - * @return ike_cert task to handle by the task_manager + * @return ike_cert_pre task to handle by the task_manager */ -ike_cert_t *ike_cert_create(ike_sa_t *ike_sa, bool initiator); +ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_CERT_H_ */ +#endif /* IKE_CERT_PRE_H_ @} */ diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c index 3c73395a5..c31e62750 100644 --- a/src/charon/sa/tasks/ike_config.c +++ b/src/charon/sa/tasks/ike_config.c @@ -1,10 +1,3 @@ -/** - * @file ike_config.c - * - * @brief Implementation of the ike_config task. - * - */ - /* * Copyright (C) 2007 Martin Willi * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser @@ -19,6 +12,8 @@ * 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. + * + * $Id: ike_config.c 3800 2008-04-14 07:18:16Z martin $ */ #include "ike_config.h" @@ -266,14 +261,14 @@ static status_t build_i(private_ike_config_t *this, message_t *message) /* reuse virtual IP if we already have one */ vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); - if (vip) + if (!vip) { - this->virtual_ip = vip->clone(vip); + config = this->ike_sa->get_peer_cfg(this->ike_sa); + vip = config->get_virtual_ip(config); } - else + if (vip) { - config = this->ike_sa->get_peer_cfg(this->ike_sa); - this->virtual_ip = config->get_my_virtual_ip(config); + this->virtual_ip = vip->clone(vip); } build_payloads(this, message, CFG_REQUEST); @@ -307,14 +302,20 @@ static status_t build_r(private_ike_config_t *this, message_t *message) if (config && this->virtual_ip) { - host_t *ip; + host_t *ip = NULL; DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip); - ip = config->get_other_virtual_ip(config, this->virtual_ip); - if (ip == NULL || ip->is_anyaddr(ip)) + if (config->get_pool(config)) + { + ip = charon->attributes->acquire_address(charon->attributes, + config->get_pool(config), + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_other_auth(this->ike_sa), + this->virtual_ip); + } + if (ip == NULL) { DBG1(DBG_IKE, "not assigning a virtual IP to peer"); - DESTROY_IF(ip); return SUCCESS; } DBG1(DBG_IKE, "assigning virtual IP %H to peer", ip); @@ -323,16 +324,6 @@ static status_t build_r(private_ike_config_t *this, message_t *message) this->virtual_ip->destroy(this->virtual_ip); this->virtual_ip = ip; - /* DNS testing values - if (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS) - { - ip->destroy(ip); - ip = host_create_from_string("10.3.0.1", 0); - this->dns->insert_last(this->dns, ip); - ip = host_create_from_string("10.3.0.2", 0); - this->dns->insert_last(this->dns, ip); - } */ - build_payloads(this, message, CFG_REPLY); } return SUCCESS; @@ -359,7 +350,11 @@ static status_t process_i(private_ike_config_t *this, message_t *message) if (this->virtual_ip == NULL) { /* force a configured virtual IP, even server didn't return one */ config = this->ike_sa->get_peer_cfg(this->ike_sa); - this->virtual_ip = config->get_my_virtual_ip(config); + this->virtual_ip = config->get_virtual_ip(config); + if (this->virtual_ip) + { + this->virtual_ip = this->virtual_ip->clone(this->virtual_ip); + } } if (this->virtual_ip && !this->virtual_ip->is_anyaddr(this->virtual_ip)) diff --git a/src/charon/sa/tasks/ike_config.h b/src/charon/sa/tasks/ike_config.h index a7cfddff0..23410a196 100644 --- a/src/charon/sa/tasks/ike_config.h +++ b/src/charon/sa/tasks/ike_config.h @@ -1,10 +1,3 @@ -/** - * @file ike_config.h - * - * @brief Interface ike_config_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_config.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_config ike_config + * @{ @ingroup tasks */ #ifndef IKE_CONFIG_H_ @@ -30,13 +30,8 @@ typedef struct ike_config_t ike_config_t; #include <sa/tasks/task.h> /** - * @brief Task of type IKE_CONFIG, sets up a virtual IP and other + * Task of type IKE_CONFIG, sets up a virtual IP and other * configurations for an IKE_SA. - * - * @b Constructors: - * - ike_config_create() - * - * @ingroup tasks */ struct ike_config_t { @@ -47,7 +42,7 @@ struct ike_config_t { }; /** - * @brief Create a new ike_config task. + * Create a new ike_config task. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE for initiator @@ -55,4 +50,4 @@ struct ike_config_t { */ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_CONFIG_H_ */ +#endif /* IKE_CONFIG_H_ @} */ diff --git a/src/charon/sa/tasks/ike_delete.c b/src/charon/sa/tasks/ike_delete.c index 1a3656ca6..aa7950ef7 100644 --- a/src/charon/sa/tasks/ike_delete.c +++ b/src/charon/sa/tasks/ike_delete.c @@ -1,10 +1,3 @@ -/** - * @file ike_delete.c - * - * @brief Implementation of the ike_delete task. - * - */ - /* * Copyright (C) 2006-2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: ike_delete.c 3802 2008-04-14 08:17:18Z martin $ */ #include "ike_delete.h" @@ -87,18 +82,18 @@ static status_t process_r(private_ike_delete_t *this, message_t *message) * come so far without being correct */ switch (this->ike_sa->get_state(this->ike_sa)) { - case IKE_DELETING: - this->simultaneous = TRUE; - break; case IKE_ESTABLISHED: DBG1(DBG_IKE, "deleting IKE_SA on request"); + this->ike_sa->set_state(this->ike_sa, IKE_DELETING); + this->ike_sa->reestablish(this->ike_sa); break; - case IKE_REKEYING: - break; + case IKE_DELETING: + this->simultaneous = TRUE; + /* FALL */ default: + this->ike_sa->set_state(this->ike_sa, IKE_DELETING); break; } - this->ike_sa->set_state(this->ike_sa, IKE_DELETING); return NEED_MORE; } diff --git a/src/charon/sa/tasks/ike_delete.h b/src/charon/sa/tasks/ike_delete.h index e8ec5ebbe..6d08d345d 100644 --- a/src/charon/sa/tasks/ike_delete.h +++ b/src/charon/sa/tasks/ike_delete.h @@ -1,10 +1,3 @@ -/** - * @file ike_delete.h - * - * @brief Interface ike_delete_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_delete.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_delete ike_delete + * @{ @ingroup tasks */ #ifndef IKE_DELETE_H_ @@ -30,12 +30,7 @@ typedef struct ike_delete_t ike_delete_t; #include <sa/tasks/task.h> /** - * @brief Task of type ike_delete, delete an IKE_SA. - * - * @b Constructors: - * - ike_delete_create() - * - * @ingroup tasks + * Task of type ike_delete, delete an IKE_SA. */ struct ike_delete_t { @@ -46,7 +41,7 @@ struct ike_delete_t { }; /** - * @brief Create a new ike_delete task. + * Create a new ike_delete task. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE if we initiate the delete @@ -54,4 +49,4 @@ struct ike_delete_t { */ ike_delete_t *ike_delete_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_DELETE_H_ */ +#endif /* IKE_DELETE_H_ @} */ diff --git a/src/charon/sa/tasks/ike_dpd.c b/src/charon/sa/tasks/ike_dpd.c index be751766e..9f1d43cbf 100644 --- a/src/charon/sa/tasks/ike_dpd.c +++ b/src/charon/sa/tasks/ike_dpd.c @@ -1,10 +1,3 @@ -/** - * @file ike_dpd.c - * - * @brief Implementation of the ike_dpd task. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: ike_dpd.c 3589 2008-03-13 14:14:44Z martin $ */ #include "ike_dpd.h" diff --git a/src/charon/sa/tasks/ike_dpd.h b/src/charon/sa/tasks/ike_dpd.h index 531b0502d..62b8a6a10 100644 --- a/src/charon/sa/tasks/ike_dpd.h +++ b/src/charon/sa/tasks/ike_dpd.h @@ -1,10 +1,3 @@ -/** - * @file ike_dpd.h - * - * @brief Interface ike_dpd_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_dpd.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_dpd ike_dpd + * @{ @ingroup tasks */ #ifndef IKE_DPD_H_ @@ -30,14 +30,9 @@ typedef struct ike_dpd_t ike_dpd_t; #include <sa/tasks/task.h> /** - * @brief Task of type ike_dpd, detects dead peers. + * Task of type ike_dpd, detects dead peers. * * The DPD task actually does nothing, as a DPD has no associated payloads. - * - * @b Constructors: - * - ike_dpd_create() - * - * @ingroup tasks */ struct ike_dpd_t { @@ -48,11 +43,11 @@ struct ike_dpd_t { }; /** - * @brief Create a new ike_dpd task. + * Create a new ike_dpd task. * * @param initiator TRUE if thask is the original initator * @return ike_dpd task to handle by the task_manager */ ike_dpd_t *ike_dpd_create(bool initiator); -#endif /* IKE_DPD_H_ */ +#endif /* IKE_DPD_H_ @} */ diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index 42b47a82f..7def3a556 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -1,11 +1,5 @@ -/** - * @file ike_init.c - * - * @brief Implementation of the ike_init task. - * - */ - /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -19,6 +13,8 @@ * 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. + * + * $Id: ike_init.c 4086 2008-06-22 11:24:33Z andreas $ */ #include "ike_init.h" @@ -195,7 +191,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message) this->dh_group = ke_payload->get_dh_group_number(ke_payload); if (!this->initiator) { - this->dh = diffie_hellman_create(this->dh_group); + this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); } if (this->dh) { @@ -222,13 +218,12 @@ static void process_payloads(private_ike_init_t *this, message_t *message) */ static status_t build_i(private_ike_init_t *this, message_t *message) { - randomizer_t *randomizer; - status_t status; + rng_t *rng; this->config = this->ike_sa->get_ike_cfg(this->ike_sa); SIG(IKE_UP_START, "initiating IKE_SA '%s' to %H", this->ike_sa->get_name(this->ike_sa), - this->config->get_other_host(this->config)); + this->ike_sa->get_other_host(this->ike_sa)); this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING); if (this->retry++ >= MAX_RETRIES) @@ -241,7 +236,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message) if (!this->dh) { this->dh_group = this->config->get_dh_group(this->config); - this->dh = diffie_hellman_create(this->dh_group); + this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); if (this->dh == NULL) { SIG(IKE_UP_FAILED, "configured DH group %N not supported", @@ -253,15 +248,14 @@ static status_t build_i(private_ike_init_t *this, message_t *message) /* generate nonce only when we are trying the first time */ if (this->my_nonce.ptr == NULL) { - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, - &this->my_nonce); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { - SIG(IKE_UP_FAILED, "error generating random nonce value"); + SIG(IKE_UP_FAILED, "error generating nonce"); return FAILED; } + rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce); + rng->destroy(rng); } if (this->cookie.ptr) @@ -270,30 +264,90 @@ static status_t build_i(private_ike_init_t *this, message_t *message) } build_payloads(this, message); - + +#ifdef ME + { + chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa); + if (connect_id.ptr) + { + message->add_notify(message, FALSE, ME_CONNECTID, connect_id); + } + } +#endif /* ME */ return NEED_MORE; } /** - * Implementation of task_t.process for initiator + * Implementation of task_t.process for responder */ static status_t process_r(private_ike_init_t *this, message_t *message) { - randomizer_t *randomizer; + rng_t *rng; this->config = this->ike_sa->get_ike_cfg(this->ike_sa); - SIG(IKE_UP_FAILED, "%H is initiating an IKE_SA", + SIG(IKE_UP_START, "%H is initiating an IKE_SA", message->get_source(message)); this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING); - randomizer = randomizer_create(); - if (randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, - &this->my_nonce) != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) + { + DBG1(DBG_IKE, "error generating nonce"); + return FAILED; + } + rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce); + rng->destroy(rng); + +#ifdef ME { - DBG1(DBG_IKE, "error generating random nonce value"); + chunk_t connect_id = chunk_empty; + iterator_t *iterator; + payload_t *payload; + + /* check for a ME_CONNECTID notify */ + iterator = message->get_payload_iterator(message); + while (iterator->iterate(iterator, (void**)&payload)) + { + if (payload->get_type(payload) == NOTIFY) + { + notify_payload_t *notify = (notify_payload_t*)payload; + notify_type_t type = notify->get_notify_type(notify); + + switch (type) + { + case ME_CONNECTID: + { + chunk_free(&connect_id); + connect_id = chunk_clone(notify->get_notification_data(notify)); + DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id); + break; + } + default: + { + if (type < 16383) + { + DBG1(DBG_IKE, "received %N notify error", + notify_type_names, type); + break; + } + DBG2(DBG_IKE, "received %N notify", + notify_type_names, type); + break; + } + } + } + } + iterator->destroy(iterator); + + if (connect_id.ptr) + { + charon->connect_manager->stop_checks(charon->connect_manager, + connect_id); + chunk_free(&connect_id); + } } - randomizer->destroy(randomizer); +#endif /* ME */ process_payloads(this, message); @@ -321,11 +375,11 @@ static status_t build_r(private_ike_init_t *this, message_t *message) !this->proposal->has_dh_group(this->proposal, this->dh_group) || this->dh->get_shared_secret(this->dh, &secret) != SUCCESS) { - algorithm_t *algo; + u_int16_t group; + if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, - &algo)) + &group, NULL)) { - u_int16_t group = algo->algorithm; SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N", diffie_hellman_group_names, this->dh_group, diffie_hellman_group_names, group); @@ -370,9 +424,16 @@ static status_t build_r(private_ike_init_t *this, message_t *message) message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); return FAILED; } - - build_payloads(this, message); + /* Keep the selected IKE proposal for status information purposes */ + { + char buf[BUF_LEN]; + + snprintf(buf, BUF_LEN, "%P", this->proposal); + this->ike_sa->set_proposal(this->ike_sa, buf+4); + } + + build_payloads(this, message); return SUCCESS; } @@ -427,7 +488,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message) this->cookie = chunk_clone(notify->get_notification_data(notify)); this->ike_sa->reset(this->ike_sa); iterator->destroy(iterator); - DBG1(DBG_IKE, "received %N notify", notify_type_names, type); + DBG2(DBG_IKE, "received %N notify", notify_type_names, type); return NEED_MORE; } default: @@ -439,7 +500,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message) iterator->destroy(iterator); return FAILED; } - DBG1(DBG_IKE, "received %N notify", + DBG2(DBG_IKE, "received %N notify", notify_type_names, type); break; } @@ -454,7 +515,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message) if (this->proposal == NULL || this->other_nonce.len == 0 || this->my_nonce.len == 0) { - SIG(IKE_UP_FAILED, "peers proposal selection invalid"); + SIG(IKE_UP_FAILED, "peer's proposal selection invalid"); return FAILED; } @@ -462,7 +523,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message) !this->proposal->has_dh_group(this->proposal, this->dh_group) || this->dh->get_shared_secret(this->dh, &secret) != SUCCESS) { - SIG(IKE_UP_FAILED, "peers DH group selection invalid"); + SIG(IKE_UP_FAILED, "peer's DH group selection invalid"); return FAILED; } @@ -494,6 +555,15 @@ static status_t process_i(private_ike_init_t *this, message_t *message) SIG(IKE_UP_FAILED, "key derivation failed"); return FAILED; } + + /* Keep the selected IKE proposal for status information purposes */ + { + char buf[BUF_LEN]; + + snprintf(buf, BUF_LEN, "%P", this->proposal); + this->ike_sa->set_proposal(this->ike_sa, buf+4); + } + return SUCCESS; } @@ -532,7 +602,7 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa) this->ike_sa = ike_sa; this->proposal = NULL; - this->dh = diffie_hellman_create(this->dh_group); + this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); } /** diff --git a/src/charon/sa/tasks/ike_init.h b/src/charon/sa/tasks/ike_init.h index f60c096e8..0e5a913fd 100644 --- a/src/charon/sa/tasks/ike_init.h +++ b/src/charon/sa/tasks/ike_init.h @@ -1,10 +1,3 @@ -/** - * @file ike_init.h - * - * @brief Interface ike_init_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_init.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_init ike_init + * @{ @ingroup tasks */ #ifndef IKE_INIT_H_ @@ -30,14 +30,9 @@ typedef struct ike_init_t ike_init_t; #include <sa/tasks/task.h> /** - * @brief Task of type IKE_INIT, creates an IKE_SA without authentication. + * Task of type IKE_INIT, creates an IKE_SA without authentication. * * The authentication of is handle in the ike_auth task. - * - * @b Constructors: - * - ike_init_create() - * - * @ingroup tasks */ struct ike_init_t { @@ -47,16 +42,15 @@ struct ike_init_t { task_t task; /** - * @brief Get the lower of the two nonces, used for rekey collisions. + * Get the lower of the two nonces, used for rekey collisions. * - * @param this calling object * @return lower nonce */ chunk_t (*get_lower_nonce) (ike_init_t *this); }; /** - * @brief Create a new IKE_INIT task. + * Create a new IKE_INIT task. * * @param ike_sa IKE_SA this task works for (new one when rekeying) * @param initiator TRUE if thask is the original initator @@ -65,4 +59,4 @@ struct ike_init_t { */ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa); -#endif /* IKE_INIT_H_ */ +#endif /* IKE_INIT_H_ @} */ diff --git a/src/charon/sa/tasks/ike_p2p.c b/src/charon/sa/tasks/ike_me.c index 84b88e16b..2d7c64d70 100644 --- a/src/charon/sa/tasks/ike_p2p.c +++ b/src/charon/sa/tasks/ike_me.c @@ -1,12 +1,5 @@ -/** - * @file ike_p2p.c - * - * @brief Implementation of the ike_p2p task. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,9 +11,11 @@ * 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. + * + * $Id: ike_me.c 3806 2008-04-15 05:56:35Z martin $ */ - -#include "ike_p2p.h" + +#include "ike_me.h" #include <string.h> @@ -31,27 +26,20 @@ #include <encoding/payloads/endpoint_notify.h> #include <processing/jobs/mediation_job.h> -#define P2P_SESSIONID_LEN 8 -#define P2P_SESSIONKEY_LEN 16 +#define ME_CONNECTID_LEN 4 +#define ME_CONNECTKEY_LEN 16 -/* FIXME: proposed values */ -#define P2P_SESSIONID_MIN_LEN 4 -#define P2P_SESSIONID_MAX_LEN 16 -#define P2P_SESSIONKEY_MIN_LEN 8 -#define P2P_SESSIONKEY_MAX_LEN 64 - - -typedef struct private_ike_p2p_t private_ike_p2p_t; +typedef struct private_ike_me_t private_ike_me_t; /** - * Private members of a ike_p2p_t task. + * Private members of a ike_me_t task. */ -struct private_ike_p2p_t { +struct private_ike_me_t { /** * Public methods and task_t interface. */ - ike_p2p_t public; + ike_me_t public; /** * Assigned IKE_SA. @@ -105,12 +93,12 @@ struct private_ike_p2p_t { /** * Received ID used for connectivity checks */ - chunk_t session_id; + chunk_t connect_id; /** * Received key used for connectivity checks */ - chunk_t session_key; + chunk_t connect_key; /** * Peer config of the mediated connection @@ -138,7 +126,7 @@ static void add_endpoints_to_message(message_t *message, linked_list_t *endpoint /** * Gathers endpoints and adds them to the current message */ -static void gather_and_add_endpoints(private_ike_p2p_t *this, message_t *message) +static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message) { iterator_t *iterator; host_t *addr, *host; @@ -176,7 +164,7 @@ static void gather_and_add_endpoints(private_ike_p2p_t *this, message_t *message /** * read notifys from message and evaluate them */ -static void process_payloads(private_ike_p2p_t *this, message_t *message) +static void process_payloads(private_ike_me_t *this, message_t *message) { iterator_t *iterator; payload_t *payload; @@ -193,55 +181,55 @@ static void process_payloads(private_ike_p2p_t *this, message_t *message) switch (notify->get_notify_type(notify)) { - case P2P_CONNECT_FAILED: + case ME_CONNECT_FAILED: { - DBG2(DBG_IKE, "received P2P_CONNECT_FAILED notify"); + DBG2(DBG_IKE, "received ME_CONNECT_FAILED notify"); this->failed = TRUE; break; } - case P2P_MEDIATION: + case ME_MEDIATION: { - DBG2(DBG_IKE, "received P2P_MEDIATION notify"); + DBG2(DBG_IKE, "received ME_MEDIATION notify"); this->mediation = TRUE; break; } - case P2P_ENDPOINT: + case ME_ENDPOINT: { endpoint_notify_t *endpoint = endpoint_notify_create_from_payload(notify); if (!endpoint) { - DBG1(DBG_IKE, "received invalid P2P_ENDPOINT notify"); + DBG1(DBG_IKE, "received invalid ME_ENDPOINT notify"); break; } - DBG1(DBG_IKE, "received %N P2P_ENDPOINT %#H", p2p_endpoint_type_names, + DBG1(DBG_IKE, "received %N ME_ENDPOINT %#H", me_endpoint_type_names, endpoint->get_type(endpoint), endpoint->get_host(endpoint)); this->remote_endpoints->insert_last(this->remote_endpoints, endpoint); break; } - case P2P_CALLBACK: + case ME_CALLBACK: { - DBG2(DBG_IKE, "received P2P_CALLBACK notify"); + DBG2(DBG_IKE, "received ME_CALLBACK notify"); this->callback = TRUE; break; } - case P2P_SESSIONID: + case ME_CONNECTID: { - chunk_free(&this->session_id); - this->session_id = chunk_clone(notify->get_notification_data(notify)); - DBG3(DBG_IKE, "received p2p_sessionid %B", &this->session_id); + chunk_free(&this->connect_id); + this->connect_id = chunk_clone(notify->get_notification_data(notify)); + DBG2(DBG_IKE, "received ME_CONNECTID %#B", &this->connect_id); break; } - case P2P_SESSIONKEY: + case ME_CONNECTKEY: { - chunk_free(&this->session_key); - this->session_key = chunk_clone(notify->get_notification_data(notify)); - DBG4(DBG_IKE, "received p2p_sessionkey %B", &this->session_key); + chunk_free(&this->connect_key); + this->connect_key = chunk_clone(notify->get_notification_data(notify)); + DBG4(DBG_IKE, "received ME_CONNECTKEY %#B", &this->connect_key); break; } - case P2P_RESPONSE: + case ME_RESPONSE: { - DBG2(DBG_IKE, "received P2P_RESPONSE notify"); + DBG2(DBG_IKE, "received ME_RESPONSE notify"); this->response = TRUE; break; } @@ -253,9 +241,9 @@ static void process_payloads(private_ike_p2p_t *this, message_t *message) } /** - * Implementation of task_t.process for initiator + * Implementation of task_t.build for initiator */ -static status_t build_i(private_ike_p2p_t *this, message_t *message) +static status_t build_i(private_ike_me_t *this, message_t *message) { switch(message->get_exchange_type(message)) { @@ -264,8 +252,8 @@ static status_t build_i(private_ike_p2p_t *this, message_t *message) peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); if (peer_cfg->is_mediation(peer_cfg)) { - DBG2(DBG_IKE, "adding P2P_MEDIATION"); - message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty); + DBG2(DBG_IKE, "adding ME_MEDIATION"); + message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty); } else { @@ -283,48 +271,40 @@ static status_t build_i(private_ike_p2p_t *this, message_t *message) } break; } - case P2P_CONNECT: + case ME_CONNECT: { id_payload_t *id_payload; - randomizer_t *rand = randomizer_create(); + rng_t *rng; id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id); message->add_payload(message, (payload_t*)id_payload); - if (!this->response) + rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (!rng) { - /* only the initiator creates a session ID. the responder returns - * the session ID that it received from the initiator */ - if (rand->allocate_pseudo_random_bytes(rand, - P2P_SESSIONID_LEN, &this->session_id) != SUCCESS) - { - DBG1(DBG_IKE, "unable to generate session ID for P2P_CONNECT"); - rand->destroy(rand); - return FAILED; - } + DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT"); + return FAILED; } - - if (rand->allocate_pseudo_random_bytes(rand, - P2P_SESSIONKEY_LEN, &this->session_key) != SUCCESS) + if (!this->response) { - DBG1(DBG_IKE, "unable to generate session key for P2P_CONNECT"); - rand->destroy(rand); - return FAILED; + /* only the initiator creates a connect ID. the responder returns + * the connect ID that it received from the initiator */ + rng->allocate_bytes(rng, ME_CONNECTID_LEN, &this->connect_id); } + rng->allocate_bytes(rng, ME_CONNECTKEY_LEN, &this->connect_key); + rng->destroy(rng); - rand->destroy(rand); - - message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id); - message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key); + message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id); + message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key); if (this->response) { - message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty); + message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty); } else { - /* FIXME: should we make that configurable */ - message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty); + /* FIXME: should we make that configurable? */ + message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty); } gather_and_add_endpoints(this, message); @@ -340,17 +320,17 @@ static status_t build_i(private_ike_p2p_t *this, message_t *message) /** * Implementation of task_t.process for responder */ -static status_t process_r(private_ike_p2p_t *this, message_t *message) +static status_t process_r(private_ike_me_t *this, message_t *message) { switch(message->get_exchange_type(message)) { - case P2P_CONNECT: + case ME_CONNECT: { id_payload_t *id_payload; id_payload = (id_payload_t*)message->get_payload(message, ID_PEER); if (!id_payload) { - DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload, aborting"); break; } this->peer_id = id_payload->get_identification(id_payload); @@ -359,32 +339,32 @@ static status_t process_r(private_ike_p2p_t *this, message_t *message) if (this->callback) { - DBG1(DBG_IKE, "received P2P_CALLBACK for '%D'", this->peer_id); + DBG1(DBG_IKE, "received ME_CALLBACK for '%D'", this->peer_id); break; } - if (!this->session_id.ptr) + if (!this->connect_id.ptr) { - DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify, aborting"); this->invalid_syntax = TRUE; break; } - if (!this->session_key.ptr) + if (!this->connect_key.ptr) { - DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify, aborting"); this->invalid_syntax = TRUE; break; } if (!this->remote_endpoints->get_count(this->remote_endpoints)) { - DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT payloads, aborting"); this->invalid_syntax = TRUE; break; } - DBG1(DBG_IKE, "received P2P_CONNECT"); + DBG1(DBG_IKE, "received ME_CONNECT"); break; } default: @@ -396,11 +376,11 @@ static status_t process_r(private_ike_p2p_t *this, message_t *message) /** * Implementation of task_t.build for responder */ -static status_t build_r(private_ike_p2p_t *this, message_t *message) +static status_t build_r(private_ike_me_t *this, message_t *message) { switch(message->get_exchange_type(message)) { - case P2P_CONNECT: + case ME_CONNECT: { if (this->invalid_syntax) { @@ -422,7 +402,7 @@ static status_t build_r(private_ike_p2p_t *this, message_t *message) * as initiator, upon receiving a response from another peer, * update the checklist and start sending checks */ charon->connect_manager->set_responder_data(charon->connect_manager, - this->session_id, this->session_key, this->remote_endpoints); + this->connect_id, this->connect_key, this->remote_endpoints); } else { @@ -430,10 +410,10 @@ static status_t build_r(private_ike_p2p_t *this, message_t *message) * as responder, create a checklist with the initiator's data */ charon->connect_manager->set_initiator_data(charon->connect_manager, this->peer_id, this->ike_sa->get_my_id(this->ike_sa), - this->session_id, this->session_key, this->remote_endpoints, + this->connect_id, this->connect_key, this->remote_endpoints, FALSE); if (this->ike_sa->respond(this->ike_sa, this->peer_id, - this->session_id) != SUCCESS) + this->connect_id) != SUCCESS) { return FAILED; } @@ -449,7 +429,7 @@ static status_t build_r(private_ike_p2p_t *this, message_t *message) /** * Implementation of task_t.process for initiator */ -static status_t process_i(private_ike_p2p_t *this, message_t *message) +static status_t process_i(private_ike_me_t *this, message_t *message) { switch(message->get_exchange_type(message)) { @@ -459,7 +439,7 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message) if (!this->mediation) { - DBG1(DBG_IKE, "server did not return a P2P_MEDIATION, aborting"); + DBG1(DBG_IKE, "server did not return a ME_MEDIATION, aborting"); return FAILED; } @@ -485,16 +465,14 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message) break; } - case P2P_CONNECT: + case ME_CONNECT: { process_payloads(this, message); if (this->failed) { DBG1(DBG_IKE, "peer '%D' is not online", this->peer_id); - /* FIXME: notify the mediated connection (job?) - * FIXME: probably delete the created checklist, at least as - * responder */ + /* FIXME: notify the mediated connection (job?) */ } else { @@ -503,7 +481,7 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message) /* FIXME: handle result of set_responder_data. * as responder, we update the checklist and start sending checks */ charon->connect_manager->set_responder_data(charon->connect_manager, - this->session_id, this->session_key, this->local_endpoints); + this->connect_id, this->connect_key, this->local_endpoints); } else { @@ -511,8 +489,10 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message) * as initiator, we create a checklist and set the initiator's data */ charon->connect_manager->set_initiator_data(charon->connect_manager, this->ike_sa->get_my_id(this->ike_sa), this->peer_id, - this->session_id, this->session_key, this->local_endpoints, + this->connect_id, this->connect_key, this->local_endpoints, TRUE); + /* FIXME: also start a timer for the whole transaction (maybe + * within the connect_manager?) */ } } break; @@ -524,29 +504,29 @@ static status_t process_i(private_ike_p2p_t *this, message_t *message) } /** - * Implementation of task_t.process for initiator (mediation server) + * Implementation of task_t.build for initiator (mediation server) */ -static status_t build_i_ms(private_ike_p2p_t *this, message_t *message) +static status_t build_i_ms(private_ike_me_t *this, message_t *message) { switch(message->get_exchange_type(message)) { - case P2P_CONNECT: + case ME_CONNECT: { id_payload_t *id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id); message->add_payload(message, (payload_t*)id_payload); if (this->callback) { - message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty); + message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty); } else { if (this->response) { - message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty); + message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty); } - message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id); - message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key); + message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id); + message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key); add_endpoints_to_message(message, this->remote_endpoints); } @@ -562,27 +542,37 @@ static status_t build_i_ms(private_ike_p2p_t *this, message_t *message) /** * Implementation of task_t.process for responder (mediation server) */ -static status_t process_r_ms(private_ike_p2p_t *this, message_t *message) +static status_t process_r_ms(private_ike_me_t *this, message_t *message) { switch(message->get_exchange_type(message)) { case IKE_SA_INIT: { + /* FIXME: we should check for SA* and TS* payloads + * if any are there send NO_ADDITIONAL_SAS back and delete this SA */ process_payloads(this, message); return this->mediation ? NEED_MORE : SUCCESS; } case IKE_AUTH: { + /* FIXME: we should check whether the current peer_config is configured + * as mediation connection */ process_payloads(this, message); break; } - case P2P_CONNECT: + case CREATE_CHILD_SA: + { + /* FIXME: if this is not to rekey the IKE SA we have to return a + * NO_ADDITIONAL_SAS and then delete the SA */ + break; + } + case ME_CONNECT: { id_payload_t *id_payload; id_payload = (id_payload_t*)message->get_payload(message, ID_PEER); if (!id_payload) { - DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload, aborting"); this->invalid_syntax = TRUE; break; } @@ -591,23 +581,23 @@ static status_t process_r_ms(private_ike_p2p_t *this, message_t *message) process_payloads(this, message); - if (!this->session_id.ptr) + if (!this->connect_id.ptr) { - DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify, aborting"); this->invalid_syntax = TRUE; break; } - if (!this->session_key.ptr) + if (!this->connect_key.ptr) { - DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify, aborting"); this->invalid_syntax = TRUE; break; } if (!this->remote_endpoints->get_count(this->remote_endpoints)) { - DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting"); + DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT payloads, aborting"); this->invalid_syntax = TRUE; break; } @@ -623,13 +613,13 @@ static status_t process_r_ms(private_ike_p2p_t *this, message_t *message) /** * Implementation of task_t.build for responder (mediation server) */ -static status_t build_r_ms(private_ike_p2p_t *this, message_t *message) +static status_t build_r_ms(private_ike_me_t *this, message_t *message) { switch(message->get_exchange_type(message)) { case IKE_SA_INIT: { - message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty); + message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty); return NEED_MORE; } case IKE_AUTH: @@ -645,17 +635,17 @@ static status_t build_r_ms(private_ike_p2p_t *this, message_t *message) endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, host, NULL); message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint)); + endpoint->destroy(endpoint); } - charon->mediation_manager->update_sa_id(charon->mediation_manager, - this->ike_sa->get_other_id(this->ike_sa), - this->ike_sa->get_id(this->ike_sa)); + /* FIXME: we actually must delete any existing IKE_SAs with the same remote id */ + this->ike_sa->act_as_mediation_server(this->ike_sa); SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully"); break; } - case P2P_CONNECT: + case ME_CONNECT: { if (this->invalid_syntax) { @@ -678,13 +668,13 @@ static status_t build_r_ms(private_ike_p2p_t *this, message_t *message) if (!peer_sa) { /* the peer is not online */ - message->add_notify(message, TRUE, P2P_CONNECT_FAILED, chunk_empty); + message->add_notify(message, TRUE, ME_CONNECT_FAILED, chunk_empty); break; } job_t *job = (job_t*)mediation_job_create(this->peer_id, - this->ike_sa->get_other_id(this->ike_sa), this->session_id, - this->session_key, this->remote_endpoints, this->response); + this->ike_sa->get_other_id(this->ike_sa), this->connect_id, + this->connect_key, this->remote_endpoints, this->response); charon->processor->queue_job(charon->processor, job); break; @@ -698,64 +688,71 @@ static status_t build_r_ms(private_ike_p2p_t *this, message_t *message) /** * Implementation of task_t.process for initiator (mediation server) */ -static status_t process_i_ms(private_ike_p2p_t *this, message_t *message) +static status_t process_i_ms(private_ike_me_t *this, message_t *message) { + /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED + * here if the responding peer is not able to proceed. in this case we shall + * notify the initiating peer with a ME_CONNECT request containing only a + * ME_CONNECT_FAILED */ return SUCCESS; } /** - * Implementation of ike_p2p.connect + * Implementation of ike_me.connect */ -static void p2p_connect(private_ike_p2p_t *this, identification_t *peer_id) +static void me_connect(private_ike_me_t *this, identification_t *peer_id) { this->peer_id = peer_id->clone(peer_id); } /** - * Implementation of ike_p2p.respond + * Implementation of ike_me.respond */ -static void p2p_respond(private_ike_p2p_t *this, identification_t *peer_id, - chunk_t session_id) +static void me_respond(private_ike_me_t *this, identification_t *peer_id, + chunk_t connect_id) { this->peer_id = peer_id->clone(peer_id); - this->session_id = chunk_clone(session_id); + this->connect_id = chunk_clone(connect_id); this->response = TRUE; } /** - * Implementation of ike_p2p.callback + * Implementation of ike_me.callback */ -static void p2p_callback(private_ike_p2p_t *this, identification_t *peer_id) +static void me_callback(private_ike_me_t *this, identification_t *peer_id) { this->peer_id = peer_id->clone(peer_id); this->callback = TRUE; } /** - * Implementation of ike_p2p.relay + * Implementation of ike_me.relay */ -static void relay(private_ike_p2p_t *this, identification_t *requester, chunk_t session_id, - chunk_t session_key, linked_list_t *endpoints, bool response) +static void relay(private_ike_me_t *this, identification_t *requester, chunk_t connect_id, + chunk_t connect_key, linked_list_t *endpoints, bool response) { this->peer_id = requester->clone(requester); - this->session_id = chunk_clone(session_id); - this->session_key = chunk_clone(session_key); + this->connect_id = chunk_clone(connect_id); + this->connect_key = chunk_clone(connect_key); + + this->remote_endpoints->destroy_offset(this->remote_endpoints, offsetof(endpoint_notify_t, destroy)); this->remote_endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone)); + this->response = response; } /** * Implementation of task_t.get_type */ -static task_type_t get_type(private_ike_p2p_t *this) +static task_type_t get_type(private_ike_me_t *this) { - return IKE_P2P; + return IKE_ME; } /** * Implementation of task_t.migrate */ -static void migrate(private_ike_p2p_t *this, ike_sa_t *ike_sa) +static void migrate(private_ike_me_t *this, ike_sa_t *ike_sa) { this->ike_sa = ike_sa; } @@ -763,12 +760,12 @@ static void migrate(private_ike_p2p_t *this, ike_sa_t *ike_sa) /** * Implementation of task_t.destroy */ -static void destroy(private_ike_p2p_t *this) +static void destroy(private_ike_me_t *this) { DESTROY_IF(this->peer_id); - chunk_free(&this->session_id); - chunk_free(&this->session_key); + chunk_free(&this->connect_id); + chunk_free(&this->connect_key); this->local_endpoints->destroy_offset(this->local_endpoints, offsetof(endpoint_notify_t, destroy)); this->remote_endpoints->destroy_offset(this->remote_endpoints, offsetof(endpoint_notify_t, destroy)); @@ -780,16 +777,15 @@ static void destroy(private_ike_p2p_t *this) /* * Described in header. */ -ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator) +ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator) { - private_ike_p2p_t *this = malloc_thing(private_ike_p2p_t); + private_ike_me_t *this = malloc_thing(private_ike_me_t); this->public.task.get_type = (task_type_t(*)(task_t*))get_type; this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; this->public.task.destroy = (void(*)(task_t*))destroy; - ike_sa_id_t *id = ike_sa->get_id(ike_sa); - if (id->is_initiator(id)) + if (ike_sa->is_ike_initiator(ike_sa)) { if (initiator) { @@ -817,17 +813,17 @@ ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator) } } - this->public.connect = (void(*)(ike_p2p_t*,identification_t*))p2p_connect; - this->public.respond = (void(*)(ike_p2p_t*,identification_t*,chunk_t))p2p_respond; - this->public.callback = (void(*)(ike_p2p_t*,identification_t*))p2p_callback; - this->public.relay = (void(*)(ike_p2p_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay; + this->public.connect = (void(*)(ike_me_t*,identification_t*))me_connect; + this->public.respond = (void(*)(ike_me_t*,identification_t*,chunk_t))me_respond; + this->public.callback = (void(*)(ike_me_t*,identification_t*))me_callback; + this->public.relay = (void(*)(ike_me_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay; this->ike_sa = ike_sa; this->initiator = initiator; this->peer_id = NULL; - this->session_id = chunk_empty; - this->session_key = chunk_empty; + this->connect_id = chunk_empty; + this->connect_key = chunk_empty; this->local_endpoints = linked_list_create(); this->remote_endpoints = linked_list_create(); this->mediation = FALSE; diff --git a/src/charon/sa/tasks/ike_p2p.h b/src/charon/sa/tasks/ike_me.h index 327ac49d8..c9a515c8f 100644 --- a/src/charon/sa/tasks/ike_p2p.h +++ b/src/charon/sa/tasks/ike_me.h @@ -1,10 +1,3 @@ -/** - * @file ike_p2p.h - * - * @brief Interface ike_p2p_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Hochschule fuer Technik Rapperswil @@ -18,35 +11,37 @@ * 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. + * + * $Id: ike_me.h 3666 2008-03-26 18:40:19Z tobias $ */ -#ifndef IKE_P2P_H_ -#define IKE_P2P_H_ +/** + * @defgroup ike_me ike_me + * @{ @ingroup tasks + */ + +#ifndef IKE_ME_H_ +#define IKE_ME_H_ -typedef struct ike_p2p_t ike_p2p_t; +typedef struct ike_me_t ike_me_t; #include <library.h> #include <sa/ike_sa.h> #include <sa/tasks/task.h> /** - * @brief Task of type IKE_P2P, detects and handles P2P-NAT-T extensions. + * Task of type IKE_ME, detects and handles IKE-ME extensions. * - * This tasks handles the P2P_MEDIATION notify exchange to setup a mediation - * connection, allows to initiate mediated connections using P2P_CONNECT + * This tasks handles the ME_MEDIATION Notify exchange to setup a mediation + * connection, allows to initiate mediated connections using ME_CONNECT * exchanges and to request reflexive addresses from the mediation server using - * P2P_ENDPOINT notifies. + * ME_ENDPOINT notifies. * * @note This task has to be activated before the IKE_AUTH task, because that * task generates the IKE_SA_INIT message so that no more payloads can be added * to it afterwards. - * - * @b Constructors: - * - ike_p2p_create() - * - * @ingroup tasks */ -struct ike_p2p_t { +struct ike_me_t { /** * Implements the task_t interface @@ -54,57 +49,52 @@ struct ike_p2p_t { task_t task; /** - * @brief Initiates a connection with another peer (i.e. sends a P2P_CONNECT + * Initiates a connection with another peer (i.e. sends a ME_CONNECT * to the mediation server) * - * @param this object * @param peer_id ID of the other peer (gets cloned) */ - void (*connect)(ike_p2p_t *this, identification_t *peer_id); + void (*connect)(ike_me_t *this, identification_t *peer_id); /** - * @brief Responds to a P2P_CONNECT from another peer (i.e. sends a P2P_CONNECT + * Responds to a ME_CONNECT from another peer (i.e. sends a ME_CONNECT * to the mediation server) * - * @param this object * @param peer_id ID of the other peer (gets cloned) - * @param session_id the session ID as provided by the initiator (gets cloned) + * @param connect_id the connect ID as provided by the initiator (gets cloned) */ - void (*respond)(ike_p2p_t *this, identification_t *peer_id, chunk_t session_id); + void (*respond)(ike_me_t *this, identification_t *peer_id, chunk_t connect_id); /** - * @brief Sends a P2P_CALLBACK to a peer that previously requested another peer. + * Sends a ME_CALLBACK to a peer that previously requested another peer. * - * @param this object * @param peer_id ID of the other peer (gets cloned) */ - void (*callback)(ike_p2p_t *this, identification_t *peer_id); + void (*callback)(ike_me_t *this, identification_t *peer_id); /** - * @brief Relays data to another peer (i.e. sends a P2P_CONNECT to the peer) + * Relays data to another peer (i.e. sends a ME_CONNECT to the peer) * * Data gets cloned. * - * @param this object * @param requester ID of the requesting peer - * @param session_id content of the P2P_SESSIONID notify - * @param session_key content of the P2P_SESSIONKEY notify + * @param connect_id content of the ME_CONNECTID notify + * @param connect_key content of the ME_CONNECTKEY notify * @param endpoints endpoints * @param response TRUE if this is a response */ - void (*relay)(ike_p2p_t *this, identification_t *requester, chunk_t session_id, - chunk_t session_key, linked_list_t *endpoints, bool response); + void (*relay)(ike_me_t *this, identification_t *requester, chunk_t connect_id, + chunk_t connect_key, linked_list_t *endpoints, bool response); }; /** - * @brief Create a new ike_p2p task. + * Create a new ike_me task. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE if taks is initiated by us - * @return ike_p2p task to handle by the task_manager + * @return ike_me task to handle by the task_manager */ -ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator); - +ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator); -#endif /*IKE_P2P_H_*/ +#endif /*IKE_ME_H_ @} */ diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index a53c243f0..23c68b9e9 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -1,10 +1,3 @@ -/** - * @file ike_mobike.c - * - * @brief Implementation of the ike_mobike task. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: ike_mobike.c 4006 2008-05-23 15:43:42Z martin $ */ #include "ike_mobike.h" @@ -28,6 +23,7 @@ #include <sa/tasks/ike_natd.h> #include <encoding/payloads/notify_payload.h> +#define COOKIE2_SIZE 16 typedef struct private_ike_mobike_t private_ike_mobike_t; @@ -125,6 +121,12 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message) this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE); break; } + case COOKIE2: + { + chunk_free(&this->cookie2); + this->cookie2 = chunk_clone(notify->get_notification_data(notify)); + break; + } case ADDITIONAL_IP6_ADDRESS: { family = AF_INET6; @@ -211,6 +213,23 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message) } /** + * build a cookie and add it to the message + */ +static void build_cookie(private_ike_mobike_t *this, message_t *message) +{ + rng_t *rng; + + chunk_free(&this->cookie2); + rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (rng) + { + rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2); + rng->destroy(rng); + message->add_notify(message, FALSE, COOKIE2, this->cookie2); + } +} + +/** * update addresses of associated CHILD_SAs */ static void update_children(private_ike_mobike_t *this) @@ -262,6 +281,11 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet) charon->kernel_interface, other); if (me) { + if (me->get_family(me) != other->get_family(other)) + { + me->destroy(me); + continue; + } /* reuse port for an active address, 4500 otherwise */ me->set_port(me, me->ip_equals(me, me_old) ? me_old->get_port(me_old) : IKEV2_NATT_PORT); @@ -297,6 +321,7 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message) if (this->update) { message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty); + build_cookie(this, message); update_children(this); } if (this->address) @@ -363,6 +388,11 @@ static status_t build_r(private_ike_mobike_t *this, message_t *message) { this->natd->task.build(&this->natd->task, message); } + if (this->cookie2.ptr) + { + message->add_notify(message, FALSE, COOKIE2, this->cookie2); + chunk_free(&this->cookie2); + } if (this->update) { update_children(this); @@ -392,7 +422,25 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) /* newer update queued, ignore this one */ return SUCCESS; } - process_payloads(this, message); + if (this->cookie2.ptr) + { /* check cookie if we included none */ + chunk_t cookie2; + + cookie2 = this->cookie2; + this->cookie2 = chunk_empty; + process_payloads(this, message); + if (!chunk_equals(cookie2, this->cookie2)) + { + chunk_free(&cookie2); + DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA"); + return FAILED; + } + chunk_free(&cookie2); + } + else + { + process_payloads(this, message); + } if (this->natd) { this->natd->task.process(&this->natd->task, message); diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h index bb5150723..9dd29970e 100644 --- a/src/charon/sa/tasks/ike_mobike.h +++ b/src/charon/sa/tasks/ike_mobike.h @@ -1,10 +1,3 @@ -/** - * @file ike_mobike.h - * - * @brief Interface ike_mobike_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_mobike.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_mobike ike_mobike + * @{ @ingroup tasks */ #ifndef IKE_MOBIKE_H_ @@ -31,7 +31,7 @@ typedef struct ike_mobike_t ike_mobike_t; #include <network/packet.h> /** - * @brief Task of type ike_mobike, detects and handles MOBIKE extension. + * Task of type ike_mobike, detects and handles MOBIKE extension. * * The MOBIKE extension is defined in RFC4555. It allows to update IKE * and IPsec tunnel addresses. @@ -39,11 +39,6 @@ typedef struct ike_mobike_t ike_mobike_t; * support, allows the exchange of ADDITIONAL_*_ADDRESS to exchange additional * endpoints and handles the UPDATE_SA_ADDRESS notify to finally update * endpoints. - * - * @b Constructors: - * - ike_mobike_create() - * - * @ingroup tasks */ struct ike_mobike_t { @@ -53,36 +48,33 @@ struct ike_mobike_t { task_t task; /** - * @brief Use the task to roam to other addresses. + * Use the task to roam to other addresses. * - * @param this calling object * @param address TRUE to include address list update */ void (*roam)(ike_mobike_t *this, bool address); /** - * @brief Transmision hook, called by task manager. + * Transmision hook, called by task manager. * * The task manager calls this hook whenever it transmits a packet. It * allows the mobike task to send the packet on multiple paths to do path * probing. * - * @param this calling object * @param packet the packet to transmit */ void (*transmit)(ike_mobike_t *this, packet_t *packet); /** - * @brief Check if this task is probing for routability. + * Check if this task is probing for routability. * - * @param this calling object * @return TRUE if task is probing */ bool (*is_probing)(ike_mobike_t *this); }; /** - * @brief Create a new ike_mobike task. + * Create a new ike_mobike task. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE if taks is initiated by us @@ -90,5 +82,4 @@ struct ike_mobike_t { */ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_MOBIKE_H_ */ - +#endif /* IKE_MOBIKE_H_ @} */ diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c index 4c64ff8ba..69e5bac26 100644 --- a/src/charon/sa/tasks/ike_natd.c +++ b/src/charon/sa/tasks/ike_natd.c @@ -1,10 +1,3 @@ -/** - * @file ike_natd.c - * - * @brief Implementation of the ike_natd task. - * - */ - /* * Copyright (C) 2006-2007 Martin Willi * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger @@ -19,6 +12,8 @@ * 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. + * + * $Id: ike_natd.c 3806 2008-04-15 05:56:35Z martin $ */ #include "ike_natd.h" @@ -118,17 +113,17 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this, */ static chunk_t generate_natd_hash_faked(private_ike_natd_t *this) { - randomizer_t *randomizer; + rng_t *rng; chunk_t chunk; - randomizer = randomizer_create(); - if (randomizer->allocate_pseudo_random_bytes(randomizer, HASH_SIZE_SHA1, - &chunk) != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { DBG1(DBG_IKE, "unable to get random bytes for NATD fake"); - chunk = chunk_empty; + return chunk_empty; } - randomizer->destroy(randomizer); + rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk); + rng->destroy(rng); return chunk; } @@ -259,7 +254,7 @@ static status_t process_i(private_ike_natd_t *this, message_t *message) { peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); -#ifdef P2P +#ifdef ME /* if we are on a mediated connection we have already switched to * port 4500 and the correct destination port is already configured, * therefore we must not switch again */ @@ -267,14 +262,14 @@ static status_t process_i(private_ike_natd_t *this, message_t *message) { return SUCCESS; } -#endif /* P2P */ +#endif /* ME */ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY) || -#ifdef P2P +#ifdef ME /* if we are on a mediation connection we swith to port 4500 even * if no NAT is detected. */ peer_cfg->is_mediation(peer_cfg) || -#endif /* P2P */ +#endif /* ME */ /* if peer supports NAT-T, we switch to port 4500 even * if no NAT is detected. MOBIKE requires this. */ (peer_cfg->use_mobike(peer_cfg) && @@ -308,6 +303,12 @@ static status_t build_i(private_ike_natd_t *this, message_t *message) iterator_t *iterator; host_t *host; + if (this->hasher == NULL) + { + DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported"); + return NEED_MORE; + } + /* destination is always set */ host = message->get_destination(message); notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host); @@ -368,6 +369,12 @@ static status_t build_r(private_ike_natd_t *this, message_t *message) if (this->src_seen && this->dst_seen) { + if (this->hasher == NULL) + { + DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported"); + return SUCCESS; + } + /* initiator seems to support NAT detection, add response */ me = message->get_source(message); notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me); @@ -415,7 +422,7 @@ static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa) */ static void destroy(private_ike_natd_t *this) { - this->hasher->destroy(this->hasher); + DESTROY_IF(this->hasher); free(this); } @@ -443,7 +450,7 @@ ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator) this->ike_sa = ike_sa; this->initiator = initiator; - this->hasher = hasher_create(HASH_SHA1); + this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); this->src_seen = FALSE; this->dst_seen = FALSE; this->src_matched = FALSE; diff --git a/src/charon/sa/tasks/ike_natd.h b/src/charon/sa/tasks/ike_natd.h index 8d0cb58b4..d78c931d9 100644 --- a/src/charon/sa/tasks/ike_natd.h +++ b/src/charon/sa/tasks/ike_natd.h @@ -1,10 +1,3 @@ -/** - * @file ike_natd.h - * - * @brief Interface ike_natd_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_natd.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_natd ike_natd + * @{ @ingroup tasks */ #ifndef IKE_NATD_H_ @@ -30,12 +30,7 @@ typedef struct ike_natd_t ike_natd_t; #include <sa/tasks/task.h> /** - * @brief Task of type ike_natd, detects NAT situation in IKE_SA_INIT exchange. - * - * @b Constructors: - * - ike_natd_create() - * - * @ingroup tasks + * Task of type ike_natd, detects NAT situation in IKE_SA_INIT exchange. */ struct ike_natd_t { @@ -46,7 +41,7 @@ struct ike_natd_t { }; /** - * @brief Create a new ike_natd task. + * Create a new ike_natd task. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE if thask is the original initator @@ -54,4 +49,4 @@ struct ike_natd_t { */ ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_NATD_H_ */ +#endif /* IKE_NATD_H_ @} */ diff --git a/src/charon/sa/tasks/ike_reauth.c b/src/charon/sa/tasks/ike_reauth.c index 0e98382a8..854e9359d 100644 --- a/src/charon/sa/tasks/ike_reauth.c +++ b/src/charon/sa/tasks/ike_reauth.c @@ -1,10 +1,3 @@ -/** - * @file ike_reauth.c - * - * @brief Implementation of the ike_reauth task. - * - */ - /* * Copyright (C) 2006-2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,8 @@ * 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. + * + * $Id: ike_reauth.c 3793 2008-04-11 08:14:48Z martin $ */ #include "ike_reauth.h" @@ -66,22 +61,30 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message) host_t *host; iterator_t *iterator; child_sa_t *child_sa; + peer_cfg_t *peer_cfg; /* process delete response first */ this->ike_delete->task.process(&this->ike_delete->task, message); - /* reestablish only if we have children */ + peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); + + /* reauthenticate only if we have children */ iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa); - if (iterator->get_count(iterator) == 0) + if (iterator->get_count(iterator) == 0 +#ifdef ME + /* we allow a peer to reauth a mediation connection (without CHILD_SA) */ + && !peer_cfg->is_mediation(peer_cfg) +#endif /* ME */ + ) { - DBG1(DBG_IKE, "unable to reestablish IKE_SA, no CHILD_SA to recreate"); + DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate"); iterator->destroy(iterator); return FAILED; } new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE); - new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa)); + new->set_peer_cfg(new, peer_cfg); host = this->ike_sa->get_other_host(this->ike_sa); new->set_other_host(new, host->clone(host)); host = this->ike_sa->get_my_host(this->ike_sa); @@ -93,6 +96,20 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message) new->set_virtual_ip(new, TRUE, host); } +#ifdef ME + /* we initiate the new IKE_SA of the mediation connection without CHILD_SA */ + if (peer_cfg->is_mediation(peer_cfg)) + { + if (new->initiate(new, NULL) == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, new); + DBG1(DBG_IKE, "reauthenticating IKE_SA failed"); + return FAILED; + } + } +#endif /* ME */ + while (iterator->iterate(iterator, (void**)&child_sa)) { switch (child_sa->get_state(child_sa)) @@ -114,7 +131,7 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message) iterator->destroy(iterator); charon->ike_sa_manager->checkin_and_destroy( charon->ike_sa_manager, new); - DBG1(DBG_IKE, "reestablishing IKE_SA failed"); + DBG1(DBG_IKE, "reauthenticating IKE_SA failed"); return FAILED; } break; diff --git a/src/charon/sa/tasks/ike_reauth.h b/src/charon/sa/tasks/ike_reauth.h index 3c872e1e1..1076cc7cc 100644 --- a/src/charon/sa/tasks/ike_reauth.h +++ b/src/charon/sa/tasks/ike_reauth.h @@ -1,10 +1,3 @@ -/** - * @file ike_reauth.h - * - * @brief Interface ike_reauth_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_reauth.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_reauth ike_reauth + * @{ @ingroup tasks */ #ifndef IKE_REAUTH_H_ @@ -30,12 +30,7 @@ typedef struct ike_reauth_t ike_reauth_t; #include <sa/tasks/task.h> /** - * @brief Task of type ike_reauth, reestablishes an IKE_SA. - * - * @b Constructors: - * - ike_reauth_create() - * - * @ingroup tasks + * Task of type ike_reauth, reestablishes an IKE_SA. */ struct ike_reauth_t { @@ -46,7 +41,7 @@ struct ike_reauth_t { }; /** - * @brief Create a new ike_reauth task. + * Create a new ike_reauth task. * * This task is initiator only. * @@ -55,5 +50,4 @@ struct ike_reauth_t { */ ike_reauth_t *ike_reauth_create(ike_sa_t *ike_sa); -#endif /* IKE_REAUTH_H_ */ - +#endif /* IKE_REAUTH_H_ @} */ diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c index 827f95156..9c0d1805c 100644 --- a/src/charon/sa/tasks/ike_rekey.c +++ b/src/charon/sa/tasks/ike_rekey.c @@ -1,10 +1,3 @@ -/** - * @file ike_rekey.c - * - * @brief Implementation of the ike_rekey task. - * - */ - /* * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,8 @@ * 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. + * + * $Id: ike_rekey.c 3589 2008-03-13 14:14:44Z martin $ */ #include "ike_rekey.h" diff --git a/src/charon/sa/tasks/ike_rekey.h b/src/charon/sa/tasks/ike_rekey.h index 125422efd..1bfde8a54 100644 --- a/src/charon/sa/tasks/ike_rekey.h +++ b/src/charon/sa/tasks/ike_rekey.h @@ -1,10 +1,3 @@ -/** - * @file ike_rekey.h - * - * @brief Interface ike_rekey_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,6 +11,13 @@ * 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. + * + * $Id: ike_rekey.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup ike_rekey ike_rekey + * @{ @ingroup tasks */ #ifndef IKE_REKEY_H_ @@ -30,12 +30,7 @@ typedef struct ike_rekey_t ike_rekey_t; #include <sa/tasks/task.h> /** - * @brief Task of type IKE_REKEY, rekey an established IKE_SA. - * - * @b Constructors: - * - ike_rekey_create() - * - * @ingroup tasks + * Task of type IKE_REKEY, rekey an established IKE_SA. */ struct ike_rekey_t { @@ -45,20 +40,19 @@ struct ike_rekey_t { task_t task; /** - * @brief Register a rekeying task which collides with this one. + * Register a rekeying task which collides with this one. * * If two peers initiate rekeying at the same time, the collision must * be handled gracefully. The task manager is aware of what exchanges * are going on and notifies the outgoing task by passing the incoming. * - * @param this task initated by us * @param other incoming task */ void (*collide)(ike_rekey_t* this, task_t *other); }; /** - * @brief Create a new IKE_REKEY task. + * Create a new IKE_REKEY task. * * @param ike_sa IKE_SA this task works for * @param initiator TRUE for initiator, FALSE for responder @@ -66,4 +60,4 @@ struct ike_rekey_t { */ ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator); -#endif /* IKE_REKEY_H_ */ +#endif /* IKE_REKEY_H_ @} */ diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c index cc20a8861..3192b688a 100644 --- a/src/charon/sa/tasks/task.c +++ b/src/charon/sa/tasks/task.c @@ -1,10 +1,3 @@ -/** - * @file task.c - * - * @brief Enum values for task types - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2007 Martin Willi @@ -19,6 +12,8 @@ * 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. + * + * $Id: task.c 3666 2008-03-26 18:40:19Z tobias $ */ #include "task.h" @@ -29,15 +24,16 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY, "IKE_MOBIKE", "IKE_AUTHENTICATE", "IKE_AUTH_LIFETIME", - "IKE_CERT", + "IKE_CERT_PRE", + "IKE_CERT_POST", "IKE_CONFIG", "IKE_REKEY", "IKE_REAUTH", "IKE_DELETE", "IKE_DPD", -#ifdef P2P - "IKE_P2P", -#endif /* P2P */ +#ifdef ME + "IKE_ME", +#endif /* ME */ "CHILD_CREATE", "CHILD_DELETE", "CHILD_REKEY", diff --git a/src/charon/sa/tasks/task.h b/src/charon/sa/tasks/task.h index a59207711..26b4f214e 100644 --- a/src/charon/sa/tasks/task.h +++ b/src/charon/sa/tasks/task.h @@ -1,10 +1,3 @@ -/** - * @file task.h - * - * @brief Interface task_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2006 Martin Willi @@ -19,6 +12,13 @@ * 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. + * + * $Id: task.h 3666 2008-03-26 18:40:19Z tobias $ + */ + +/** + * @defgroup task task + * @{ @ingroup tasks */ #ifndef TASK_H_ @@ -32,9 +32,7 @@ typedef struct task_t task_t; #include <encoding/message.h> /** - * @brief Different kinds of tasks. - * - * @ingroup tasks + * Different kinds of tasks. */ enum task_type_t { /** establish an unauthenticated IKE_SA */ @@ -47,8 +45,10 @@ enum task_type_t { IKE_AUTHENTICATE, /** AUTH_LIFETIME negotiation, RFC4478 */ IKE_AUTH_LIFETIME, - /** exchange certificates and requests */ - IKE_CERT, + /** certificate processing before authentication (certreqs, cert parsing) */ + IKE_CERT_PRE, + /** certificate processing after authentication (certs payload generation) */ + IKE_CERT_POST, /** Configuration payloads, virtual IP and such */ IKE_CONFIG, /** rekey an IKE_SA */ @@ -59,10 +59,10 @@ enum task_type_t { IKE_DELETE, /** liveness check */ IKE_DPD, -#ifdef P2P - /** handle P2P-NAT-T stuff */ - IKE_P2P, -#endif /* P2P */ +#ifdef ME + /** handle ME stuff */ + IKE_ME, +#endif /* ME */ /** establish a CHILD_SA within an IKE_SA */ CHILD_CREATE, /** delete an established CHILD_SA */ @@ -77,7 +77,7 @@ enum task_type_t { extern enum_name_t *task_type_names; /** - * @brief Interface for a task, an operation handled within exchanges. + * Interface for a task, an operation handled within exchanges. * * A task is an elemantary operation. It may be handled by a single or by * multiple exchanges. An exchange may even complete multiple tasks. @@ -94,18 +94,12 @@ extern enum_name_t *task_type_names; * the task needs further build()/process() calls to complete, the manager * leaves the taks in the queue. A returned FAILED indicates a critical failure. * The manager closes the IKE_SA whenever a task returns FAILED. - * - * @b Constructors: - * - None, use implementations specific constructors - * - * @ingroup tasks */ struct task_t { /** - * @brief Build a request or response message for this task. + * Build a request or response message for this task. * - * @param this calling object * @param message message to add payloads to * @return * - FAILED if a critical error occured @@ -115,9 +109,8 @@ struct task_t { status_t (*build) (task_t *this, message_t *message); /** - * @brief Process a request or response message for this task. + * Process a request or response message for this task. * - * @param this calling object * @param message message to read payloads from * @return * - FAILED if a critical error occured @@ -127,14 +120,12 @@ struct task_t { status_t (*process) (task_t *this, message_t *message); /** - * @brief Get the type of the task implementation. - * - * @param this calling object + * Get the type of the task implementation. */ task_type_t (*get_type) (task_t *this); /** - * @brief Migrate a task to a new IKE_SA. + * Migrate a task to a new IKE_SA. * * After migrating a task, it goes back to a state where it can be * used again to initate an exchange. This is useful when a task @@ -144,17 +135,14 @@ struct task_t { * try. * The ike_sa is the new IKE_SA this task belongs to and operates on. * - * @param this calling object * @param ike_sa new IKE_SA this task works for */ void (*migrate) (task_t *this, ike_sa_t *ike_sa); /** - * @brief Destroys a task_t object. - * - * @param this calling object + * Destroys a task_t object. */ void (*destroy) (task_t *this); }; -#endif /* TASK_H_ */ +#endif /* TASK_H_ @} */ |