aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2009-04-14 10:34:24 +0000
committerMartin Willi <martin@strongswan.org>2009-04-14 10:34:24 +0000
commita44bb9345f0482b3dace19a27ee40320ddadc75f (patch)
tree34d75bd95b2868900213e13c31ddd892d2fd4904 /src
parent6e5c8d9413234b18a0631cddadd973a9f509708b (diff)
downloadstrongswan-a44bb9345f0482b3dace19a27ee40320ddadc75f.tar.bz2
strongswan-a44bb9345f0482b3dace19a27ee40320ddadc75f.tar.xz
merged multi-auth branch back into trunk
Diffstat (limited to 'src')
-rw-r--r--src/_copyright/Makefile.am5
-rw-r--r--src/charon/Makefile.am12
-rw-r--r--src/charon/bus/bus.c40
-rw-r--r--src/charon/bus/bus.h26
-rw-r--r--src/charon/config/attributes/attribute_manager.c6
-rw-r--r--src/charon/config/attributes/attribute_manager.h7
-rw-r--r--src/charon/config/attributes/attribute_provider.h4
-rw-r--r--src/charon/config/auth_cfg.c770
-rw-r--r--src/charon/config/auth_cfg.h201
-rw-r--r--src/charon/config/backend.h16
-rw-r--r--src/charon/config/backend_manager.c312
-rw-r--r--src/charon/config/backend_manager.h30
-rw-r--r--src/charon/config/peer_cfg.c147
-rw-r--r--src/charon/config/peer_cfg.h76
-rw-r--r--src/charon/config/proposal.c240
-rw-r--r--src/charon/config/proposal_keywords.h26
-rw-r--r--src/charon/config/proposal_keywords.txt101
-rw-r--r--src/charon/credentials/auth_info.c607
-rw-r--r--src/charon/credentials/auth_info.h198
-rw-r--r--src/charon/credentials/credential_manager.c154
-rw-r--r--src/charon/credentials/credential_manager.h16
-rw-r--r--src/charon/credentials/sets/auth_cfg_wrapper.c (renamed from src/charon/credentials/sets/auth_info_wrapper.c)85
-rw-r--r--src/charon/credentials/sets/auth_cfg_wrapper.h (renamed from src/charon/credentials/sets/auth_info_wrapper.h)26
-rw-r--r--src/charon/encoding/generator.c8
-rw-r--r--src/charon/encoding/message.c130
-rw-r--r--src/charon/encoding/message.h19
-rw-r--r--src/charon/plugins/eap_mschapv2/eap_mschapv2.c72
-rw-r--r--src/charon/plugins/eap_sim_file/eap_sim_file_card.c6
-rw-r--r--src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c5
-rw-r--r--src/charon/plugins/load_tester/load_tester_config.c149
-rw-r--r--src/charon/plugins/nm/nm_creds.c4
-rw-r--r--src/charon/plugins/nm/nm_service.c17
-rw-r--r--src/charon/plugins/smp/smp.c9
-rw-r--r--src/charon/plugins/sql/pool.c5
-rw-r--r--src/charon/plugins/sql/sql_attribute.c4
-rw-r--r--src/charon/plugins/sql/sql_config.c18
-rw-r--r--src/charon/plugins/stroke/stroke_attribute.c4
-rw-r--r--src/charon/plugins/stroke/stroke_config.c696
-rw-r--r--src/charon/plugins/stroke/stroke_cred.c25
-rw-r--r--src/charon/plugins/stroke/stroke_list.c263
-rw-r--r--src/charon/plugins/stroke/stroke_socket.c10
-rw-r--r--src/charon/plugins/uci/uci_config.c41
-rw-r--r--src/charon/plugins/uci/uci_control.c45
-rw-r--r--src/charon/plugins/uci/uci_creds.c8
-rw-r--r--src/charon/plugins/unit_tester/tests/test_auth_info.c29
-rw-r--r--src/charon/plugins/unit_tester/tests/test_med_db.c2
-rw-r--r--src/charon/plugins/unit_tester/tests/test_pool.c13
-rw-r--r--src/charon/processing/jobs/initiate_mediation_job.c16
-rw-r--r--src/charon/sa/authenticators/authenticator.c46
-rw-r--r--src/charon/sa/authenticators/authenticator.h81
-rw-r--r--src/charon/sa/authenticators/eap/eap_manager.c20
-rw-r--r--src/charon/sa/authenticators/eap/eap_method.c33
-rw-r--r--src/charon/sa/authenticators/eap/eap_method.h9
-rw-r--r--src/charon/sa/authenticators/eap/sim_manager.h4
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.c767
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.h105
-rw-r--r--src/charon/sa/authenticators/psk_authenticator.c139
-rw-r--r--src/charon/sa/authenticators/psk_authenticator.h28
-rw-r--r--src/charon/sa/authenticators/pubkey_authenticator.c223
-rw-r--r--src/charon/sa/authenticators/pubkey_authenticator.h28
-rw-r--r--src/charon/sa/connect_manager.c8
-rw-r--r--src/charon/sa/ike_sa.c60
-rw-r--r--src/charon/sa/ike_sa.h25
-rw-r--r--src/charon/sa/ike_sa_manager.c99
-rw-r--r--src/charon/sa/task_manager.c13
-rw-r--r--src/charon/sa/tasks/child_create.c99
-rw-r--r--src/charon/sa/tasks/child_delete.c7
-rw-r--r--src/charon/sa/tasks/child_rekey.c18
-rw-r--r--src/charon/sa/tasks/ike_auth.c1099
-rw-r--r--src/charon/sa/tasks/ike_auth_lifetime.c8
-rw-r--r--src/charon/sa/tasks/ike_cert_post.c120
-rw-r--r--src/charon/sa/tasks/ike_cert_pre.c276
-rw-r--r--src/charon/sa/tasks/ike_config.c30
-rw-r--r--src/charon/sa/tasks/ike_init.c41
-rw-r--r--src/charon/sa/tasks/ike_me.c10
-rw-r--r--src/charon/sa/tasks/ike_mobike.c18
-rw-r--r--src/charon/sa/tasks/ike_natd.c8
-rw-r--r--src/charon/sa/tasks/ike_rekey.c12
-rw-r--r--src/libfreeswan/Makefile.am6
-rw-r--r--src/libfreeswan/freeswan.h4
-rw-r--r--src/libstrongswan/credentials/certificates/certificate.c12
-rw-r--r--src/libstrongswan/credentials/certificates/certificate.h12
-rw-r--r--src/libstrongswan/plugins/curl/curl_fetcher.c26
-rw-r--r--src/libstrongswan/settings.h2
-rw-r--r--src/libstrongswan/utils/enumerator.h2
-rw-r--r--src/libstrongswan/utils/identification.c69
-rw-r--r--src/libstrongswan/utils/identification.h12
-rw-r--r--src/libstrongswan/utils/linked_list.h1
-rw-r--r--src/pluto/Makefile.am16
-rw-r--r--src/pluto/ac.c2
-rw-r--r--src/pluto/alg_info.c7
-rw-r--r--src/pluto/constants.c14
-rw-r--r--src/pluto/constants.h9
-rw-r--r--src/pluto/crl.c2
-rw-r--r--src/pluto/defs.h7
-rw-r--r--src/pluto/demux.c2
-rw-r--r--src/pluto/fetch.c2
-rw-r--r--src/pluto/id.c2
-rw-r--r--src/pluto/ike_alg.c8
-rw-r--r--src/pluto/kernel.c2
-rw-r--r--src/pluto/keys.c2
-rw-r--r--src/pluto/modecfg.c179
-rw-r--r--src/pluto/nat_traversal.c4
-rw-r--r--src/pluto/pem.c5
-rw-r--r--src/pluto/pgp.c4
-rw-r--r--src/pluto/plutomain.c8
-rw-r--r--src/pluto/server.c6
-rw-r--r--src/pluto/smartcard.c4
-rw-r--r--src/pluto/state.c22
-rw-r--r--src/pluto/vendor.c4
-rw-r--r--src/pluto/virtual.c18
-rw-r--r--src/pluto/x509.c166
-rw-r--r--src/starter/Makefile.am9
-rw-r--r--src/starter/args.c5
-rw-r--r--src/starter/confread.h6
-rw-r--r--src/starter/invokecharon.c11
-rw-r--r--src/starter/invokecharon.h2
-rw-r--r--src/starter/invokepluto.c12
-rw-r--r--src/starter/invokepluto.h2
-rw-r--r--src/starter/ipsec.conf.580
-rw-r--r--src/starter/keywords.h10
-rw-r--r--src/starter/keywords.txt10
-rw-r--r--src/starter/starter.c10
-rw-r--r--src/starter/starterstroke.c5
-rw-r--r--src/stroke/stroke_msg.h7
-rw-r--r--src/whack/Makefile.am7
126 files changed, 5064 insertions, 3890 deletions
diff --git a/src/_copyright/Makefile.am b/src/_copyright/Makefile.am
index 00d5fb2ff..8b46f11a4 100644
--- a/src/_copyright/Makefile.am
+++ b/src/_copyright/Makefile.am
@@ -2,5 +2,8 @@ ipsec_PROGRAMS = _copyright
_copyright_SOURCES = _copyright.c
dist_man8_MANS = _copyright.8
-INCLUDES = -I$(top_srcdir)/src/libfreeswan
+INCLUDES = \
+-I$(top_srcdir)/src/libfreeswan \
+-I$(top_srcdir)/src/libstrongswan
+
_copyright_LDADD = $(top_builddir)/src/libfreeswan/libfreeswan.a
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index 9da2b238a..cc1cffdaa 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -8,7 +8,8 @@ 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/proposal.c config/proposal.h config/proposal_keywords.c config/proposal_keywords.h \
+config/auth_cfg.c config/auth_cfg.h \
config/traffic_selector.c config/traffic_selector.h \
config/attributes/attribute_provider.h \
config/attributes/attribute_manager.c config/attributes/attribute_manager.h \
@@ -93,8 +94,7 @@ 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 \
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/auth_cfg_wrapper.c credentials/sets/auth_cfg_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
@@ -108,6 +108,12 @@ AM_CFLAGS = -rdynamic \
-DRESOLV_CONF=\"${resolv_conf}\"
charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lm -ldl
+EXTRA_DIST = config/proposal_keywords.txt
+MAINTAINERCLEANFILES = config/proposal_keywords.c
+
+config/proposal_keywords.c: config/proposal_keywords.txt config/proposal_keywords.h
+ $(GPERF) -C -G -c -t < $< > $@
+
# compile options
#################
diff --git a/src/charon/bus/bus.c b/src/charon/bus/bus.c
index 670c535b0..c0b8e45e1 100644
--- a/src/charon/bus/bus.c
+++ b/src/charon/bus/bus.c
@@ -521,6 +521,45 @@ static void child_keys(private_bus_t *this, child_sa_t *child_sa,
}
/**
+ * Implementation of bus_t.authorize
+ */
+static bool authorize(private_bus_t *this, linked_list_t *auth, bool final)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep, success = TRUE;
+
+ ike_sa = pthread_getspecific(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->authorize)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->authorize(entry->listener, ike_sa,
+ auth, final, &success);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ break;
+ }
+ if (!success)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+ return success;
+}
+
+/**
* Implementation of bus_t.destroy.
*/
static void destroy(private_bus_t *this)
@@ -548,6 +587,7 @@ bus_t *bus_create()
this->public.message = (void(*)(bus_t*, message_t *message, bool incoming))message;
this->public.ike_keys = (void(*)(bus_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys;
this->public.child_keys = (void(*)(bus_t*, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys;
+ this->public.authorize = (bool(*)(bus_t*, linked_list_t *auth, bool final))authorize;
this->public.destroy = (void(*)(bus_t*)) destroy;
this->listeners = linked_list_create();
diff --git a/src/charon/bus/bus.h b/src/charon/bus/bus.h
index 90ad2017f..5c479b6cb 100644
--- a/src/charon/bus/bus.h
+++ b/src/charon/bus/bus.h
@@ -210,6 +210,23 @@ struct listener_t {
*/
bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
+
+ /**
+ * Hook called to invoke additional authorization rules.
+ *
+ * An authorization hook gets invoked several times: After each
+ * authentication round, the hook gets invoked with with final = FALSE.
+ * After authentication is complete and the peer configuration is selected,
+ * it is invoked again, but with final = TRUE.
+ *
+ * @param ike_sa IKE_SA to authorize
+ * @param auth list of auth_cfg_t, done in peers authentication rounds
+ * @param final TRUE if this is the final hook invocation
+ * @param success set to TRUE to complete IKE_SA, FALSE abort
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*authorize)(listener_t *this, ike_sa_t *ike_sa, linked_list_t *auth,
+ bool final, bool *success);
};
/**
@@ -317,6 +334,15 @@ struct bus_t {
void (*message)(bus_t *this, message_t *message, bool incoming);
/**
+ * IKE_SA authorization hook.
+ *
+ * @param auth list of auth_cfg_t, containing peers authentication info
+ * @param final TRUE if this is the final invocation
+ * @return TRUE to establish IKE_SA, FALSE to send AUTH_FAILED
+ */
+ bool (*authorize)(bus_t *this, linked_list_t *auth, bool final);
+
+ /**
* IKE_SA keymat hook.
*
* @param ike_sa IKE_SA this keymat belongs to
diff --git a/src/charon/config/attributes/attribute_manager.c b/src/charon/config/attributes/attribute_manager.c
index a069c954a..f0ae4ffa0 100644
--- a/src/charon/config/attributes/attribute_manager.c
+++ b/src/charon/config/attributes/attribute_manager.c
@@ -49,7 +49,7 @@ struct private_attribute_manager_t {
*/
static host_t* acquire_address(private_attribute_manager_t *this,
char *pool, identification_t *id,
- auth_info_t *auth, host_t *requested)
+ host_t *requested)
{
enumerator_t *enumerator;
attribute_provider_t *current;
@@ -59,7 +59,7 @@ static host_t* acquire_address(private_attribute_manager_t *this,
enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &current))
{
- host = current->acquire_address(current, pool, id, auth, requested);
+ host = current->acquire_address(current, pool, id, requested);
if (host)
{
break;
@@ -143,7 +143,7 @@ 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.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_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;
diff --git a/src/charon/config/attributes/attribute_manager.h b/src/charon/config/attributes/attribute_manager.h
index aef6e7b6e..0ac37e78a 100644
--- a/src/charon/config/attributes/attribute_manager.h
+++ b/src/charon/config/attributes/attribute_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -36,14 +36,13 @@ 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 id peer identity to get address forua
* @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);
+ host_t *requested);
/**
* Release a previously acquired address.
diff --git a/src/charon/config/attributes/attribute_provider.h b/src/charon/config/attributes/attribute_provider.h
index 5d563e86b..cbd0075ad 100644
--- a/src/charon/config/attributes/attribute_provider.h
+++ b/src/charon/config/attributes/attribute_provider.h
@@ -25,7 +25,6 @@
#include <library.h>
#include <utils/host.h>
-#include <credentials/auth_info.h>
typedef struct attribute_provider_t attribute_provider_t;
@@ -39,13 +38,12 @@ struct attribute_provider_t {
*
* @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);
+ host_t *requested);
/**
* Release a previously acquired address.
*
diff --git a/src/charon/config/auth_cfg.c b/src/charon/config/auth_cfg.c
new file mode 100644
index 000000000..90fe9877d
--- /dev/null
+++ b/src/charon/config/auth_cfg.c
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2007-2009 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 "auth_cfg.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+#include <credentials/certificates/certificate.h>
+
+ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_SUBJECT_HASH_URL,
+ "RULE_IDENTITY",
+ "RULE_AUTH_CLASS",
+ "RULE_EAP_IDENTITY",
+ "RULE_EAP_TYPE",
+ "RULE_EAP_VENDOR",
+ "RULE_CA_CERT",
+ "RULE_IM_CERT",
+ "RULE_SUBJECT_CERT",
+ "RULE_CRL_VALIDATION",
+ "RULE_OCSP_VALIDATION",
+ "RULE_AC_GROUP",
+ "HELPER_IM_CERT",
+ "HELPER_SUBJECT_CERT",
+ "HELPER_IM_HASH_URL",
+ "HELPER_SUBJECT_HASH_URL",
+);
+
+typedef struct private_auth_cfg_t private_auth_cfg_t;
+
+/**
+ * private data of item_set
+ */
+struct private_auth_cfg_t {
+
+ /**
+ * public functions
+ */
+ auth_cfg_t public;
+
+ /**
+ * list of entry_t
+ */
+ linked_list_t *entries;
+};
+
+typedef struct entry_t entry_t;
+
+struct entry_t {
+ /** rule type */
+ auth_rule_t type;
+ /** associated value */
+ void *value;
+};
+
+/**
+ * enumerator for auth_cfg_t.create_enumerator()
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** inner enumerator from linked_list_t */
+ enumerator_t *inner;
+ /** current entry */
+ entry_t *current;
+} entry_enumerator_t;
+
+/**
+ * enumerate function for item_enumerator_t
+ */
+static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
+{
+ entry_t *entry;
+
+ if (this->inner->enumerate(this->inner, &entry))
+ {
+ this->current = entry;
+ *type = entry->type;
+ *value = entry->value;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function for item_enumerator_t
+ */
+static void entry_enumerator_destroy(entry_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of auth_cfg_t.create_enumerator.
+ */
+static enumerator_t* create_enumerator(private_auth_cfg_t *this)
+{
+ entry_enumerator_t *enumerator;
+
+ enumerator = malloc_thing(entry_enumerator_t);
+ enumerator->inner = this->entries->create_enumerator(this->entries);
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)entry_enumerator_destroy;
+ enumerator->current = NULL;
+ return &enumerator->public;
+}
+
+/**
+ * Destroy the value associated with an entry
+ */
+static void destroy_entry_value(entry_t *entry)
+{
+ switch (entry->type)
+ {
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id = (identification_t*)entry->value;
+ id->destroy(id);
+ break;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)entry->value;
+ cert->destroy(cert);
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ free(entry->value);
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ break;
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.replace.
+ */
+static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator,
+ auth_rule_t type, ...)
+{
+ if (enumerator->current)
+ {
+ va_list args;
+
+ va_start(args, type);
+
+ destroy_entry_value(enumerator->current);
+ enumerator->current->type = type;
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ /* integer type */
+ enumerator->current->value = (void*)va_arg(args, u_int);
+ break;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* pointer type */
+ enumerator->current->value = va_arg(args, void*);
+ break;
+ }
+ va_end(args);
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.get.
+ */
+static void* get(private_auth_cfg_t *this, auth_rule_t type)
+{
+ enumerator_t *enumerator;
+ void *current_value, *best_value = NULL;
+ auth_rule_t current_type;
+ bool found = FALSE;
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current_type, &current_value))
+ {
+ if (type == current_type)
+ {
+ if (type == AUTH_RULE_CRL_VALIDATION ||
+ type == AUTH_RULE_OCSP_VALIDATION)
+ { /* for CRL/OCSP validation, always get() the highest value */
+ if (!found || current_value > best_value)
+ {
+ best_value = current_value;
+ }
+ found = TRUE;
+ continue;
+ }
+ best_value = current_value;
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found)
+ {
+ return best_value;
+ }
+ switch (type)
+ {
+ /* use some sane defaults if we don't find an entry */
+ case AUTH_RULE_AUTH_CLASS:
+ return (void*)AUTH_CLASS_ANY;
+ case AUTH_RULE_EAP_TYPE:
+ return (void*)EAP_NAK;
+ case AUTH_RULE_EAP_VENDOR:
+ return (void*)0;
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ return (void*)VALIDATION_FAILED;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.add.
+ */
+static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
+{
+ entry_t *entry = malloc_thing(entry_t);
+ va_list args;
+
+ va_start(args, type);
+ entry->type = type;
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ /* integer type */
+ entry->value = (void*)va_arg(args, u_int);
+ break;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* pointer type */
+ entry->value = va_arg(args, void*);
+ break;
+ }
+ va_end(args);
+ this->entries->insert_last(this->entries, entry);
+}
+
+/**
+ * Implementation of auth_cfg_t.complies.
+ */
+static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints,
+ bool log_error)
+{
+ enumerator_t *e1, *e2;
+ bool success = TRUE;
+ auth_rule_t t1, t2;
+ void *value;
+
+ e1 = constraints->create_enumerator(constraints);
+ while (e1->enumerate(e1, &t1, &value))
+ {
+ switch (t1)
+ {
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)value;
+
+ success = FALSE;
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &c2))
+ {
+ if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
+ c1->equals(c1, c2))
+ {
+ success = TRUE;
+ }
+ }
+ e2->destroy(e2);
+ if (!success && log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated by CA '%D'.", c1->get_subject(c1));
+ }
+ break;
+ }
+ case AUTH_RULE_SUBJECT_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)value;
+ c2 = get(this, AUTH_RULE_SUBJECT_CERT);
+ if (!c2 || !c1->equals(c1, c2))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated with peer cert '%D'.",
+ c1->get_subject(c1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ {
+ cert_validation_t validated, required;
+
+ required = (uintptr_t)value;
+ validated = (uintptr_t)get(this, t1);
+ switch (required)
+ {
+ case VALIDATION_FAILED:
+ /* no constraint */
+ break;
+ case VALIDATION_SKIPPED:
+ if (validated == VALIDATION_SKIPPED)
+ {
+ break;
+ }
+ /* FALL */
+ case VALIDATION_GOOD:
+ if (validated == VALIDATION_GOOD)
+ {
+ break;
+ }
+ /* FALL */
+ default:
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: %N is %N, "
+ "but requires at least %N", auth_rule_names,
+ t1, cert_validation_names, validated,
+ cert_validation_names, required);
+ }
+ break;
+ }
+ break;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ {
+ identification_t *id1, *id2;
+
+ id1 = (identification_t*)value;
+ id2 = get(this, t1);
+ if (!id2 || !id2->matches(id2, id1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: %sidentity '%D'"
+ " required ", t1 == AUTH_RULE_IDENTITY ? "" :
+ "EAP ", id1);
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ {
+ if ((uintptr_t)value != AUTH_CLASS_ANY &&
+ (uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires %N authentication, "
+ "but %N was used", auth_class_names, (uintptr_t)value,
+ auth_class_names, (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_EAP_TYPE:
+ {
+ if ((uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires %N, "
+ "but %N was used", eap_type_names, (uintptr_t)value,
+ eap_type_names, (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_EAP_VENDOR:
+ {
+ if ((uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
+ "but %d was used", (uintptr_t)value,
+ (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_AC_GROUP:
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check %N not implemented!",
+ auth_rule_names, t1);
+ }
+ break;
+ }
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* skip helpers */
+ continue;
+ }
+ if (!success)
+ {
+ break;
+ }
+ }
+ e1->destroy(e1);
+ return success;
+}
+
+/**
+ * Implementation of auth_cfg_t.merge.
+ */
+static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
+{
+ if (!other)
+ { /* nothing to merge */
+ return;
+ }
+ if (copy)
+ {
+ enumerator_t *enumerator;
+ auth_rule_t type;
+ void *value;
+
+ enumerator = create_enumerator(other);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ switch (type)
+ {
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)value;
+
+ add(this, type, cert->get_ref(cert));
+ break;
+ }
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ {
+ add(this, type, (uintptr_t)value);
+ break;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id = (identification_t*)value;
+
+ add(this, type, id->clone(id));
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ add(this, type, strdup((char*)value));
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ entry_t *entry;
+
+ while (other->entries->remove_first(other->entries,
+ (void**)&entry) == SUCCESS)
+ {
+ this->entries->insert_last(this->entries, entry);
+ }
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.equals.
+ */
+static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
+{
+ enumerator_t *e1, *e2;
+ entry_t *i1, *i2;
+ bool equal = TRUE, found;
+
+ if (this->entries->get_count(this->entries) !=
+ other->entries->get_count(other->entries))
+ {
+ return FALSE;
+ }
+ e1 = this->entries->create_enumerator(this->entries);
+ while (e1->enumerate(e1, &i1))
+ {
+ found = FALSE;
+ e2 = other->entries->create_enumerator(other->entries);
+ while (e2->enumerate(e2, &i2))
+ {
+ if (i1->type == i2->type)
+ {
+ switch (i1->type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ {
+ if (i1->value == i2->value)
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_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 AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id1, *id2;
+
+ id1 = (identification_t*)i1->value;
+ id2 = (identification_t*)i2->value;
+
+ if (id1->equals(id1, id2))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ if (streq(i1->value, i2->value))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ e2->destroy(e2);
+ if (!found)
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ return equal;
+}
+
+/**
+ * Implementation of auth_cfg_t.purge
+ */
+static void purge(private_auth_cfg_t *this, bool keep_ca)
+{
+ entry_t *entry;
+ linked_list_t *cas;
+
+ cas = linked_list_create();
+ while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS)
+ {
+ if (keep_ca && entry->type == AUTH_RULE_CA_CERT)
+ {
+ cas->insert_first(cas, entry);
+ }
+ else
+ {
+ destroy_entry_value(entry);
+ free(entry);
+ }
+ }
+ while (cas->remove_last(cas, (void**)&entry) == SUCCESS)
+ {
+ this->entries->insert_first(this->entries, entry);
+ }
+ cas->destroy(cas);
+}
+
+/**
+ * Implementation of auth_cfg_t.clone
+ */
+static auth_cfg_t* clone_(private_auth_cfg_t *this)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *clone;
+ entry_t *entry;
+
+ clone = auth_cfg_create();
+ enumerator = this->entries->create_enumerator(this->entries);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ switch (entry->type)
+ {
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_AC_GROUP:
+ {
+ identification_t *id = (identification_t*)entry->value;
+ clone->add(clone, entry->type, id->clone(id));
+ break;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)entry->value;
+ clone->add(clone, entry->type, cert->get_ref(cert));
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ clone->add(clone, entry->type, strdup(entry->value));
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ clone->add(clone, entry->type, (uintptr_t)entry->value);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return clone;
+}
+
+/**
+ * Implementation of auth_cfg_t.destroy
+ */
+static void destroy(private_auth_cfg_t *this)
+{
+ purge(this, FALSE);
+ this->entries->destroy(this->entries);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+auth_cfg_t *auth_cfg_create()
+{
+ private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t);
+
+ this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add;
+ this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get;
+ this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator;
+ this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace;
+ this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies;
+ this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge;
+ this->public.purge = (void(*)(auth_cfg_t*,bool))purge;
+ this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals;
+ this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_;
+ this->public.destroy = (void(*)(auth_cfg_t*))destroy;
+
+ this->entries = linked_list_create();
+
+ return &this->public;
+}
+
diff --git a/src/charon/config/auth_cfg.h b/src/charon/config/auth_cfg.h
new file mode 100644
index 000000000..c6bc1959b
--- /dev/null
+++ b/src/charon/config/auth_cfg.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2007-2009 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.
+ */
+
+/**
+ * @defgroup auth_cfg auth_cfg
+ * @{ @ingroup config
+ */
+
+#ifndef AUTH_CFG_H_
+#define AUTH_CFG_H_
+
+#include <utils/enumerator.h>
+
+typedef struct auth_cfg_t auth_cfg_t;
+typedef enum auth_rule_t auth_rule_t;
+
+/**
+ * Authentication config to use during authentication process.
+ *
+ * Each authentication config contains a set of rules. These rule-sets are used
+ * in two ways:
+ * - For configs specifying local authentication behavior, the rules define
+ * which authentication method in which way.
+ * - For configs specifying remote peer authentication, the rules define
+ * constraints the peer has to fullfill.
+ *
+ * Additionally to the rules, there is a set of helper items. These are used
+ * to transport credentials during the authentication process.
+ */
+enum auth_rule_t {
+
+ /** identity to use for IKEv2 authentication exchange, identification_t* */
+ AUTH_RULE_IDENTITY,
+ /** authentication class, auth_class_t */
+ AUTH_RULE_AUTH_CLASS,
+ /** EAP identity to use within EAP-Identity exchange, identification_t* */
+ AUTH_RULE_EAP_IDENTITY,
+ /** EAP type to propose for peer authentication, eap_type_t */
+ AUTH_RULE_EAP_TYPE,
+ /** EAP vendor for vendor specific type, u_int32_t */
+ AUTH_RULE_EAP_VENDOR,
+ /** certificate authority, certificate_t* */
+ AUTH_RULE_CA_CERT,
+ /** intermediate certificate in trustchain, certificate_t* */
+ AUTH_RULE_IM_CERT,
+ /** subject certificate, certificate_t* */
+ AUTH_RULE_SUBJECT_CERT,
+ /** result of a CRL validation, cert_validation_t */
+ AUTH_RULE_CRL_VALIDATION,
+ /** result of a OCSP validation, cert_validation_t */
+ AUTH_RULE_OCSP_VALIDATION,
+ /** subject is in attribute certificate group, identification_t* */
+ AUTH_RULE_AC_GROUP,
+
+ /** intermediate certificate, certificate_t* */
+ AUTH_HELPER_IM_CERT,
+ /** subject certificate, certificate_t* */
+ AUTH_HELPER_SUBJECT_CERT,
+ /** Hash and URL of a intermediate certificate, char* */
+ AUTH_HELPER_IM_HASH_URL,
+ /** Hash and URL of a end-entity certificate, char* */
+ AUTH_HELPER_SUBJECT_HASH_URL,
+};
+
+/**
+ * enum name for auth_rule_t.
+ */
+extern enum_name_t *auth_rule_names;
+
+/**
+ * Authentication/Authorization round.
+ *
+ * RFC4739 defines multiple authentication rounds. This class defines such
+ * a round from a configuration perspective, either for the local or the remote
+ * peer. Local config are called "rulesets", as they define how we authenticate.
+ * Remote peer configs are called "constraits", they define what is needed to
+ * complete the authentication round successfully.
+ *
+ * @verbatim
+
+ [Repeat for each configuration]
+ +--------------------------------------------------+
+ | |
+ | |
+ | +----------+ IKE_AUTH +--------- + |
+ | | config | -----------> | | |
+ | | ruleset | | | |
+ | +----------+ [ <----------- ] | | |
+ | [ optional EAP ] | Peer | |
+ | +----------+ [ -----------> ] | | |
+ | | config | | | |
+ | | constr. | <----------- | | |
+ | +----------+ IKE_AUTH +--------- + |
+ | |
+ | |
+ +--------------------------------------------------+
+
+ @endverbatim
+ *
+ * Values for each items are either pointers (casted to void*) or short
+ * integers (use uintptr_t cast).
+ */
+struct auth_cfg_t {
+
+ /**
+ * Add an rule to the set.
+ *
+ * @param rule rule type
+ * @param ... associated value to rule
+ */
+ void (*add)(auth_cfg_t *this, auth_rule_t rule, ...);
+
+ /**
+ * Get an rule value.
+ *
+ * @param rule rule type
+ * @return bool if item has been found
+ */
+ void* (*get)(auth_cfg_t *this, auth_rule_t rule);
+
+ /**
+ * Create an enumerator over added rules.
+ *
+ * @return enumerator over (auth_rule_t, union{void*,uintpr_t})
+ */
+ enumerator_t* (*create_enumerator)(auth_cfg_t *this);
+
+ /**
+ * Replace an rule at enumerator position.
+ *
+ * @param pos enumerator position position
+ * @param rule rule type
+ * @param ... associated value to rule
+ */
+ void (*replace)(auth_cfg_t *this, enumerator_t *pos,
+ auth_rule_t rule, ...);
+
+ /**
+ * Check if a used config fulfills a set of configured constraints.
+ *
+ * @param constraints required authorization rules
+ * @param log_error wheter to log compliance errors
+ * @return TRUE if this complies with constraints
+ */
+ bool (*complies)(auth_cfg_t *this, auth_cfg_t *constraints, bool log_error);
+
+ /**
+ * Merge items from other into this.
+ *
+ * @param other items to read for merge
+ * @param copy TRUE to copy items, FALSE to move them
+ */
+ void (*merge)(auth_cfg_t *this, auth_cfg_t *other, bool copy);
+
+ /**
+ * Purge all rules in a config.
+ *
+ * @param keep_ca wheter to keep AUTH_RULE_CA_CERT entries
+ */
+ void (*purge)(auth_cfg_t *this, bool keep_ca);
+
+ /**
+ * Check two configs for equality.
+ *
+ * @param other other config to compaire against this
+ * @return TRUE if auth infos identical
+ */
+ bool (*equals)(auth_cfg_t *this, auth_cfg_t *other);
+
+ /**
+ * Clone a authentication config, including all rules.
+ *
+ * @return cloned configuration
+ */
+ auth_cfg_t* (*clone)(auth_cfg_t *this);
+
+ /**
+ * Destroy a config with all associated rules/values.
+ */
+ void (*destroy)(auth_cfg_t *this);
+};
+
+/**
+ * Create a authentication config.
+ */
+auth_cfg_t *auth_cfg_create();
+
+#endif /** AUTH_CFG_H_ @}*/
diff --git a/src/charon/config/backend.h b/src/charon/config/backend.h
index 4673d3984..42633f73b 100644
--- a/src/charon/config/backend.h
+++ b/src/charon/config/backend.h
@@ -28,7 +28,6 @@ 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>
/**
@@ -45,6 +44,10 @@ struct backend_t {
*
* Hosts may be NULL to get all.
*
+ * There is no requirement for the backend to filter the configurations
+ * using the supplied hosts; but it may do so if it increases lookup times
+ * (e.g. include hosts in SQL query).
+ *
* @param me address of local host
* @param other address of remote host
* @return enumerator over ike_cfg_t's
@@ -52,10 +55,17 @@ struct backend_t {
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.
+ * Create an enumerator over all peer configs matching two identities.
*
* IDs may be NULL to get all.
*
+ * As configurations are looked up in the first authentication round (when
+ * multiple authentication), the backend implementation should compare
+ * the identities to the first auth_cfgs only.
+ * There is no requirement for the backend to filter the configurations
+ * using the supplied identities; but it may do so if it increases lookup
+ * times (e.g. include hosts in SQL query).
+ *
* @param me identity of ourself
* @param other identity of remote host
* @return enumerator over peer_cfg_t
@@ -64,7 +74,7 @@ struct backend_t {
identification_t *me,
identification_t *other);
/**
- * Get a peer_cfg identified by it's name, or a name of its child.
+ * Get a peer_cfg identified by it's name, or a name of its children.
*
* @param name name of peer/child cfg
* @return matching peer_config, or NULL if none found
diff --git a/src/charon/config/backend_manager.c b/src/charon/config/backend_manager.c
index c31df8d04..28e50ef0a 100644
--- a/src/charon/config/backend_manager.c
+++ b/src/charon/config/backend_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2007-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -68,15 +68,6 @@ typedef struct {
} 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;
-
-/**
* inner enumerator constructor for IKE cfgs
*/
static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data)
@@ -85,59 +76,58 @@ static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data)
}
/**
- * inner enumerator constructor for Peer cfgs
- */
-static enumerator_t *peer_enum_create(backend_t *backend, peer_data_t *data)
-{
- return backend->create_peer_cfg_enumerator(backend, data->me, data->other);
-}
-/**
- * inner enumerator constructor for all Peer cfgs
- */
-static enumerator_t *peer_enum_create_all(backend_t *backend)
-{
- return backend->create_peer_cfg_enumerator(backend, NULL, NULL);
-}
-
-/**
* get a match of a candidate ike_cfg for two hosts
*/
-static ike_cfg_match_t get_match(ike_cfg_t *cand, host_t *me, host_t *other)
+static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other)
{
host_t *me_cand, *other_cand;
ike_cfg_match_t match = MATCH_NONE;
- me_cand = host_create_from_dns(cand->get_my_addr(cand),
- me->get_family(me), 0);
- if (!me_cand)
- {
- return MATCH_NONE;
- }
- if (me_cand->ip_equals(me_cand, me))
+ if (me)
{
- match += MATCH_ME;
+ me_cand = host_create_from_dns(cand->get_my_addr(cand),
+ me->get_family(me), 0);
+ if (!me_cand)
+ {
+ return MATCH_NONE;
+ }
+ if (me_cand->ip_equals(me_cand, me))
+ {
+ match += MATCH_ME;
+ }
+ else if (me_cand->is_anyaddr(me_cand))
+ {
+ match += MATCH_ANY;
+ }
+ me_cand->destroy(me_cand);
}
- else if (me_cand->is_anyaddr(me_cand))
+ else
{
match += MATCH_ANY;
}
- me_cand->destroy(me_cand);
- other_cand = host_create_from_dns(cand->get_other_addr(cand),
- other->get_family(other), 0);
- if (!other_cand)
- {
- return MATCH_NONE;
- }
- if (other_cand->ip_equals(other_cand, other))
+ if (other)
{
- match += MATCH_OTHER;
+ other_cand = host_create_from_dns(cand->get_other_addr(cand),
+ other->get_family(other), 0);
+ if (!other_cand)
+ {
+ return MATCH_NONE;
+ }
+ if (other_cand->ip_equals(other_cand, other))
+ {
+ match += MATCH_OTHER;
+ }
+ else if (other_cand->is_anyaddr(other_cand))
+ {
+ match += MATCH_ANY;
+ }
+ other_cand->destroy(other_cand);
}
- else if (other_cand->is_anyaddr(other_cand))
+ else
{
match += MATCH_ANY;
}
- other_cand->destroy(other_cand);
return match;
}
@@ -165,7 +155,7 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
(void*)ike_enum_create, data, (void*)free);
while (enumerator->enumerate(enumerator, (void**)&current))
{
- match = get_match(current, me, other);
+ match = get_ike_match(current, me, other);
if (match)
{
@@ -191,87 +181,198 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
return found;
}
+/**
+ * Get the best ID match in one of the configs auth_cfg
+ */
+static id_match_t get_peer_match(identification_t *id,
+ peer_cfg_t *cfg, bool local)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+ identification_t *candidate;
+ id_match_t match = ID_MATCH_NONE;
+
+ if (!id)
+ {
+ return ID_MATCH_ANY;
+ }
+
+ /* compare first auth config only */
+ enumerator = cfg->create_auth_cfg_enumerator(cfg, local);
+ if (enumerator->enumerate(enumerator, &auth))
+ {
+ candidate = auth->get(auth, AUTH_RULE_IDENTITY);
+ if (candidate)
+ {
+ match = id->matches(id, candidate);
+ /* match vice-versa, as the proposed IDr might be ANY */
+ if (!match)
+ {
+ match = candidate->matches(candidate, id);
+ }
+ }
+ else
+ {
+ match = ID_MATCH_ANY;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return match;
+}
+
+/**
+ * data to pass nested peer enumerator
+ */
+typedef struct {
+ rwlock_t *lock;
+ identification_t *me;
+ identification_t *other;
+} peer_data_t;
-static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this)
+/**
+ * list element to help sorting
+ */
+typedef struct {
+ id_match_t match_peer;
+ ike_cfg_match_t match_ike;
+ peer_cfg_t *cfg;
+} match_entry_t;
+
+/**
+ * inner enumerator constructor for peer cfgs
+ */
+static enumerator_t *peer_enum_create(backend_t *backend, peer_data_t *data)
{
- this->lock->read_lock(this->lock);
- return enumerator_create_nested(
- this->backends->create_enumerator(this->backends),
- (void*)peer_enum_create_all, this->lock,
- (void*)this->lock->unlock);
+ return backend->create_peer_cfg_enumerator(backend, data->me, data->other);
+}
+
+/**
+ * unlock/cleanup peer enumerator
+ */
+static void peer_enum_destroy(peer_data_t *data)
+{
+ data->lock->unlock(data->lock);
+ free(data);
+}
+
+/**
+ * convert enumerator value from match_entry to config
+ */
+static bool peer_enum_filter(linked_list_t *configs,
+ match_entry_t **in, peer_cfg_t **out)
+{
+ *out = (*in)->cfg;
+ return TRUE;
+}
+
+/**
+ * Clean up temporary config list
+ */
+static void peer_enum_filter_destroy(linked_list_t *configs)
+{
+ match_entry_t *entry;
+
+ while (configs->remove_last(configs, (void**)&entry) == SUCCESS)
+ {
+ entry->cfg->destroy(entry->cfg);
+ free(entry);
+ }
+ configs->destroy(configs);
+}
+
+/**
+ * Insert entry into match-sorted list, using helper
+ */
+static void insert_sorted(match_entry_t *entry, linked_list_t *list,
+ linked_list_t *helper)
+{
+ match_entry_t *current;
+
+ while (list->remove_first(list, (void**)&current) == SUCCESS)
+ {
+ helper->insert_last(helper, current);
+ }
+ while (helper->remove_first(helper, (void**)&current) == SUCCESS)
+ {
+ if (entry && (
+ (entry->match_ike > current->match_ike &&
+ entry->match_peer >= current->match_peer) ||
+ (entry->match_ike >= current->match_ike &&
+ entry->match_peer > current->match_peer)))
+ {
+ list->insert_last(list, entry);
+ entry = NULL;
+ }
+ list->insert_last(list, current);
+ }
+ if (entry)
+ {
+ list->insert_last(list, entry);
+ }
}
/**
- * implements backend_manager_t.get_peer_cfg.
+ * Implements backend_manager_t.create_peer_cfg_enumerator.
*/
-static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, host_t *me,
- host_t *other, identification_t *my_id,
- identification_t *other_id, auth_info_t *auth)
+static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this,
+ host_t *me, host_t *other, identification_t *my_id,
+ identification_t *other_id)
{
- peer_cfg_t *current, *found = NULL;
enumerator_t *enumerator;
- id_match_t best_peer = ID_MATCH_NONE;
- ike_cfg_match_t best_ike = MATCH_NONE;
peer_data_t *data;
-
- DBG2(DBG_CFG, "looking for a peer config for %H[%D]...%H[%D]",
- me, my_id, other, other_id);
+ peer_cfg_t *cfg;
+ linked_list_t *configs, *helper;
data = malloc_thing(peer_data_t);
- data->this = this;
+ data->lock = this->lock;
data->me = my_id;
data->other = other_id;
+ /* create a sorted list with all matches */
this->lock->read_lock(this->lock);
enumerator = enumerator_create_nested(
- this->backends->create_enumerator(this->backends),
- (void*)peer_enum_create, data, (void*)free);
- while (enumerator->enumerate(enumerator, &current))
+ this->backends->create_enumerator(this->backends),
+ (void*)peer_enum_create, data, (void*)peer_enum_destroy);
+
+ if (!me && !other && !my_id && !other_id)
+ { /* shortcut if we are doing a "listall" */
+ return enumerator;
+ }
+
+ DBG1(DBG_CFG, "looking for peer configs matching %H[%D]...%H[%D]",
+ me, my_id, other, other_id);
+
+ configs = linked_list_create();
+ /* only once allocated helper list for sorting */
+ helper = linked_list_create();
+ while (enumerator->enumerate(enumerator, &cfg))
{
- identification_t *my_cand, *other_cand;
- id_match_t m1, m2, match_peer;
+ id_match_t match_peer_me, match_peer_other;
ike_cfg_match_t match_ike;
+ match_entry_t *entry;
- my_cand = current->get_my_id(current);
- other_cand = current->get_other_id(current);
-
- /* own ID may have wildcards in both, config and request (missing IDr) */
- m1 = my_cand->matches(my_cand, my_id);
- if (!m1)
- {
- m1 = my_id->matches(my_id, my_cand);
- }
- m2 = other_id->matches(other_id, other_cand);
-
- match_peer = m1 + m2;
- match_ike = get_match(current->get_ike_cfg(current), me, other);
+ match_peer_me = get_peer_match(my_id, cfg, TRUE);
+ match_peer_other = get_peer_match(other_id, cfg, FALSE);
+ match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other);
- if (m1 && m2 && match_ike &&
- auth->complies(auth, current->get_auth(current)))
+ if (match_peer_me && match_peer_other && match_ike)
{
- DBG2(DBG_CFG, " candidate \"%s\": %D...%D with prio %d.%d",
- current->get_name(current), my_cand, other_cand,
- match_peer, match_ike);
- if ((match_peer > best_peer && match_ike >= best_ike) ||
- (match_peer >= best_peer && match_ike > best_ike))
- {
- DESTROY_IF(found);
- found = current;
- found->get_ref(found);
- best_peer = match_peer;
- best_ike = match_ike;
- }
+ DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d (me/other/ike)",
+ cfg->get_name(cfg), match_peer_me, match_peer_other, match_ike);
+
+ entry = malloc_thing(match_entry_t);
+ entry->match_peer = match_peer_me + match_peer_other;
+ entry->match_ike = match_ike;
+ entry->cfg = cfg->get_ref(cfg);
+ insert_sorted(entry, configs, helper);
}
}
- if (found)
- {
- DBG1(DBG_CFG, "found matching peer config \"%s\": %D...%D with prio %d.%d",
- found->get_name(found), found->get_my_id(found),
- found->get_other_id(found), best_peer, best_ike);
- }
enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- return found;
+ helper->destroy(helper);
+
+ return enumerator_create_filter(configs->create_enumerator(configs),
+ (void*)peer_enum_filter, configs,
+ (void*)peer_enum_filter_destroy);
}
/**
@@ -332,9 +433,8 @@ 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*,host_t*,host_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.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*))create_peer_cfg_enumerator;
+ this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*,host_t*,host_t*,identification_t*,identification_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;
diff --git a/src/charon/config/backend_manager.h b/src/charon/config/backend_manager.h
index 1fd921c48..b3c74fb7b 100644
--- a/src/charon/config/backend_manager.h
+++ b/src/charon/config/backend_manager.h
@@ -64,20 +64,6 @@ struct backend_manager_t {
host_t *my_host, host_t *other_host);
/**
- * Get a peer_config identified by two IDs and authorization info.
- *
- * @param me own address
- * @param other peer address
- * @param my_id own ID
- * @param other_id peer ID
- * @param auth_info authorization info
- * @return matching peer_config, or NULL if none found
- */
- peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this, host_t *me,
- host_t *other, identification_t *my_id,
- identification_t *other_id, auth_info_t *auth);
-
- /**
* Get a peer_config identified by it's name.
*
* @param name name of the peer_config
@@ -86,12 +72,20 @@ struct backend_manager_t {
peer_cfg_t* (*get_peer_cfg_by_name)(backend_manager_t *this, char *name);
/**
- * Create an enumerator over all peer configs.
+ * Create an enumerator over all matching peer configs.
+ *
+ * Pass NULL as parameters to match any. The enumerator enumerates over
+ * peer_cfgs, ordered by priority (best match first).
*
- * @return enumerator over peer configs
+ * @param me local address
+ * @param other remote address
+ * @param my_id IDr in first authentication round
+ * @param other_id IDi in first authentication round
+ * @return enumerator over peer_cfg_t
*/
- enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this);
-
+ enumerator_t* (*create_peer_cfg_enumerator)(backend_manager_t *this,
+ host_t *me, host_t *other, identification_t *my_id,
+ identification_t *other_id);
/**
* Register a backend on the manager.
*
diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c
index 398244f6d..5d9db1b22 100644
--- a/src/charon/config/peer_cfg.c
+++ b/src/charon/config/peer_cfg.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007-2008 Tobias Brunner
- * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -82,16 +82,6 @@ struct private_peer_cfg_t {
mutex_t *mutex;
/**
- * id to use to identify us
- */
- identification_t *my_id;
-
- /**
- * allowed id for other
- */
- identification_t *other_id;
-
- /**
* should we send a certificate
*/
cert_policy_t cert_policy;
@@ -147,10 +137,15 @@ struct private_peer_cfg_t {
char *pool;
/**
- * required authorization constraints
+ * local authentication configs (rulesets)
*/
- auth_info_t *auth;
-
+ linked_list_t *local_auth;
+
+ /**
+ * remote authentication configs (constraints)
+ */
+ linked_list_t *remote_auth;
+
#ifdef ME
/**
* Is this a mediation connection?
@@ -287,22 +282,6 @@ static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
}
/**
- * Implementation of peer_cfg_t.get_my_id
- */
-static identification_t *get_my_id(private_peer_cfg_t *this)
-{
- return this->my_id;
-}
-
-/**
- * Implementation of peer_cfg_t.get_other_id
- */
-static identification_t *get_other_id(private_peer_cfg_t *this)
-{
- return this->other_id;
-}
-
-/**
* Implementation of peer_cfg_t.get_cert_policy.
*/
static cert_policy_t get_cert_policy(private_peer_cfg_t *this)
@@ -397,13 +376,34 @@ static char* get_pool(private_peer_cfg_t *this)
{
return this->pool;
}
-
+
/**
- * Implementation of peer_cfg_t.get_auth.
+ * Implementation of peer_cfg_t.add_auth_cfg
*/
-static auth_info_t* get_auth(private_peer_cfg_t *this)
+static void add_auth_cfg(private_peer_cfg_t *this,
+ auth_cfg_t *cfg, bool local)
{
- return this->auth;
+ if (local)
+ {
+ this->local_auth->insert_last(this->local_auth, cfg);
+ }
+ else
+ {
+ this->remote_auth->insert_last(this->remote_auth, cfg);
+ }
+}
+
+/**
+ * Implementation of peer_cfg_t.create_auth_cfg_enumerator
+ */
+static enumerator_t* create_auth_cfg_enumerator(private_peer_cfg_t *this,
+ bool local)
+{
+ if (local)
+ {
+ return this->local_auth->create_enumerator(this->local_auth);
+ }
+ return this->remote_auth->create_enumerator(this->remote_auth);
}
#ifdef ME
@@ -433,6 +433,60 @@ static identification_t* get_peer_id(private_peer_cfg_t *this)
#endif /* ME */
/**
+ * check auth configs for equality
+ */
+static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
+{
+ enumerator_t *e1, *e2;
+ auth_cfg_t *cfg1, *cfg2;
+ bool equal = TRUE;
+
+ if (this->local_auth->get_count(this->local_auth) !=
+ other->local_auth->get_count(other->local_auth))
+ {
+ return FALSE;
+ }
+ if (this->remote_auth->get_count(this->remote_auth) !=
+ other->remote_auth->get_count(other->remote_auth))
+ {
+ return FALSE;
+ }
+
+ e1 = this->local_auth->create_enumerator(this->local_auth);
+ e2 = other->local_auth->create_enumerator(other->local_auth);
+ while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
+ {
+ if (!cfg1->equals(cfg1, cfg2))
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ if (!equal)
+ {
+ return FALSE;
+ }
+
+ e1 = this->remote_auth->create_enumerator(this->remote_auth);
+ e2 = other->remote_auth->create_enumerator(other->remote_auth);
+ while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
+ {
+ if (!cfg1->equals(cfg1, cfg2))
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ return equal;
+}
+
+/**
* Implementation of peer_cfg_t.equals.
*/
static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other)
@@ -448,8 +502,6 @@ static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other)
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->keyingtries == other->keyingtries &&
@@ -464,7 +516,7 @@ static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other)
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)
+ auth_cfg_equal(this, other)
#ifdef ME
&& this->mediation == other->mediation &&
this->mediated_by == other->mediated_by &&
@@ -492,11 +544,13 @@ static void destroy(private_peer_cfg_t *this)
if (ref_put(&this->refcount))
{
this->ike_cfg->destroy(this->ike_cfg);
- 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);
+ this->child_cfgs->destroy_offset(this->child_cfgs,
+ offsetof(child_cfg_t, destroy));
DESTROY_IF(this->virtual_ip);
- this->auth->destroy(this->auth);
+ this->local_auth->destroy_offset(this->local_auth,
+ offsetof(auth_cfg_t, destroy));
+ this->remote_auth->destroy_offset(this->remote_auth,
+ offsetof(auth_cfg_t, destroy));
#ifdef ME
DESTROY_IF(this->mediated_by);
DESTROY_IF(this->peer_id);
@@ -512,7 +566,6 @@ static void destroy(private_peer_cfg_t *this)
* Described in header-file
*/
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,
cert_policy_t cert_policy, unique_policy_t unique,
u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time,
@@ -531,8 +584,6 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
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_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
this->public.get_unique_policy = (unique_policy_t (*) (peer_cfg_t *))get_unique_policy;
this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries;
@@ -543,7 +594,8 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
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.add_auth_cfg = (void(*)(peer_cfg_t*, auth_cfg_t *cfg, bool local))add_auth_cfg;
+ this->public.create_auth_cfg_enumerator = (enumerator_t*(*)(peer_cfg_t*, bool local))create_auth_cfg_enumerator;
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;
@@ -559,8 +611,6 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->ike_cfg = ike_cfg;
this->child_cfgs = linked_list_create();
this->mutex = mutex_create(MUTEX_DEFAULT);
- this->my_id = my_id;
- this->other_id = other_id;
this->cert_policy = cert_policy;
this->unique = unique;
this->keyingtries = keyingtries;
@@ -580,7 +630,8 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->dpd = dpd;
this->virtual_ip = virtual_ip;
this->pool = pool ? strdup(pool) : NULL;
- this->auth = auth_info_create();
+ this->local_auth = linked_list_create();
+ this->remote_auth = linked_list_create();
this->refcount = 1;
#ifdef ME
this->mediation = mediation;
diff --git a/src/charon/config/peer_cfg.h b/src/charon/config/peer_cfg.h
index 3a776927e..7cfe61207 100644
--- a/src/charon/config/peer_cfg.h
+++ b/src/charon/config/peer_cfg.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007-2008 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -38,7 +38,7 @@ typedef struct peer_cfg_t peer_cfg_t;
#include <config/child_cfg.h>
#include <sa/authenticators/authenticator.h>
#include <sa/authenticators/eap/eap_method.h>
-#include <credentials/auth_info.h>
+#include <config/auth_cfg.h>
/**
* Certificate sending policy. This is also used for certificate
@@ -87,27 +87,33 @@ extern enum_name_t *unique_policy_names;
* exactly one ike_cfg_t, which is use for initiation. Additionally, it contains
* multiple child_cfg_t defining which CHILD_SAs are allowed for this peer.
* @verbatim
-
- +-------------------+ +---------------+
- +---------------+ | peer_cfg | +---------------+ |
- | ike_cfg | +-------------------+ | child_cfg | |
- +---------------+ | - ids | +---------------+ |
- | - hosts | 1 1 | - cas | 1 n | - proposals | |
- | - proposals |<------| - auth info |-------->| - traffic sel | |
- | - ... | | - dpd config | | - ... |-+
- +---------------+ | - ... | +---------------+
- +-------------------+
- ^
- |
- +-------------------+
- | auth_info |
- +-------------------+
- | auth_items |
- +-------------------+
+ +-------------------+ +---------------+
+ +---------------+ | peer_cfg | +---------------+ |
+ | ike_cfg | +-------------------+ | child_cfg | |
+ +---------------+ | - ids | +---------------+ |
+ | - hosts | 1 1 | - cas | 1 n | - proposals | |
+ | - proposals |<-----| - auth info |----->| - traffic sel | |
+ | - ... | | - dpd config | | - ... |-+
+ +---------------+ | - ... | +---------------+
+ +-------------------+
+ | 1 0 |
+ | |
+ v n n V
+ +-------------------+ +-------------------+
+ +-------------------+ | +-------------------+ |
+ | auth_cfg | | | auth_cfg | |
+ +-------------------+ | +-------------------+ |
+ | - local rules |-+ | - remote constr. |-+
+ +-------------------+ +-------------------+
@endverbatim
- * 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.
+ *
+ * Each peer_cfg has two lists of authentication config attached. Local
+ * authentication configs define how to authenticate ourself against the remote
+ * peer. Each config is enforced using the multiple authentication extension
+ * (RFC4739).
+ * The remote authentication configs are handled as constraints. The peer has
+ * to fullfill each of these rules (using multiple authentication, in any order)
+ * to gain access to the configuration.
*/
struct peer_cfg_t {
@@ -169,25 +175,20 @@ struct peer_cfg_t {
host_t *other_host);
/**
- * Get the authentication constraint items.
+ * Add an authentication config to the peer configuration.
*
- * @return auth_info object to manipulate requirements
+ * @param config config to add
+ * @param local TRUE for local rules, FALSE for remote constraints
*/
- auth_info_t* (*get_auth)(peer_cfg_t *this);
-
- /**
- * Get own ID.
- *
- * @return own id
- */
- identification_t* (*get_my_id)(peer_cfg_t *this);
+ void (*add_auth_cfg)(peer_cfg_t *this, auth_cfg_t *cfg, bool local);
/**
- * Get peers ID.
- *
- * @return other id
+ * Create an enumerator over registered authentication configs.
+ *
+ * @param local TRUE for local rules, FALSE for remote constraints
+ * @return enumerator over auth_cfg_t*
*/
- identification_t* (*get_other_id)(peer_cfg_t *this);
+ enumerator_t* (*create_auth_cfg_enumerator)(peer_cfg_t *this, bool local);
/**
* Should be sent a certificate for this connection?
@@ -331,8 +332,6 @@ struct peer_cfg_t {
* @param name name of the peer_cfg
* @param ike_version which IKE version we sould use for this peer
* @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 cert_policy should we send a certificate payload?
* @param unique uniqueness of an IKE_SA
* @param keyingtries how many keying tries should be done before giving up
@@ -350,7 +349,6 @@ struct peer_cfg_t {
* @return peer_cfg_t object
*/
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,
cert_policy_t cert_policy, unique_policy_t unique,
u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time,
diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c
index da6973925..7bddff174 100644
--- a/src/charon/config/proposal.c
+++ b/src/charon/config/proposal.c
@@ -19,6 +19,7 @@
#include <string.h>
#include "proposal.h"
+#include "proposal_keywords.h"
#include <daemon.h>
#include <utils/linked_list.h>
@@ -583,222 +584,59 @@ static void check_proposal(private_proposal_t *this)
}
}
+struct proposal_token {
+ char *name;
+ transform_type_t type;
+ u_int16_t algorithm;
+ u_int16_t keysize;
+};
+
/**
* add a algorithm identified by a string to the proposal.
- * TODO: we could use gperf here.
*/
static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
{
- if (strncmp(alg.ptr, "null", alg.len) == 0)
- {
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_NULL, 0);
- }
- else if (strncmp(alg.ptr, "aes128", alg.len) == 0)
- {
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
- }
- else if (strncmp(alg.ptr, "aes192", alg.len) == 0)
- {
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
- }
- else if (strncmp(alg.ptr, "aes256", alg.len) == 0)
+ const proposal_token_t *token = in_word_set(alg.ptr, alg.len);
+
+ if (token == NULL)
{
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
+ return FAILED;
}
- 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;
+ add_algorithm(this, token->type, token->algorithm, token->keysize);
- 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);
- }
- /* blowfish only uses some predefined key sizes yet */
- else if (strncmp(alg.ptr, "blowfish128", alg.len) == 0)
- {
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128);
- }
- else if (strncmp(alg.ptr, "blowfish192", alg.len) == 0)
- {
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192);
- }
- else if (strncmp(alg.ptr, "blowfish256", alg.len) == 0)
- {
- add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
- }
- else if (strncmp(alg.ptr, "sha", alg.len) == 0 ||
- strncmp(alg.ptr, "sha1", alg.len) == 0)
- {
- /* sha means we use SHA for both, PRF and AUTH */
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
- if (this->protocol == PROTO_IKE)
- {
- add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
- }
- }
- else if (strncmp(alg.ptr, "sha256", alg.len) == 0 ||
- strncmp(alg.ptr, "sha2_256", alg.len) == 0)
+ if (this->protocol == PROTO_IKE && token->type == INTEGRITY_ALGORITHM)
{
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0);
- if (this->protocol == PROTO_IKE)
- {
- add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0);
- }
- }
- else if (strncmp(alg.ptr, "sha384", alg.len) == 0 ||
- strncmp(alg.ptr, "sha2_384", alg.len) == 0)
- {
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0);
- if (this->protocol == PROTO_IKE)
- {
- add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_384, 0);
- }
- }
- else if (strncmp(alg.ptr, "sha512", alg.len) == 0 ||
- strncmp(alg.ptr, "sha2_512", alg.len) == 0)
- {
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0);
- if (this->protocol == PROTO_IKE)
- {
- add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_512, 0);
- }
- }
- else if (strncmp(alg.ptr, "md5", alg.len) == 0)
- {
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
- if (this->protocol == PROTO_IKE)
+ pseudo_random_function_t prf;
+
+ switch (token->algorithm)
{
- add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
+ case AUTH_HMAC_SHA1_96:
+ prf = PRF_HMAC_SHA1;
+ break;
+ case AUTH_HMAC_SHA2_256_128:
+ prf = PRF_HMAC_SHA2_256;
+ break;
+ case AUTH_HMAC_SHA2_384_192:
+ prf = PRF_HMAC_SHA2_384;
+ break;
+ case AUTH_HMAC_SHA2_512_256:
+ prf = PRF_HMAC_SHA2_512;
+ break;
+ case AUTH_HMAC_MD5_96:
+ prf = PRF_HMAC_MD5;
+ break;
+ case AUTH_AES_XCBC_96:
+ prf = PRF_AES128_XCBC;
+ break;
+ default:
+ prf = PRF_UNDEFINED;
}
- }
- else if (strncmp(alg.ptr, "aesxcbc", alg.len) == 0)
- {
- add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
- if (this->protocol == PROTO_IKE)
+ if (prf != PRF_UNDEFINED)
{
- add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0);
+ add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
}
}
- else if (strncmp(alg.ptr, "modpnull", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_NULL, 0);
- }
- else if (strncmp(alg.ptr, "modp768", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0);
- }
- else if (strncmp(alg.ptr, "modp1024", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
- }
- else if (strncmp(alg.ptr, "modp1536", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
- }
- else if (strncmp(alg.ptr, "modp2048", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
- }
- else if (strncmp(alg.ptr, "modp3072", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0);
- }
- else if (strncmp(alg.ptr, "modp4096", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
- }
- else if (strncmp(alg.ptr, "modp6144", alg.len) == 0)
- {
- add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0);
- }
- else if (strncmp(alg.ptr, "modp8192", alg.len) == 0)
- {
- 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;
- }
return SUCCESS;
}
diff --git a/src/charon/config/proposal_keywords.h b/src/charon/config/proposal_keywords.h
new file mode 100644
index 000000000..ae10d3464
--- /dev/null
+++ b/src/charon/config/proposal_keywords.h
@@ -0,0 +1,26 @@
+/* proposal keywords
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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:$
+ */
+
+#ifndef _PROPOSAL_KEYWORDS_H_
+#define _PROPOSAL_KEYWORDS_H_
+
+typedef struct proposal_token proposal_token_t;
+
+extern const proposal_token_t* in_word_set(register const char *str, register unsigned int len);
+
+#endif /* _PROPOSAL_KEYWORDS_H_ */
+
diff --git a/src/charon/config/proposal_keywords.txt b/src/charon/config/proposal_keywords.txt
new file mode 100644
index 000000000..e195b1f72
--- /dev/null
+++ b/src/charon/config/proposal_keywords.txt
@@ -0,0 +1,101 @@
+%{
+/* proposal keywords
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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:$
+ */
+
+#include <string.h>
+
+#include "proposal.h"
+
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+
+%}
+struct proposal_token {
+ char *name;
+ transform_type_t type;
+ u_int16_t algorithm;
+ u_int16_t keysize;
+};
+%%
+null, ENCRYPTION_ALGORITHM, ENCR_NULL, 0
+aes128, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128
+aes192, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192
+aes256, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256
+aes128ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128
+aes128ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128
+aes128ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
+aes128ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
+aes128ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
+aes128ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
+aes192ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
+aes192ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
+aes192ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
+aes192ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
+aes192ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
+aes192ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
+aes256ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
+aes256ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
+aes256ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
+aes256ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
+aes256ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
+aes256ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
+aes128gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
+aes128gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
+aes128gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
+aes128gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
+aes128gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
+aes128gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
+aes192gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
+aes192gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
+aes192gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
+aes192gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
+aes192gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
+aes192gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
+aes256gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
+aes256gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
+aes256gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
+aes256gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
+aes256gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
+aes256gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
+3des, ENCRYPTION_ALGORITHM, ENCR_3DES, 0
+blowfish128, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128
+blowfish192, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192
+blowfish256, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256
+sha, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0
+sha1, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0
+sha256, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0
+sha2_256, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0
+sha384, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0
+sha2_384, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0
+sha512, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0
+sha2_512, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0
+md5, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0
+aesxcbc, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0
+modpnull, DIFFIE_HELLMAN_GROUP, MODP_NULL, 0
+modp768, DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0
+modp1024, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0
+modp1536, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0
+modp2048, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0
+modp3072, DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0
+modp4096, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0
+modp6144, DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0
+modp8192, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0
+ecp192, DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0
+ecp224, DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0
+ecp256, DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0
+ecp384, DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0
+ecp521, DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0
diff --git a/src/charon/credentials/auth_info.c b/src/charon/credentials/auth_info.c
deleted file mode 100644
index 62d5ea9b3..000000000
--- a/src/charon/credentials/auth_info.c
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * 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$
- */
-
-
-#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_AUTH_CLASS",
- "AUTHN_EAP_TYPE",
- "AUTHN_EAP_VENDOR",
- "AUTHN_EAP_IDENTITY",
- "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, &current_type, &current_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 AUTHN_AUTH_CLASS:
- case AUTHN_EAP_TYPE:
- case AUTHN_EAP_VENDOR:
- case AUTHZ_EAP:
- {
- u_int *intval = malloc_thing(u_int);
-
- *intval = *(u_int*)value;
- item->value = intval;
- break;
- }
- case AUTHN_EAP_IDENTITY:
- 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_AUTH_CLASS:
- case AUTHN_EAP_TYPE:
- case AUTHN_EAP_VENDOR:
- case AUTHN_EAP_IDENTITY:
- 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_EAP_IDENTITY:
- 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 AUTHN_AUTH_CLASS:
- case AUTHN_EAP_TYPE:
- case AUTHN_EAP_VENDOR:
- {
- if (*(u_int*)i1->value == *(u_int*)i2->value)
- {
- found = TRUE;
- break;
- }
- }
- 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_AUTH_CLASS:
- case AUTHN_EAP_TYPE:
- case AUTHN_EAP_VENDOR:
- 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_EAP_IDENTITY:
- 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.purge
- */
-static void purge(private_auth_info_t *this)
-{
- item_t *item;
-
- while (this->items->remove_last(this->items, (void**)&item) == SUCCESS)
- {
- destroy_item_value(item);
- free(item);
- }
-}
-
-/**
- * Implementation of auth_info_t.destroy
- */
-static void destroy(private_auth_info_t *this)
-{
- purge(this);
- 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.purge = (void(*)(auth_info_t*))purge;
- 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
deleted file mode 100644
index f480a6e08..000000000
--- a/src/charon/credentials/auth_info.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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
- */
-
- /** authentication class to use, value is auth_class_t* */
- AUTHN_AUTH_CLASS,
- /** EAP method to request from peer, value is eap_type_t* */
- AUTHN_EAP_TYPE,
- /** EAP vendor to used in conjunction with EAP method, value is u_int32_t* */
- AUTHN_EAP_VENDOR,
- /** EAP identity to use within EAP-Identity exchange */
- AUTHN_EAP_IDENTITY,
- /** 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_type_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);
-
- /**
- * Purge all items in auth_info.
- */
- void (*purge)(auth_info_t *this);
-
- /**
- * 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
index 2721edc4a..3cd4e35ed 100644
--- a/src/charon/credentials/credential_manager.c
+++ b/src/charon/credentials/credential_manager.c
@@ -23,7 +23,7 @@
#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <credentials/sets/cert_cache.h>
-#include <credentials/sets/auth_info_wrapper.h>
+#include <credentials/sets/auth_cfg_wrapper.h>
#include <credentials/sets/ocsp_response_wrapper.h>
#include <credentials/certificates/x509.h>
#include <credentials/certificates/crl.h>
@@ -625,7 +625,7 @@ static certificate_t *get_better_ocsp(private_credential_manager_t *this,
*/
static cert_validation_t check_ocsp(private_credential_manager_t *this,
x509_t *subject, x509_t *issuer,
- auth_info_t *auth)
+ auth_cfg_t *auth)
{
enumerator_t *enumerator;
cert_validation_t valid = VALIDATION_SKIPPED;
@@ -706,7 +706,11 @@ static cert_validation_t check_ocsp(private_credential_manager_t *this,
}
if (auth)
{
- auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
+ auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
+ if (valid == VALIDATION_GOOD)
+ { /* successful OCSP check fulfills also CRL constraint */
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
+ }
}
DESTROY_IF(best);
return valid;
@@ -728,6 +732,7 @@ static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
}
crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
+ chunk_free(&chunk);
if (!crl)
{
DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
@@ -833,7 +838,7 @@ static certificate_t *get_better_crl(private_credential_manager_t *this,
*/
static cert_validation_t check_crl(private_credential_manager_t *this,
x509_t *subject, x509_t *issuer,
- auth_info_t *auth)
+ auth_cfg_t *auth)
{
cert_validation_t valid = VALIDATION_SKIPPED;
identification_t *keyid = NULL;
@@ -841,7 +846,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
certificate_t *current;
public_key_t *public;
enumerator_t *enumerator;
- char *uri;
+ char *uri = NULL;
/* derive the authorityKeyIdentifier from the issuer's public key */
current = &issuer->interface;
@@ -920,7 +925,16 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
}
if (auth)
{
- auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
+ if (valid == VALIDATION_SKIPPED)
+ { /* if we skipped CRL validation, we use the result of OCSP for
+ * constraint checking */
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION,
+ auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
+ }
+ else
+ {
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
+ }
}
DESTROY_IF(best);
return valid;
@@ -931,7 +945,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
*/
static bool check_certificate(private_credential_manager_t *this,
certificate_t *subject, certificate_t *issuer,
- bool crl, bool ocsp, auth_info_t *auth)
+ bool crl, bool ocsp, auth_cfg_t *auth)
{
time_t not_before, not_after;
@@ -963,7 +977,7 @@ static bool check_certificate(private_credential_manager_t *this,
DBG1(DBG_CFG, "certificate status is good");
return TRUE;
case VALIDATION_REVOKED:
- /* has already been logged */
+ /* has already been logged */
return FALSE;
case VALIDATION_SKIPPED:
DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
@@ -983,8 +997,8 @@ static bool check_certificate(private_credential_manager_t *this,
case VALIDATION_GOOD:
DBG1(DBG_CFG, "certificate status is good");
return TRUE;
- case VALIDATION_REVOKED:
- /* has already been logged */
+ case VALIDATION_REVOKED:
+ /* has already been logged */
return FALSE;
case VALIDATION_FAILED:
case VALIDATION_SKIPPED:
@@ -1050,14 +1064,14 @@ static certificate_t *get_issuer_cert(private_credential_manager_t *this,
* 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,
+ certificate_t *subject, auth_cfg_t *result,
bool trusted, bool crl, bool ocsp)
{
certificate_t *current, *issuer;
- auth_info_t *auth;
+ auth_cfg_t *auth;
u_int level = 0;
- auth = auth_info_create();
+ auth = auth_cfg_create();
current = subject->get_ref(subject);
while (level++ < MAX_CA_LEVELS)
{
@@ -1067,14 +1081,14 @@ static bool verify_trust_chain(private_credential_manager_t *this,
/* 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);
+ auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using trusted ca certificate \"%D\"",
issuer->get_subject(issuer));
trusted = TRUE;
}
else
{
- auth->add_item(auth, AUTHZ_IM_CERT, issuer);
+ auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using trusted intermediate ca certificate "
"\"%D\"", issuer->get_subject(issuer));
}
@@ -1091,7 +1105,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
issuer->destroy(issuer);
break;
}
- auth->add_item(auth, AUTHZ_IM_CERT, issuer);
+ auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using untrusted intermediate certificate "
"\"%D\"", issuer->get_subject(issuer));
}
@@ -1123,7 +1137,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
}
if (trusted)
{
- result->merge(result, auth);
+ result->merge(result, auth, FALSE);
}
auth->destroy(auth);
return trusted;
@@ -1149,20 +1163,20 @@ typedef struct {
bool ocsp;
/** pretrusted certificate we have served at first invocation */
certificate_t *pretrusted;
- /** currently enumerating auth info */
- auth_info_t *auth;
+ /** currently enumerating auth config */
+ auth_cfg_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 **cert, auth_cfg_t **auth)
{
certificate_t *current;
DESTROY_IF(this->auth);
- this->auth = auth_info_create();
+ this->auth = auth_cfg_create();
if (!this->candidates)
{
@@ -1181,7 +1195,8 @@ static bool trusted_enumerate(trusted_enumerator_t *this,
verify_trust_chain(this->this, this->pretrusted, this->auth,
TRUE, this->crl, this->ocsp))
{
- this->auth->add_item(this->auth, AUTHZ_CA_CERT, this->pretrusted);
+ this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
+ this->pretrusted->get_ref(this->pretrusted));
DBG1(DBG_CFG, " using trusted certificate \"%D\"",
this->pretrusted->get_subject(this->pretrusted));
*cert = this->pretrusted;
@@ -1264,15 +1279,15 @@ typedef struct {
private_credential_manager_t *this;
/** currently enumerating key */
public_key_t *current;
- /** credset wrapper around auth */
- auth_info_wrapper_t *wrapper;
+ /** credset wrapper around auth config */
+ auth_cfg_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)
+ public_key_t **key, auth_cfg_t **auth)
{
certificate_t *cert;
@@ -1312,7 +1327,7 @@ static void public_destroy(public_enumerator_t *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)
+ key_type_t type, identification_t *id, auth_cfg_t *auth)
{
public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
@@ -1324,7 +1339,7 @@ static enumerator_t* create_public_enumerator(private_credential_manager_t *this
enumerator->wrapper = NULL;
if (auth)
{
- enumerator->wrapper = auth_info_wrapper_create(auth);
+ enumerator->wrapper = auth_cfg_wrapper_create(auth);
add_local_set(this, &enumerator->wrapper->set);
}
this->lock->read_lock(this->lock);
@@ -1334,40 +1349,22 @@ static enumerator_t* create_public_enumerator(private_credential_manager_t *this
/**
* Check if a certificate's keyid is contained in the auth helper
*/
-static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert)
+static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
{
enumerator_t *enumerator;
identification_t *value;
- auth_item_t type;
+ auth_rule_t type;
bool found = FALSE;
- enumerator = auth->create_item_enumerator(auth);
+ enumerator = auth->create_enumerator(auth);
while (enumerator->enumerate(enumerator, &type, &value))
{
- if (type == AUTHN_CA_CERT && cert->equals(cert, (certificate_t*)value))
+ if (type == AUTH_RULE_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;
@@ -1376,19 +1373,21 @@ static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert)
/**
* 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)
+static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
+ certificate_t *subject, auth_cfg_t *auth)
{
certificate_t *issuer, *current;
- auth_info_t *trustchain;
+ auth_cfg_t *trustchain;
u_int level = 0;
- trustchain = auth_info_create();
+ trustchain = auth_cfg_create();
- if (!auth->get_item(auth, AUTHN_CA_CERT, (void**)&current))
+ current = auth->get(auth, AUTH_RULE_CA_CERT);
+ if (!current)
{
/* no trust anchor specified, return this cert only */
- trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, subject);
+ trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT,
+ subject->get_ref(subject));
return trustchain;
}
current = subject->get_ref(subject);
@@ -1396,26 +1395,23 @@ static auth_info_t *build_trustchain(private_credential_manager_t *this,
{
if (auth_contains_cacert(auth, current))
{
- trustchain->add_item(trustchain, AUTHZ_CA_CERT, current);
- current->destroy(current);
+ trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
return trustchain;
}
if (subject == current)
{
- trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, current);
+ trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
}
else
{
- trustchain->add_item(trustchain, AUTHZ_IM_CERT, current);
+ trustchain->add(trustchain, AUTH_RULE_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++;
}
@@ -1451,12 +1447,12 @@ static private_key_t *get_private_by_cert(private_credential_manager_t *this,
*/
static private_key_t *get_private(private_credential_manager_t *this,
key_type_t type, identification_t *id,
- auth_info_t *auth)
+ auth_cfg_t *auth)
{
enumerator_t *enumerator;
certificate_t *cert;
private_key_t *private = NULL;
- auth_info_t *trustchain;
+ auth_cfg_t *trustchain;
/* check if this is a lookup by key ID, and do it if so */
if (id)
@@ -1471,8 +1467,25 @@ static private_key_t *get_private(private_credential_manager_t *this,
break;
}
}
-
- /* try to build a trustchain for each certificate found */
+
+ /* if a specific certificate is preferred, check for a matching key */
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ trustchain->destroy(trustchain);
+ }
+ return private;
+ }
+ }
+
+ /* try to build a trust chain for each certificate found */
enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
while (enumerator->enumerate(enumerator, &cert))
{
@@ -1482,7 +1495,7 @@ static private_key_t *get_private(private_credential_manager_t *this,
trustchain = build_trustchain(this, cert, auth);
if (trustchain)
{
- auth->merge(auth, trustchain);
+ auth->merge(auth, trustchain, FALSE);
trustchain->destroy(trustchain);
break;
}
@@ -1491,6 +1504,7 @@ static private_key_t *get_private(private_credential_manager_t *this,
}
}
enumerator->destroy(enumerator);
+
/* if no valid trustchain was found, fall back to the first usable cert */
if (!private)
{
@@ -1500,7 +1514,7 @@ static private_key_t *get_private(private_credential_manager_t *this,
private = get_private_by_cert(this, cert, type);
if (private)
{
- auth->add_item(auth, AUTHZ_SUBJECT_CERT, cert);
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
break;
}
}
@@ -1566,8 +1580,8 @@ credential_manager_t *credential_manager_create()
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.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_cfg_t*))get_private;
+ this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_cfg_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;
diff --git a/src/charon/credentials/credential_manager.h b/src/charon/credentials/credential_manager.h
index 23f43cf55..c628e7e10 100644
--- a/src/charon/credentials/credential_manager.h
+++ b/src/charon/credentials/credential_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2008 Martin Willi
+ * Copyright (C) 2007-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
#include <utils/identification.h>
#include <utils/enumerator.h>
-#include <credentials/auth_info.h>
+#include <config/auth_cfg.h>
#include <credentials/credential_set.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/shared_key.h>
@@ -122,7 +122,6 @@ struct credential_manager_t {
* @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,
@@ -138,11 +137,11 @@ struct credential_manager_t {
*
* @param type type of the key to get
* @param id identification the key belongs to
- * @param auth auth_info helper, including trusted CA certificates
+ * @param auth auth config, 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);
+ identification_t *id, auth_cfg_t *auth);
/**
* Create an enumerator over trusted public keys.
@@ -150,9 +149,8 @@ struct credential_manager_t {
* 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.
+ * The resulting enumerator enumerates over public_key_t *, auth_cfg_t *,
+ * where the auth config helper contains rules for constraint checks.
*
* @param type type of the key to get
* @param id owner of the key, signer of the signature
@@ -160,7 +158,7 @@ struct credential_manager_t {
* @return enumerator
*/
enumerator_t* (*create_public_enumerator)(credential_manager_t *this,
- key_type_t type, identification_t *id, auth_info_t *auth);
+ key_type_t type, identification_t *id, auth_cfg_t *auth);
/**
* Cache a certificate by invoking cache_cert() on all registerd sets.
diff --git a/src/charon/credentials/sets/auth_info_wrapper.c b/src/charon/credentials/sets/auth_cfg_wrapper.c
index 7ec75be15..2e93cc53a 100644
--- a/src/charon/credentials/sets/auth_info_wrapper.c
+++ b/src/charon/credentials/sets/auth_cfg_wrapper.c
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2008-2009 Martin Willi
* 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
@@ -18,36 +18,36 @@
#include <daemon.h>
-#include "auth_info_wrapper.h"
+#include "auth_cfg_wrapper.h"
-typedef struct private_auth_info_wrapper_t private_auth_info_wrapper_t;
+typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t;
/**
- * private data of auth_info_wrapper
+ * private data of auth_cfg_wrapper
*/
-struct private_auth_info_wrapper_t {
+struct private_auth_cfg_wrapper_t {
/**
* public functions
*/
- auth_info_wrapper_t public;
+ auth_cfg_wrapper_t public;
/**
* wrapped auth info
*/
- auth_info_t *auth;
+ auth_cfg_t *auth;
};
/**
- * enumerator for auth_info_wrapper_t.create_cert_enumerator()
+ * enumerator for auth_cfg_wrapper_t.create_cert_enumerator()
*/
typedef struct {
/** implements enumerator_t */
enumerator_t public;
- /** inner enumerator from auth_info */
+ /** inner enumerator from auth_cfg */
enumerator_t *inner;
- /** wrapped auth info */
- auth_info_t *auth;
+ /** wrapped auth round */
+ auth_cfg_t *auth;
/** enumerated cert type */
certificate_type_t cert;
/** enumerated key type */
@@ -57,10 +57,11 @@ typedef struct {
} wrapper_enumerator_t;
/**
- * Tries to fetch a certificate that was supplied as "Hash and URL" (replaces the
- * item's type and value in place).
+ * Tries to fetch a certificate that was supplied as "Hash and URL"
+ * (replaces rule type and value in place).
*/
-static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void **value)
+static bool fetch_cert(wrapper_enumerator_t *enumerator,
+ auth_rule_t *rule, void **value)
{
char *url = (char*)*value;
if (!url)
@@ -77,29 +78,38 @@ static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void
{
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);
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, NULL);
return FALSE;
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, data, BUILD_END);
+ BUILD_BLOB_ASN1_DER, data, BUILD_END);
free(data.ptr);
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);
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, 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;
+ if (*rule == AUTH_HELPER_IM_HASH_URL)
+ {
+ *rule = AUTH_HELPER_IM_CERT;
+ }
+ else
+ {
+ *rule = AUTH_HELPER_SUBJECT_CERT;
+ }
*value = cert;
- enumerator->auth->replace_item(enumerator->inner, *type, cert);
-
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, cert->get_ref(cert));
return TRUE;
}
@@ -108,26 +118,25 @@ static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void
*/
static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
{
- auth_item_t type;
+ auth_rule_t rule;
certificate_t *current;
public_key_t *public;
- while (this->inner->enumerate(this->inner, &type, &current))
+ while (this->inner->enumerate(this->inner, &rule, &current))
{
- if (type == AUTHN_IM_HASH_URL ||
- type == AUTHN_SUBJECT_HASH_URL)
- {
- if (!fetch_cert(this, &type, (void**)&current))
+ if (rule == AUTH_HELPER_IM_HASH_URL ||
+ rule == AUTH_HELPER_SUBJECT_HASH_URL)
+ { /* on-demand fetching of hash and url certificates */
+ if (!fetch_cert(this, &rule, (void**)&current))
{
continue;
}
}
- else if (type != AUTHN_SUBJECT_CERT &&
- type != AUTHN_IM_CERT)
- {
+ else if (rule != AUTH_HELPER_SUBJECT_CERT &&
+ rule != AUTH_HELPER_IM_CERT)
+ { /* handle only HELPER certificates */
continue;
}
-
if (this->cert != CERT_ANY && this->cert != current->get_type(current))
{ /* CERT type requested, but does not match */
continue;
@@ -164,9 +173,9 @@ static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
}
/**
- * implementation of auth_info_wrapper_t.set.create_cert_enumerator
+ * implementation of auth_cfg_wrapper_t.set.create_cert_enumerator
*/
-static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this,
+static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this,
certificate_type_t cert, key_type_t key,
identification_t *id, bool trusted)
{
@@ -181,16 +190,16 @@ static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this,
enumerator->cert = cert;
enumerator->key = key;
enumerator->id = id;
- enumerator->inner = this->auth->create_item_enumerator(this->auth);
+ enumerator->inner = this->auth->create_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
+ * Implementation of auth_cfg_wrapper_t.destroy
*/
-static void destroy(private_auth_info_wrapper_t *this)
+static void destroy(private_auth_cfg_wrapper_t *this)
{
free(this);
}
@@ -198,16 +207,16 @@ static void destroy(private_auth_info_wrapper_t *this)
/*
* see header file
*/
-auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth)
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth)
{
- private_auth_info_wrapper_t *this = malloc_thing(private_auth_info_wrapper_t);
+ private_auth_cfg_wrapper_t *this = malloc_thing(private_auth_cfg_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->public.destroy = (void(*)(auth_cfg_wrapper_t*))destroy;
this->auth = auth;
diff --git a/src/charon/credentials/sets/auth_info_wrapper.h b/src/charon/credentials/sets/auth_cfg_wrapper.h
index 9186715f0..9baf064af 100644
--- a/src/charon/credentials/sets/auth_info_wrapper.h
+++ b/src/charon/credentials/sets/auth_cfg_wrapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,22 +16,22 @@
*/
/**
- * @defgroup auth_info_wrapper auth_info_wrapper
+ * @defgroup auth_cfg_wrapper auth_cfg_wrapper
* @{ @ingroup sets
*/
-#ifndef AUTH_INFO_WRAPPER_H_
-#define AUTH_INFO_WRAPPER_H_
+#ifndef AUTH_CFG_WRAPPER_H_
+#define AUTH_CFG_WRAPPER_H_
+#include <config/auth_cfg.h>
#include <credentials/credential_set.h>
-#include <credentials/auth_info.h>
-typedef struct auth_info_wrapper_t auth_info_wrapper_t;
+typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t;
/**
- * A wrapper around auth_info_t to handle it like a credential set.
+ * A wrapper around auth_cfg_t to handle it as a credential set.
*/
-struct auth_info_wrapper_t {
+struct auth_cfg_wrapper_t {
/**
* implements credential_set_t
@@ -39,17 +39,17 @@ struct auth_info_wrapper_t {
credential_set_t set;
/**
- * Destroy a auth_info_wrapper instance.
+ * Destroy a auth_cfg_wrapper instance.
*/
- void (*destroy)(auth_info_wrapper_t *this);
+ void (*destroy)(auth_cfg_wrapper_t *this);
};
/**
- * Create a auth_info_wrapper instance.
+ * Create a auth_cfg_wrapper instance.
*
* @param auth the wrapped auth info
* @return wrapper around auth
*/
-auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth);
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth);
-#endif /** AUTH_INFO_WRAPPER_H_ @}*/
+#endif /** AUTH_CFG_WRAPPER_H_ @}*/
diff --git a/src/charon/encoding/generator.c b/src/charon/encoding/generator.c
index ca7cb1e77..759f4ed55 100644
--- a/src/charon/encoding/generator.c
+++ b/src/charon/encoding/generator.c
@@ -523,17 +523,16 @@ static void generate_payload (private_generator_t *this,payload_t *payload)
{
int i;
this->data_struct = payload;
- size_t rule_count;
+ size_t rule_count, offset_start;
encoding_rule_t *rules;
payload_type_t payload_type;
- u_int8_t *payload_start;
/* get payload type */
payload_type = payload->get_type(payload);
/* spi size has to get reseted */
this->last_spi_size = 0;
- payload_start = this->out_position;
+ offset_start = this->out_position - this->buffer;
DBG2(DBG_ENC, "generating payload of type %N",
payload_type_names, payload_type);
@@ -893,7 +892,8 @@ static void generate_payload (private_generator_t *this,payload_t *payload)
DBG2(DBG_ENC, "generating %N payload finished",
payload_type_names, payload_type);
DBG3(DBG_ENC, "generated data for this payload %b",
- payload_start, this->out_position-payload_start);
+ this->buffer + offset_start,
+ this->out_position - this->buffer - offset_start);
}
/**
diff --git a/src/charon/encoding/message.c b/src/charon/encoding/message.c
index a605bd3fd..993d48b89 100644
--- a/src/charon/encoding/message.c
+++ b/src/charon/encoding/message.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -208,7 +208,7 @@ 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},
+ {ID_INITIATOR, 0, 1, TRUE, FALSE},
{CERTIFICATE, 0, 4, TRUE, FALSE},
{CERTIFICATE_REQUEST, 0, 1, TRUE, FALSE},
{ID_RESPONDER, 0, 1, TRUE, FALSE},
@@ -217,9 +217,9 @@ static payload_rule_t ike_auth_i_payload_rules[] = {
{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},
+ {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE},
+ {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE},
#endif /* ME */
{CONFIGURATION, 0, 1, TRUE, FALSE},
{VENDOR_ID, 0, 10, TRUE, FALSE},
@@ -261,9 +261,9 @@ static payload_rule_t ike_auth_r_payload_rules[] = {
/* payload type min max encr suff */
{NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
{EXTENSIBLE_AUTHENTICATION, 0, 1, TRUE, TRUE},
+ {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},
@@ -846,11 +846,11 @@ static host_t * get_destination(private_message_t *this)
}
/**
- * Implementation of message_t.get_payload_iterator.
+ * Implementation of message_t.create_payload_enumerator.
*/
-static iterator_t *get_payload_iterator(private_message_t *this)
+static enumerator_t *create_payload_enumerator(private_message_t *this)
{
- return this->payloads->create_iterator(this->payloads, TRUE);
+ return this->payloads->create_enumerator(this->payloads);
}
/**
@@ -859,10 +859,10 @@ static iterator_t *get_payload_iterator(private_message_t *this)
static payload_t *get_payload(private_message_t *this, payload_type_t type)
{
payload_t *current, *found = NULL;
- iterator_t *iterator;
+ enumerator_t *enumerator;
- iterator = this->payloads->create_iterator(this->payloads, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current))
{
if (current->get_type(current) == type)
{
@@ -870,16 +870,42 @@ static payload_t *get_payload(private_message_t *this, payload_type_t type)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return found;
}
/**
+ * Implementation of message_t.get_notify
+ */
+static notify_payload_t* get_notify(private_message_t *this, notify_type_t type)
+{
+ enumerator_t *enumerator;
+ notify_payload_t *notify = NULL;
+ payload_t *payload;
+
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify = (notify_payload_t*)payload;
+ if (notify->get_notify_type(notify) == type)
+ {
+ break;
+ }
+ notify = NULL;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return notify;
+}
+
+/**
* get a string representation of the message
*/
static char* get_string(private_message_t *this, char *buf, int len)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
int written;
char *pos = buf;
@@ -898,8 +924,8 @@ static char* get_string(private_message_t *this, char *buf, int len)
pos += written;
len -= written;
- iterator = this->payloads->create_iterator(this->payloads, TRUE);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &payload))
{
written = snprintf(pos, len, " %N", payload_type_short_names,
payload->get_type(payload));
@@ -922,7 +948,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
len -= written;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
/* remove last space */
snprintf(pos, len, " ]");
@@ -1076,7 +1102,7 @@ static status_t generate(private_message_t *this, crypter_t *crypter,
generator_t *generator;
ike_header_t *ike_header;
payload_t *payload, *next_payload;
- iterator_t *iterator;
+ enumerator_t *enumerator;
status_t status;
chunk_t packet_data;
char str[256];
@@ -1131,21 +1157,20 @@ static status_t generate(private_message_t *this, crypter_t *crypter,
ike_header->set_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id));
ike_header->set_initiator_spi(ike_header, this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
ike_header->set_responder_spi(ike_header, this->ike_sa_id->get_responder_spi(this->ike_sa_id));
-
+
generator = generator_create();
payload = (payload_t*)ike_header;
-
/* 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))
+ enumerator = create_payload_enumerator(this);
+ while (enumerator->enumerate(enumerator, &next_payload))
{
payload->set_next_type(payload, next_payload->get_type(next_payload));
generator->generate_payload(generator, payload);
payload = next_payload;
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
/* last payload has no next payload*/
payload->set_next_type(payload, NO_PAYLOAD);
@@ -1411,72 +1436,78 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
static status_t verify(private_message_t *this)
{
int i;
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *current_payload;
size_t total_found_payloads = 0;
DBG2(DBG_ENC, "verifying message structure");
- iterator = this->payloads->create_iterator(this->payloads,TRUE);
/* check for payloads with wrong count*/
- for (i = 0; i < this->message_rule->payload_rule_count;i++)
+ for (i = 0; i < this->message_rule->payload_rule_count; i++)
{
size_t found_payloads = 0;
-
- /* check all payloads for specific rule */
- iterator->reset(iterator);
+ payload_rule_t *rule;
- while(iterator->iterate(iterator,(void **)&current_payload))
+ rule = &this->message_rule->payload_rules[i];
+ enumerator = create_payload_enumerator(this);
+
+ /* check all payloads for specific rule */
+ while (enumerator->enumerate(enumerator, &current_payload))
{
payload_type_t current_payload_type;
+ unknown_payload_t *unknown_payload;
current_payload_type = current_payload->get_type(current_payload);
if (current_payload_type == UNKNOWN_PAYLOAD)
{
/* unknown payloads are ignored, IF they are not critical */
- unknown_payload_t *unknown_payload = (unknown_payload_t*)current_payload;
+ unknown_payload = (unknown_payload_t*)current_payload;
if (unknown_payload->is_critical(unknown_payload))
{
DBG1(DBG_ENC, "%N is not supported, but its critical!",
payload_type_names, current_payload_type);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return NOT_SUPPORTED;
}
}
- else if (current_payload_type == this->message_rule->payload_rules[i].payload_type)
+ else if (current_payload_type == rule->payload_type)
{
found_payloads++;
total_found_payloads++;
- DBG2(DBG_ENC, "found payload of type %N",
- payload_type_names, this->message_rule->payload_rules[i].payload_type);
+ DBG2(DBG_ENC, "found payload of type %N", payload_type_names,
+ rule->payload_type);
- /* as soon as ohe payload occures more then specified, the verification fails */
- if (found_payloads > this->message_rule->payload_rules[i].max_occurence)
+ /* as soon as ohe payload occures more then specified,
+ * the verification fails */
+ if (found_payloads >
+ rule->max_occurence)
{
- DBG1(DBG_ENC, "payload of type %N more than %d times (%d) occured in current message",
- payload_type_names, current_payload_type,
- this->message_rule->payload_rules[i].max_occurence, found_payloads);
- iterator->destroy(iterator);
+ DBG1(DBG_ENC, "payload of type %N more than %d times (%d) "
+ "occured in current message", payload_type_names,
+ current_payload_type, rule->max_occurence,
+ found_payloads);
+ enumerator->destroy(enumerator);
return VERIFY_ERROR;
}
}
}
- if (found_payloads < this->message_rule->payload_rules[i].min_occurence)
+ if (found_payloads < rule->min_occurence)
{
DBG1(DBG_ENC, "payload of type %N not occured %d times (%d)",
- payload_type_names, this->message_rule->payload_rules[i].payload_type,
- this->message_rule->payload_rules[i].min_occurence, found_payloads);
- iterator->destroy(iterator);
+ payload_type_names, rule->payload_type, rule->min_occurence,
+ found_payloads);
+ enumerator->destroy(enumerator);
return VERIFY_ERROR;
}
- if ((this->message_rule->payload_rules[i].sufficient) && (this->payloads->get_count(this->payloads) == total_found_payloads))
+ if (rule->sufficient &&
+ this->payloads->get_count(this->payloads) == total_found_payloads)
{
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return SUCCESS;
}
+ enumerator->destroy(enumerator);
}
- iterator->destroy(iterator);
return SUCCESS;
}
@@ -1604,8 +1635,9 @@ message_t *message_create_from_packet(packet_t *packet)
this->public.get_source = (host_t * (*) (message_t*)) get_source;
this->public.set_destination = (void (*) (message_t*,host_t*)) set_destination;
this->public.get_destination = (host_t * (*) (message_t*)) get_destination;
- this->public.get_payload_iterator = (iterator_t * (*) (message_t *)) get_payload_iterator;
+ this->public.create_payload_enumerator = (enumerator_t * (*) (message_t *)) create_payload_enumerator;
this->public.get_payload = (payload_t * (*) (message_t *, payload_type_t)) get_payload;
+ this->public.get_notify = (notify_payload_t*(*)(message_t*, notify_type_t type))get_notify;
this->public.parse_header = (status_t (*) (message_t *)) parse_header;
this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body;
this->public.get_packet = (packet_t * (*) (message_t*)) get_packet;
diff --git a/src/charon/encoding/message.h b/src/charon/encoding/message.h
index fcd206cb5..095371747 100644
--- a/src/charon/encoding/message.h
+++ b/src/charon/encoding/message.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -286,14 +286,11 @@ struct message_t {
void (*set_destination) (message_t *this, host_t *host);
/**
- * Returns an iterator on all stored payloads.
- *
- * @warning Don't insert payloads over this iterator.
- * Use add_payload() instead.
+ * Create an enumerator over all payloads.
*
- * @return iterator_t object which has to get destroyd by the caller
+ * @return enumerator over payload_t
*/
- iterator_t * (*get_payload_iterator) (message_t *this);
+ enumerator_t * (*create_payload_enumerator) (message_t *this);
/**
* Find a payload of a specific type.
@@ -306,6 +303,14 @@ struct message_t {
payload_t* (*get_payload) (message_t *this, payload_type_t type);
/**
+ * Get the first notify payload of a specific type.
+ *
+ * @param type type of notification payload
+ * @return notify payload, NULL if no such notify found
+ */
+ notify_payload_t* (*get_notify)(message_t *this, notify_type_t type);
+
+ /**
* Returns a clone of the internal stored packet_t object.
*
* @return packet_t object as clone of internal one
diff --git a/src/charon/plugins/eap_mschapv2/eap_mschapv2.c b/src/charon/plugins/eap_mschapv2/eap_mschapv2.c
index 2f276eb0b..9bbff817a 100644
--- a/src/charon/plugins/eap_mschapv2/eap_mschapv2.c
+++ b/src/charon/plugins/eap_mschapv2/eap_mschapv2.c
@@ -17,6 +17,9 @@
#include "eap_mschapv2.h"
+#include <ctype.h>
+#include <unistd.h>
+
#include <daemon.h>
#include <library.h>
#include <utils/enumerator.h>
@@ -141,7 +144,7 @@ ENUM_END(mschapv2_error_names, ERROR_CHANGING_PASSWORD);
/* Name we send as authenticator */
#define MSCHAPV2_HOST_NAME "strongSwan"
/* Message sent on success */
-#define SUCCESS_MESSAGE " M=Welcome to strongSwan"
+#define SUCCESS_MESSAGE " M=Welcome2strongSwan"
/* Message sent on failure */
#define FAILURE_MESSAGE "E=691 R=1 C="
/* Length of the complete failure message */
@@ -366,7 +369,6 @@ static status_t AuthenticatorResponse(chunk_t password_hash_hash,
static const chunk_t magic1 = chunk_from_buf(magic1_data);
static const chunk_t magic2 = chunk_from_buf(magic2_data);
- status_t status = FAILED;
chunk_t digest = chunk_empty, concat;
hasher_t *hasher;
@@ -527,6 +529,24 @@ static chunk_t ascii_to_unicode(chunk_t ascii)
}
/**
+ * sanitize a string for printing
+ */
+static char* sanitize(char *str)
+{
+ char *pos = str;
+
+ while (pos && *pos)
+ {
+ if (!isprint(*pos))
+ {
+ *pos = '?';
+ }
+ pos++;
+ }
+ return str;
+}
+
+/**
* Returns a chunk of just the username part of the given user identity.
* Note: the chunk points to internal data of the identification.
*/
@@ -535,7 +555,7 @@ static chunk_t extract_username(identification_t* identification)
char *has_domain;
chunk_t id;
id = identification->get_encoding(identification);
- has_domain = (char*)memrchr(id.ptr, '\\', id.len);
+ has_domain = (char*)memchr(id.ptr, '\\', id.len);
if (has_domain)
{
int len;
@@ -625,7 +645,8 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
if (cha->value_size != CHALLENGE_LEN)
{
- DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: invalid challenge size");
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "invalid challenge size");
return FAILED;
}
@@ -643,11 +664,11 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
rng->destroy(rng);
shared = charon->credentials->get_shared(charon->credentials,
- SHARED_EAP, this->peer, this->server);
+ SHARED_EAP, this->peer, this->server);
if (shared == NULL)
{
DBG1(DBG_IKE, "no EAP key found for hosts '%D' - '%D'",
- this->server, this->peer);
+ this->server, this->peer);
return NOT_FOUND;
}
@@ -725,7 +746,8 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
token += 2;
if (strlen(token) != AUTH_RESPONSE_LEN - 2)
{
- DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: invalid auth string");
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "invalid auth string");
goto error;
}
hex = chunk_create(token, AUTH_RESPONSE_LEN - 2);
@@ -741,7 +763,8 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
if (auth_string.ptr == NULL)
{
- DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: auth string missing");
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "auth string missing");
goto error;
}
@@ -751,7 +774,7 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
goto error;
}
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 succeeded: '%s'", msg);
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 succeeded: '%s'", sanitize(msg));
eap = alloca(len);
eap->code = EAP_RESPONSE;
@@ -780,7 +803,6 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
char *message, *token, *msg = NULL;
int message_len, error, retryable;
chunk_t challenge = chunk_empty;
- u_int16_t len = SHORT_HEADER_LEN;
data = in->get_data(in);
eap = (eap_mschapv2_header_t*)data.ptr;
@@ -816,7 +838,8 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
token += 2;
if (strlen(token) != 2 * CHALLENGE_LEN)
{
- DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: invalid challenge");
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message:"
+ "invalid challenge");
goto error;
}
hex = chunk_create(token, 2 * CHALLENGE_LEN);
@@ -836,7 +859,8 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
}
enumerator->destroy(enumerator);
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed with error %N: '%s'", mschapv2_error_names, error, msg);
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed with error %N: '%s'",
+ mschapv2_error_names, error, sanitize(msg));
/**
* at this point, if the error is retryable, we MAY retry the authentication
@@ -898,8 +922,8 @@ static status_t process_peer(private_eap_mschapv2_t *this, eap_payload_t *in,
}
default:
{
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported OpCode (%N)!",
- mschapv2_opcode_names, eap->opcode);
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
+ "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
break;
}
}
@@ -925,7 +949,8 @@ static status_t process_server_retry(private_eap_mschapv2_t *this,
* so, to clean up our state we just fail with an EAP-Failure.
* this gives an unknown error on the windows side, but is also fine
* with the standard. */
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed: maximum number of retries reached");
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed: "
+ "maximum number of retries reached");
return FAILED;
}
@@ -977,6 +1002,7 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
identification_t *userid;
shared_key_t *shared;
int name_len;
+ char buf[256];
data = in->get_data(in);
eap = (eap_mschapv2_header_t*)data.ptr;
@@ -991,10 +1017,10 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
peer_challenge = chunk_create(res->response.peer_challenge, CHALLENGE_LEN);
name_len = min(data.len - RESPONSE_PAYLOAD_LEN, 255);
- userid = identification_create_from_encoding(ID_EAP,
- chunk_create(res->name, name_len));
+ snprintf(buf, sizeof(buf), "%.*s", name_len, res->name);
+ userid = identification_create_from_string(buf);
+ DBG2(DBG_IKE, "EAP-MS-CHAPv2 username: '%D'", userid);
username = extract_username(userid);
- DBG2(DBG_IKE, "EAP-MS-CHAPv2 username: '%.*s'", name_len, res->name);
shared = charon->credentials->get_shared(charon->credentials,
SHARED_EAP, this->server, userid);
@@ -1015,7 +1041,8 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
password = ascii_to_unicode(shared->get_key(shared));
shared->destroy(shared);
- if (GenerateStuff(this, this->challenge, peer_challenge, username, password) != SUCCESS)
+ if (GenerateStuff(this, this->challenge, peer_challenge,
+ username, password) != SUCCESS)
{
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
userid->destroy(userid);
@@ -1063,7 +1090,8 @@ static status_t process_server(private_eap_mschapv2_t *this, eap_payload_t *in,
if (this->identifier != in->get_identifier(in))
{
- DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: unexpected identifier");
+ DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
+ "unexpected identifier");
return FAILED;
}
@@ -1092,8 +1120,8 @@ static status_t process_server(private_eap_mschapv2_t *this, eap_payload_t *in,
}
default:
{
- DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported OpCode (%N)!",
- mschapv2_opcode_names, eap->opcode);
+ DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
+ "OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
break;
}
}
diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_card.c b/src/charon/plugins/eap_sim_file/eap_sim_file_card.c
index 7969007d0..cd71adf5b 100644
--- a/src/charon/plugins/eap_sim_file/eap_sim_file_card.c
+++ b/src/charon/plugins/eap_sim_file/eap_sim_file_card.c
@@ -52,13 +52,13 @@ static bool get_triplet(private_eap_sim_file_card_t *this,
identification_t *id;
char *c_rand, *c_sres, *c_kc;
-
- DBG1(DBG_CFG, "looking for rand: %b", rand, RAND_LEN);
+ DBG2(DBG_CFG, "looking for rand: %b", rand, RAND_LEN);
enumerator = this->triplets->create_enumerator(this->triplets);
while (enumerator->enumerate(enumerator, &id, &c_rand, &c_sres, &c_kc))
{
- DBG1(DBG_CFG, "found triplet: %b %b %b", c_rand, RAND_LEN, c_sres, SRES_LEN, c_kc, KC_LEN);
+ DBG2(DBG_CFG, "found triplet: rand %b\nsres %b\n kc %b",
+ c_rand, RAND_LEN, c_sres, SRES_LEN, c_kc, KC_LEN);
if (memeq(c_rand, rand, RAND_LEN))
{
memcpy(sres, c_sres, SRES_LEN);
diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c b/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c
index 409e9cbd5..9d30f891c 100644
--- a/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c
+++ b/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c
@@ -196,8 +196,7 @@ static void read_triplets(private_eap_sim_file_triplets_t *this, char *path)
switch (i++)
{
case 0: /* IMSI */
- triplet->imsi = identification_create_from_encoding(ID_EAP,
- chunk_create(token, strlen(token)));
+ triplet->imsi = identification_create_from_string(token);
continue;
case 1: /* rand */
parse_token(triplet->rand, token, RAND_LEN);
@@ -221,7 +220,7 @@ static void read_triplets(private_eap_sim_file_triplets_t *this, char *path)
continue;
}
- DBG1(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",
+ DBG2(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",
triplet->imsi, triplet->rand, RAND_LEN,
triplet->sres, SRES_LEN, triplet->kc, KC_LEN);
diff --git a/src/charon/plugins/load_tester/load_tester_config.c b/src/charon/plugins/load_tester/load_tester_config.c
index f3cd33b61..25055daef 100644
--- a/src/charon/plugins/load_tester/load_tester_config.c
+++ b/src/charon/plugins/load_tester/load_tester_config.c
@@ -57,9 +57,14 @@ struct private_load_tester_config_t {
proposal_t *proposal;
/**
- * Authentication method to use
+ * Authentication method(s) to use/expect from initiator
*/
- auth_class_t class;
+ char *initiator_auth;
+
+ /**
+ * Authentication method(s) use/expected from responder
+ */
+ char *responder_auth;
/**
* incremental numbering of generated configs
@@ -68,6 +73,97 @@ struct private_load_tester_config_t {
};
/**
+ * Generate auth config from string
+ */
+static void generate_auth_cfg(private_load_tester_config_t *this, char *str,
+ peer_cfg_t *peer_cfg, bool local, int num)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+ identification_t *id;
+ auth_class_t class;
+ eap_type_t type;
+ char buf[128];
+ int rnd = 0;
+
+ enumerator = enumerator_create_token(str, "|", " ");
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ auth = auth_cfg_create();
+ rnd++;
+
+ if (streq(str, "psk"))
+ { /* PSK authentication, use FQDNs */
+ class = AUTH_CLASS_PSK;
+ if ((local && !num) || (!local && num))
+ {
+ id = identification_create_from_string("srv.strongswan.org");
+ }
+ else if (local)
+ {
+ snprintf(buf, sizeof(buf), "c%d-r%d.strongswan.org", num, rnd);
+ id = identification_create_from_string(buf);
+ }
+ else
+ {
+ id = identification_create_from_string("*.strongswan.org");
+ }
+ }
+ else if (strneq(str, "eap", strlen("eap")))
+ { /* EAP authentication, use a NAI */
+ class = AUTH_CLASS_EAP;
+ if (*(str + strlen("eap")) == '-')
+ {
+ type = eap_type_from_string(str + strlen("eap-"));
+ if (type)
+ {
+ auth->add(auth, AUTH_RULE_EAP_TYPE, type);
+ }
+ }
+ if (local && num)
+ {
+ snprintf(buf, sizeof(buf), "1%.10d%.4d@strongswan.org", num, rnd);
+ id = identification_create_from_string(buf);
+ }
+ else
+ {
+ id = identification_create_from_encoding(ID_ANY, chunk_empty);
+ }
+ }
+ else
+ {
+ if (!streq(str, "pubkey"))
+ {
+ DBG1(DBG_CFG, "invalid authentication: '%s', fallback to pubkey",
+ str);
+ }
+ /* certificate authentication, use distinguished names */
+ class = AUTH_CLASS_PUBKEY;
+ if ((local && !num) || (!local && num))
+ {
+ id = identification_create_from_string(
+ "CN=srv, OU=load-test, O=strongSwan");
+ }
+ else if (local)
+ {
+ snprintf(buf, sizeof(buf),
+ "CN=c%d-r%d, OU=load-test, O=strongSwan", num, rnd);
+ id = identification_create_from_string(buf);
+ }
+ else
+ {
+ id = identification_create_from_string(
+ "CN=*, OU=load-test, O=strongSwan");
+ }
+ }
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, class);
+ auth->add(auth, AUTH_RULE_IDENTITY, id);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, local);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
* Generate a new initiator config, num = 0 for responder config
*/
static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
@@ -76,36 +172,26 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
child_cfg_t *child_cfg;
peer_cfg_t *peer_cfg;
traffic_selector_t *ts;
- auth_info_t *auth;
- identification_t *local, *remote;
proposal_t *proposal;
- char buf[128];
-
- if (num)
- { /* initiator */
- snprintf(buf, sizeof(buf), "CN=cli-%d, OU=load-test, O=strongSwan", num);
- local = identification_create_from_string(buf);
- snprintf(buf, sizeof(buf), "CN=srv, OU=load-test, O=strongSwan", num);
- remote = identification_create_from_string(buf);
- }
- else
- { /* responder */
- local = identification_create_from_string(
- "CN=srv, OU=load-test, O=strongSwan");
- remote = identification_create_from_string(
- "CN=*, OU=load-test, O=strongSwan");
- }
ike_cfg = ike_cfg_create(FALSE, FALSE, "0.0.0.0", this->remote);
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
- peer_cfg = peer_cfg_create("load-test", 2, ike_cfg, local, remote,
+ peer_cfg = peer_cfg_create("load-test", 2, ike_cfg,
CERT_SEND_IF_ASKED, UNIQUE_NO, 1, 0, 0, /* keytries, rekey, reauth */
0, 0, FALSE, 0, /* jitter, overtime, mobike, dpddelay */
this->vip ? this->vip->clone(this->vip) : NULL,
this->pool, FALSE, NULL, NULL);
- auth = peer_cfg->get_auth(peer_cfg);
- auth->add_item(auth, AUTHN_AUTH_CLASS, &this->class);
- child_cfg = child_cfg_create("load-test", 600, 400, 100, NULL, TRUE,
+ if (num)
+ { /* initiator */
+ generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
+ generate_auth_cfg(this, this->responder_auth, peer_cfg, FALSE, num);
+ }
+ else
+ { /* responder */
+ generate_auth_cfg(this, this->responder_auth, peer_cfg, TRUE, num);
+ generate_auth_cfg(this, this->initiator_auth, peer_cfg, FALSE, num);
+ }
+ child_cfg = child_cfg_create("load-test", 1200, 600, 0, NULL, TRUE,
MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
child_cfg->add_proposal(child_cfg, proposal);
@@ -169,7 +255,6 @@ static void destroy(private_load_tester_config_t *this)
load_tester_config_t *load_tester_config_create()
{
private_load_tester_config_t *this = malloc_thing(private_load_tester_config_t);
- char *authstr;
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;
@@ -195,16 +280,10 @@ load_tester_config_t *load_tester_config_create()
this->proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha1-modp768");
}
- authstr = lib->settings->get_str(lib->settings,
- "charon.plugins.load_tester.auth", "pubkey");
- if (streq(authstr, "psk"))
- {
- this->class = AUTH_CLASS_PSK;
- }
- else
- {
- this->class = AUTH_CLASS_PUBKEY;
- }
+ this->initiator_auth = lib->settings->get_str(lib->settings,
+ "charon.plugins.load_tester.initiator_auth", "pubkey");
+ this->responder_auth = lib->settings->get_str(lib->settings,
+ "charon.plugins.load_tester.responder_auth", "pubkey");
this->num = 1;
this->peer_cfg = generate_config(this, 0);
diff --git a/src/charon/plugins/nm/nm_creds.c b/src/charon/plugins/nm/nm_creds.c
index e7cd640a7..de9eb3b1b 100644
--- a/src/charon/plugins/nm/nm_creds.c
+++ b/src/charon/plugins/nm/nm_creds.c
@@ -259,9 +259,7 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id
{
this->lock->write_lock(this->lock);
DESTROY_IF(this->user);
- /* for EAP authentication, we use always use ID_EAP type */
- this->user = identification_create_from_encoding(ID_EAP,
- id->get_encoding(id));
+ this->user = id->clone(id);
free(this->pass);
this->pass = password ? strdup(password) : NULL;
this->lock->unlock(this->lock);
diff --git a/src/charon/plugins/nm/nm_service.c b/src/charon/plugins/nm/nm_service.c
index 72744b784..abe55eb7d 100644
--- a/src/charon/plugins/nm/nm_service.c
+++ b/src/charon/plugins/nm/nm_service.c
@@ -151,7 +151,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
child_cfg_t *child_cfg;
traffic_selector_t *ts;
ike_sa_t *ike_sa;
- auth_info_t *auth;
+ auth_cfg_t *auth;
auth_class_t auth_class = AUTH_CLASS_EAP;
certificate_t *cert = NULL;
bool agent = FALSE;
@@ -223,8 +223,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
str = nm_setting_vpn_get_data_item(settings, "user");
if (str)
{
- user = identification_create_from_encoding(ID_KEY_ID,
- chunk_create(str, strlen(str)));
+ user = identification_create_from_string(str);
str = nm_setting_vpn_get_secret(settings, "password");
creds->set_username_password(creds, user, (char*)str);
}
@@ -322,15 +321,21 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", (char*)address);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg,
- user, gateway->clone(gateway),
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, 0, /* mobike, DPD */
virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
NULL, FALSE, NULL, NULL); /* pool, mediation */
- auth = peer_cfg->get_auth(peer_cfg);
- auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_class);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
+ auth->add(auth, AUTH_RULE_IDENTITY, user);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY, gateway->clone(gateway));
+ peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
+
child_cfg = child_cfg_create(CONFIG_NAME,
10800, 10200, /* lifetime 3h, rekey 2h50min */
300, /* jitter 5min */
diff --git a/src/charon/plugins/smp/smp.c b/src/charon/plugins/smp/smp.c
index 1283873a4..33a2bb491 100644
--- a/src/charon/plugins/smp/smp.c
+++ b/src/charon/plugins/smp/smp.c
@@ -294,8 +294,9 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
/* <configlist> */
xmlTextWriterStartElement(writer, "configlist");
- enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
- while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ NULL, NULL, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
{
enumerator_t *children;
child_cfg_t *child_cfg;
@@ -310,8 +311,8 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
/* <peerconfig> */
xmlTextWriterStartElement(writer, "peerconfig");
xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
- write_id(writer, "local", peer_cfg->get_my_id(peer_cfg));
- write_id(writer, "remote", peer_cfg->get_other_id(peer_cfg));
+
+ /* TODO: write auth_cfgs */
/* <ikeconfig> */
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
diff --git a/src/charon/plugins/sql/pool.c b/src/charon/plugins/sql/pool.c
index 9761e88e9..a1c67c691 100644
--- a/src/charon/plugins/sql/pool.c
+++ b/src/charon/plugins/sql/pool.c
@@ -401,11 +401,6 @@ static enumerator_t *create_lease_query(char *filter)
{
id = identification_create_from_string(value);
}
- if (!id)
- {
- fprintf(stderr, "invalid 'id' in filter string.\n");
- exit(-1);
- }
break;
case FIL_ADDR:
if (value)
diff --git a/src/charon/plugins/sql/sql_attribute.c b/src/charon/plugins/sql/sql_attribute.c
index 826aa8318..484085d11 100644
--- a/src/charon/plugins/sql/sql_attribute.c
+++ b/src/charon/plugins/sql/sql_attribute.c
@@ -179,7 +179,7 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
*/
static host_t* acquire_address(private_sql_attribute_t *this,
char *name, identification_t *id,
- auth_info_t *auth, host_t *requested)
+ host_t *requested)
{
enumerator_t *enumerator;
u_int pool, timeout, identity;
@@ -263,7 +263,7 @@ sql_attribute_t *sql_attribute_create(database_t *db)
private_sql_attribute_t *this = malloc_thing(private_sql_attribute_t);
time_t now = time(NULL);
- this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,auth_info_t *, host_t *))acquire_address;
+ this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address;
this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
this->public.destroy = (void(*)(sql_attribute_t*))destroy;
diff --git a/src/charon/plugins/sql/sql_config.c b/src/charon/plugins/sql/sql_config.c
index 8efa1cb2e..802bbe777 100644
--- a/src/charon/plugins/sql/sql_config.c
+++ b/src/charon/plugins/sql/sql_config.c
@@ -267,7 +267,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
peer_cfg_t *peer_cfg, *mediated_cfg;
ike_cfg_t *ike;
host_t *vip = NULL;
- auth_info_t *auth;
+ auth_cfg_t *auth;
local_id = identification_create_from_encoding(l_type, l_data);
remote_id = identification_create_from_encoding(r_type, r_data);
@@ -291,20 +291,26 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
if (ike)
{
peer_cfg = peer_cfg_create(
- name, 2, ike, local_id, remote_id, cert_policy, uniqueid,
+ name, 2, ike, cert_policy, uniqueid,
keyingtries, rekeytime, reauthtime, jitter, overtime,
mobike, dpd_delay, vip, pool,
mediation, mediated_cfg, peer_id);
- auth = peer_cfg->get_auth(peer_cfg);
- auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_method);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
+ auth->add(auth, AUTH_RULE_IDENTITY, local_id->clone(local_id));
+ peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_IDENTITY, remote_id->clone(remote_id));
if (eap_type)
{
- auth->add_item(auth, AUTHN_EAP_TYPE, &eap_type);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+ auth->add(auth, AUTH_RULE_EAP_TYPE, eap_type);
if (eap_vendor)
{
- auth->add_item(auth, AUTHN_EAP_VENDOR, &eap_vendor);
+ auth->add(auth, AUTH_RULE_EAP_VENDOR, eap_vendor);
}
}
+ peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
add_child_cfgs(this, peer_cfg, id);
return peer_cfg;
}
diff --git a/src/charon/plugins/stroke/stroke_attribute.c b/src/charon/plugins/stroke/stroke_attribute.c
index f850b5320..0ebc367fa 100644
--- a/src/charon/plugins/stroke/stroke_attribute.c
+++ b/src/charon/plugins/stroke/stroke_attribute.c
@@ -191,7 +191,7 @@ int host2offset(pool_t *pool, host_t *addr)
*/
static host_t* acquire_address(private_stroke_attribute_t *this,
char *name, identification_t *id,
- auth_info_t *auth, host_t *requested)
+ host_t *requested)
{
pool_t *pool;
uintptr_t offset = 0;
@@ -530,7 +530,7 @@ 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.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,host_t *))acquire_address;
this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_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;
diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c
index 59c58ca0d..4a0b1ff42 100644
--- a/src/charon/plugins/stroke/stroke_config.c
+++ b/src/charon/plugins/stroke/stroke_config.c
@@ -55,90 +55,21 @@ struct private_stroke_config_t {
};
/**
- * 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);
+ return enumerator_create_cleaner(this->list->create_enumerator(this->list),
+ (void*)this->mutex->unlock, this->mutex);
}
/**
* filter function for ike configs
*/
-static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
+static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
{
*out = (*in)->get_ike_cfg(*in);
return TRUE;
@@ -150,17 +81,10 @@ static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
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);
+ (void*)ike_filter, this->mutex,
+ (void*)this->mutex->unlock);
}
/**
@@ -171,34 +95,34 @@ static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *nam
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, &current))
{
- /* 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;
- }
+ /* 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);
@@ -206,22 +130,6 @@ static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *nam
}
/**
- * check if a certificate has an ID
- */
-static identification_t *update_peerid(certificate_t *cert, identification_t *id)
-{
- if (id->get_type(id) == ID_ANY || !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,
@@ -332,45 +240,303 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
return ike_cfg;
}
+
/**
- * build a peer_cfg from a stroke msg
+ * Add CRL constraint to config
*/
-static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
- stroke_msg_t *msg, ike_cfg_t *ike_cfg,
- identification_t **my_issuer,
- identification_t **other_issuer)
+static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
{
- 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;
+ /* CRL/OCSP policy, for remote config only */
+ if (!local)
+ {
+ switch (policy)
+ {
+ case CRL_STRICT_YES:
+ /* if yes, we require a GOOD validation */
+ cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
+ break;
+ case CRL_STRICT_IFURI:
+ /* for ifuri, a SKIPPED validation is sufficient */
+ cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_SKIPPED);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * build authentication config
+ */
+static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
+ stroke_msg_t *msg, bool local, bool primary)
+{
+ identification_t *identity;
+ certificate_t *certificate;
+ char *auth, *id, *cert, *ca;
+ stroke_end_t *end, *other_end;
+ auth_cfg_t *cfg;
+ char eap_buf[32];
- me = identification_create_from_string(msg->add_conn.me.id ?
- msg->add_conn.me.id : msg->add_conn.me.address);
- if (!me)
+ /* select strings */
+ if (local)
{
- DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id);
- return NULL;
+ end = &msg->add_conn.me;
+ other_end = &msg->add_conn.other;
}
- other = identification_create_from_string(msg->add_conn.other.id ?
- msg->add_conn.other.id : msg->add_conn.other.address);
- if (!other)
+ else
{
- DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id);
- me->destroy(me);
- return NULL;
+ end = &msg->add_conn.other;
+ other_end = &msg->add_conn.me;
+ }
+ if (primary)
+ {
+ auth = end->auth;
+ id = end->id;
+ if (!id)
+ { /* leftid/rightid fallback to address */
+ id = end->address;
+ }
+ cert = end->cert;
+ ca = end->ca;
+ if (ca && streq(ca, "%same"))
+ {
+ ca = other_end->ca;
+ }
+ }
+ else
+ {
+ auth = end->auth2;
+ id = end->id2;
+ if (local && !id)
+ { /* leftid2 falls back to leftid */
+ id = end->id;
+ }
+ cert = end->cert2;
+ ca = end->ca2;
+ if (ca && streq(ca, "%same"))
+ {
+ ca = other_end->ca2;
+ }
}
+ if (!auth)
+ {
+ if (primary)
+ {
+ if (local)
+ { /* "leftauth" not defined, fall back to deprecated "authby" */
+ switch (msg->add_conn.auth_method)
+ {
+ default:
+ case AUTH_CLASS_PUBKEY:
+ auth = "pubkey";
+ break;
+ case AUTH_CLASS_PSK:
+ auth = "psk";
+ break;
+ case AUTH_CLASS_EAP:
+ auth = "eap";
+ break;
+ }
+ }
+ else
+ { /* "rightauth" not defined, fall back to deprecated "eap" */
+ if (msg->add_conn.eap_type)
+ {
+ if (msg->add_conn.eap_vendor)
+ {
+ snprintf(eap_buf, sizeof(eap_buf), "eap-%d-%d",
+ msg->add_conn.eap_type,
+ msg->add_conn.eap_vendor);
+ }
+ else
+ {
+ snprintf(eap_buf, sizeof(eap_buf), "eap-%d",
+ msg->add_conn.eap_type);
+ }
+ auth = eap_buf;
+ }
+ else
+ { /* not EAP => no constraints for this peer */
+ auth = "any";
+ }
+ }
+ }
+ else
+ { /* no second authentication round, fine */
+ return NULL;
+ }
+ }
+
+ cfg = auth_cfg_create();
+
+ /* add identity and peer certifcate */
+ identity = identification_create_from_string(id);
+ if (cert)
+ {
+ certificate = this->cred->load_peer(this->cred, cert);
+ if (certificate)
+ {
+ if (local)
+ {
+ this->ca->check_for_hash_and_url(this->ca, certificate);
+ }
+ cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
+ if (identity->get_type(identity) == ID_ANY ||
+ !certificate->has_subject(certificate, identity))
+ {
+ DBG1(DBG_CFG, " peerid %D not confirmed by certificate, "
+ "defaulting to subject DN: %D", identity,
+ certificate->get_subject(certificate));
+ identity->destroy(identity);
+ identity = certificate->get_subject(certificate);
+ identity = identity->clone(identity);
+ }
+ }
+ }
+ cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+
+ /* CA constraint */
+ if (ca)
+ {
+ identity = identification_create_from_string(ca);
+ certificate = charon->credentials->get_cert(charon->credentials,
+ CERT_X509, KEY_ANY, identity, TRUE);
+ identity->destroy(identity);
+ if (certificate)
+ {
+ cfg->add(cfg, AUTH_RULE_CA_CERT, certificate);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "CA certificate %s not found, discarding CA "
+ "constraint", ca);
+ }
+ }
+
+ /* AC groups */
+ if (end->groups)
+ {
+ enumerator_t *enumerator;
+ char *group;
+
+ enumerator = enumerator_create_token(end->groups, ",", " ");
+ while (enumerator->enumerate(enumerator, &group))
+ {
+ identity = identification_create_from_encoding(ID_IETF_ATTR_STRING,
+ chunk_create(group, strlen(group)));
+ cfg->add(cfg, AUTH_RULE_AC_GROUP, identity);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ /* authentication metod (class, actually) */
+ if (streq(auth, "pubkey") ||
+ streq(auth, "rsasig") || streq(auth, "rsa") ||
+ streq(auth, "ecdsasig") || streq(auth, "ecdsa"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ build_crl_policy(cfg, local, msg->add_conn.crl_policy);
+ }
+ else if (streq(auth, "psk") || streq(auth, "secret"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ }
+ else if (strneq(auth, "eap", 3))
+ {
+ enumerator_t *enumerator;
+ char *str;
+ int i = 0, type = 0, vendor;
+
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+
+ /* parse EAP string, format: eap[-type[-vendor]] */
+ enumerator = enumerator_create_token(auth, "-", " ");
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ switch (i)
+ {
+ case 1:
+ type = eap_type_from_string(str);
+ if (!type)
+ {
+ type = atoi(str);
+ if (!type)
+ {
+ DBG1(DBG_CFG, "unknown EAP method: %s", str);
+ break;
+ }
+ }
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
+ break;
+ case 2:
+ if (type)
+ {
+ vendor = atoi(str);
+ if (vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "unknown EAP vendor: %s", str);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ i++;
+ }
+ enumerator->destroy(enumerator);
+
+ if (msg->add_conn.eap_identity)
+ {
+ if (streq(msg->add_conn.eap_identity, "%identity"))
+ {
+ identity = identification_create_from_encoding(ID_ANY,
+ chunk_empty);
+ }
+ else
+ {
+ identity = identification_create_from_string(
+ msg->add_conn.eap_identity);
+ }
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, identity);
+ }
+ }
+ else
+ {
+ if (!streq(auth, "any"))
+ {
+ DBG1(DBG_CFG, "authentication method %s unknown, fallback to any",
+ auth);
+ }
+ build_crl_policy(cfg, local, msg->add_conn.crl_policy);
+ }
+ return 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 *peer_id = NULL;
+ peer_cfg_t *mediated_by = NULL;
+ host_t *vip = NULL;
+ unique_policy_t unique;
+ u_int32_t rekey = 0, reauth = 0, over, jitter;
+ peer_cfg_t *peer_cfg;
+ auth_cfg_t *auth_cfg;
#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;
}
@@ -388,8 +554,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
msg->add_conn.ikeme.mediated_by);
- me->destroy(me);
- other->destroy(other);
return NULL;
}
@@ -399,56 +563,19 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
"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)
+ if (msg->add_conn.ikeme.peerid)
{
- 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;
+ peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
}
- }
- 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)
+ else if (msg->add_conn.other.id)
{
- identification_t *issuer = cert->get_issuer(cert);
-
- *my_issuer = issuer->clone(issuer);
- 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)
- {
- identification_t *issuer = cert->get_issuer(cert);
-
- *other_issuer = issuer->clone(issuer);
- other = update_peerid(cert, other);
- cert->destroy(cert);
+ peer_id = identification_create_from_string(msg->add_conn.other.id);
}
}
+#endif /* ME */
+
jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
over = msg->add_conn.rekey.margin;
if (msg->add_conn.rekey.reauth)
@@ -512,179 +639,45 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
/* 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,
+ peer_cfg = peer_cfg_create(msg->add_conn.name,
+ msg->add_conn.ikev2 ? 2 : 1, ike_cfg,
msg->add_conn.me.sendcert, unique,
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,
- identification_t *other_ca)
-{
- identification_t *id;
- bool my_ca_same = FALSE;
- bool other_ca_same = FALSE;
- cert_validation_t valid;
-
- 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)
+ /* build leftauth= */
+ auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
+ if (auth_cfg)
{
- if (my_ca)
- {
- my_ca->destroy(my_ca);
- my_ca = NULL;
- }
- if (streq(msg->add_conn.me.ca, "%same"))
- {
- my_ca_same = TRUE;
- }
- else
- {
- my_ca = identification_create_from_string(msg->add_conn.me.ca);
- }
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
}
-
- if (msg->add_conn.other.ca)
- {
- if (other_ca)
- {
- other_ca->destroy(other_ca);
- other_ca = NULL;
- }
- 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);
+ else
+ { /* we require at least one config on our side */
+ peer_cfg->destroy(peer_cfg);
+ return NULL;
}
- auth->add_item(auth, AUTHN_AUTH_CLASS, &msg->add_conn.auth_method);
- if (msg->add_conn.eap_type)
+ /* build leftauth2= */
+ auth_cfg = build_auth_cfg(this, msg, TRUE, FALSE);
+ if (auth_cfg)
{
- auth->add_item(auth, AUTHN_EAP_TYPE, &msg->add_conn.eap_type);
- if (msg->add_conn.eap_vendor)
- {
- auth->add_item(auth, AUTHN_EAP_VENDOR, &msg->add_conn.eap_vendor);
- }
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
}
-
- if (msg->add_conn.eap_identity)
+ /* build rightauth= */
+ auth_cfg = build_auth_cfg(this, msg, FALSE, TRUE);
+ if (auth_cfg)
{
- if (streq(msg->add_conn.eap_identity, "%identity"))
- {
- id = identification_create_from_encoding(ID_ANY, chunk_empty);
- }
- else
- {
- id = identification_create_from_encoding(ID_EAP, chunk_create(
- msg->add_conn.eap_identity,
- strlen(msg->add_conn.eap_identity)));
- }
- auth->add_item(auth, AUTHN_EAP_IDENTITY, id);
- id->destroy(id);
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
}
-
- if (msg->add_conn.other.groups)
+ /* build rightauth2= */
+ auth_cfg = build_auth_cfg(this, msg, FALSE, FALSE);
+ if (auth_cfg)
{
- chunk_t line = { msg->add_conn.other.groups,
- strlen(msg->add_conn.other.groups) };
-
- while (eat_whitespace(&line))
- {
- chunk_t group;
-
- /* extract the next comma-separated group attribute */
- if (!extract_token(&group, ',', &line))
- {
- group = line;
- line.len = 0;
- }
-
- /* remove any trailing spaces */
- while (group.len > 0 && *(group.ptr + group.len - 1) == ' ')
- {
- group.len--;
- }
-
- /* add the group attribute to the list */
- if (group.len > 0)
- {
- identification_t *ac_group;
-
- ac_group = identification_create_from_encoding(
- ID_IETF_ATTR_STRING, group);
- auth->add_item(auth, AUTHZ_AC_GROUP, ac_group);
- ac_group->destroy(ac_group);
- }
- }
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
}
+ return peer_cfg;
}
/**
@@ -799,7 +792,6 @@ 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;
- identification_t *my_issuer = NULL, *other_issuer = NULL;
enumerator_t *enumerator;
bool use_existing = FALSE;
@@ -808,15 +800,13 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
{
return;
}
- peer_cfg = build_peer_cfg(this, msg, ike_cfg, &my_issuer, &other_issuer);
+ 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),
- my_issuer, other_issuer);
enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
while (enumerator->enumerate(enumerator, &existing))
{
@@ -850,9 +840,7 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
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));
+ DBG1(DBG_CFG, "added configuration '%s'", msg->add_conn.name);
this->mutex->lock(this->mutex);
this->list->insert_last(this->list, peer_cfg);
this->mutex->unlock(this->mutex);
diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c
index 434aec22b..7fb33da9e 100644
--- a/src/charon/plugins/stroke/stroke_cred.c
+++ b/src/charon/plugins/stroke/stroke_cred.c
@@ -905,26 +905,13 @@ static void load_secrets(private_stroke_cred_t *this)
continue;
}
- if (type == SHARED_EAP)
+ /* NULL terminate the ID string */
+ *(id.ptr + id.len) = '\0';
+ peer_id = identification_create_from_string(id.ptr);
+ if (peer_id->get_type(peer_id) == ID_ANY)
{
- /* we use a special EAP identity type for EAP secrets */
- peer_id = identification_create_from_encoding(ID_EAP, id);
- }
- else
- {
- /* 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;
- }
+ peer_id->destroy(peer_id);
+ continue;
}
shared_key->add_owner(shared_key, peer_id);
diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c
index 94b3def3a..9c98770dd 100644
--- a/src/charon/plugins/stroke/stroke_list.c
+++ b/src/charon/plugins/stroke/stroke_list.c
@@ -55,23 +55,6 @@ struct private_stroke_list_t {
};
/**
- * get the authentication class of a config
- */
-auth_class_t get_auth_class(peer_cfg_t *config)
-{
- auth_class_t *class;
- auth_info_t *auth_info;
-
- auth_info = config->get_auth(config);
- if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
- {
- return *class;
- }
- /* fallback to pubkey authentication */
- return AUTH_CLASS_PUBKEY;
-}
-
-/**
* log an IKE_SA to out
*/
static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
@@ -110,9 +93,11 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
{
time_t rekey, reauth;
+ peer_cfg_t *peer_cfg;
rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY);
reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
if (rekey)
{
@@ -120,9 +105,24 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
}
if (reauth)
{
- fprintf(out, ", %N reauthentication in %V", auth_class_names,
- get_auth_class(ike_sa->get_peer_cfg(ike_sa)),
- &reauth, &now);
+ bool first = TRUE;
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+
+ fprintf(out, ", ");
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, TRUE);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ if (!first)
+ {
+ fprintf(out, "+");
+ }
+ first = FALSE;
+ fprintf(out, "%N", auth_class_names,
+ auth->get(auth, AUTH_RULE_AUTH_CLASS));
+ }
+ enumerator->destroy(enumerator);
+ fprintf(out, " reauthentication in %V", &reauth, &now);
}
if (!rekey && !reauth)
{
@@ -248,6 +248,107 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
}
/**
+ * Log a configs local or remote authentication config to out
+ */
+static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
+{
+ enumerator_t *enumerator, *rules;
+ auth_rule_t rule;
+ auth_cfg_t *auth;
+ auth_class_t auth_class;
+ identification_t *id;
+ certificate_t *cert;
+ cert_validation_t valid;
+ char *name;
+
+ name = peer_cfg->get_name(peer_cfg);
+
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ fprintf(out, "%12s: %s [%D] uses ", name, local ? "local: " : "remote:",
+ auth->get(auth, AUTH_RULE_IDENTITY));
+
+ auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
+ if (auth_class != AUTH_CLASS_EAP)
+ {
+ fprintf(out, "%N authentication\n", auth_class_names, auth_class);
+ }
+ else
+ {
+ if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
+ {
+ fprintf(out, "EAP authentication");
+ }
+ else
+ {
+ if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
+ {
+ fprintf(out, "EAP_%d-%d authentication",
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
+ }
+ else
+ {
+ fprintf(out, "%N authentication", eap_type_names,
+ (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE));
+ }
+ }
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ fprintf(out, " with EAP identity '%D'", id);
+ }
+ fprintf(out, "\n");
+ }
+
+ cert = auth->get(auth, AUTH_RULE_CA_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: ca: \"%D\"\n", name, cert->get_subject(cert));
+ }
+
+ cert = auth->get(auth, AUTH_RULE_IM_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: im-ca: \"%D\"\n", name, cert->get_subject(cert));
+ }
+
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ fprintf(out, "%12s: cert: \"%D\"\n", name,
+ cert->get_subject(cert));
+ }
+
+ valid = (uintptr_t)auth->get(auth, AUTH_RULE_OCSP_VALIDATION);
+ if (valid != VALIDATION_FAILED)
+ {
+ fprintf(out, "%12s: ocsp: status must be GOOD%s\n", name,
+ (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
+ }
+
+ valid = (uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION);
+ if (valid != VALIDATION_FAILED)
+ {
+ fprintf(out, "%12s: crl: status must be GOOD%s\n", name,
+ (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
+ }
+
+ rules = auth->create_enumerator(auth);
+ while (rules->enumerate(rules, &rule, &id))
+ {
+ if (rule == AUTH_RULE_AC_GROUP)
+ {
+ fprintf(out, "%12s: group: %D\n", name, id);
+ }
+ }
+ rules->destroy(rules);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
* Implementation of stroke_list_t.status.
*/
static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all)
@@ -313,138 +414,42 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
enumerator->destroy(enumerator);
fprintf(out, "Connections:\n");
- enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
- while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends, NULL, NULL, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
{
- void *ptr;
- certificate_t *cert;
- auth_item_t item;
- auth_info_t *auth;
- enumerator_t *auth_enumerator;
- identification_t *my_ca = NULL, *other_ca = NULL;
- identification_t *eap_identity = NULL;
- u_int32_t *eap_type = NULL;
- bool ac_groups = FALSE;
-
if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
(name && !streq(name, peer_cfg->get_name(peer_cfg))))
{
continue;
}
- /* determine any required CAs, EAP type, EAP identity,
- * and the presence of AC groups
- */
- auth = peer_cfg->get_auth(peer_cfg);
- auth_enumerator = auth->create_item_enumerator(auth);
- while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
- {
- switch (item)
- {
- case AUTHN_EAP_TYPE:
- eap_type = (u_int32_t *)ptr;
- break;
- case AUTHN_EAP_IDENTITY:
- eap_identity = (identification_t *)ptr;
- break;
- case AUTHN_CA_CERT:
- cert = (certificate_t *)ptr;
- my_ca = cert->get_subject(cert);
- break;
- case AUTHN_CA_CERT_NAME:
- my_ca = (identification_t *)ptr;
- break;
- case AUTHZ_CA_CERT:
- cert = (certificate_t *)ptr;
- other_ca = cert->get_subject(cert);
- break;
- case AUTHZ_CA_CERT_NAME:
- other_ca = (identification_t *)ptr;
- break;
- case AUTHZ_AC_GROUP:
- ac_groups = TRUE;
- break;
- default:
- break;
- }
- }
- auth_enumerator->destroy(auth_enumerator);
-
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));
- if (my_ca || other_ca)
- {
- fprintf(out, "%12s: CAs: ", peer_cfg->get_name(peer_cfg));
- if (my_ca)
- {
- fprintf(out, "\"%D\"...", my_ca);
- }
- else
- {
- fprintf(out, "%%any...");
- }
- if (other_ca)
- {
- fprintf(out, "\"%D\"\n", other_ca);
- }
- else
- {
- fprintf(out, "%%any\n");
- }
- }
-
- if (ac_groups)
- {
- bool first = TRUE;
-
- fprintf(out, "%12s: groups: ", peer_cfg->get_name(peer_cfg));
- auth_enumerator = auth->create_item_enumerator(auth);
- while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
- {
- if (item == AUTHZ_AC_GROUP)
- {
- identification_t *group = (identification_t *)ptr;
-
- fprintf(out, "%s%D", first? "":", ", group);
- first = FALSE;
- }
- }
- auth_enumerator->destroy(auth_enumerator);
- fprintf(out, "\n");
- }
-
- fprintf(out, "%12s: %N ", peer_cfg->get_name(peer_cfg),
- auth_class_names, get_auth_class(peer_cfg));
- if (eap_type)
- {
- fprintf(out, "and %N ", eap_type_names, *eap_type);
- }
- fprintf(out, "authentication");
- if (eap_identity)
- {
- fprintf(out, ", EAP identity: '%D'", eap_identity);
- }
+ fprintf(out, "%12s: %s...%s", peer_cfg->get_name(peer_cfg),
+ ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg));
+
dpd = peer_cfg->get_dpd(peer_cfg);
if (dpd)
{
fprintf(out, ", dpddelay=%us", dpd);
}
fprintf(out, "\n");
-
+
+ log_auth_cfgs(out, peer_cfg, TRUE);
+ log_auth_cfgs(out, peer_cfg, FALSE);
+
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", child_cfg->get_name(child_cfg),
+ fprintf(out, "%12s: child: %#R=== %#R", 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));
-
+
if (dpd)
{
fprintf(out, ", dpdaction=%N", action_names,
diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c
index 53edde031..85f1e8f4e 100644
--- a/src/charon/plugins/stroke/stroke_socket.c
+++ b/src/charon/plugins/stroke/stroke_socket.c
@@ -143,18 +143,28 @@ 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->auth);
+ pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
+ pop_string(msg, &end->id2);
pop_string(msg, &end->cert);
+ pop_string(msg, &end->cert2);
pop_string(msg, &end->ca);
+ pop_string(msg, &end->ca2);
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, " %sauth=%s", label, end->auth);
+ DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
+ DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
DBG2(DBG_CFG, " %scert=%s", label, end->cert);
+ DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
DBG2(DBG_CFG, " %sca=%s", label, end->ca);
+ DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
}
diff --git a/src/charon/plugins/uci/uci_config.c b/src/charon/plugins/uci/uci_config.c
index c9d54a532..d185476fd 100644
--- a/src/charon/plugins/uci/uci_config.c
+++ b/src/charon/plugins/uci/uci_config.c
@@ -83,24 +83,6 @@ static proposal_t *create_proposal(char *string, protocol_id_t proto)
}
/**
- * 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)
@@ -163,8 +145,7 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
char *remote_id, *remote_addr, *remote_net;
child_cfg_t *child_cfg;
ike_cfg_t *ike_cfg;
- auth_info_t *auth;
- auth_class_t class;
+ auth_cfg_t *auth;
/* defaults */
name = "unnamed";
@@ -187,16 +168,26 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **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,
+ name, 2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
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 */
- auth = this->peer_cfg->get_auth(this->peer_cfg);
- class = AUTH_CLASS_PSK;
- auth->add_item(auth, AUTHN_AUTH_CLASS, &class);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_string(local_id));
+ this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, TRUE);
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ if (remote_id)
+ {
+ auth->add(auth, AUTH_RULE_IDENTITY,
+ identification_create_from_string(remote_id));
+ }
+ this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
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);
diff --git a/src/charon/plugins/uci/uci_control.c b/src/charon/plugins/uci/uci_control.c
index 2ffdd2b7b..7a428afb0 100644
--- a/src/charon/plugins/uci/uci_control.c
+++ b/src/charon/plugins/uci/uci_control.c
@@ -39,15 +39,15 @@ typedef struct private_uci_control_t private_uci_control_t;
* private data of uci_control_t
*/
struct private_uci_control_t {
-
+
/**
- * Public part
- */
+ * Public part
+ */
uci_control_t public;
-
+
/**
- * Job
- */
+ * Job
+ */
callback_job_t *job;
};
@@ -86,13 +86,14 @@ static void status(private_uci_control_t *this, char *name)
char buf[2048];
FILE *out = NULL;
- configs = charon->backends->create_peer_cfg_enumerator(charon->backends);
- while (configs->enumerate(configs, &peer_cfg))
- {
- if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
- {
- continue;
- }
+ configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ NULL, NULL, NULL, NULL);
+ while (configs->enumerate(configs, &peer_cfg))
+ {
+ if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
+ {
+ continue;
+ }
sas = charon->controller->create_ike_sa_enumerator(charon->controller);
while (sas->enumerate(sas, &ike_sa))
{
@@ -108,9 +109,9 @@ static void status(private_uci_control_t *this, char *name)
continue;
}
}
- fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
- ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
-
+ fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
+ ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
+
children = ike_sa->create_child_sa_iterator(ike_sa);
while (children->iterate(children, (void**)&child_sa))
{
@@ -118,7 +119,7 @@ static void status(private_uci_control_t *this, char *name)
child_sa->get_traffic_selectors(child_sa, FALSE));
}
children->destroy(children);
- fprintf(out, "\n");
+ fprintf(out, "\n");
}
sas->destroy(sas);
}
@@ -142,7 +143,7 @@ static void initiate(private_uci_control_t *this, char *name)
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
enumerator_t *enumerator;
-
+
peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
if (peer_cfg)
{
@@ -174,7 +175,7 @@ static void terminate(private_uci_control_t *this, char *name)
enumerator_t *enumerator;
ike_sa_t *ike_sa;
u_int id;
-
+
enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
while (enumerator->enumerate(enumerator, &ike_sa))
{
@@ -240,7 +241,7 @@ static job_requeue_t receive(private_uci_control_t *this)
char message[128];
int oldstate, len;
FILE *in;
-
+
memset(message, 0, sizeof(message));
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
in = fopen(FIFO_FILE, "r");
@@ -281,9 +282,9 @@ static void destroy(private_uci_control_t *this)
uci_control_t *uci_control_create()
{
private_uci_control_t *this = malloc_thing(private_uci_control_t);
-
+
this->public.destroy = (void(*)(uci_control_t*))destroy;
-
+
unlink(FIFO_FILE);
if (mkfifo(FIFO_FILE, S_IRUSR|S_IWUSR) != 0)
{
diff --git a/src/charon/plugins/uci/uci_creds.c b/src/charon/plugins/uci/uci_creds.c
index 60f6fc934..2813850e8 100644
--- a/src/charon/plugins/uci/uci_creds.c
+++ b/src/charon/plugins/uci/uci_creds.c
@@ -81,10 +81,6 @@ static bool shared_enumerator_enumerate(shared_enumerator_t *this,
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);
@@ -96,10 +92,6 @@ static bool shared_enumerator_enumerate(shared_enumerator_t *this,
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);
diff --git a/src/charon/plugins/unit_tester/tests/test_auth_info.c b/src/charon/plugins/unit_tester/tests/test_auth_info.c
index 1719190b1..37bdd1087 100644
--- a/src/charon/plugins/unit_tester/tests/test_auth_info.c
+++ b/src/charon/plugins/unit_tester/tests/test_auth_info.c
@@ -15,7 +15,7 @@
#include <daemon.h>
#include <library.h>
-#include <credentials/auth_info.h>
+#include <config/auth_cfg.h>
char buf[] = {0x01,0x02,0x03,0x04};
@@ -75,14 +75,14 @@ chunk_t certchunk = chunk_from_buf(certbuf);
/*******************************************************************************
* auth info test
******************************************************************************/
-bool test_auth_info()
+bool test_auth_cfg()
{
- auth_info_t *auth = auth_info_create(), *auth2;
+ auth_cfg_t *auth = auth_cfg_create(), *auth2;
certificate_t *c1, *c2;
enumerator_t *enumerator;
int round = 0;
void *value;
- auth_item_t type;
+ auth_rule_t type;
c1 = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, certchunk,
@@ -92,8 +92,9 @@ bool test_auth_info()
return FALSE;
}
- auth->add_item(auth, AUTHN_SUBJECT_CERT, c1);
- if (!auth->get_item(auth, AUTHN_SUBJECT_CERT, (void**)&c2))
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, c1->get_ref(c1));
+ c2 = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (!c2)
{
return FALSE;
}
@@ -102,11 +103,11 @@ bool test_auth_info()
return FALSE;
}
- enumerator = auth->create_item_enumerator(auth);
+ enumerator = auth->create_enumerator(auth);
while (enumerator->enumerate(enumerator, &type, &value))
{
round++;
- if (round == 1 && type == AUTHN_SUBJECT_CERT && value == c1)
+ if (round == 1 && type == AUTH_RULE_SUBJECT_CERT && value == c1)
{
continue;
}
@@ -114,20 +115,20 @@ bool test_auth_info()
}
enumerator->destroy(enumerator);
- auth2 = auth_info_create();
- auth2->add_item(auth2, AUTHN_CA_CERT, c1);
- auth2->merge(auth2, auth);
+ auth2 = auth_cfg_create();
+ auth2->add(auth2, AUTH_RULE_CA_CERT, c1->get_ref(c1));
+ auth2->merge(auth2, auth, FALSE);
round = 0;
- enumerator = auth2->create_item_enumerator(auth2);
+ enumerator = auth2->create_enumerator(auth2);
while (enumerator->enumerate(enumerator, &type, &value))
{
round++;
- if (round == 1 && type == AUTHN_CA_CERT && value == c1)
+ if (round == 1 && type == AUTH_RULE_CA_CERT && value == c1)
{
continue;
}
- if (round == 2 && type == AUTHN_SUBJECT_CERT && value == c1)
+ if (round == 2 && type == AUTH_RULE_SUBJECT_CERT && value == c1)
{
continue;
}
diff --git a/src/charon/plugins/unit_tester/tests/test_med_db.c b/src/charon/plugins/unit_tester/tests/test_med_db.c
index d65eb0cc4..7b4603bd7 100644
--- a/src/charon/plugins/unit_tester/tests/test_med_db.c
+++ b/src/charon/plugins/unit_tester/tests/test_med_db.c
@@ -33,8 +33,8 @@ bool test_med_db()
chunk_t keyid = chunk_from_buf(keyid_buf);
identification_t *id, *found;
enumerator_t *enumerator;
- auth_info_t *auth;
public_key_t *public;
+ auth_cfg_t *auth;
bool good = FALSE;
id = identification_create_from_encoding(ID_KEY_ID, keyid);
diff --git a/src/charon/plugins/unit_tester/tests/test_pool.c b/src/charon/plugins/unit_tester/tests/test_pool.c
index b11f71704..3c792ef04 100644
--- a/src/charon/plugins/unit_tester/tests/test_pool.c
+++ b/src/charon/plugins/unit_tester/tests/test_pool.c
@@ -25,14 +25,10 @@
static void* testing(void *thread)
{
- int i;
- auth_info_t *auth;
+ int i;
host_t *addr[ALLOCS];
identification_t *id[ALLOCS];
-
- auth = auth_info_create();
-
/* prepare identities */
for (i = 0; i < ALLOCS; i++)
{
@@ -40,17 +36,13 @@ static void* testing(void *thread)
snprintf(buf, sizeof(buf), "%d-%d@strongswan.org", (int)thread, i);
id[i] = identification_create_from_string(buf);
- if (!id[i])
- {
- return (void*)FALSE;
- }
}
/* allocate addresses */
for (i = 0; i < ALLOCS; i++)
{
addr[i] = charon->attributes->acquire_address(charon->attributes,
- "test", id[i], auth, NULL);
+ "test", id[i], NULL);
if (!addr[i])
{
return (void*)FALSE;
@@ -69,7 +61,6 @@ static void* testing(void *thread)
addr[i]->destroy(addr[i]);
id[i]->destroy(id[i]);
}
- auth->destroy(auth);
return (void*)TRUE;
}
diff --git a/src/charon/processing/jobs/initiate_mediation_job.c b/src/charon/processing/jobs/initiate_mediation_job.c
index db9e76e63..69eac3b21 100644
--- a/src/charon/processing/jobs/initiate_mediation_job.c
+++ b/src/charon/processing/jobs/initiate_mediation_job.c
@@ -75,6 +75,8 @@ static void initiate(private_initiate_mediation_job_t *this)
{
ike_sa_t *mediated_sa, *mediation_sa;
peer_cfg_t *mediated_cfg, *mediation_cfg;
+ enumerator_t *enumerator;
+ auth_cfg_t *auth_cfg;
mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
this->mediated_sa_id);
@@ -88,8 +90,20 @@ static void initiate(private_initiate_mediation_job_t *this)
mediation_cfg = mediated_cfg->get_mediated_by(mediated_cfg);
mediation_cfg->get_ref(mediation_cfg);
+ enumerator = mediation_cfg->create_auth_cfg_enumerator(mediation_cfg,
+ TRUE);
+ if (!enumerator->enumerate(enumerator, &auth_cfg) ||
+ auth_cfg->get(auth_cfg, AUTH_RULE_IDENTITY) == NULL)
+ {
+ mediated_cfg->destroy(mediated_cfg);
+ mediation_cfg->destroy(mediation_cfg);
+ enumerator->destroy(enumerator);
+ destroy(this);
+ return;
+ }
+
if (charon->connect_manager->check_and_register(charon->connect_manager,
- mediation_cfg->get_my_id(mediation_cfg),
+ auth_cfg->get(auth_cfg, AUTH_RULE_IDENTITY),
mediated_cfg->get_peer_id(mediated_cfg),
this->mediated_sa_id))
{
diff --git a/src/charon/sa/authenticators/authenticator.c b/src/charon/sa/authenticators/authenticator.c
index cdd3245fe..0c33528a0 100644
--- a/src/charon/sa/authenticators/authenticator.c
+++ b/src/charon/sa/authenticators/authenticator.c
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2006-2009 Martin Willi
* 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
@@ -23,6 +23,7 @@
#include <sa/authenticators/pubkey_authenticator.h>
#include <sa/authenticators/psk_authenticator.h>
#include <sa/authenticators/eap_authenticator.h>
+#include <encoding/payloads/auth_payload.h>
ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS,
@@ -35,7 +36,8 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
"ECDSA-521 signature");
ENUM_END(auth_method_names, AUTH_ECDSA_521);
-ENUM(auth_class_names, AUTH_CLASS_PUBKEY, AUTH_CLASS_EAP,
+ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP,
+ "any",
"public key",
"pre-shared key",
"EAP",
@@ -44,17 +46,23 @@ ENUM(auth_class_names, AUTH_CLASS_PUBKEY, AUTH_CLASS_EAP,
/**
* Described in header.
*/
-authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa,
- auth_class_t class)
+authenticator_t *authenticator_create_builder(
+ ike_sa_t *ike_sa, auth_cfg_t *cfg,
+ chunk_t received_nonce, chunk_t sent_init)
{
- switch (class)
+ switch ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS))
{
+ case AUTH_CLASS_ANY:
+ /* defaults to PUBKEY */
case AUTH_CLASS_PUBKEY:
- return (authenticator_t*)pubkey_authenticator_create(ike_sa);
+ return (authenticator_t*)pubkey_authenticator_create_builder(ike_sa,
+ received_nonce, sent_init);
case AUTH_CLASS_PSK:
- return (authenticator_t*)psk_authenticator_create(ike_sa);
+ return (authenticator_t*)psk_authenticator_create_builder(ike_sa,
+ received_nonce, sent_init);
case AUTH_CLASS_EAP:
- return (authenticator_t*)eap_authenticator_create(ike_sa);
+ return (authenticator_t*)eap_authenticator_create_builder(ike_sa,
+ received_nonce, sent_init);
default:
return NULL;
}
@@ -63,19 +71,31 @@ authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa,
/**
* Described in header.
*/
-authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa,
- auth_method_t method)
+authenticator_t *authenticator_create_verifier(
+ ike_sa_t *ike_sa, message_t *message,
+ chunk_t sent_nonce, chunk_t received_init)
{
- switch (method)
+ auth_payload_t *auth_payload;
+
+ auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ if (auth_payload == NULL)
+ {
+ return (authenticator_t*)eap_authenticator_create_verifier(ike_sa,
+ sent_nonce, received_init);
+ }
+ switch (auth_payload->get_auth_method(auth_payload))
{
case AUTH_RSA:
case AUTH_ECDSA_256:
case AUTH_ECDSA_384:
case AUTH_ECDSA_521:
- return (authenticator_t*)pubkey_authenticator_create(ike_sa);
+ return (authenticator_t*)pubkey_authenticator_create_verifier(ike_sa,
+ sent_nonce, received_init);
case AUTH_PSK:
- return (authenticator_t*)psk_authenticator_create(ike_sa);
+ return (authenticator_t*)psk_authenticator_create_verifier(ike_sa,
+ sent_nonce, received_init);
default:
return NULL;
}
}
+
diff --git a/src/charon/sa/authenticators/authenticator.h b/src/charon/sa/authenticators/authenticator.h
index cd42191e6..db3f110ca 100644
--- a/src/charon/sa/authenticators/authenticator.h
+++ b/src/charon/sa/authenticators/authenticator.h
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -30,9 +30,8 @@ typedef enum auth_class_t auth_class_t;
typedef struct authenticator_t authenticator_t;
#include <library.h>
+#include <config/auth_cfg.h>
#include <sa/ike_sa.h>
-#include <config/peer_cfg.h>
-#include <encoding/payloads/auth_payload.h>
/**
* Method to use for authentication, as defined in IKEv2.
@@ -84,6 +83,8 @@ extern enum_name_t *auth_method_names;
* certificate finally dictates wich method is used.
*/
enum auth_class_t {
+ /** any class acceptable */
+ AUTH_CLASS_ANY = 0,
/** authentication using public keys (RSA, ECDSA) */
AUTH_CLASS_PUBKEY = 1,
/** authentication using a pre-shared secrets */
@@ -100,66 +101,64 @@ extern enum_name_t *auth_class_names;
/**
* Authenticator interface implemented by the various authenticators.
*
- * Currently the following two AUTH methods are supported:
- * - shared key message integrity code
- * - RSA digital signature
- * - EAP using the EAP framework and one of the EAP plugins
- * - ECDSA is supported using OpenSSL
+ * An authenticator implementation handles AUTH and EAP payloads. Received
+ * messages are passed to the process() method, to send authentication data
+ * the message is passed to the build() method.
*/
struct authenticator_t {
/**
- * Verify a received authentication payload.
+ * Process an incoming message using the authenticator.
*
- * @param ike_sa_init binary representation of received ike_sa_init
- * @param my_nonce the sent nonce
- * @param auth_payload authentication payload to verify
+ * @param message message containing authentication payloads
* @return
- * - SUCCESS,
- * - FAILED if verification failed
- * - INVALID_ARG if auth_method does not match
- * - NOT_FOUND if credentials not found
+ * - SUCCESS if authentication successful
+ * - FAILED if authentication failed
+ * - NEED_MORE if another exchange required
*/
- status_t (*verify) (authenticator_t *this, chunk_t ike_sa_init,
- chunk_t my_nonce, auth_payload_t *auth_payload);
-
+ status_t (*process)(authenticator_t *this, message_t *message);
+
/**
- * Build an authentication payload to send to the other peer.
+ * Attach authentication data to an outgoing message.
*
- * @param ike_sa_init binary representation of sent ike_sa_init
- * @param other_nonce the received nonce
- * @param auth_payload the resulting authentication payload
+ * @param message message to add authentication data to
* @return
- * - SUCCESS,
- * - NOT_FOUND if credentials not found
+ * - SUCCESS if authentication successful
+ * - FAILED if authentication failed
+ * - NEED_MORE if another exchange required
*/
- status_t (*build) (authenticator_t *this, chunk_t ike_sa_init,
- chunk_t other_nonce, auth_payload_t **auth_payload);
-
+ status_t (*build)(authenticator_t *this, message_t *message);
+
/**
- * Destroys a authenticator_t object.
+ * Destroy authenticator instance.
*/
void (*destroy) (authenticator_t *this);
};
/**
- * Creates an authenticator for the specified auth class (as configured).
+ * Create an authenticator to build signatures.
*
- * @param ike_sa associated ike_sa
- * @param class class of authentication to use
- * @return authenticator_t object
+ * @param ike_sa associated ike_sa
+ * @param cfg authentication configuration
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return authenticator, NULL if not supported
*/
-authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa,
- auth_class_t class);
+authenticator_t *authenticator_create_builder(
+ ike_sa_t *ike_sa, auth_cfg_t *cfg,
+ chunk_t received_nonce, chunk_t sent_init);
/**
- * Creates an authenticator for method (as received in payload).
+ * Create an authenticator to verify signatures.
*
- * @param ike_sa associated ike_sa
- * @param method method as found in payload
- * @return authenticator_t object
+ * @param ike_sa associated ike_sa
+ * @param message message containing authentication data
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @return authenticator, NULL if not supported
*/
-authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa,
- auth_method_t method);
+authenticator_t *authenticator_create_verifier(
+ ike_sa_t *ike_sa, message_t *message,
+ chunk_t sent_nonce, chunk_t received_init);
#endif /** AUTHENTICATOR_H_ @}*/
diff --git a/src/charon/sa/authenticators/eap/eap_manager.c b/src/charon/sa/authenticators/eap/eap_manager.c
index 578d302ea..ecb46c293 100644
--- a/src/charon/sa/authenticators/eap/eap_manager.c
+++ b/src/charon/sa/authenticators/eap/eap_manager.c
@@ -65,9 +65,9 @@ struct private_eap_manager_t {
linked_list_t *methods;
/**
- * mutex to lock methods
+ * rwlock to lock methods
*/
- mutex_t *mutex;
+ rwlock_t *lock;
};
/**
@@ -84,9 +84,9 @@ static void add_method(private_eap_manager_t *this, eap_type_t type,
entry->role = role;
entry->constructor = constructor;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
this->methods->insert_last(this->methods, entry);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -97,7 +97,7 @@ static void remove_method(private_eap_manager_t *this, eap_constructor_t constru
enumerator_t *enumerator;
eap_entry_t *entry;
- this->mutex->lock(this->mutex);
+ this->lock->write_lock(this->lock);
enumerator = this->methods->create_enumerator(this->methods);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -108,7 +108,7 @@ static void remove_method(private_eap_manager_t *this, eap_constructor_t constru
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
}
/**
@@ -123,7 +123,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
eap_entry_t *entry;
eap_method_t *method = NULL;
- this->mutex->lock(this->mutex);
+ this->lock->read_lock(this->lock);
enumerator = this->methods->create_enumerator(this->methods);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -138,7 +138,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
}
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
+ this->lock->unlock(this->lock);
return method;
}
@@ -148,7 +148,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
static void destroy(private_eap_manager_t *this)
{
this->methods->destroy_function(this->methods, free);
- this->mutex->destroy(this->mutex);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -165,7 +165,7 @@ eap_manager_t *eap_manager_create()
this->public.destroy = (void(*)(eap_manager_t*))destroy;
this->methods = linked_list_create();
- this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
return &this->public;
}
diff --git a/src/charon/sa/authenticators/eap/eap_method.c b/src/charon/sa/authenticators/eap/eap_method.c
index d27a8ac2f..9aef352e2 100644
--- a/src/charon/sa/authenticators/eap/eap_method.c
+++ b/src/charon/sa/authenticators/eap/eap_method.c
@@ -36,6 +36,36 @@ ENUM_NEXT(eap_type_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
"EAP_EXPERIMENTAL");
ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
+/*
+ * See header
+ */
+eap_type_t eap_type_from_string(char *name)
+{
+ int i;
+ static struct {
+ char *name;
+ eap_type_t type;
+ } types[] = {
+ {"identity", EAP_IDENTITY},
+ {"md5", EAP_MD5},
+ {"otp", EAP_OTP},
+ {"gtc", EAP_GTC},
+ {"sim", EAP_SIM},
+ {"aka", EAP_AKA},
+ {"mschapv2", EAP_MSCHAPV2},
+ {"radius", EAP_RADIUS},
+ };
+
+ for (i = 0; i < countof(types); i++)
+ {
+ if (strcasecmp(name, types[i].name) == 0)
+ {
+ return types[i].type;
+ }
+ }
+ return 0;
+}
+
ENUM(eap_code_names, EAP_REQUEST, EAP_FAILURE,
"EAP_REQUEST",
"EAP_RESPONSE",
@@ -48,3 +78,6 @@ ENUM(eap_role_names, EAP_SERVER, EAP_PEER,
"EAP_PEER",
);
+
+
+
diff --git a/src/charon/sa/authenticators/eap/eap_method.h b/src/charon/sa/authenticators/eap/eap_method.h
index 1aa6162ee..43a336ada 100644
--- a/src/charon/sa/authenticators/eap/eap_method.h
+++ b/src/charon/sa/authenticators/eap/eap_method.h
@@ -69,6 +69,14 @@ enum eap_type_t {
extern enum_name_t *eap_type_names;
/**
+ * Lookup the EAP method type from a string.
+ *
+ * @param name EAP method name (such as "md5", "aka")
+ * @return method type, 0 if unkown
+ */
+eap_type_t eap_type_from_string(char *name);
+
+/**
* EAP code, type of an EAP message
*/
enum eap_code_t {
@@ -83,7 +91,6 @@ enum eap_code_t {
*/
extern enum_name_t *eap_code_names;
-
/**
* Interface of an EAP method for server and client side.
*
diff --git a/src/charon/sa/authenticators/eap/sim_manager.h b/src/charon/sa/authenticators/eap/sim_manager.h
index 69a2e4df9..3c6d66dfe 100644
--- a/src/charon/sa/authenticators/eap/sim_manager.h
+++ b/src/charon/sa/authenticators/eap/sim_manager.h
@@ -39,7 +39,7 @@ struct sim_card_t {
* The returned identity owned by the sim_card and not destroyed outside.
* The SIM card may return ID_ANY if it does not support/use an IMSI.
*
- * @return identity of type ID_EAP/ID_ANY
+ * @return identity
*/
identification_t* (*get_imsi)(sim_card_t *this);
@@ -63,7 +63,7 @@ struct sim_provider_t {
/**
* Get a single triplet to authenticate a EAP client.
*
- * @param imsi client identity of type ID_EAP
+ * @param imsi client identity
* @param rand RAND output buffer, fixed size 16 bytes
* @param sres SRES output buffer, fixed size 4 byte
* @param kc KC output buffer, fixed size 8 bytes
diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c
index 9d7113fd2..876cb7b74 100644
--- a/src/charon/sa/authenticators/eap_authenticator.c
+++ b/src/charon/sa/authenticators/eap_authenticator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Martin Willi
+ * Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,13 +15,12 @@
* $Id$
*/
-#include <string.h>
-
#include "eap_authenticator.h"
#include <daemon.h>
-#include <config/peer_cfg.h>
#include <sa/authenticators/eap/eap_method.h>
+#include <encoding/payloads/auth_payload.h>
+#include <encoding/payloads/eap_payload.h>
typedef struct private_eap_authenticator_t private_eap_authenticator_t;
@@ -41,9 +40,14 @@ struct private_eap_authenticator_t {
ike_sa_t *ike_sa;
/**
- * Role of this authenticator, PEER or SERVER
+ * nonce to include in AUTH calculation
*/
- eap_role_t role;
+ chunk_t nonce;
+
+ /**
+ * IKE_SA_INIT message data to include in AUTH calculation
+ */
+ chunk_t ike_sa_init;
/**
* Current EAP method processing
@@ -56,442 +60,509 @@ struct private_eap_authenticator_t {
chunk_t msk;
/**
- * should we do a EAP-Identity exchange as server?
+ * EAP authentication method completed successfully
*/
- bool do_eap_identity;
+ bool eap_complete;
/**
- * saved EAP type if we do eap_identity
+ * authentication payload verified successfully
*/
- eap_type_t type;
+ bool auth_complete;
/**
- * saved vendor id if we do eap_identity
+ * generated EAP payload
*/
- u_int32_t vendor;
+ eap_payload_t *eap_payload;
+
+ /**
+ * EAP identity of peer
+ */
+ identification_t *eap_identity;
};
+
/**
- * Implementation of authenticator_t.verify.
+ * load an EAP method
*/
-static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
- chunk_t my_nonce, auth_payload_t *auth_payload)
+static eap_method_t *load_method(private_eap_authenticator_t *this,
+ eap_type_t type, u_int32_t vendor, eap_role_t role)
{
- chunk_t auth_data, recv_auth_data;
- identification_t *other_id;
- keymat_t *keymat;
-
- other_id = this->ike_sa->get_other_id(this->ike_sa);
- keymat = this->ike_sa->get_keymat(this->ike_sa);
-
- auth_data = keymat->get_psk_sig(keymat, TRUE, ike_sa_init, my_nonce,
- this->msk, other_id);
+ identification_t *server, *peer;
- recv_auth_data = auth_payload->get_data(auth_payload);
- if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
+ if (role == EAP_SERVER)
{
- DBG1(DBG_IKE, "verification of AUTH payload created from EAP MSK failed");
- chunk_free(&auth_data);
- return FAILED;
+ server = this->ike_sa->get_my_id(this->ike_sa);
+ peer = this->ike_sa->get_other_id(this->ike_sa);
}
- chunk_free(&auth_data);
-
- DBG1(DBG_IKE, "authentication of '%D' with %N successful",
- other_id, auth_class_names, AUTH_CLASS_EAP);
- return SUCCESS;
-}
-
-/**
- * Implementation of authenticator_t.build.
- */
-static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init,
- chunk_t other_nonce, auth_payload_t **auth_payload)
-{
- identification_t *my_id;
- chunk_t auth_data;
- keymat_t *keymat;
-
- my_id = this->ike_sa->get_my_id(this->ike_sa);
- keymat = this->ike_sa->get_keymat(this->ike_sa);
-
- DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
- my_id, auth_class_names, AUTH_CLASS_EAP);
-
- auth_data = keymat->get_psk_sig(keymat, FALSE, ike_sa_init, other_nonce,
- this->msk, my_id);
-
- *auth_payload = auth_payload_create();
- (*auth_payload)->set_auth_method(*auth_payload, AUTH_PSK);
- (*auth_payload)->set_data(*auth_payload, auth_data);
- chunk_free(&auth_data);
-
- return SUCCESS;
+ else
+ {
+ server = this->ike_sa->get_other_id(this->ike_sa);
+ peer = this->ike_sa->get_my_id(this->ike_sa);
+ }
+ if (this->eap_identity)
+ {
+ peer = this->eap_identity;
+ }
+ return charon->eap->create_instance(charon->eap, type, vendor,
+ role, server, peer);
}
/**
- * get the peers identity to use in the EAP method
+ * Initiate EAP conversation as server
*/
-static identification_t *get_peer_id(private_eap_authenticator_t *this)
+static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
+ bool do_identity)
{
+ auth_cfg_t *auth;
+ eap_type_t type;
identification_t *id;
- peer_cfg_t *config;
- auth_info_t *auth;
+ u_int32_t vendor;
+ eap_payload_t *out;
- id = this->ike_sa->get_eap_identity(this->ike_sa);
- if (!id)
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+
+ /* initiate EAP-Identity exchange if required */
+ if (!this->eap_identity && do_identity)
{
- config = this->ike_sa->get_peer_cfg(this->ike_sa);
- auth = config->get_auth(config);
- if (!auth->get_item(auth, AUTHN_EAP_IDENTITY, (void**)&id) ||
- id->get_type(id) == ID_ANY)
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (id)
{
- if (this->role == EAP_PEER)
- {
- id = this->ike_sa->get_my_id(this->ike_sa);
- }
- else
+ this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
+ if (this->method)
{
- id = this->ike_sa->get_other_id(this->ike_sa);
+ if (this->method->initiate(this->method, &out) == NEED_MORE)
+ {
+ DBG1(DBG_IKE, "initiating EAP-Identity request");
+ return out;
+ }
+ this->method->destroy(this->method);
}
+ DBG1(DBG_IKE, "EAP-Identity request configured, but not supported");
}
}
- if (id->get_type(id) == ID_EAP)
+ /* invoke real EAP method */
+ type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
+ vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
+ this->method = load_method(this, type, vendor, EAP_SERVER);
+ if (this->method &&
+ this->method->initiate(this->method, &out) == NEED_MORE)
{
- return id->clone(id);
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "initiating EAP vendor type %d-%d", type, vendor);
+
+ }
+ else
+ {
+ DBG1(DBG_IKE, "initiating %N", eap_type_names, type);
+ }
+ return out;
}
- return identification_create_from_encoding(ID_EAP, id->get_encoding(id));
-}
-
-/**
- * get the servers identity to use in the EAP method
- */
-static identification_t *get_server_id(private_eap_authenticator_t *this)
-{
- identification_t *id;
-
- if (this->role == EAP_SERVER)
+ if (vendor)
{
- id = this->ike_sa->get_my_id(this->ike_sa);
+ DBG1(DBG_IKE, "initiating EAP vendor type %d-%d failed", type, vendor);
}
else
{
- id = this->ike_sa->get_other_id(this->ike_sa);
- }
- if (id->get_type(id) == ID_EAP)
- {
- return id->clone(id);
+ DBG1(DBG_IKE, "initiating %N failed", eap_type_names, type);
}
- return identification_create_from_encoding(ID_EAP, id->get_encoding(id));
+ return eap_payload_create_code(EAP_FAILURE, 0);
}
/**
- * load an EAP method using the correct identities
+ * Handle EAP exchange as server
*/
-static eap_method_t *load_method(private_eap_authenticator_t *this,
- eap_type_t type, u_int32_t vendor, eap_role_t role)
+static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
+ eap_payload_t *in)
{
- identification_t *server, *peer;
- eap_method_t *method;
+ eap_type_t type, received_type;
+ u_int32_t vendor, received_vendor;
+ eap_payload_t *out;
+ auth_cfg_t *cfg;
- server = get_server_id(this);
- peer = get_peer_id(this);
- method = charon->eap->create_instance(charon->eap, type, vendor, role,
- server, peer);
- server->destroy(server);
- peer->destroy(peer);
- return method;
-}
-
-/**
- * Implementation of eap_authenticator_t.initiate
- */
-static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
- u_int32_t vendor, eap_payload_t **out)
-{
- /* if initiate() is called, role is always server */
- this->role = EAP_SERVER;
-
- if (this->do_eap_identity)
- { /* do an EAP-Identity request first */
- this->type = type;
- this->vendor = vendor;
- vendor = 0;
- type = EAP_IDENTITY;
- }
-
- if (type == 0)
+ if (in->get_code(in) != EAP_RESPONSE)
{
- DBG1(DBG_IKE,
- "client requested EAP authentication, but configuration forbids it");
- *out = eap_payload_create_code(EAP_FAILURE, 0);
- return FAILED;
+ DBG1(DBG_IKE, "received %N, sending %N",
+ eap_code_names, in->get_code(in), eap_code_names, EAP_FAILURE);
+ return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
}
- if (vendor)
- {
- DBG1(DBG_IKE, "requesting vendor specific EAP method %d-%d",
- type, vendor);
- }
- else
- {
- DBG1(DBG_IKE, "requesting EAP method %N", eap_type_names, type);
- }
- this->method = load_method(this, type, vendor, this->role);
- if (this->method == NULL)
+ type = this->method->get_type(this->method, &vendor);
+ received_type = in->get_type(in, &received_vendor);
+ if (type != received_type || vendor != received_vendor)
{
- if (vendor == 0 && type == EAP_IDENTITY)
+ if (received_vendor == 0 && received_type == EAP_NAK)
{
- DBG1(DBG_IKE, "skipping %N, no implementation found",
- eap_type_names, type);
- this->do_eap_identity = FALSE;
- return initiate(this, this->type, this->vendor, out);
+ DBG1(DBG_IKE, "received %N, sending %N",
+ eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE);
}
- DBG1(DBG_IKE, "configured EAP server method not supported, sending %N",
- eap_code_names, EAP_FAILURE);
- *out = eap_payload_create_code(EAP_FAILURE, 0);
- return FAILED;
+ else
+ {
+ DBG1(DBG_IKE, "received invalid EAP response, sending %N",
+ eap_code_names, EAP_FAILURE);
+ }
+ return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
}
- if (this->method->initiate(this->method, out) != NEED_MORE)
+
+ switch (this->method->process(this->method, in, &out))
{
- DBG1(DBG_IKE, "failed to initiate EAP exchange, sending %N",
- eap_code_names, EAP_FAILURE);
- *out = eap_payload_create_code(EAP_FAILURE, 0);
- return FAILED;
+ case NEED_MORE:
+ return out;
+ case SUCCESS:
+ if (type == EAP_IDENTITY)
+ {
+ chunk_t data;
+ char buf[256];
+
+ if (this->method->get_msk(this->method, &data) == SUCCESS)
+ {
+ snprintf(buf, sizeof(buf), "%.*s", data.len, data.ptr);
+ this->eap_identity = identification_create_from_string(buf);
+ DBG1(DBG_IKE, "received EAP identity '%D'",
+ this->eap_identity);
+ }
+ /* restart EAP exchange, but with real method */
+ this->method->destroy(this->method);
+ return server_initiate_eap(this, FALSE);
+ }
+ if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
+ {
+ this->msk = chunk_clone(this->msk);
+ }
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
+ "%sMSK established", type, vendor,
+ this->msk.ptr ? "" : "no ");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
+ eap_type_names, type, this->msk.ptr ? "" : "no ");
+ }
+ this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED,
+ TRUE);
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
+ if (vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
+ }
+ this->eap_complete = TRUE;
+ return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
+ case FAILED:
+ default:
+ if (vendor)
+ {
+ DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for "
+ "peer %D", type, vendor,
+ this->ike_sa->get_other_id(this->ike_sa));
+ }
+ else
+ {
+ DBG1(DBG_IKE, "EAP method %N failed for peer %D",
+ eap_type_names, type,
+ this->ike_sa->get_other_id(this->ike_sa));
+ }
+ return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
}
- return NEED_MORE;
}
/**
* Processing method for a peer
*/
-static status_t process_peer(private_eap_authenticator_t *this,
- eap_payload_t *in, eap_payload_t **out)
+static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
+ eap_payload_t *in)
{
eap_type_t type;
u_int32_t vendor;
+ auth_cfg_t *auth;
+ eap_payload_t *out;
+ identification_t *id;
type = in->get_type(in, &vendor);
if (!vendor && type == EAP_IDENTITY)
{
- eap_method_t *method;
+ DESTROY_IF(this->eap_identity);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
+ if (!id || id->get_type(id) == ID_ANY)
+ {
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ }
+ DBG1(DBG_IKE, "server requested %N, sending '%D'",
+ eap_type_names, type, id);
+ this->eap_identity = id->clone(id);
- method = load_method(this, type, 0, EAP_PEER);
- if (method == NULL || method->process(method, in, out) != SUCCESS)
+ this->method = load_method(this, type, vendor, EAP_PEER);
+ if (this->method)
{
- DBG1(DBG_IKE, "EAP server requested %N, but unable to process",
- eap_type_names, type);
- DESTROY_IF(method);
- return FAILED;
+ if (this->method->process(this->method, in, &out) == SUCCESS)
+ {
+ this->method->destroy(this->method);
+ this->method = NULL;
+ return out;
+ }
+ this->method->destroy(this->method);
+ this->method = NULL;
}
- DBG1(DBG_IKE, "EAP server requested %N", eap_type_names, type);
- method->destroy(method);
- return NEED_MORE;
+ DBG1(DBG_IKE, "%N not supported, sending EAP_NAK",
+ eap_type_names, type);
+ return eap_payload_create_nak(in->get_identifier(in));
}
-
- /* create an eap_method for the first call */
if (this->method == NULL)
{
if (vendor)
{
- DBG1(DBG_IKE, "EAP server requested vendor specific EAP method %d-%d",
+ DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d",
type, vendor);
}
else
{
- DBG1(DBG_IKE, "EAP server requested %N authentication",
+ DBG1(DBG_IKE, "server requested %N authentication",
eap_type_names, type);
}
this->method = load_method(this, type, vendor, EAP_PEER);
- if (this->method == NULL)
+ if (!this->method)
{
- DBG1(DBG_IKE, "EAP server requested unsupported "
- "EAP method, sending EAP_NAK");
- *out = eap_payload_create_nak(in->get_identifier(in));
- return NEED_MORE;
+ DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK");
+ return eap_payload_create_nak(in->get_identifier(in));
}
}
type = this->method->get_type(this->method, &vendor);
- switch (this->method->process(this->method, in, out))
+ if (this->method->process(this->method, in, &out) == NEED_MORE)
+ { /* client methods should never return SUCCESS */
+ return out;
+ }
+
+ if (vendor)
{
- case NEED_MORE:
- return NEED_MORE;
- case SUCCESS:
- if (vendor)
- {
- DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeded",
- type, vendor);
- }
- else
- {
- DBG1(DBG_IKE, "EAP method %N succeeded", eap_type_names, type);
- }
- return SUCCESS;
- case FAILED:
- default:
- if (vendor)
- {
- DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed",
- type, vendor);
- }
- else
- {
- DBG1(DBG_IKE, "EAP method %N failed",
- eap_type_names, type);
- }
- return FAILED;
+ DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", type, vendor);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
}
+ return NULL;
}
/**
- * handle an EAP-Identity response on the server
+ * Verify AUTH payload
*/
-static status_t process_eap_identity(private_eap_authenticator_t *this,
- eap_payload_t **out)
+static bool verify_auth(private_eap_authenticator_t *this, message_t *message)
{
- chunk_t data;
- identification_t *id;
-
- if (this->method->get_msk(this->method, &data) == SUCCESS)
+ auth_payload_t *auth_payload;
+ chunk_t auth_data, recv_auth_data;
+ identification_t *other_id;
+ auth_cfg_t *auth;
+ keymat_t *keymat;
+
+ auth_payload = (auth_payload_t*)message->get_payload(message,
+ AUTHENTICATION);
+ if (!auth_payload)
{
- id = identification_create_from_encoding(ID_EAP, data);
- DBG1(DBG_IKE, "using EAP identity '%D'", id);
- this->ike_sa->set_eap_identity(this->ike_sa, id);
+ DBG1(DBG_IKE, "AUTH payload missing");
+ return FALSE;
}
- /* restart EAP exchange, but with real method */
- this->method->destroy(this->method);
- this->method = NULL;
- this->do_eap_identity = FALSE;
- return initiate(this, this->type, this->vendor, out);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ auth_data = keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init,
+ this->nonce, this->msk, other_id);
+ recv_auth_data = auth_payload->get_data(auth_payload);
+ if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
+ {
+ DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
+ this->msk.ptr ? "" : "out");
+ chunk_free(&auth_data);
+ return FALSE;
+ }
+ chunk_free(&auth_data);
+
+ DBG1(DBG_IKE, "authentication of '%D' with %N successful",
+ other_id, auth_class_names, AUTH_CLASS_EAP);
+ this->auth_complete = TRUE;
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+ return TRUE;
+}
+
+/**
+ * Build AUTH payload
+ */
+static void build_auth(private_eap_authenticator_t *this, message_t *message)
+{
+ auth_payload_t *auth_payload;
+ identification_t *my_id;
+ chunk_t auth_data;
+ keymat_t *keymat;
+
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+
+ DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
+ my_id, auth_class_names, AUTH_CLASS_EAP);
+
+ auth_data = keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init,
+ this->nonce, this->msk, my_id);
+ auth_payload = auth_payload_create();
+ auth_payload->set_auth_method(auth_payload, AUTH_PSK);
+ auth_payload->set_data(auth_payload, auth_data);
+ message->add_payload(message, (payload_t*)auth_payload);
+ chunk_free(&auth_data);
}
/**
- * Processing method for a server
+ * Implementation of authenticator_t.process for a server
*/
static status_t process_server(private_eap_authenticator_t *this,
- eap_payload_t *in, eap_payload_t **out)
+ message_t *message)
{
- eap_type_t type;
- u_int32_t vendor;
+ eap_payload_t *eap_payload;
- type = this->method->get_type(this->method, &vendor);
+ if (this->eap_complete)
+ {
+ if (!verify_auth(this, message))
+ {
+ return FAILED;
+ }
+ return NEED_MORE;
+ }
- switch (this->method->process(this->method, in, out))
+ if (!this->method)
{
- case NEED_MORE:
- return NEED_MORE;
- case SUCCESS:
- if (this->do_eap_identity)
- {
- return process_eap_identity(this, out);
- }
- if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
- {
- this->msk = chunk_clone(this->msk);
- }
- if (vendor)
- {
- DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeded, "
- "%sMSK established", type, vendor,
- this->msk.ptr ? "" : "no ");
- }
- else
- {
- DBG1(DBG_IKE, "EAP method %N succeded, %sMSK established",
- eap_type_names, type, this->msk.ptr ? "" : "no ");
- }
- *out = eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
- return SUCCESS;
- case FAILED:
- default:
- if (vendor)
- {
- DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for "
- "peer %D", type, vendor,
- this->ike_sa->get_other_id(this->ike_sa));
- }
- else
- {
- DBG1(DBG_IKE, "EAP method %N failed for peer '%D'",
- eap_type_names, type,
- this->ike_sa->get_other_id(this->ike_sa));
- }
- *out = eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
+ this->eap_payload = server_initiate_eap(this, TRUE);
+ }
+ else
+ {
+ eap_payload = (eap_payload_t*)message->get_payload(message,
+ EXTENSIBLE_AUTHENTICATION);
+ if (!eap_payload)
+ {
return FAILED;
+ }
+ this->eap_payload = server_process_eap(this, eap_payload);
}
+ return NEED_MORE;
}
/**
- * Implementation of eap_authenticator_t.process
+ * Implementation of authenticator_t.build for a server
*/
-static status_t process(private_eap_authenticator_t *this, eap_payload_t *in,
- eap_payload_t **out)
+static status_t build_server(private_eap_authenticator_t *this,
+ message_t *message)
{
- eap_code_t code = in->get_code(in);
+ if (this->eap_payload)
+ {
+ eap_code_t code;
+
+ code = this->eap_payload->get_code(this->eap_payload);
+ message->add_payload(message, (payload_t*)this->eap_payload);
+ this->eap_payload = NULL;
+ if (code == EAP_FAILURE)
+ {
+ return FAILED;
+ }
+ return NEED_MORE;
+ }
+ if (this->eap_complete && this->auth_complete)
+ {
+ build_auth(this, message);
+ return SUCCESS;
+ }
+ return FAILED;
+}
+
+/**
+ * Implementation of authenticator_t.process for a client
+ */
+static status_t process_client(private_eap_authenticator_t *this,
+ message_t *message)
+{
+ eap_payload_t *eap_payload;
- switch (this->role)
+ if (this->eap_complete)
{
- case EAP_SERVER:
+ if (!verify_auth(this, message))
{
- switch (code)
- {
- case EAP_RESPONSE:
- {
- return process_server(this, in, out);
- }
- default:
- {
- DBG1(DBG_IKE, "received %N, sending %N",
- eap_code_names, code, eap_code_names, EAP_FAILURE);
- *out = eap_payload_create_code(EAP_FAILURE,
- in->get_identifier(in));
- return FAILED;
- }
- }
+ return FAILED;
}
- case EAP_PEER:
+ return SUCCESS;
+ }
+
+ eap_payload = (eap_payload_t*)message->get_payload(message,
+ EXTENSIBLE_AUTHENTICATION);
+ if (eap_payload)
+ {
+ switch (eap_payload->get_code(eap_payload))
{
- switch (code)
+ case EAP_REQUEST:
+ {
+ this->eap_payload = client_process_eap(this, eap_payload);
+ return NEED_MORE;
+ }
+ case EAP_SUCCESS:
{
- case EAP_REQUEST:
+ eap_type_t type;
+ u_int32_t vendor;
+ auth_cfg_t *cfg;
+
+ if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
{
- return process_peer(this, in, out);
+ this->msk = chunk_clone(this->msk);
}
- case EAP_SUCCESS:
+ type = this->method->get_type(this->method, &vendor);
+ if (vendor)
{
- if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
- {
- this->msk = chunk_clone(this->msk);
- }
- return SUCCESS;
+ DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
+ "%sMSK established", type, vendor,
+ this->msk.ptr ? "" : "no ");
}
- case EAP_FAILURE:
- default:
+ else
{
- DBG1(DBG_IKE, "received %N, EAP authentication failed",
- eap_code_names, code);
- return FAILED;
+ DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
+ eap_type_names, type, this->msk.ptr ? "" : "no ");
}
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
+ if (vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
+ }
+ this->eap_complete = TRUE;
+ return NEED_MORE;
+ }
+ case EAP_FAILURE:
+ default:
+ {
+ DBG1(DBG_IKE, "received %N, EAP authentication failed",
+ eap_code_names, eap_payload->get_code(eap_payload));
+ return FAILED;
}
- }
- default:
- {
- return FAILED;
}
}
+ return FAILED;
}
/**
- * Implementation of authenticator_t.is_mutual.
+ * Implementation of authenticator_t.build for a client
*/
-static bool is_mutual(private_eap_authenticator_t *this)
+static status_t build_client(private_eap_authenticator_t *this,
+ message_t *message)
{
- if (this->method)
+ if (this->eap_payload)
{
- return this->method->is_mutual(this->method);
+ message->add_payload(message, (payload_t*)this->eap_payload);
+ this->eap_payload = NULL;
+ return NEED_MORE;
}
- return FALSE;
+ if (this->eap_complete)
+ {
+ build_auth(this, message);
+ return NEED_MORE;
+ }
+ return NEED_MORE;
}
/**
@@ -500,6 +571,8 @@ static bool is_mutual(private_eap_authenticator_t *this)
static void destroy(private_eap_authenticator_t *this)
{
DESTROY_IF(this->method);
+ DESTROY_IF(this->eap_payload);
+ DESTROY_IF(this->eap_identity);
chunk_free(&this->msk);
free(this);
}
@@ -507,46 +580,50 @@ static void destroy(private_eap_authenticator_t *this)
/*
* Described in header.
*/
-eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa)
+eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init)
{
- peer_cfg_t *config;
- auth_info_t *auth;
- identification_t *id;
private_eap_authenticator_t *this = malloc_thing(private_eap_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;
-
- this->public.is_mutual = (bool(*)(eap_authenticator_t*))is_mutual;
- this->public.initiate = (status_t(*)(eap_authenticator_t*,eap_type_t,u_int32_t,eap_payload_t**))initiate;
- this->public.process = (status_t(*)(eap_authenticator_t*,eap_payload_t*,eap_payload_t**))process;
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build_client;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process_client;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
- /* private data */
this->ike_sa = ike_sa;
- this->role = EAP_PEER;
+ this->ike_sa_init = sent_init;
+ this->nonce = received_nonce;
+ this->msk = chunk_empty;
this->method = NULL;
+ this->eap_payload = NULL;
+ this->eap_complete = FALSE;
+ this->auth_complete = FALSE;
+ this->eap_identity = NULL;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init)
+{
+ private_eap_authenticator_t *this = malloc_thing(private_eap_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))build_server;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process_server;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->ike_sa_init = received_init;
+ this->nonce = sent_nonce;
this->msk = chunk_empty;
- this->do_eap_identity = FALSE;
- this->type = 0;
- this->vendor = 0;
+ this->method = NULL;
+ this->eap_payload = NULL;
+ this->eap_complete = FALSE;
+ this->auth_complete = FALSE;
+ this->eap_identity = NULL;
- config = ike_sa->get_peer_cfg(ike_sa);
- if (config)
- {
- auth = config->get_auth(config);
- if (auth->get_item(auth, AUTHN_EAP_IDENTITY, (void**)&id))
- {
- if (id->get_type(id) == ID_ANY)
- { /* %any as configured EAP identity runs EAP-Identity first */
- this->do_eap_identity = TRUE;
- }
- else
- {
- ike_sa->set_eap_identity(ike_sa, id->clone(id));
- }
- }
- }
return &this->public;
}
+
diff --git a/src/charon/sa/authenticators/eap_authenticator.h b/src/charon/sa/authenticators/eap_authenticator.h
index 0aaa07f35..ac01647b1 100644
--- a/src/charon/sa/authenticators/eap_authenticator.h
+++ b/src/charon/sa/authenticators/eap_authenticator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Martin Willi
+ * Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,21 +26,13 @@
typedef struct eap_authenticator_t eap_authenticator_t;
#include <sa/authenticators/authenticator.h>
-#include <encoding/payloads/eap_payload.h>
/**
- * Implementation of the authenticator_t interface using AUTH_CLASS_EAP.
+ * Implementation of authenticator_t using EAP authentication.
*
* Authentication using EAP involves the most complex authenticator. It stays
* alive over multiple ike_auth transactions and handles multiple EAP
* messages.
- * EAP authentication must be clearly distinguished between using
- * mutual EAP methods and using methods not providing server authentication.
- * If no mutual authentication is used, the server must prove it's identity
- * by traditional AUTH methods (RSA, psk). Only when the EAP method is mutual,
- * the client should accept an EAP-only authentication.
- * RFC4306 does always use traditional authentiction, EAP only authentication
- * is described in the internet draft draft-eronen-ipsec-ikev2-eap-auth-05.txt.
*
* @verbatim
ike_sa_init
@@ -49,12 +41,12 @@ typedef struct eap_authenticator_t eap_authenticator_t;
followed by multiple ike_auth:
+--------+ +--------+
- | EAP | ID, SA, TS, N(EAP_ONLY) | EAP |
+ | EAP | IDi, [IDr,] SA, TS | EAP |
| client | ---------------------------> | server |
- | | ID, [AUTH,] EAP | | AUTH payload is
- | | <--------------------------- | | only included if
- | | EAP | | authentication
- | | ---------------------------> | | is not mutual.
+ | | ID, AUTH, EAP | |
+ | | <--------------------------- | |
+ | | EAP | |
+ | | ---------------------------> | |
| | EAP | |
| | <--------------------------- | |
| | EAP | |
@@ -74,74 +66,29 @@ struct eap_authenticator_t {
/**
* Implemented authenticator_t interface.
*/
- authenticator_t authenticator_interface;
-
- /**
- * 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
- * provide mutual authentication, which would result in a redundant
- * authentication. If the client supports EAP_ONLY_AUTHENTICATION, and
- * the the server provides mutual authentication, authentication using
- * RSA/PSK may be omitted. If the server did not include a traditional
- * AUTH payload, the client must verify that the server initiated mutual
- * EAP authentication before it can trust the server.
- *
- * @return TRUE, if no AUTH payload required, FALSE otherwise
- */
- bool (*is_mutual) (eap_authenticator_t* this);
-
- /**
- * 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 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
- * @return
- * - FAILED, if initiation failed
- * - NEED_MORE, if more EAP exchanges reqired
- */
- status_t (*initiate) (eap_authenticator_t* this, eap_type_t type,
- u_int32_t vendor, eap_payload_t **out);
-
- /**
- * Process an EAP message.
- *
- * After receiving an EAP message "in", the peer/server processes
- * the payload and creates a reply/subsequent request.
- * The server side always returns NEED_MORE if another EAP message
- * is expected from the client, SUCCESS if EAP exchange completed and
- * "out" is EAP_SUCCES, or FAILED if the EAP exchange failed with
- * a EAP_FAILURE payload in "out". Anyway, a payload in "out" is always
- * created.
- * The peer (client) side only creates a "out" payload if result is
- * NEED_MORE, a SUCCESS/FAILED is returned whenever a
- * EAP_SUCCESS/EAP_FAILURE message is received in "in".
- * If a SUCCESS is returned (on any side), the EAP authentication was
- * successful and the AUTH payload can be exchanged.
- *
- * @param in received EAP message
- * @param out created EAP message to send
- * @return
- * - FAILED, if authentication/EAP exchange failed
- * - SUCCESS, if authentication completed
- * - NEED_MORE, if more EAP exchanges reqired
- */
- status_t (*process) (eap_authenticator_t* this,
- eap_payload_t *in, eap_payload_t **out);
+ authenticator_t authenticator;
};
/**
- * Creates an authenticator for AUTH_CLASS_EAP.
+ * Create an authenticator to authenticate against an EAP server.
*
- * @param ike_sa associated ike_sa
- * @return eap_authenticator_t object
+ * @param ike_sa associated ike_sa
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return EAP authenticator
+ */
+eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init);
+
+/**
+ * Create an authenticator to authenticate EAP clients.
+ *
+ * @param ike_sa associated ike_sa
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @return EAP authenticator
*/
-eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa);
+eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init);
#endif /** EAP_AUTHENTICATOR_H_ @}*/
diff --git a/src/charon/sa/authenticators/psk_authenticator.c b/src/charon/sa/authenticators/psk_authenticator.c
index a3c84c491..45baa8e9c 100644
--- a/src/charon/sa/authenticators/psk_authenticator.c
+++ b/src/charon/sa/authenticators/psk_authenticator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -16,13 +16,10 @@
* $Id$
*/
-#include <string.h>
-
#include "psk_authenticator.h"
#include <daemon.h>
-#include <credentials/auth_info.h>
-
+#include <encoding/payloads/auth_payload.h>
typedef struct private_psk_authenticator_t private_psk_authenticator_t;
@@ -40,22 +37,74 @@ struct private_psk_authenticator_t {
* Assigned IKE_SA
*/
ike_sa_t *ike_sa;
+
+ /**
+ * nonce to include in AUTH calculation
+ */
+ chunk_t nonce;
+
+ /**
+ * IKE_SA_INIT message data to include in AUTH calculation
+ */
+ chunk_t ike_sa_init;
};
+/*
+ * Implementation of authenticator_t.build for builder
+ */
+static status_t build(private_psk_authenticator_t *this, message_t *message)
+{
+ identification_t *my_id, *other_id;
+ auth_payload_t *auth_payload;
+ shared_key_t *key;
+ chunk_t auth_data;
+ keymat_t *keymat;
+
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ 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);
+ key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
+ my_id, other_id);
+ if (key == NULL)
+ {
+ DBG1(DBG_IKE, "no shared key found for '%D' - '%D'", my_id, other_id);
+ return NOT_FOUND;
+ }
+ auth_data = keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init,
+ this->nonce, key->get_key(key), my_id);
+ key->destroy(key);
+ DBG2(DBG_IKE, "successfully created shared key MAC");
+ auth_payload = auth_payload_create();
+ auth_payload->set_auth_method(auth_payload, AUTH_PSK);
+ auth_payload->set_data(auth_payload, auth_data);
+ chunk_free(&auth_data);
+ message->add_payload(message, (payload_t*)auth_payload);
+
+ return SUCCESS;
+}
+
/**
- * Implementation of authenticator_t.verify.
+ * Implementation of authenticator_t.process for verifier
*/
-static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
- chunk_t my_nonce, auth_payload_t *auth_payload)
+static status_t process(private_psk_authenticator_t *this, message_t *message)
{
chunk_t auth_data, recv_auth_data;
identification_t *my_id, *other_id;
+ auth_payload_t *auth_payload;
+ auth_cfg_t *auth;
shared_key_t *key;
enumerator_t *enumerator;
bool authenticated = FALSE;
int keys_found = 0;
keymat_t *keymat;
+ auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ if (!auth_payload)
+ {
+ return FAILED;
+ }
keymat = this->ike_sa->get_keymat(this->ike_sa);
recv_auth_data = auth_payload->get_data(auth_payload);
my_id = this->ike_sa->get_my_id(this->ike_sa);
@@ -66,8 +115,8 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
{
keys_found++;
- auth_data = keymat->get_psk_sig(keymat, TRUE, ike_sa_init, my_nonce,
- key->get_key(key), other_id);
+ auth_data = keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init,
+ this->nonce, key->get_key(key), other_id);
if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "authentication of '%D' with %N successful",
@@ -89,42 +138,19 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
keys_found, keys_found == 1 ? "" : "s", my_id, other_id);
return FAILED;
}
+
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
return SUCCESS;
}
/**
- * Implementation of authenticator_t.build.
+ * Implementation of authenticator_t.process for builder
+ * Implementation of authenticator_t.build for verifier
*/
-static status_t build(private_psk_authenticator_t *this, chunk_t ike_sa_init,
- chunk_t other_nonce, auth_payload_t **auth_payload)
+static status_t return_failed()
{
- identification_t *my_id, *other_id;
- shared_key_t *key;
- chunk_t auth_data;
- keymat_t *keymat;
-
- keymat = this->ike_sa->get_keymat(this->ike_sa);
- 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);
- key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
- my_id, other_id);
- if (key == NULL)
- {
- DBG1(DBG_IKE, "no shared key found for '%D' - '%D'", my_id, other_id);
- return NOT_FOUND;
- }
- auth_data = keymat->get_psk_sig(keymat, FALSE, ike_sa_init, other_nonce,
- key->get_key(key), my_id);
- key->destroy(key);
- DBG2(DBG_IKE, "successfully created shared key MAC");
- *auth_payload = auth_payload_create();
- (*auth_payload)->set_auth_method(*auth_payload, AUTH_PSK);
- (*auth_payload)->set_data(*auth_payload, auth_data);
-
- chunk_free(&auth_data);
- return SUCCESS;
+ return FAILED;
}
/**
@@ -138,17 +164,38 @@ static void destroy(private_psk_authenticator_t *this)
/*
* Described in header.
*/
-psk_authenticator_t *psk_authenticator_create(ike_sa_t *ike_sa)
+psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init)
+{
+ private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->ike_sa_init = sent_init;
+ this->nonce = received_nonce;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init)
{
private_psk_authenticator_t *this = malloc_thing(private_psk_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;
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))return_failed;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
- /* private data */
this->ike_sa = ike_sa;
+ this->ike_sa_init = received_init;
+ this->nonce = sent_nonce;
return &this->public;
}
+
diff --git a/src/charon/sa/authenticators/psk_authenticator.h b/src/charon/sa/authenticators/psk_authenticator.h
index 9849acdbc..c307aee52 100644
--- a/src/charon/sa/authenticators/psk_authenticator.h
+++ b/src/charon/sa/authenticators/psk_authenticator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Martin Willi
+ * Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -28,22 +28,36 @@ typedef struct psk_authenticator_t psk_authenticator_t;
#include <sa/authenticators/authenticator.h>
/**
- * Implementation of the authenticator_t interface using AUTH_PSK.
+ * Implementation of authenticator_t using pre-shared keys.
*/
struct psk_authenticator_t {
/**
* Implemented authenticator_t interface.
*/
- authenticator_t authenticator_interface;
+ authenticator_t authenticator;
};
/**
- * Creates an authenticator for AUTH_PSK.
+ * Create an authenticator to build PSK signatures.
*
- * @param ike_sa associated ike_sa
- * @return psk_authenticator_t object
+ * @param ike_sa associated ike_sa
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return PSK authenticator
*/
-psk_authenticator_t *psk_authenticator_create(ike_sa_t *ike_sa);
+psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init);
+
+/**
+ * Create an authenticator to verify PSK signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @return PSK authenticator
+ */
+psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init);
#endif /** PSK_AUTHENTICATOR_H_ @}*/
diff --git a/src/charon/sa/authenticators/pubkey_authenticator.c b/src/charon/sa/authenticators/pubkey_authenticator.c
index 49a4283d2..482d6b91d 100644
--- a/src/charon/sa/authenticators/pubkey_authenticator.c
+++ b/src/charon/sa/authenticators/pubkey_authenticator.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -17,13 +17,10 @@
* $Id$
*/
-#include <string.h>
-
#include "pubkey_authenticator.h"
#include <daemon.h>
-#include <credentials/auth_info.h>
-
+#include <encoding/payloads/auth_payload.h>
typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t;
@@ -41,90 +38,35 @@ struct private_pubkey_authenticator_t {
* Assigned IKE_SA
*/
ike_sa_t *ike_sa;
-};
-
-/**
- * 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 *id;
- auth_info_t *auth, *current_auth;
- enumerator_t *enumerator;
- key_type_t key_type = KEY_ECDSA;
- signature_scheme_t scheme;
- status_t status = FAILED;
- keymat_t *keymat;
- 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);
- keymat = this->ike_sa->get_keymat(this->ike_sa);
- octets = keymat->get_auth_octets(keymat, TRUE, ike_sa_init, my_nonce, id);
- auth = this->ike_sa->get_other_auth(this->ike_sa);
- enumerator = charon->credentials->create_public_enumerator(
- charon->credentials, key_type, id, auth);
- while (enumerator->enumerate(enumerator, &public, &current_auth))
- {
- if (public->verify(public, scheme, octets, auth_data))
- {
- DBG1(DBG_IKE, "authentication of '%D' with %N successful",
- 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;
-}
+ /**
+ * nonce to include in AUTH calculation
+ */
+ chunk_t nonce;
+
+ /**
+ * IKE_SA_INIT message data to include in AUTH calculation
+ */
+ chunk_t ike_sa_init;
+};
/**
- * Implementation of authenticator_t.build.
+ * Implementation of authenticator_t.build for builder
*/
-static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
- chunk_t other_nonce, auth_payload_t **auth_payload)
+static status_t build(private_pubkey_authenticator_t *this, message_t *message)
{
chunk_t octets, auth_data;
status_t status = FAILED;
private_key_t *private;
identification_t *id;
- auth_info_t *auth;
+ auth_cfg_t *auth;
+ auth_payload_t *auth_payload;
auth_method_t auth_method;
signature_scheme_t scheme;
keymat_t *keymat;
id = this->ike_sa->get_my_id(this->ike_sa);
- auth = this->ike_sa->get_my_auth(this->ike_sa);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
private = charon->credentials->get_private(charon->credentials, KEY_ANY,
id, auth);
if (private == NULL)
@@ -169,15 +111,15 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
return status;
}
keymat = this->ike_sa->get_keymat(this->ike_sa);
- octets = keymat->get_auth_octets(keymat, FALSE, ike_sa_init, other_nonce, id);
-
+ octets = keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
+ this->nonce, id);
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;
+ auth_payload = auth_payload_create();
+ auth_payload->set_auth_method(auth_payload, auth_method);
+ auth_payload->set_data(auth_payload, auth_data);
chunk_free(&auth_data);
+ message->add_payload(message, (payload_t*)auth_payload);
status = SUCCESS;
}
DBG1(DBG_IKE, "authentication of '%D' (myself) with %N %s", id,
@@ -190,6 +132,93 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
}
/**
+ * Implementation of authenticator_t.process for verifier
+ */
+static status_t process(private_pubkey_authenticator_t *this, message_t *message)
+{
+ public_key_t *public;
+ auth_method_t auth_method;
+ auth_payload_t *auth_payload;
+ chunk_t auth_data, octets;
+ identification_t *id;
+ auth_cfg_t *auth, *current_auth;
+ enumerator_t *enumerator;
+ key_type_t key_type = KEY_ECDSA;
+ signature_scheme_t scheme;
+ status_t status = NOT_FOUND;
+ keymat_t *keymat;
+
+ auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ if (!auth_payload)
+ {
+ return FAILED;
+ }
+ auth_method = auth_payload->get_auth_method(auth_payload);
+ switch (auth_method)
+ {
+ case AUTH_RSA:
+ /* We currently accept SHA1 signatures only
+ * 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);
+ id = this->ike_sa->get_other_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ octets = keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init,
+ this->nonce, id);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ enumerator = charon->credentials->create_public_enumerator(
+ charon->credentials, key_type, id, auth);
+ while (enumerator->enumerate(enumerator, &public, &current_auth))
+ {
+ if (public->verify(public, scheme, octets, auth_data))
+ {
+ DBG1(DBG_IKE, "authentication of '%D' with %N successful",
+ id, auth_method_names, auth_method);
+ status = SUCCESS;
+ auth->merge(auth, current_auth, FALSE);
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ break;
+ }
+ else
+ {
+ status = FAILED;
+ DBG1(DBG_IKE, "signature validation failed, looking for another key");
+ }
+ }
+ enumerator->destroy(enumerator);
+ chunk_free(&octets);
+ if (status == NOT_FOUND)
+ {
+ DBG1(DBG_IKE, "no trusted %N public key found for '%D'",
+ key_type_names, key_type, id);
+ }
+ return status;
+}
+
+/**
+ * Implementation of authenticator_t.process for builder
+ * Implementation of authenticator_t.build for verifier
+ */
+static status_t return_failed()
+{
+ return FAILED;
+}
+
+/**
* Implementation of authenticator_t.destroy.
*/
static void destroy(private_pubkey_authenticator_t *this)
@@ -200,17 +229,37 @@ static void destroy(private_pubkey_authenticator_t *this)
/*
* Described in header.
*/
-pubkey_authenticator_t *pubkey_authenticator_create(ike_sa_t *ike_sa)
+pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init)
+{
+ private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t);
+
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
+
+ this->ike_sa = ike_sa;
+ this->ike_sa_init = sent_init;
+ this->nonce = received_nonce;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init)
{
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;
+ this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))return_failed;
+ this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process;
+ this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
- /* private data */
this->ike_sa = ike_sa;
+ this->ike_sa_init = received_init;
+ this->nonce = sent_nonce;
return &this->public;
}
diff --git a/src/charon/sa/authenticators/pubkey_authenticator.h b/src/charon/sa/authenticators/pubkey_authenticator.h
index 4a2d9e219..997b1b593 100644
--- a/src/charon/sa/authenticators/pubkey_authenticator.h
+++ b/src/charon/sa/authenticators/pubkey_authenticator.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2006 Martin Willi
+ * Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,22 +29,36 @@ typedef struct pubkey_authenticator_t pubkey_authenticator_t;
#include <sa/authenticators/authenticator.h>
/**
- * Implementation of the authenticator_t interface using AUTH_PUBKEY.
+ * Implementation of authenticator_t using public key authenitcation.
*/
struct pubkey_authenticator_t {
/**
* Implemented authenticator_t interface.
*/
- authenticator_t authenticator_interface;
+ authenticator_t authenticator;
};
/**
- * Creates an authenticator for AUTH_PUBKEY.
+ * Create an authenticator to build public key signatures.
*
- * @param ike_sa associated ike_sa
- * @return pubkey_authenticator_t object
+ * @param ike_sa associated ike_sa
+ * @param received_nonce nonce received in IKE_SA_INIT
+ * @param sent_init sent IKE_SA_INIT message data
+ * @return public key authenticator
*/
-pubkey_authenticator_t *pubkey_authenticator_create(ike_sa_t *ike_sa);
+pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
+ chunk_t received_nonce, chunk_t sent_init);
+
+/**
+ * Create an authenticator to verify public key signatures.
+ *
+ * @param ike_sa associated ike_sa
+ * @param sent_nonce nonce sent in IKE_SA_INIT
+ * @param received_init received IKE_SA_INIT message data
+ * @return public key authenticator
+ */
+pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
+ chunk_t sent_nonce, chunk_t received_init);
#endif /** PUBKEY_AUTHENTICATOR_H_ @}*/
diff --git a/src/charon/sa/connect_manager.c b/src/charon/sa/connect_manager.c
index fa5824bf4..f597d3550 100644
--- a/src/charon/sa/connect_manager.c
+++ b/src/charon/sa/connect_manager.c
@@ -734,11 +734,11 @@ static void build_pairs(check_list_t *checklist)
*/
static status_t process_payloads(message_t *message, check_t *check)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) != NOTIFY)
{
@@ -796,7 +796,7 @@ static status_t process_payloads(message_t *message, check_t *check)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (!check->connect_id.ptr || !check->endpoint || !check->auth.ptr)
{
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index 17ba15e27..2a1b96bbb 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -109,14 +109,14 @@ struct private_ike_sa_t {
peer_cfg_t *peer_cfg;
/**
- * associated authentication/authorization info for local peer
+ * currently used authentication ruleset, local (as auth_cfg_t)
*/
- auth_info_t *my_auth;
+ auth_cfg_t *my_auth;
/**
- * associated authentication/authorization info for remote peer
+ * currently used authentication constraints, remote (as auth_cfg_t)
*/
- auth_info_t *other_auth;
+ auth_cfg_t *other_auth;
/**
* Selected IKE proposal
@@ -355,40 +355,23 @@ 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;
-
+
if (this->ike_cfg == NULL)
{
this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
this->ike_cfg->get_ref(this->ike_cfg);
}
- /* apply IDs if they are not already set */
- if (this->my_id->contains_wildcards(this->my_id))
- {
- DESTROY_IF(this->my_id);
- this->my_id = this->peer_cfg->get_my_id(this->peer_cfg);
- this->my_id = this->my_id->clone(this->my_id);
- }
- if (this->other_id->contains_wildcards(this->other_id))
- {
- DESTROY_IF(this->other_id);
- this->other_id = this->peer_cfg->get_other_id(this->peer_cfg);
- this->other_id = this->other_id->clone(this->other_id);
- }
-}
-
-/**
- * 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.
+ * Implementation of ike_sa_t.get_auth_cfg
*/
-static auth_info_t* get_other_auth(private_ike_sa_t *this)
+static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local)
{
+ if (local)
+ {
+ return this->my_auth;
+ }
return this->other_auth;
}
@@ -1483,14 +1466,6 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
status = this->task_manager->process_message(this->task_manager, message);
if (status != DESTROY_ME)
{
- if (message->get_exchange_type(message) == IKE_AUTH &&
- this->state == IKE_ESTABLISHED)
- {
- /* purge auth items if SA is up, as they contain certs
- * and other memory wasting elements */
- this->my_auth->purge(this->my_auth);
- this->other_auth->purge(this->other_auth);
- }
return status;
}
/* if IKE_SA gets closed for any reasons, reroute routed children */
@@ -2304,9 +2279,9 @@ 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);
DESTROY_IF(this->proposal);
+ this->my_auth->destroy(this->my_auth);
+ this->other_auth->destroy(this->other_auth);
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
@@ -2334,8 +2309,7 @@ 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_auth_cfg = (auth_cfg_t*(*)(ike_sa_t*, bool local))get_auth_cfg;
this->public.get_proposal = (proposal_t*(*)(ike_sa_t*))get_proposal;
this->public.set_proposal = (void(*)(ike_sa_t*, proposal_t *proposal))set_proposal;
this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id;
@@ -2416,8 +2390,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->stats[STAT_INBOUND] = this->stats[STAT_OUTBOUND] = time(NULL);
this->ike_cfg = NULL;
this->peer_cfg = NULL;
- this->my_auth = auth_info_create();
- this->other_auth = auth_info_create();
+ this->my_auth = auth_cfg_create();
+ this->other_auth = auth_cfg_create();
this->proposal = NULL;
this->task_manager = task_manager_create(&this->public);
this->unique_id = ++unique_id;
diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h
index 2430f00a0..6542ffa50 100644
--- a/src/charon/sa/ike_sa.h
+++ b/src/charon/sa/ike_sa.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -41,7 +41,7 @@ typedef struct ike_sa_t ike_sa_t;
#include <sa/keymat.h>
#include <config/peer_cfg.h>
#include <config/ike_cfg.h>
-#include <credentials/auth_info.h>
+#include <config/auth_cfg.h>
/**
* Timeout in milliseconds after that a half open IKE_SA gets deleted.
@@ -82,6 +82,11 @@ enum ike_extension_t {
* peer supports HTTP cert lookups as specified in RFC4306
*/
EXT_HASH_AND_URL = (1<<2),
+
+ /**
+ * peer supports multiple authentication exchanges, RFC4739
+ */
+ EXT_MULTIPLE_AUTH = (1<<3),
};
/**
@@ -110,7 +115,7 @@ enum ike_condition_t {
COND_NAT_FAKE = (1<<3),
/**
- * peer has ben authenticated using EAP
+ * peer has been authenticated using EAP at least once
*/
COND_EAP_AUTHENTICATED = (1<<4),
@@ -391,18 +396,12 @@ struct ike_sa_t {
void (*set_peer_cfg) (ike_sa_t *this, peer_cfg_t *config);
/**
- * 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.
+ * Get the authentication config with rules of the current auth round.
*
- * @return auth_info for me
+ * @param local TRUE for local rules, FALSE for remote constraints
+ * @return current cfg
*/
- auth_info_t* (*get_other_auth)(ike_sa_t *this);
+ auth_cfg_t* (*get_auth_cfg)(ike_sa_t *this, bool local);
/**
* Get the selected proposal of this IKE_SA.
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c
index 0528e8bbb..f9588c201 100644
--- a/src/charon/sa/ike_sa_manager.c
+++ b/src/charon/sa/ike_sa_manager.c
@@ -1042,9 +1042,7 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
enumerator_t *enumerator;
entry_t *entry;
ike_sa_t *ike_sa = NULL;
- identification_t *my_id, *other_id;
- host_t *my_host, *other_host;
- ike_cfg_t *ike_cfg;
+ peer_cfg_t *current_cfg;
u_int segment;
if (!this->reuse_ikesa)
@@ -1054,70 +1052,29 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
return ike_sa;
}
- ike_cfg = peer_cfg->get_ike_cfg(peer_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);
-
- if (my_host && other_host)
+ enumerator = create_table_enumerator(this);
+ while (enumerator->enumerate(enumerator, &entry, &segment))
{
- enumerator = create_table_enumerator(this);
- while (enumerator->enumerate(enumerator, &entry, &segment))
+ if (!wait_for_entry(this, entry, segment))
{
- identification_t *found_my_id, *found_other_id;
- host_t *found_my_host, *found_other_host;
-
- if (!wait_for_entry(this, entry, segment))
- {
- continue;
- }
-
- if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
- {
- /* skip IKE_SAs which are not usable */
- 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);
+ continue;
+ }
+ if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
+ { /* skip IKE_SAs which are not usable */
+ 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"
- " %H[%D]...%H[%D]\n"
- " %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;
- }
+ current_cfg = entry->ike_sa->get_peer_cfg(entry->ike_sa);
+ if (current_cfg && current_cfg->equals(current_cfg, peer_cfg))
+ {
+ DBG2(DBG_MGR, "found an existing IKE_SA with a '%s' config",
+ current_cfg->get_name(current_cfg));
+ entry->checked_out = TRUE;
+ ike_sa = entry->ike_sa;
+ break;
}
- enumerator->destroy(enumerator);
}
- DESTROY_IF(my_host);
- DESTROY_IF(other_host);
+ enumerator->destroy(enumerator);
if (!ike_sa)
{ /* no IKE_SA using such a config, hand out a new */
@@ -1326,20 +1283,12 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
/* apply identities for duplicate test (only as responder) */
if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
- (!entry->my_id || !entry->other_id))
+ ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ entry->my_id == NULL && entry->other_id == NULL)
{
- if (!entry->my_id && my_id->get_type(my_id) != ID_ANY)
- {
- entry->my_id = my_id->clone(my_id);
- }
- if (!entry->other_id && other_id->get_type(other_id) != ID_ANY)
- {
- entry->other_id = other_id->clone(other_id);
- }
- if (entry->my_id && entry->other_id)
- {
- put_connected_peers(this, entry);
- }
+ entry->my_id = my_id->clone(my_id);
+ entry->other_id = other_id->clone(other_id);
+ put_connected_peers(this, entry);
}
unlock_single_segment(this, segment);
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c
index 7258de5a5..88fb7984e 100644
--- a/src/charon/sa/task_manager.c
+++ b/src/charon/sa/task_manager.c
@@ -650,6 +650,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
static status_t process_request(private_task_manager_t *this,
message_t *message)
{
+ enumerator_t *enumerator;
iterator_t *iterator;
task_t *task = NULL;
payload_t *payload;
@@ -688,8 +689,8 @@ static status_t process_request(private_task_manager_t *this,
case CREATE_CHILD_SA:
{ /* FIXME: we should prevent this on mediation connections */
bool notify_found = FALSE, ts_found = FALSE;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
switch (payload->get_type(payload))
{
@@ -716,7 +717,7 @@ static status_t process_request(private_task_manager_t *this,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (ts_found)
{
@@ -739,8 +740,8 @@ static status_t process_request(private_task_manager_t *this,
}
case INFORMATIONAL:
{
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
switch (payload->get_type(payload))
{
@@ -793,7 +794,7 @@ static status_t process_request(private_task_manager_t *this,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (task == NULL)
{
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index b3bb1840d..1e1624dca 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -570,7 +570,7 @@ static void handle_notify(private_child_create_t *this, notify_payload_t *notify
*/
static void process_payloads(private_child_create_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
sa_payload_t *sa_payload;
ke_payload_t *ke_payload;
@@ -579,8 +579,8 @@ static void process_payloads(private_child_create_t *this, message_t *message)
/* defaults to TUNNEL mode */
this->mode = MODE_TUNNEL;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
switch (payload->get_type(payload))
{
@@ -616,7 +616,7 @@ static void process_payloads(private_child_create_t *this, message_t *message)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -643,9 +643,9 @@ static status_t build_i(private_child_create_t *this, message_t *message)
}
break;
case IKE_AUTH:
- if (!message->get_payload(message, ID_INITIATOR))
+ if (message->get_message_id(message) != 1)
{
- /* send only in the first request, not in subsequent EAP */
+ /* send only in the first request, not in subsequent rounds */
return NEED_MORE;
}
break;
@@ -737,8 +737,6 @@ static status_t build_i(private_child_create_t *this, message_t *message)
*/
static status_t process_r(private_child_create_t *this, message_t *message)
{
- peer_cfg_t *peer_cfg;
-
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
@@ -747,42 +745,17 @@ static status_t process_r(private_child_create_t *this, message_t *message)
get_nonce(message, &this->other_nonce);
break;
case IKE_AUTH:
- if (message->get_payload(message, ID_INITIATOR) == NULL)
+ if (message->get_message_id(message) != 1)
{
- /* wait until extensible authentication completed, if used */
+ /* only handle first AUTH payload, not additional rounds */
return NEED_MORE;
}
default:
break;
}
-
+
process_payloads(this, message);
- if (this->tsi == NULL || this->tsr == NULL)
- {
- DBG1(DBG_IKE, "TS payload missing in message");
- return NEED_MORE;
- }
-
- peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (peer_cfg)
- {
- host_t *me, *other;
-
- me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (me == NULL)
- {
- me = this->ike_sa->get_my_host(this->ike_sa);
- }
- other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
- if (other == NULL)
- {
- other = this->ike_sa->get_other_host(this->ike_sa);
- }
-
- this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
- this->tsi, me, other);
- }
return NEED_MORE;
}
@@ -810,10 +783,11 @@ static void handle_child_sa_failure(private_child_create_t *this,
*/
static status_t build_r(private_child_create_t *this, message_t *message)
{
+ peer_cfg_t *peer_cfg;
payload_t *payload;
- iterator_t *iterator;
+ enumerator_t *enumerator;
bool no_dh = TRUE;
-
+
switch (message->get_exchange_type(message))
{
case IKE_SA_INIT:
@@ -828,9 +802,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
no_dh = FALSE;
break;
case IKE_AUTH:
- if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
- {
- /* wait until extensible authentication completed, if used */
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* wait until all authentication round completed */
return NEED_MORE;
}
default:
@@ -844,6 +817,25 @@ static status_t build_r(private_child_create_t *this, message_t *message)
return SUCCESS;
}
+ peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (peer_cfg && this->tsi && this->tsr)
+ {
+ host_t *me, *other;
+
+ me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
+ if (me == NULL)
+ {
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ }
+ other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
+ if (other == NULL)
+ {
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ }
+ this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
+ this->tsi, me, other);
+ }
+
if (this->config == NULL)
{
DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
@@ -854,8 +846,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
/* check if ike_config_t included non-critical error notifies */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -868,7 +860,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
{
DBG1(DBG_IKE,"configuration payload negotation "
"failed, no CHILD_SA built");
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
handle_child_sa_failure(this, message);
return SUCCESS;
}
@@ -877,7 +869,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
@@ -938,7 +930,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
*/
static status_t process_i(private_child_create_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
bool no_dh = TRUE;
@@ -951,9 +943,8 @@ static status_t process_i(private_child_create_t *this, message_t *message)
no_dh = FALSE;
break;
case IKE_AUTH:
- if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
- {
- /* wait until extensible authentication completed, if used */
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* wait until all authentication round completed */
return NEED_MORE;
}
default:
@@ -961,8 +952,8 @@ static status_t process_i(private_child_create_t *this, message_t *message)
}
/* check for erronous notifies */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -982,7 +973,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{
DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
notify_type_names, type);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
handle_child_sa_failure(this, message);
/* an error in CHILD_SA creation is not critical */
return SUCCESS;
@@ -1000,7 +991,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
bad_group, diffie_hellman_group_names, this->dh_group);
this->public.task.migrate(&this->public.task, this->ike_sa);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return NEED_MORE;
}
default:
@@ -1008,7 +999,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
process_payloads(this, message);
diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c
index 36d260f99..26e9695f9 100644
--- a/src/charon/sa/tasks/child_delete.c
+++ b/src/charon/sa/tasks/child_delete.c
@@ -114,15 +114,16 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
*/
static void process_payloads(private_child_delete_t *this, message_t *message)
{
- iterator_t *payloads, *spis;
+ enumerator_t *payloads;
+ iterator_t *spis;
payload_t *payload;
delete_payload_t *delete_payload;
u_int32_t *spi;
protocol_id_t protocol;
child_sa_t *child_sa;
- payloads = message->get_payload_iterator(message);
- while (payloads->iterate(payloads, (void**)&payload))
+ payloads = message->create_payload_enumerator(message);
+ while (payloads->enumerate(payloads, &payload))
{
if (payload->get_type(payload) == DELETE)
{
diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c
index 127280efc..44a22575c 100644
--- a/src/charon/sa/tasks/child_rekey.c
+++ b/src/charon/sa/tasks/child_rekey.c
@@ -103,11 +103,11 @@ static status_t process_i_delete(private_child_rekey_t *this, message_t *message
*/
static void find_child(private_child_rekey_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
notify_payload_t *notify;
u_int32_t spi;
@@ -131,7 +131,7 @@ static void find_child(private_child_rekey_t *this, message_t *message)
break;
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -220,12 +220,12 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
protocol_id_t protocol;
u_int32_t spi;
child_sa_t *to_delete;
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
/* handle NO_ADDITIONAL_SAS notify */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -239,12 +239,12 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
charon->processor->queue_job(charon->processor,
(job_t*)rekey_ike_sa_job_create(
this->ike_sa->get_id(this->ike_sa), TRUE));
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return SUCCESS;
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (this->child_create->task.process(&this->child_create->task, message) == NEED_MORE)
{
diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c
index ad1621714..d594e3baa 100644
--- a/src/charon/sa/tasks/ike_auth.c
+++ b/src/charon/sa/tasks/ike_auth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -21,14 +21,12 @@
#include <string.h>
#include <daemon.h>
-#include <crypto/diffie_hellman.h>
#include <encoding/payloads/id_payload.h>
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/eap_payload.h>
#include <encoding/payloads/nonce_payload.h>
#include <sa/authenticators/eap_authenticator.h>
-
typedef struct private_ike_auth_t private_ike_auth_t;
/**
@@ -72,220 +70,65 @@ struct private_ike_auth_t {
packet_t *other_packet;
/**
- * EAP authenticator when using EAP
+ * completed authentication configs initiated by us (auth_cfg_t)
*/
- eap_authenticator_t *eap_auth;
+ linked_list_t *my_cfgs;
/**
- * EAP payload received and ready to process
+ * completed authentication configs initiated by other (auth_cfg_t)
*/
- eap_payload_t *eap_payload;
+ linked_list_t *other_cfgs;;
/**
- * has the peer been authenticated successfully?
+ * currently active authenticator, to authenticate us
*/
- bool peer_authenticated;
-};
-
-/**
- * get the authentication class of a config
- */
-auth_class_t get_auth_class(peer_cfg_t *config)
-{
- auth_class_t *class;
- auth_info_t *auth_info;
-
- auth_info = config->get_auth(config);
- if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
- {
- return *class;
- }
- /* fallback to pubkey authentication */
- return AUTH_CLASS_PUBKEY;
-}
-
-/**
- * get the eap type/vendor
- */
-static eap_type_t get_eap_type(peer_cfg_t *config, u_int32_t *vendor)
-{
- auth_info_t *auth_info;
- u_int *ptr;
-
- *vendor = 0;
- auth_info = config->get_auth(config);
- if (auth_info->get_item(auth_info, AUTHN_EAP_VENDOR, (void**)&ptr))
- {
- *vendor = *ptr;
- }
- if (auth_info->get_item(auth_info, AUTHN_EAP_TYPE, (void**)&ptr))
- {
- return *ptr;
- }
- return EAP_NAK;
-}
-
-/**
- * build the AUTH payload
- */
-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;
- status_t status;
+ authenticator_t *my_auth;
- /* create own authenticator and add auth payload */
- config = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (!config)
- {
- DBG1(DBG_IKE, "unable to authenticate, no peer config found");
- return FAILED;
- }
-
- auth = authenticator_create_from_class(this->ike_sa, get_auth_class(config));
- if (auth == NULL)
- {
- DBG1(DBG_IKE, "configured authentication class %N not supported",
- auth_class_names, get_auth_class(config));
- return FAILED;
- }
-
- status = auth->build(auth, this->my_packet->get_data(this->my_packet),
- this->other_nonce, &auth_payload);
- auth->destroy(auth);
- if (status != SUCCESS)
- {
- DBG1(DBG_IKE, "generating authentication data failed");
- return FAILED;
- }
- message->add_payload(message, (payload_t*)auth_payload);
- return SUCCESS;
-}
-
-/**
- * build ID payload(s)
- */
-static status_t build_id(private_ike_auth_t *this, message_t *message)
-{
- identification_t *me, *other;
- id_payload_t *id;
- peer_cfg_t *config;
-
- me = this->ike_sa->get_my_id(this->ike_sa);
- other = this->ike_sa->get_other_id(this->ike_sa);
- config = this->ike_sa->get_peer_cfg(this->ike_sa);
-
- if (me->contains_wildcards(me))
- {
- me = config->get_my_id(config);
- if (me->contains_wildcards(me))
- {
- DBG1(DBG_IKE, "negotiation of own ID failed");
- return FAILED;
- }
- this->ike_sa->set_my_id(this->ike_sa, me->clone(me));
- }
+ /**
+ * currently active authenticator, to authenticate peer
+ */
+ authenticator_t *other_auth;
- id = id_payload_create_from_identification(this->initiator ? ID_INITIATOR : ID_RESPONDER, me);
- message->add_payload(message, (payload_t*)id);
+ /**
+ * peer_cfg candidates, ordered by priority
+ */
+ linked_list_t *candidates;
- /* as initiator, include other ID if it does not contain wildcards */
- if (this->initiator && !other->contains_wildcards(other))
- {
- id = id_payload_create_from_identification(ID_RESPONDER, other);
- message->add_payload(message, (payload_t*)id);
- }
- return SUCCESS;
-}
-
-/**
- * process AUTH payload
- */
-static status_t process_auth(private_ike_auth_t *this, message_t *message)
-{
- auth_payload_t *auth_payload;
- authenticator_t *auth;
- auth_method_t auth_method;
- status_t status;
+ /**
+ * selected peer config (might change when using multiple authentications)
+ */
+ peer_cfg_t *peer_cfg;
- auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+ /**
+ * have we planned an(other) authentication exchange?
+ */
+ bool do_another_auth;
- if (auth_payload == NULL)
- {
- /* AUTH payload is missing, client wants to use EAP authentication */
- return NOT_FOUND;
- }
+ /**
+ * has the peer announced another authentication exchange?
+ */
+ bool expect_another_auth;
- auth_method = auth_payload->get_auth_method(auth_payload);
- auth = authenticator_create_from_method(this->ike_sa,
- auth_payload->get_auth_method(auth_payload));
- if (auth == NULL)
- {
- DBG1(DBG_IKE, "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;
- }
- status = auth->verify(auth, this->other_packet->get_data(this->other_packet),
- this->my_nonce, auth_payload);
- auth->destroy(auth);
- if (status != SUCCESS)
- {
- DBG0(DBG_IKE, "authentication of '%D' with %N failed",
- this->ike_sa->get_other_id(this->ike_sa),
- auth_method_names, auth_method);
- return FAILED;
- }
- return SUCCESS;
-}
+ /**
+ * should we send a AUTHENTICATION_FAILED notify?
+ */
+ bool authentication_failed;
+};
/**
- * process ID payload(s)
+ * check if multiple authentication extension is enabled, configuration-wise
*/
-static status_t process_id(private_ike_auth_t *this, message_t *message)
+static bool multiple_auth_enabled()
{
- identification_t *id, *req;
- id_payload_t *idr, *idi;
-
- idi = (id_payload_t*)message->get_payload(message, ID_INITIATOR);
- idr = (id_payload_t*)message->get_payload(message, ID_RESPONDER);
-
- if ((this->initiator && idr == NULL) || (!this->initiator && idi == NULL))
- {
- DBG1(DBG_IKE, "ID payload missing in message");
- return FAILED;
- }
-
- if (this->initiator)
- {
- id = idr->get_identification(idr);
- req = this->ike_sa->get_other_id(this->ike_sa);
- if (!id->matches(id, req))
- {
- DBG0(DBG_IKE, "peer ID '%D' unacceptable, '%D' required", id, req);
- id->destroy(id);
- return FAILED;
- }
- this->ike_sa->set_other_id(this->ike_sa, id);
- }
- else
- {
- id = idi->get_identification(idi);
- this->ike_sa->set_other_id(this->ike_sa, id);
- if (idr)
- {
- id = idr->get_identification(idr);
- this->ike_sa->set_my_id(this->ike_sa, id);
- }
- }
- return SUCCESS;
+ return lib->settings->get_bool(lib->settings,
+ "charon.multiple_authentication", TRUE);
}
/**
* collect the needed information in the IKE_SA_INIT exchange from our message
*/
-static status_t collect_my_init_data(private_ike_auth_t *this, message_t *message)
+static status_t collect_my_init_data(private_ike_auth_t *this,
+ message_t *message)
{
nonce_payload_t *nonce;
@@ -297,7 +140,7 @@ static status_t collect_my_init_data(private_ike_auth_t *this, message_t *messag
}
this->my_nonce = nonce->get_nonce(nonce);
- /* pre-generate the message, so we can store it for us */
+ /* pre-generate the message, keep a copy */
if (this->ike_sa->generate_message(this->ike_sa, message,
&this->my_packet) != SUCCESS)
{
@@ -309,7 +152,8 @@ static status_t collect_my_init_data(private_ike_auth_t *this, message_t *messag
/**
* collect the needed information in the IKE_SA_INIT exchange from others message
*/
-static status_t collect_other_init_data(private_ike_auth_t *this, message_t *message)
+static status_t collect_other_init_data(private_ike_auth_t *this,
+ message_t *message)
{
/* we collect the needed information in the IKE_SA_INIT exchange */
nonce_payload_t *nonce;
@@ -322,184 +166,186 @@ static status_t collect_other_init_data(private_ike_auth_t *this, message_t *mes
}
this->other_nonce = nonce->get_nonce(nonce);
- /* pre-generate the message, so we can store it for us */
+ /* keep a copy of the received packet */
this->other_packet = message->get_packet(message);
return NEED_MORE;
}
-
/**
- * Implementation of task_t.build to create AUTH payload from EAP data
+ * Get the next authentication configuration
*/
-static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
+static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local)
{
- authenticator_t *auth;
- auth_payload_t *auth_payload;
+ enumerator_t *e1, *e2;
+ auth_cfg_t *c1, *c2, *next = NULL;
- if (!this->initiator && !this->peer_authenticated)
+ /* find an available config not already done */
+ e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, local);
+ while (e1->enumerate(e1, &c1))
{
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
- return FAILED;
- }
-
- auth = (authenticator_t*)this->eap_auth;
- if (auth->build(auth, this->my_packet->get_data(this->my_packet),
- this->other_nonce, &auth_payload) != SUCCESS)
- {
- DBG1(DBG_IKE, "generating authentication data failed");
- if (!this->initiator)
+ bool found = FALSE;
+
+ if (local)
{
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
+ e2 = this->my_cfgs->create_enumerator(this->my_cfgs);
+ }
+ else
+ {
+ e2 = this->other_cfgs->create_enumerator(this->other_cfgs);
+ }
+ while (e2->enumerate(e2, &c2))
+ {
+ if (c2->complies(c2, c1, FALSE))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ e2->destroy(e2);
+ if (!found)
+ {
+ next = c1;
+ break;
}
- return FAILED;
- }
- message->add_payload(message, (payload_t*)auth_payload);
- if (!this->initiator)
- {
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
- return SUCCESS;
}
- return NEED_MORE;
+ e1->destroy(e1);
+ return next;
}
/**
- * Implementation of task_t.process to verify AUTH payload after EAP
+ * Check if we have should initiate another authentication round
*/
-static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
+static bool do_another_auth(private_ike_auth_t *this)
{
- auth_payload_t *auth_payload;
- authenticator_t *auth;
-
- auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
- this->peer_authenticated = FALSE;
+ bool do_another = FALSE;
+ enumerator_t *done, *todo;
+ auth_cfg_t *done_cfg, *todo_cfg;
- if (auth_payload)
+ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
{
- auth = (authenticator_t*)this->eap_auth;
- if (auth->verify(auth, this->other_packet->get_data(this->other_packet),
- this->my_nonce, auth_payload) == SUCCESS)
- {
- this->peer_authenticated = TRUE;
- }
+ return FALSE;
}
-
- if (!this->peer_authenticated)
+
+ done = this->my_cfgs->create_enumerator(this->my_cfgs);
+ todo = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, TRUE);
+ while (todo->enumerate(todo, &todo_cfg))
{
- DBG0(DBG_IKE, "authentication of '%D' with %N failed",
- this->ike_sa->get_other_id(this->ike_sa),
- auth_class_names, AUTH_CLASS_EAP);
- if (this->initiator)
+ if (!done->enumerate(done, &done_cfg))
{
- return FAILED;
+ done_cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ }
+ if (!done_cfg->complies(done_cfg, todo_cfg, FALSE))
+ {
+ do_another = TRUE;
+ break;
}
- return NEED_MORE;
- }
- if (this->initiator)
- {
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
- return SUCCESS;
}
- return NEED_MORE;
+ done->destroy(done);
+ todo->destroy(todo);
+ return do_another;
}
/**
- * Implementation of task_t.process for EAP exchanges
+ * Get peer configuration candidates from backends
*/
-static status_t process_eap_i(private_ike_auth_t *this, message_t *message)
+static bool load_cfg_candidates(private_ike_auth_t *this)
{
- eap_payload_t *eap;
-
- eap = (eap_payload_t*)message->get_payload(message, EXTENSIBLE_AUTHENTICATION);
- if (eap == NULL)
- {
- DBG1(DBG_IKE, "EAP payload missing");
- return FAILED;
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ host_t *me, *other;
+ identification_t *my_id, *other_id;
+
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ me, other, my_id, other_id);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
+ {
+ peer_cfg->get_ref(peer_cfg);
+ if (this->peer_cfg == NULL)
+ { /* best match */
+ this->peer_cfg = peer_cfg;
+ this->ike_sa->set_peer_cfg(this->ike_sa, peer_cfg);
+ }
+ else
+ {
+ this->candidates->insert_last(this->candidates, peer_cfg);
+ }
}
- switch (this->eap_auth->process(this->eap_auth, eap, &eap))
+ enumerator->destroy(enumerator);
+ if (this->peer_cfg)
{
- case NEED_MORE:
- this->eap_payload = eap;
- return NEED_MORE;
- case SUCCESS:
- /* EAP exchange completed, now create and process AUTH */
- this->eap_payload = NULL;
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_auth_eap;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_auth_eap;
- return NEED_MORE;
- default:
- this->eap_payload = NULL;
- DBG0(DBG_IKE, "failed to authenticate against '%D' using EAP",
- this->ike_sa->get_other_id(this->ike_sa));
- return FAILED;
+ DBG1(DBG_CFG, "selected peer config '%s'",
+ this->peer_cfg->get_name(this->peer_cfg));
+ return TRUE;
}
+ DBG1(DBG_CFG, "no matching peer config found");
+ return FALSE;
}
/**
- * Implementation of task_t.process for EAP exchanges
- */
-static status_t process_eap_r(private_ike_auth_t *this, message_t *message)
-{
- this->eap_payload = (eap_payload_t*)message->get_payload(message,
- EXTENSIBLE_AUTHENTICATION);
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.build for EAP exchanges
- */
-static status_t build_eap_i(private_ike_auth_t *this, message_t *message)
-{
- message->add_payload(message, (payload_t*)this->eap_payload);
- return NEED_MORE;
-}
-
-/**
- * Implementation of task_t.build for EAP exchanges
+ * update the current peer candidate if necessary, using candidates
*/
-static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
+static bool update_cfg_candidates(private_ike_auth_t *this, bool strict)
{
- status_t status = NEED_MORE;
- eap_payload_t *eap;
-
- if (this->eap_payload == NULL)
- {
- DBG1(DBG_IKE, "EAP payload missing");
- return FAILED;
- }
-
- switch (this->eap_auth->process(this->eap_auth, this->eap_payload, &eap))
+ do
{
- case NEED_MORE:
+ if (this->peer_cfg)
+ {
+ bool complies = TRUE;
+ enumerator_t *e1, *e2, *tmp;
+ auth_cfg_t *c1, *c2;
- break;
- case SUCCESS:
- /* EAP exchange completed, now create and process AUTH */
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_auth_eap;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_auth_eap;
- break;
- default:
- DBG0(DBG_IKE, "authentication of '%D' with %N failed",
- this->ike_sa->get_other_id(this->ike_sa),
- auth_class_names, AUTH_CLASS_EAP);
- status = FAILED;
- break;
+ e1 = this->other_cfgs->create_enumerator(this->other_cfgs);
+ e2 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
+
+ if (strict)
+ { /* swap lists in strict mode: all configured rounds must be
+ * fulfilled. If !strict, we check only the rounds done so far. */
+ tmp = e1;
+ e1 = e2;
+ e2 = tmp;
+ }
+ while (e1->enumerate(e1, &c1))
+ {
+ /* check if done authentications comply to configured ones */
+ if ((!e2->enumerate(e2, &c2)) ||
+ (!strict && !c1->complies(c1, c2, TRUE)) ||
+ (strict && !c2->complies(c2, c1, TRUE)))
+ {
+ complies = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+ if (complies)
+ {
+ break;
+ }
+ DBG1(DBG_CFG, "selected peer config '%s' inacceptable",
+ this->peer_cfg->get_name(this->peer_cfg));
+ this->peer_cfg->destroy(this->peer_cfg);
+ }
+ if (this->candidates->remove_first(this->candidates,
+ (void**)&this->peer_cfg) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "no alternative config found");
+ this->peer_cfg = NULL;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "switching to peer config '%s'",
+ this->peer_cfg->get_name(this->peer_cfg));
+ this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
+ }
}
- message->add_payload(message, (payload_t*)eap);
- return status;
+ while (this->peer_cfg);
+
+ return this->peer_cfg != NULL;
}
/**
@@ -507,31 +353,103 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
*/
static status_t build_i(private_ike_auth_t *this, message_t *message)
{
- peer_cfg_t *config;
-
+ auth_cfg_t *cfg;
+
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
return collect_my_init_data(this, message);
}
-
- if (build_id(this, message) != SUCCESS)
+
+ if (this->peer_cfg == NULL)
{
- return FAILED;
+ this->peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ this->peer_cfg->get_ref(this->peer_cfg);
}
- config = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (get_auth_class(config) == AUTH_CLASS_EAP)
- {
- this->eap_auth = eap_authenticator_create(this->ike_sa);
+ if (message->get_message_id(message) == 1 &&
+ this->ike_sa->supports_extension(this->ike_sa, EXT_MULTIPLE_AUTH))
+ { /* in the first IKE_AUTH, indicate support for multiple authentication */
+ message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED, chunk_empty);
}
- else
+
+ if (!this->do_another_auth && !this->my_auth)
+ { /* we have done our rounds */
+ return NEED_MORE;
+ }
+
+ /* check if an authenticator is in progress */
+ if (this->my_auth == NULL)
{
- if (build_auth(this, message) != SUCCESS)
+ identification_t *id;
+ id_payload_t *id_payload;
+
+ /* clean up authentication config from a previous round */
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->purge(cfg, TRUE);
+
+ /* add (optional) IDr */
+ cfg = get_auth_cfg(this, FALSE);
+ if (cfg)
+ {
+ id = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (id && !id->contains_wildcards(id))
+ {
+ this->ike_sa->set_other_id(this->ike_sa, id->clone(id));
+ id_payload = id_payload_create_from_identification(
+ ID_RESPONDER, id);
+ message->add_payload(message, (payload_t*)id_payload);
+ }
+ }
+ /* add IDi */
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
+ id = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (!id)
+ {
+ DBG1(DBG_CFG, "configuration misses IDi");
+ return FAILED;
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
+ id_payload = id_payload_create_from_identification(ID_INITIATOR, id);
+ message->add_payload(message, (payload_t*)id_payload);
+
+ /* build authentication data */
+ this->my_auth = authenticator_create_builder(
+ this->ike_sa, cfg, this->other_nonce,
+ this->my_packet->get_data(this->my_packet));
+ if (!this->my_auth)
{
return FAILED;
}
}
-
+ switch (this->my_auth->build(this->my_auth, message))
+ {
+ case SUCCESS:
+ /* authentication step complete, reset authenticator */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), TRUE);
+ this->my_cfgs->insert_last(this->my_cfgs, cfg);
+ this->my_auth->destroy(this->my_auth);
+ this->my_auth = NULL;
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ return FAILED;
+ }
+
+ /* check for additional authentication rounds */
+ if (do_another_auth(this))
+ {
+ if (message->get_payload(message, AUTHENTICATION))
+ {
+ message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
+ }
+ }
+ else
+ {
+ this->do_another_auth = FALSE;
+ }
return NEED_MORE;
}
@@ -540,45 +458,135 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
*/
static status_t process_r(private_ike_auth_t *this, message_t *message)
{
- peer_cfg_t *config;
+ auth_cfg_t *cfg, *cand;
+ id_payload_t *id_payload;
+ identification_t *id;
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
return collect_other_init_data(this, message);
}
- if (process_id(this, message) != SUCCESS)
+ if (this->my_auth == NULL && this->do_another_auth)
+ {
+ /* handle (optional) IDr payload, apply proposed identity */
+ id_payload = (id_payload_t*)message->get_payload(message, ID_RESPONDER);
+ if (id_payload)
+ {
+ id = id_payload->get_identification(id_payload);
+ }
+ else
+ {
+ id = identification_create_from_encoding(ID_ANY, chunk_empty);
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id);
+ }
+
+ if (!this->expect_another_auth)
{
return NEED_MORE;
}
+ if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED))
+ {
+ this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
+ }
- switch (process_auth(this, message))
+ if (this->other_auth == NULL)
+ {
+ /* handle IDi payload */
+ id_payload = (id_payload_t*)message->get_payload(message, ID_INITIATOR);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDi payload missing");
+ return FAILED;
+ }
+ id = id_payload->get_identification(id_payload);
+ this->ike_sa->set_other_id(this->ike_sa, id);
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
+
+ if (this->peer_cfg == NULL)
+ {
+ if (!load_cfg_candidates(this))
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+ }
+ if (message->get_payload(message, AUTHENTICATION) == NULL)
+ { /* before authenticating with EAP, we need a EAP config */
+ cand = get_auth_cfg(this, FALSE);
+ while (!cand || (
+ (uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
+ (uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
+ { /* peer requested EAP, but current config does not match */
+ this->peer_cfg->destroy(this->peer_cfg);
+ this->peer_cfg = NULL;
+ if (!update_cfg_candidates(this, FALSE))
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+ cand = get_auth_cfg(this, FALSE);
+ }
+ cfg->merge(cfg, cand, TRUE);
+ }
+
+ /* verify authentication data */
+ this->other_auth = authenticator_create_verifier(
+ this->ike_sa, message, this->my_nonce,
+ this->other_packet->get_data(this->other_packet));
+ if (!this->other_auth)
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+ }
+ switch (this->other_auth->process(this->other_auth, message))
{
case SUCCESS:
- this->peer_authenticated = TRUE;
- break;
- case NOT_FOUND:
- /* use EAP if no AUTH payload found */
- this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED, TRUE);
+ this->other_auth->destroy(this->other_auth);
+ this->other_auth = NULL;
break;
+ case NEED_MORE:
+ if (message->get_payload(message, AUTHENTICATION))
+ { /* AUTH verification successful, but another build() needed */
+ break;
+ }
+ return NEED_MORE;
default:
+ this->authentication_failed = TRUE;
return NEED_MORE;
}
-
- config = charon->backends->get_peer_cfg(charon->backends,
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(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_auth(this->ike_sa));
- if (config)
+
+ /* store authentication information */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
+ this->other_cfgs->insert_last(this->other_cfgs, cfg);
+
+ /* another auth round done, invoke authorize hook */
+ if (!charon->bus->authorize(charon->bus, this->other_cfgs, FALSE))
+ {
+ DBG1(DBG_IKE, "round %d authorization hook forbids IKE_SA, cancelling",
+ this->other_cfgs->get_count(this->other_cfgs));
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
+
+ if (!update_cfg_candidates(this, FALSE))
{
- this->ike_sa->set_peer_cfg(this->ike_sa, config);
- config->destroy(config);
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
}
- if (!this->peer_authenticated)
- {
- this->eap_auth = eap_authenticator_create(this->ike_sa);
+
+ if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
+ {
+ this->expect_another_auth = FALSE;
+ if (!update_cfg_candidates(this, TRUE))
+ {
+ this->authentication_failed = TRUE;
+ return NEED_MORE;
+ }
}
return NEED_MORE;
}
@@ -588,52 +596,139 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
*/
static status_t build_r(private_ike_auth_t *this, message_t *message)
{
- peer_cfg_t *config;
- eap_type_t eap_type;
- u_int32_t eap_vendor;
- eap_payload_t *eap_payload;
- status_t status;
-
+ auth_cfg_t *cfg;
+
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
+ if (multiple_auth_enabled())
+ {
+ message->add_notify(message, FALSE, MULTIPLE_AUTH_SUPPORTED,
+ chunk_empty);
+ }
return collect_my_init_data(this, message);
}
- if (!this->peer_authenticated && this->eap_auth == NULL)
+ if (this->authentication_failed || this->peer_cfg == 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)
+ if (this->my_auth == NULL && this->do_another_auth)
{
- DBG1(DBG_IKE, "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);
- return FAILED;
+ identification_t *id, *id_cfg;
+ id_payload_t *id_payload;
+
+ /* add IDr */
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ cfg->purge(cfg, TRUE);
+ cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
+
+ id_cfg = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ id = this->ike_sa->get_my_id(this->ike_sa);
+ if (id->get_type(id) == ID_ANY)
+ { /* no IDr received, apply configured ID */
+ if (!id_cfg || id_cfg->contains_wildcards(id_cfg))
+ {
+ DBG1(DBG_CFG, "IDr not configured and negotiation failed");
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ this->ike_sa->set_my_id(this->ike_sa, id_cfg->clone(id_cfg));
+ id = id_cfg;
+ }
+ else
+ { /* IDr received, check if it matches configuration */
+ if (id_cfg && !id->matches(id, id_cfg))
+ {
+ DBG1(DBG_CFG, "received IDr %D, but require %D", id, id_cfg);
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ }
+
+ id_payload = id_payload_create_from_identification(ID_RESPONDER, id);
+ message->add_payload(message, (payload_t*)id_payload);
+
+ /* build authentication data */
+ this->my_auth = authenticator_create_builder(
+ this->ike_sa, cfg, this->other_nonce,
+ this->my_packet->get_data(this->my_packet));
+ if (!this->my_auth)
+ {
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
+ return FAILED;
+ }
}
- if (build_id(this, message) != SUCCESS ||
- build_auth(this, message) != SUCCESS)
+ if (this->other_auth)
{
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
- return FAILED;
+ switch (this->other_auth->build(this->other_auth, message))
+ {
+ case SUCCESS:
+ this->other_auth->destroy(this->other_auth);
+ this->other_auth = NULL;
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ if (!message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
+ { /* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ }
+ return FAILED;
+ }
}
-
- if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
- this->ike_sa))
+ if (this->my_auth)
{
- DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
- message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
- return FAILED;
+ switch (this->my_auth->build(this->my_auth, message))
+ {
+ case SUCCESS:
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
+ TRUE);
+ this->my_cfgs->insert_last(this->my_cfgs, cfg);
+ this->my_auth->destroy(this->my_auth);
+ this->my_auth = NULL;
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
}
- /* use "traditional" authentication if we could authenticate peer */
- if (this->peer_authenticated)
+ /* check for additional authentication rounds */
+ if (do_another_auth(this))
+ {
+ message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
+ }
+ else
+ {
+ this->do_another_auth = FALSE;
+ }
+ if (!this->do_another_auth && !this->expect_another_auth)
{
+ if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
+ this->ike_sa))
+ {
+ DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy");
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
+ if (!charon->bus->authorize(charon->bus, this->other_cfgs, TRUE))
+ {
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+ message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+ chunk_empty);
+ return FAILED;
+ }
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
this->ike_sa->get_name(this->ike_sa),
@@ -644,21 +739,6 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
-
- /* initiate EAP authenitcation */
- eap_type = get_eap_type(config, &eap_vendor);
- status = this->eap_auth->initiate(this->eap_auth, eap_type,
- eap_vendor, &eap_payload);
- message->add_payload(message, (payload_t*)eap_payload);
- if (status != NEED_MORE)
- {
- DBG1(DBG_IKE, "unable to initiate EAP authentication");
- return FAILED;
- }
-
- /* switch to EAP methods */
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_eap_r;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_eap_r;
return NEED_MORE;
}
@@ -667,18 +747,22 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
*/
static status_t process_i(private_ike_auth_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
- peer_cfg_t *config;
- auth_info_t *auth;
+ auth_cfg_t *cfg;
if (message->get_exchange_type(message) == IKE_SA_INIT)
{
+ if (message->get_notify(message, MULTIPLE_AUTH_SUPPORTED) &&
+ multiple_auth_enabled())
+ {
+ this->ike_sa->enable_extension(this->ike_sa, EXT_MULTIPLE_AUTH);
+ }
return collect_other_init_data(this, message);
}
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -714,7 +798,7 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
{
DBG1(DBG_IKE, "received %N notify error",
notify_type_names, type);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return FAILED;
}
DBG2(DBG_IKE, "received %N notify",
@@ -724,39 +808,115 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
- if (process_id(this, message) != SUCCESS ||
- process_auth(this, message) != SUCCESS)
+ if (this->my_auth)
{
- return FAILED;
+ switch (this->my_auth->process(this->my_auth, message))
+ {
+ case SUCCESS:
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE),
+ TRUE);
+ this->my_cfgs->insert_last(this->my_cfgs, cfg);
+ this->my_auth->destroy(this->my_auth);
+ this->my_auth = NULL;
+ this->do_another_auth = do_another_auth(this);
+ break;
+ case NEED_MORE:
+ break;
+ default:
+ return FAILED;
+ }
}
- if (this->eap_auth)
+ if (this->expect_another_auth)
{
- /* switch to EAP authentication methods */
- this->public.task.build = (status_t(*)(task_t*,message_t*))build_eap_i;
- this->public.task.process = (status_t(*)(task_t*,message_t*))process_eap_i;
- return process_eap_i(this, message);
+ if (this->other_auth == NULL)
+ {
+ id_payload_t *id_payload;
+ identification_t *id;
+
+ /* responder is not allowed to do EAP */
+ if (!message->get_payload(message, AUTHENTICATION))
+ {
+ DBG1(DBG_IKE, "AUTH payload missing");
+ return FAILED;
+ }
+
+ /* handle IDr payload */
+ id_payload = (id_payload_t*)message->get_payload(message,
+ ID_RESPONDER);
+ if (!id_payload)
+ {
+ DBG1(DBG_IKE, "IDr payload missing");
+ return FAILED;
+ }
+ id = id_payload->get_identification(id_payload);
+ this->ike_sa->set_other_id(this->ike_sa, id);
+ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+ cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
+
+ /* verify authentication data */
+ this->other_auth = authenticator_create_verifier(
+ this->ike_sa, message, this->my_nonce,
+ this->other_packet->get_data(this->other_packet));
+ if (!this->other_auth)
+ {
+ return FAILED;
+ }
+ }
+ switch (this->other_auth->process(this->other_auth, message))
+ {
+ case SUCCESS:
+ break;
+ case NEED_MORE:
+ return NEED_MORE;
+ default:
+ return FAILED;
+ }
+ /* store authentication information, reset authenticator */
+ cfg = auth_cfg_create();
+ cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
+ this->other_cfgs->insert_last(this->other_cfgs, cfg);
+ this->other_auth->destroy(this->other_auth);
+ this->other_auth = NULL;
+
+ /* another auth round done, invoke authorize hook */
+ if (!charon->bus->authorize(charon->bus, this->other_cfgs, FALSE))
+ {
+ DBG1(DBG_IKE, "round %d authorization forbids IKE_SA, cancelling",
+ this->other_cfgs->get_count(this->other_cfgs));
+ return FAILED;
+ }
}
- 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)))
+ if (message->get_notify(message, ANOTHER_AUTH_FOLLOWS) == NULL)
{
- DBG0(DBG_IKE, "authorization of '%D' for config %s failed",
- this->ike_sa->get_other_id(this->ike_sa), config->get_name(config));
- return FAILED;
+ this->expect_another_auth = FALSE;
}
- this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
- return SUCCESS;
+ if (!this->expect_another_auth && !this->do_another_auth && !this->my_auth)
+ {
+ if (!update_cfg_candidates(this, TRUE))
+ {
+ return FAILED;
+ }
+ if (!charon->bus->authorize(charon->bus, this->other_cfgs, TRUE))
+ {
+ DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+ return FAILED;
+ }
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
+ return SUCCESS;
+ }
+ return NEED_MORE;
}
/**
@@ -776,28 +936,25 @@ static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
chunk_free(&this->other_nonce);
DESTROY_IF(this->my_packet);
DESTROY_IF(this->other_packet);
- if (this->eap_auth)
- {
- this->eap_auth->authenticator_interface.destroy(
- &this->eap_auth->authenticator_interface);
- }
+ DESTROY_IF(this->peer_cfg);
+ DESTROY_IF(this->my_auth);
+ DESTROY_IF(this->other_auth);
+ this->my_cfgs->destroy_offset(this->my_cfgs, offsetof(auth_cfg_t, destroy));
+ this->other_cfgs->destroy_offset(this->other_cfgs, offsetof(auth_cfg_t, destroy));
+ this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
this->my_packet = NULL;
this->other_packet = NULL;
- this->peer_authenticated = FALSE;
- this->eap_auth = NULL;
- this->eap_payload = NULL;
this->ike_sa = ike_sa;
- if (this->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->peer_cfg = NULL;
+ this->my_auth = NULL;
+ this->other_auth = NULL;
+ this->do_another_auth = TRUE;
+ this->expect_another_auth = TRUE;
+ this->authentication_failed = FALSE;
+ this->my_cfgs = linked_list_create();
+ this->other_cfgs = linked_list_create();
+ this->candidates = linked_list_create();
}
/**
@@ -809,11 +966,12 @@ static void destroy(private_ike_auth_t *this)
chunk_free(&this->other_nonce);
DESTROY_IF(this->my_packet);
DESTROY_IF(this->other_packet);
- if (this->eap_auth)
- {
- this->eap_auth->authenticator_interface.destroy(
- &this->eap_auth->authenticator_interface);
- }
+ DESTROY_IF(this->my_auth);
+ DESTROY_IF(this->other_auth);
+ DESTROY_IF(this->peer_cfg);
+ this->my_cfgs->destroy_offset(this->my_cfgs, offsetof(auth_cfg_t, destroy));
+ this->other_cfgs->destroy_offset(this->other_cfgs, offsetof(auth_cfg_t, destroy));
+ this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
free(this);
}
@@ -823,7 +981,7 @@ static void destroy(private_ike_auth_t *this)
ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
{
private_ike_auth_t *this = malloc_thing(private_ike_auth_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;
@@ -845,9 +1003,16 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
this->other_nonce = chunk_empty;
this->my_packet = NULL;
this->other_packet = NULL;
- this->peer_authenticated = FALSE;
- this->eap_auth = NULL;
- this->eap_payload = NULL;
+ this->peer_cfg = NULL;
+ this->my_cfgs = linked_list_create();
+ this->other_cfgs = linked_list_create();
+ this->candidates = linked_list_create();
+ this->my_auth = NULL;
+ this->other_auth = NULL;
+ this->do_another_auth = TRUE;
+ this->expect_another_auth = TRUE;
+ this->authentication_failed = FALSE;
return &this->public;
}
+
diff --git a/src/charon/sa/tasks/ike_auth_lifetime.c b/src/charon/sa/tasks/ike_auth_lifetime.c
index 328f11d2c..a175aa53a 100644
--- a/src/charon/sa/tasks/ike_auth_lifetime.c
+++ b/src/charon/sa/tasks/ike_auth_lifetime.c
@@ -64,12 +64,12 @@ static void add_auth_lifetime(private_ike_auth_lifetime_t *this, message_t *mess
*/
static void process_payloads(private_ike_auth_lifetime_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
notify_payload_t *notify;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -88,7 +88,7 @@ static void process_payloads(private_ike_auth_lifetime_t *this, message_t *messa
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
diff --git a/src/charon/sa/tasks/ike_cert_post.c b/src/charon/sa/tasks/ike_cert_post.c
index 825cf0711..da3ee4dce 100644
--- a/src/charon/sa/tasks/ike_cert_post.c
+++ b/src/charon/sa/tasks/ike_cert_post.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2006-2008 Martin Willi
+ * Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -98,70 +98,68 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certifi
}
/**
- * from ike_auth.c
- */
-auth_class_t get_auth_class(peer_cfg_t *config);
-
-/**
* add certificates to message
*/
static void build_certs(private_ike_cert_post_t *this, message_t *message)
{
peer_cfg_t *peer_cfg;
+ auth_cfg_t *auth;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (peer_cfg && get_auth_class(peer_cfg) == AUTH_CLASS_PUBKEY)
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+ if (!peer_cfg ||
+ (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_PUBKEY)
+ {
+ return;
+ }
+ switch (peer_cfg->get_cert_policy(peer_cfg))
{
- 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:
{
- case CERT_NEVER_SEND:
+ cert_payload_t *payload;
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ auth_rule_t type;
+
+ /* get subject cert first, then issuing certificates */
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (!cert)
+ {
break;
- case CERT_SEND_IF_ASKED:
- if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
- {
- break;
- }
- /* FALL */
- case CERT_ALWAYS_SEND:
+ }
+ payload = build_cert_payload(this, cert);
+ if (!payload)
{
- 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))
+ break;
+ }
+ DBG1(DBG_IKE, "sending end entity cert \"%D\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &cert))
+ {
+ if (type == AUTH_RULE_IM_CERT)
{
- if (item == AUTHZ_IM_CERT)
+ payload = cert_payload_create_from_cert(cert);
+ if (payload)
{
- 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);
- }
+ DBG1(DBG_IKE, "sending issuer cert \"%D\"",
+ cert->get_subject(cert));
+ message->add_payload(message, (payload_t*)payload);
}
}
- enumerator->destroy(enumerator);
- }
- }
+ }
+ enumerator->destroy(enumerator);
+ }
}
}
@@ -170,12 +168,11 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
*/
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;
+ if (message->get_payload(message, AUTHENTICATION))
+ { /* CERT payloads are sended along AUTH payloads */
+ build_certs(this, message);
}
- build_certs(this, message);
- return SUCCESS;
+ return NEED_MORE;
}
/**
@@ -191,11 +188,14 @@ static status_t process_r(private_ike_cert_post_t *this, message_t *message)
*/
static status_t build_r(private_ike_cert_post_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
+ if (message->get_payload(message, AUTHENTICATION))
+ { /* CERT payloads are sended along AUTH payloads */
+ build_certs(this, message);
+ }
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* stay alive, we might have additional rounds with certs */
return NEED_MORE;
}
- build_certs(this, message);
return SUCCESS;
}
@@ -204,8 +204,8 @@ static status_t build_r(private_ike_cert_post_t *this, message_t *message)
*/
static status_t process_i(private_ike_cert_post_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_SA_INIT)
- {
+ if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
+ { /* stay alive, we might have additional rounds with CERTS */
return NEED_MORE;
}
return SUCCESS;
diff --git a/src/charon/sa/tasks/ike_cert_pre.c b/src/charon/sa/tasks/ike_cert_pre.c
index 79bc4f6e0..0ec7004c2 100644
--- a/src/charon/sa/tasks/ike_cert_pre.c
+++ b/src/charon/sa/tasks/ike_cert_pre.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2006-2007 Martin Willi
+ * Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -48,9 +48,9 @@ struct private_ike_cert_pre_t {
bool initiator;
/**
- * Did we send a HTTP_CERT_LOOKUP_SUPPORTED Notify?
+ * Do we accept HTTP certificate lookup requests
*/
- bool http_cert_lookup_supported_sent;
+ bool do_http_lookup;
};
/**
@@ -58,23 +58,22 @@ struct private_ike_cert_pre_t {
*/
static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
- auth_info_t *auth;
- bool ca_found = FALSE;
+ auth_cfg_t *auth;
- auth = this->ike_sa->get_my_auth(this->ike_sa);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
switch(payload->get_type(payload))
{
case CERTIFICATE_REQUEST:
{
certreq_payload_t *certreq = (certreq_payload_t*)payload;
- chunk_t keyid;
enumerator_t *enumerator;
+ chunk_t keyid;
this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE);
@@ -98,15 +97,12 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
{
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;
+ auth->add(auth, AUTH_RULE_CA_CERT, cert);
}
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);
}
@@ -129,7 +125,7 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -140,6 +136,7 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
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:
@@ -158,7 +155,7 @@ static certificate_t *try_get_cert(cert_payload_t *cert_payload)
}
id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash);
cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, id, FALSE);
+ CERT_X509, KEY_ANY, id, FALSE);
id->destroy(id);
break;
}
@@ -175,78 +172,81 @@ static certificate_t *try_get_cert(cert_payload_t *cert_payload)
*/
static void process_certs(private_ike_cert_pre_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
- auth_info_t *auth;
+ auth_cfg_t *auth;
bool first = TRUE;
- auth = this->ike_sa->get_other_auth(this->ike_sa);
+ auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &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)
+ cert_payload_t *cert_payload;
+ cert_encoding_t encoding;
+ certificate_t *cert;
+ char *url;
+
+ cert_payload = (cert_payload_t*)payload;
+ encoding = cert_payload->get_cert_encoding(cert_payload);
+
+ switch (encoding)
{
- case ENC_X509_SIGNATURE:
case ENC_X509_HASH_AND_URL:
{
- if (type == ENC_X509_HASH_AND_URL &&
- !this->http_cert_lookup_supported_sent)
+ if (!this->do_http_lookup)
{
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);
-
+ /* FALL */
+ }
+ case ENC_X509_SIGNATURE:
+ {
+ 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 */
+ { /* the first is an end entity certificate */
DBG1(DBG_IKE, "received end entity cert \"%D\"",
cert->get_subject(cert));
- auth->add_item(auth, AUTHN_SUBJECT_CERT, cert);
+ auth->add(auth, AUTH_HELPER_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);
+ auth->add(auth, AUTH_HELPER_IM_CERT, cert);
}
- cert->destroy(cert);
}
- else if (type == ENC_X509_HASH_AND_URL)
+ else if (encoding == 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);
+ /* we fetch the certificate not yet, but only if
+ * it is really needed during authentication */
+ url = cert_payload->get_url(cert_payload);
if (!url)
{
- DBG1(DBG_IKE, "received invalid hash-and-url encoded"
- " cert, ignore");
+ DBG1(DBG_IKE, "received invalid hash-and-url "
+ "encoded cert, ignore");
break;
}
-
+ url = strdup(url);
if (first)
- { /* the first certificate MUST be an end entity one */
+ { /* first URL is for an end entity certificate */
DBG1(DBG_IKE, "received hash-and-url for end"
- " entity cert \"%s\"", url);
- auth->add_item(auth, AUTHN_SUBJECT_HASH_URL, url);
+ " entity cert \"%s\"", url);
+ auth->add(auth, AUTH_HELPER_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);
+ auth->add(auth, AUTH_HELPER_IM_HASH_URL, url);
}
}
break;
@@ -264,31 +264,23 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message)
case ENC_OCSP_CONTENT:
default:
DBG1(DBG_ENC, "certificate encoding %N not supported",
- cert_encoding_names, cert_payload->get_cert_encoding(cert_payload));
+ cert_encoding_names, encoding);
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
- * add a certificate request to the message, building request payload if required.
+ * add the keyid of a certificate to the certificate request payload
*/
-static void add_certreq_payload(message_t *message, certreq_payload_t **reqp,
- certificate_t *cert)
+static void add_certreq(certreq_payload_t **req, 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:
{
+ public_key_t *public;
identification_t *keyid;
x509_t *x509 = (x509_t*)cert;
@@ -296,14 +288,18 @@ static void add_certreq_payload(message_t *message, certreq_payload_t **reqp,
{ /* no CA cert, skip */
break;
}
- if (*reqp == NULL)
+ public = cert->get_public_key(cert);
+ if (!public)
+ {
+ break;
+ }
+ if (*req == NULL)
{
- *reqp = certreq_payload_create_type(CERT_X509);
- message->add_payload(message, (payload_t*)*reqp);
+ *req = certreq_payload_create_type(CERT_X509);
}
- req = *reqp;
keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
- req->add_keyid(req, keyid->get_encoding(keyid));
+ (*req)->add_keyid(*req, keyid->get_encoding(keyid));
+ public->destroy(public);
DBG1(DBG_IKE, "sending cert request for \"%D\"",
cert->get_subject(cert));
break;
@@ -311,7 +307,30 @@ static void add_certreq_payload(message_t *message, certreq_payload_t **reqp,
default:
break;
}
- public->destroy(public);
+}
+
+/**
+ * add a auth_cfg's CA certificates to the certificate request
+ */
+static void add_certreqs(certreq_payload_t **req, auth_cfg_t *auth)
+{
+ enumerator_t *enumerator;
+ auth_rule_t type;
+ void *value;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ switch (type)
+ {
+ case AUTH_RULE_CA_CERT:
+ add_certreq(req, (certificate_t*)value);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
}
/**
@@ -319,75 +338,53 @@ static void add_certreq_payload(message_t *message, certreq_payload_t **reqp,
*/
static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
{
+ enumerator_t *enumerator;
ike_cfg_t *ike_cfg;
peer_cfg_t *peer_cfg;
- enumerator_t *enumerator;
certificate_t *cert;
- bool restricted = FALSE;
- certreq_payload_t *x509_req = NULL;
+ auth_cfg_t *auth;
+ certreq_payload_t *req = NULL;
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
if (!ike_cfg->send_certreq(ike_cfg))
{
return;
}
-
+
/* check if we require a specific CA for that peer */
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer_cfg)
{
- void *ptr;
- identification_t *id;
- auth_item_t item;
- auth_info_t *auth = peer_cfg->get_auth(peer_cfg);
- enumerator_t *auth_enumerator = auth->create_item_enumerator(auth);
-
- while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, FALSE);
+ while (enumerator->enumerate(enumerator, &auth))
{
- switch (item)
- {
- case AUTHZ_CA_CERT:
- cert = (certificate_t *)ptr;
- add_certreq_payload(message, &x509_req, cert);
- restricted = TRUE;
- break;
- case AUTHZ_CA_CERT_NAME:
- id = (identification_t *)ptr;
- enumerator = charon->credentials->create_cert_enumerator(
- charon->credentials, CERT_ANY, KEY_ANY, id, TRUE);
- while (enumerator->enumerate(enumerator, &cert, TRUE))
- {
- add_certreq_payload(message, &x509_req, cert);
- restricted = TRUE;
- }
- enumerator->destroy(enumerator);
- break;
- default:
- break;
- }
+ add_certreqs(&req, auth);
}
- auth_enumerator->destroy(auth_enumerator);
+ enumerator->destroy(enumerator);
}
-
- if (!restricted)
+
+ if (!req)
{
- /* otherwise include all trusted CA certificates */
+ /* otherwise add all trusted CA certificates */
enumerator = charon->credentials->create_cert_enumerator(
charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE);
- while (enumerator->enumerate(enumerator, &cert, TRUE))
+ while (enumerator->enumerate(enumerator, &cert))
{
- add_certreq_payload(message, &x509_req, cert);
+ add_certreq(&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))
+ if (req)
{
- message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED, chunk_empty);
- this->http_cert_lookup_supported_sent = TRUE;
+ message->add_payload(message, (payload_t*)req);
+
+ if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE))
+ {
+ message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED,
+ chunk_empty);
+ this->do_http_lookup = TRUE;
+ }
}
}
@@ -396,11 +393,10 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
*/
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;
+ if (message->get_message_id(message) == 1)
+ { /* initiator sends CERTREQs in first IKE_AUTH */
+ build_certreqs(this, message);
}
- build_certreqs(this, message);
return NEED_MORE;
}
@@ -408,13 +404,12 @@ static status_t build_i(private_ike_cert_pre_t *this, message_t *message)
* 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;
+{
+ if (message->get_exchange_type(message) != IKE_SA_INIT)
+ { /* handle certreqs/certs in any IKE_AUTH, just in case */
+ process_certreqs(this, message);
+ process_certs(this, message);
}
- process_certreqs(this, message);
- process_certs(this, message);
return NEED_MORE;
}
@@ -426,9 +421,12 @@ 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;
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ {
+ return SUCCESS;
+ }
+ return NEED_MORE;
}
/**
@@ -439,10 +437,38 @@ 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;
+
+ /* as ike_auth is not processed yet, we don't know if authentication
+ * is complete (and we can return SUCCESS). Therefore we check for
+ * an AUTH payload without a ANOTHER_AUTH_FOLLOWS notify. */
+ if (message->get_payload(message, AUTHENTICATION))
+ {
+ enumerator_t *enumerator;
+ payload_t *payload;
+ notify_payload_t *notify;
+ bool done = TRUE;
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify = (notify_payload_t*)payload;
+ if (notify->get_notify_type(notify) == ANOTHER_AUTH_FOLLOWS)
+ {
+ done = FALSE;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (done)
+ {
+ return SUCCESS;
+ }
+ }
+ return NEED_MORE;
}
/**
@@ -493,7 +519,7 @@ ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator)
this->ike_sa = ike_sa;
this->initiator = initiator;
- this->http_cert_lookup_supported_sent = FALSE;
+ this->do_http_lookup = FALSE;
return &this->public;
}
diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c
index 04c9e57b8..cb769f9b4 100644
--- a/src/charon/sa/tasks/ike_config.c
+++ b/src/charon/sa/tasks/ike_config.c
@@ -260,11 +260,12 @@ static void process_attribute(private_ike_config_t *this,
*/
static void process_payloads(private_ike_config_t *this, message_t *message)
{
- iterator_t *iterator, *attributes;
+ enumerator_t *enumerator;
+ iterator_t *attributes;
payload_t *payload;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == CONFIGURATION)
{
@@ -290,7 +291,7 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -298,9 +299,8 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
*/
static status_t build_i(private_ike_config_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_AUTH &&
- message->get_payload(message, ID_INITIATOR))
- {
+ if (message->get_message_id(message) == 1)
+ { /* in first IKE_AUTH only */
peer_cfg_t *config;
host_t *vip;
@@ -327,9 +327,8 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
*/
static status_t process_r(private_ike_config_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_AUTH &&
- message->get_payload(message, ID_INITIATOR))
- {
+ if (message->get_message_id(message) == 1)
+ { /* in first IKE_AUTH only */
process_payloads(this, message);
}
return NEED_MORE;
@@ -340,9 +339,8 @@ static status_t process_r(private_ike_config_t *this, message_t *message)
*/
static status_t build_r(private_ike_config_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_AUTH &&
- message->get_payload(message, EXTENSIBLE_AUTHENTICATION) == NULL)
- {
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ { /* in last IKE_AUTH exchange */
peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config && this->virtual_ip)
@@ -355,7 +353,6 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
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)
@@ -384,9 +381,8 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
*/
static status_t process_i(private_ike_config_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_AUTH &&
- !message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
- {
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
+ { /* in last IKE_AUTH exchange */
host_t *ip;
peer_cfg_t *config;
diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c
index 4f28909da..2aac7b02e 100644
--- a/src/charon/sa/tasks/ike_init.c
+++ b/src/charon/sa/tasks/ike_init.c
@@ -170,11 +170,11 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
*/
static void process_payloads(private_ike_init_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
-
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
switch (payload->get_type(payload))
{
@@ -182,7 +182,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
{
sa_payload_t *sa_payload = (sa_payload_t*)payload;
linked_list_t *proposal_list;
-
+
proposal_list = sa_payload->get_proposals(sa_payload);
this->proposal = this->config->select_proposal(this->config,
proposal_list);
@@ -225,7 +225,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -317,12 +317,12 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
#ifdef ME
{
chunk_t connect_id = chunk_empty;
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
-
+
/* check for a ME_CONNECTID notify */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -353,7 +353,7 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
if (connect_id.ptr)
{
@@ -458,12 +458,12 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
*/
static status_t process_i(private_ike_init_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
-
+
/* check for erronous notifies */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -489,19 +489,22 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
this->ike_sa->reset(this->ike_sa);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return NEED_MORE;
}
case NAT_DETECTION_SOURCE_IP:
case NAT_DETECTION_DESTINATION_IP:
/* skip, handled in ike_natd_t */
break;
+ case MULTIPLE_AUTH_SUPPORTED:
+ /* handled in ike_auth_t */
+ break;
case COOKIE:
{
chunk_free(&this->cookie);
this->cookie = chunk_clone(notify->get_notification_data(notify));
this->ike_sa->reset(this->ike_sa);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
DBG2(DBG_IKE, "received %N notify", notify_type_names, type);
return NEED_MORE;
}
@@ -511,7 +514,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
{
DBG1(DBG_IKE, "received %N notify error",
notify_type_names, type);
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return FAILED;
}
DBG2(DBG_IKE, "received %N notify",
@@ -521,7 +524,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
process_payloads(this, message);
diff --git a/src/charon/sa/tasks/ike_me.c b/src/charon/sa/tasks/ike_me.c
index 32c264c43..07dfb20a5 100644
--- a/src/charon/sa/tasks/ike_me.c
+++ b/src/charon/sa/tasks/ike_me.c
@@ -166,11 +166,11 @@ static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
*/
static void process_payloads(private_ike_me_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
-
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) != NOTIFY)
{
@@ -237,7 +237,7 @@ static void process_payloads(private_ike_me_t *this, message_t *message)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index b2ef2731f..29bb61730 100644
--- a/src/charon/sa/tasks/ike_mobike.c
+++ b/src/charon/sa/tasks/ike_mobike.c
@@ -97,12 +97,12 @@ static void flush_additional_addresses(private_ike_mobike_t *this)
*/
static void process_payloads(private_ike_mobike_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
bool first = TRUE;
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
int family = AF_INET;
notify_payload_t *notify;
@@ -181,7 +181,7 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
}
/**
@@ -332,9 +332,8 @@ static void transmit(private_ike_mobike_t *this, packet_t *packet)
*/
static status_t build_i(private_ike_mobike_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_AUTH &&
- message->get_payload(message, ID_INITIATOR))
- {
+ if (message->get_message_id(message) == 1)
+ { /* only in first IKE_AUTH */
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
build_address_list(this, message);
}
@@ -381,9 +380,8 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message)
*/
static status_t process_r(private_ike_mobike_t *this, message_t *message)
{
- if (message->get_exchange_type(message) == IKE_AUTH &&
- message->get_payload(message, ID_INITIATOR))
- {
+ if (message->get_message_id(message) == 1)
+ { /* only first IKE_AUTH */
process_payloads(this, message);
}
else if (message->get_exchange_type(message) == INFORMATIONAL)
diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c
index a20af7ce7..f6bb2d43b 100644
--- a/src/charon/sa/tasks/ike_natd.c
+++ b/src/charon/sa/tasks/ike_natd.c
@@ -166,7 +166,7 @@ static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
*/
static void process_payloads(private_ike_natd_t *this, message_t *message)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
notify_payload_t *notify;
chunk_t hash, src_hash, dst_hash;
@@ -184,8 +184,8 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash);
DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash);
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) != NOTIFY)
{
@@ -235,7 +235,7 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
chunk_free(&src_hash);
chunk_free(&dst_hash);
diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c
index 6dbad5ff6..3c49f329a 100644
--- a/src/charon/sa/tasks/ike_rekey.c
+++ b/src/charon/sa/tasks/ike_rekey.c
@@ -194,12 +194,12 @@ static status_t build_r(private_ike_rekey_t *this, message_t *message)
static status_t process_i(private_ike_rekey_t *this, message_t *message)
{
ike_sa_id_t *to_delete;
- iterator_t *iterator;
+ enumerator_t *enumerator;
payload_t *payload;
-
+
/* handle NO_ADDITIONAL_SAS notify */
- iterator = message->get_payload_iterator(message);
- while (iterator->iterate(iterator, (void**)&payload))
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
{
if (payload->get_type(payload) == NOTIFY)
{
@@ -213,12 +213,12 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
charon->processor->queue_job(charon->processor,
(job_t*)rekey_ike_sa_job_create(
this->ike_sa->get_id(this->ike_sa), TRUE));
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
return SUCCESS;
}
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
switch (this->ike_init->task.process(&this->ike_init->task, message))
{
diff --git a/src/libfreeswan/Makefile.am b/src/libfreeswan/Makefile.am
index d916fca17..190a8c892 100644
--- a/src/libfreeswan/Makefile.am
+++ b/src/libfreeswan/Makefile.am
@@ -12,7 +12,11 @@ libfreeswan_a_SOURCES = addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c ato
satot.c subnetof.c subnettoa.c subnettot.c \
subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
ultoa.c ultot.c version.c
-INCLUDES = -I$(top_srcdir)/src/pluto
+
+INCLUDES = \
+-I$(top_srcdir)/src/libstrongswan \
+-I$(top_srcdir)/src/pluto
+
dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atosa.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \
keyblobtoid.3 optionsfrom.3 portof.3 prng.3 rangetosubnet.3 sameaddr.3 subnetof.3 \
ttoaddr.3 ttodata.3 ttosa.3 ttoul.3 version.3
diff --git a/src/libfreeswan/freeswan.h b/src/libfreeswan/freeswan.h
index cf1f7b832..56b9893b0 100644
--- a/src/libfreeswan/freeswan.h
+++ b/src/libfreeswan/freeswan.h
@@ -44,7 +44,7 @@
#endif /* __KERNEL__ */
#include <ipsec_param.h>
-
+#include <utils.h>
/*
* Grab the kernel version to see if we have NET_21, and therefore
@@ -147,7 +147,6 @@ struct sa_id { /* old v4-only version */
};
/* misc */
-typedef const char *err_t; /* error message, or NULL for success */
struct prng { /* pseudo-random-number-generator guts */
unsigned char sbox[256];
int i, j;
@@ -446,7 +445,6 @@ bitstomask(
/* option pickup from files (userland only because of use of FILE) */
const char *optionsfrom(const char *filename, int *argcp, char ***argvp,
int optind, FILE *errorreport);
-#define ignore_result(call) { if (call); }
#endif
/*
diff --git a/src/libstrongswan/credentials/certificates/certificate.c b/src/libstrongswan/credentials/certificates/certificate.c
index 1a83bdf4c..3437d5ad8 100644
--- a/src/libstrongswan/credentials/certificates/certificate.c
+++ b/src/libstrongswan/credentials/certificates/certificate.c
@@ -31,11 +31,11 @@ ENUM(certificate_type_names, CERT_ANY, CERT_PGP,
"PGP",
);
-ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_SKIPPED,
- "VALIDATION_GOOD",
- "VALIDATION_STALE",
- "VALIDATION_REVOKED",
- "VALIDATION_FAILED",
- "VALIDATION_SKIPPED",
+ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_REVOKED,
+ "GOOD",
+ "SKIPPED",
+ "STALE",
+ "FAILED",
+ "REVOKED",
);
diff --git a/src/libstrongswan/credentials/certificates/certificate.h b/src/libstrongswan/credentials/certificates/certificate.h
index 1fb151d9f..81fce5508 100644
--- a/src/libstrongswan/credentials/certificates/certificate.h
+++ b/src/libstrongswan/credentials/certificates/certificate.h
@@ -58,18 +58,20 @@ extern enum_name_t *certificate_type_names;
/**
* Result of a certificate validation.
+ *
+ * Order of values is relevant, sorted from good to bad.
*/
enum cert_validation_t {
/** certificate has been validated successfully */
- VALIDATION_GOOD,
+ VALIDATION_GOOD = 0,
+ /** validation has been skipped due to missing validation information */
+ VALIDATION_SKIPPED,
/** certificate has been validated, but check based on stale information */
VALIDATION_STALE,
- /** certificate has been revoked */
- VALIDATION_REVOKED,
/** validation failed due to a processing error */
VALIDATION_FAILED,
- /** validation has been skipped due to missing validation information */
- VALIDATION_SKIPPED,
+ /** certificate has been revoked */
+ VALIDATION_REVOKED,
};
/**
diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c
index eac3b07a2..b213c7b47 100644
--- a/src/libstrongswan/plugins/curl/curl_fetcher.c
+++ b/src/libstrongswan/plugins/curl/curl_fetcher.c
@@ -35,7 +35,7 @@ struct private_curl_fetcher_t {
* Public data
*/
curl_fetcher_t public;
-
+
/**
* CURL handle
*/
@@ -52,15 +52,15 @@ struct private_curl_fetcher_t {
*/
static size_t append(void *ptr, size_t size, size_t nmemb, chunk_t *data)
{
- size_t realsize = size * nmemb;
-
- data->ptr = (u_char*)realloc(data->ptr, data->len + realsize);
- if (data->ptr)
- {
+ size_t realsize = size * nmemb;
+
+ data->ptr = (u_char*)realloc(data->ptr, data->len + realsize);
+ if (data->ptr)
+ {
memcpy(&data->ptr[data->len], ptr, realsize);
data->len += realsize;
- }
- return realsize;
+ }
+ return realsize;
}
/**
@@ -91,7 +91,7 @@ static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result)
headers = curl_slist_append(headers, buf);
curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers);
}
-
+
DBG2("sending http request to '%s'...", uri);
switch (curl_easy_perform(this->curl))
{
@@ -102,7 +102,7 @@ static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result)
status = SUCCESS;
break;
default:
- DBG1("libcurl http request failed: %s", error);
+ DBG1("libcurl http request failed: %s", error);
status = FAILED;
break;
}
@@ -158,7 +158,7 @@ static void destroy(private_curl_fetcher_t *this)
curl_fetcher_t *curl_fetcher_create()
{
private_curl_fetcher_t *this = malloc_thing(private_curl_fetcher_t);
-
+
this->curl = curl_easy_init();
if (this->curl == NULL)
{
@@ -166,11 +166,11 @@ curl_fetcher_t *curl_fetcher_create()
return NULL;
}
this->request_type = NULL;
-
+
this->public.interface.fetch = (status_t(*)(fetcher_t*,char*,chunk_t*))fetch;
this->public.interface.set_option = (bool(*)(fetcher_t*, fetcher_option_t option, ...))set_option;
this->public.interface.destroy = (void (*)(fetcher_t*))destroy;
-
+
return &this->public;
}
diff --git a/src/libstrongswan/settings.h b/src/libstrongswan/settings.h
index c487f7775..1434b410c 100644
--- a/src/libstrongswan/settings.h
+++ b/src/libstrongswan/settings.h
@@ -25,7 +25,7 @@
typedef struct settings_t settings_t;
-#include <library.h>
+#include <utils.h>
#include <utils/enumerator.h>
/**
diff --git a/src/libstrongswan/utils/enumerator.h b/src/libstrongswan/utils/enumerator.h
index 5899194a5..8af45ec10 100644
--- a/src/libstrongswan/utils/enumerator.h
+++ b/src/libstrongswan/utils/enumerator.h
@@ -25,7 +25,7 @@
typedef struct enumerator_t enumerator_t;
-#include <library.h>
+#include <utils.h>
/**
* Enumerate is simpler, but more flexible than iterator.
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 9497f3569..213642e9a 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -208,34 +208,22 @@ static void update_chunk(chunk_t *ch, int n)
* Remove any malicious characters from a chunk. We are very restrictive, but
* whe use these strings only to present it to the user.
*/
-static chunk_t sanitize_chunk(chunk_t chunk)
+static bool sanitize_chunk(chunk_t chunk, chunk_t *clone)
{
char *pos;
- chunk_t clone = chunk_clone(chunk);
+ bool all_printable = TRUE;
- for (pos = clone.ptr; pos < (char*)(clone.ptr + clone.len); pos++)
+ *clone = chunk_clone(chunk);
+
+ for (pos = clone->ptr; pos < (char*)(clone->ptr + clone->len); pos++)
{
- switch (*pos)
+ if (!isprint(*pos))
{
- case '\0':
- case ' ':
- case '*':
- case '-':
- case '.':
- case '/':
- case '0' ... '9':
- case ':':
- case '=':
- case '@':
- case 'A' ... 'Z':
- case '_':
- case 'a' ... 'z':
- break;
- default:
- *pos = '?';
+ *pos = '?';
+ all_printable = FALSE;
}
}
- return clone;
+ return all_printable;
}
/**
@@ -404,7 +392,7 @@ static bool dntoa(chunk_t dn, chunk_t *str)
update_chunk(str, snprintf(str->ptr,str->len,"%s", oid_names[oid_code].name));
}
/* print value */
- proper = sanitize_chunk(value);
+ sanitize_chunk(value, &proper);
update_chunk(str, snprintf(str->ptr,str->len,"=%.*s", (int)proper.len, proper.ptr));
chunk_free(&proper);
}
@@ -945,9 +933,8 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
case ID_FQDN:
case ID_RFC822_ADDR:
case ID_DER_ASN1_GN_URI:
- case ID_EAP:
case ID_IETF_ATTR_STRING:
- proper = sanitize_chunk(this->encoded);
+ sanitize_chunk(this->encoded, &proper);
snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
chunk_free(&proper);
break;
@@ -961,6 +948,16 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
snprintf(buf, sizeof(buf), "(ASN.1 general Name");
break;
case ID_KEY_ID:
+ if (sanitize_chunk(this->encoded, &proper))
+ { /* fully printable, use ascii version */
+ snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
+ }
+ else
+ { /* not printable, hex dump */
+ snprintf(buf, sizeof(buf), "%#B", &this->encoded);
+ }
+ chunk_free(&proper);
+ break;
case ID_PUBKEY_INFO_SHA1:
case ID_PUBKEY_SHA1:
case ID_CERT_DER_SHA1:
@@ -1043,8 +1040,9 @@ identification_t *identification_create_from_string(char *string)
*/
if (atodn(string, &this->encoded) != SUCCESS)
{
- free(this);
- return NULL;
+ this->type = ID_KEY_ID;
+ this->encoded = chunk_clone(chunk_create(string, strlen(string)));
+ return &this->public;
}
this->type = ID_DER_ASN1_DN;
this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
@@ -1084,11 +1082,11 @@ identification_t *identification_create_from_string(char *string)
(identification_t*,identification_t*))matches_string;
this->public.equals = (bool (*)
(identification_t*,identification_t*))equals_strcasecmp;
- return &(this->public);
+ return &this->public;
}
this->encoded = chunk_clone(chunk);
this->type = ID_IPV4_ADDR;
- return &(this->public);
+ return &this->public;
}
else
{
@@ -1098,12 +1096,14 @@ identification_t *identification_create_from_string(char *string)
if (inet_pton(AF_INET6, string, &address) <= 0)
{
- free(this);
- return NULL;
+ this->type = ID_KEY_ID;
+ this->encoded = chunk_clone(chunk_create(string,
+ strlen(string)));
+ return &this->public;
}
this->encoded = chunk_clone(chunk);
this->type = ID_IPV6_ADDR;
- return &(this->public);
+ return &this->public;
}
}
}
@@ -1117,7 +1117,7 @@ identification_t *identification_create_from_string(char *string)
this->type = ID_KEY_ID;
this->encoded = chunk_from_hex(
chunk_create(string, strlen(string)), NULL);
- return &(this->public);
+ return &this->public;
}
else
{
@@ -1128,7 +1128,7 @@ identification_t *identification_create_from_string(char *string)
(identification_t*,identification_t*))matches_string;
this->public.equals = (bool (*)
(identification_t*,identification_t*))equals_strcasecmp;
- return &(this->public);
+ return &this->public;
}
}
else
@@ -1140,7 +1140,7 @@ identification_t *identification_create_from_string(char *string)
(identification_t*,identification_t*))matches_string;
this->public.equals = (bool (*)
(identification_t*,identification_t*))equals_strcasecmp;
- return &(this->public);
+ return &this->public;
}
}
}
@@ -1180,7 +1180,6 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
case ID_PUBKEY_INFO_SHA1:
case ID_PUBKEY_SHA1:
case ID_CERT_DER_SHA1:
- case ID_EAP:
case ID_IETF_ATTR_STRING:
default:
break;
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index 6cfc7c473..90eadb625 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -143,16 +143,11 @@ enum id_type_t {
* SHA1 hash of the binary DER encoding of a certificate
*/
ID_CERT_DER_SHA1 = 204,
-
- /**
- * Generic EAP identity
- */
- ID_EAP = 205,
/**
* IETF Attribute Syntax String (RFC 3281)
*/
- ID_IETF_ATTR_STRING = 206,
+ ID_IETF_ATTR_STRING = 205,
};
/**
@@ -257,8 +252,11 @@ struct identification_t {
* N, G, I, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
* unstructuredName, TCGID.
*
+ * This constructor never returns NULL. If it does not find a suitable
+ * conversion function, it will copy the string to an ID_KEY_ID.
+ *
* @param string input string, which will be converted
- * @return created identification_t, NULL if not supported.
+ * @return identification_t
*/
identification_t * identification_create_from_string(char *string);
diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h
index b7152500c..7c388f764 100644
--- a/src/libstrongswan/utils/linked_list.h
+++ b/src/libstrongswan/utils/linked_list.h
@@ -27,7 +27,6 @@
typedef struct linked_list_t linked_list_t;
-#include <library.h>
#include <utils/iterator.h>
#include <utils/enumerator.h>
diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am
index f788bc3d1..d3e7ddc89 100644
--- a/src/pluto/Makefile.am
+++ b/src/pluto/Makefile.am
@@ -84,11 +84,12 @@ AM_CFLAGS = \
-DIPSEC_CONFDIR=\"${confdir}\" \
-DIPSEC_PIDDIR=\"${piddir}\" \
-DSHARED_SECRETS_FILE=\"${confdir}/ipsec.secrets\" \
+-DSTRONGSWAN_CONF=\"${strongswan_conf}\" \
-DKERNEL26_SUPPORT -DKERNEL26_HAS_KAME_DUPLICATES \
-DPLUTO -DKLIPS -DDEBUG
pluto_LDADD = \
-oid.o \
+oid.o debug.o linked_list.o enumerator.o settings.o \
$(LIBFREESWANDIR)/libfreeswan.a \
$(LIBCRYPTODIR)/libcrypto.a \
-lgmp -lresolv -lpthread -ldl
@@ -99,9 +100,22 @@ $(LIBFREESWANDIR)/libfreeswan.a \
dist_man_MANS = pluto.8 ipsec.secrets.5
+# Copy functions from libstrongswan
oid.o : $(LIBSTRONGSWANDIR)/asn1/oid.c $(LIBSTRONGSWANDIR)/asn1/oid.h
$(COMPILE) -c -o $@ $<
+debug.o : $(LIBSTRONGSWANDIR)/debug.c $(LIBSTRONGSWANDIR)/debug.h
+ $(COMPILE) -c -o $@ $<
+
+linked_list.o : $(LIBSTRONGSWANDIR)/utils/linked_list.c $(LIBSTRONGSWANDIR)/utils/linked_list.h
+ $(COMPILE) -c -o $@ $<
+
+enumerator.o : $(LIBSTRONGSWANDIR)/utils/enumerator.c $(LIBSTRONGSWANDIR)/utils/enumerator.h
+ $(COMPILE) -c -o $@ $<
+
+settings.o : $(LIBSTRONGSWANDIR)/settings.c $(LIBSTRONGSWANDIR)/settings.h
+ $(COMPILE) -c -o $@ $<
+
# This compile option activates the sending of a strongSwan VID
if USE_VENDORID
AM_CFLAGS += -DVENDORID
diff --git a/src/pluto/ac.c b/src/pluto/ac.c
index 12f4f68d8..171f6edec 100644
--- a/src/pluto/ac.c
+++ b/src/pluto/ac.c
@@ -321,7 +321,7 @@ static bool
same_attribute(const ietfAttr_t *a, const ietfAttr_t *b)
{
return (a->kind == b->kind && a->value.len == b->value.len
- && memcmp(a->value.ptr, b->value.ptr, b->value.len) == 0);
+ && memeq(a->value.ptr, b->value.ptr, b->value.len));
}
bool
diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c
index c998e54e9..ba2fead7a 100644
--- a/src/pluto/alg_info.c
+++ b/src/pluto/alg_info.c
@@ -171,12 +171,15 @@ static int
ealg_getbyname_esp(const char *const str, int len)
{
if (!str || !*str)
+ {
return -1;
+ }
/* leave special case for eg: "id248" string */
- if (strcmp("id", str) == 0)
+ if (streq("id", str))
+ {
return ESP_MAGIC_ID;
-
+ }
return enum_search_prefix(&esp_transformid_names, "ESP_", str, len);
}
diff --git a/src/pluto/constants.c b/src/pluto/constants.c
index 70215441b..7ae04e0c4 100644
--- a/src/pluto/constants.c
+++ b/src/pluto/constants.c
@@ -1208,14 +1208,20 @@ enum_search(enum_names *ed, const char *str)
unsigned en;
for (p = ed; p != NULL; p = p->en_next_range)
+ {
for (en = p->en_first; en <= p->en_last ;en++)
{
ptr = p->en_names[en - p->en_first];
- if (ptr == 0) continue;
- /* if (strncmp(ptr, str, strlen(ptr))==0) */
- if (strcmp(ptr, str) == 0)
- return en;
+ if (ptr == 0)
+ {
+ continue;
+ }
+ if (streq(ptr, str))
+ {
+ return en;
+ }
}
+ }
return -1;
}
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
index 13251dc3b..60f431049 100644
--- a/src/pluto/constants.h
+++ b/src/pluto/constants.h
@@ -19,6 +19,8 @@
#ifndef _CONSTANTS_H
#define _CONSTANTS_H
+#include <utils.h>
+
extern const char compile_time_interop_options[];
extern void init_constants(void);
@@ -39,17 +41,10 @@ extern void init_constants(void);
* <freeswan.h> defines err_t for this return type.
*/
-typedef int bool;
-#define FALSE 0
-#define TRUE 1
-
#define NULL_FD (-1) /* NULL file descriptor */
#define dup_any(fd) ((fd) == NULL_FD? NULL_FD : dup(fd))
#define close_any(fd) { if ((fd) != NULL_FD) { close(fd); (fd) = NULL_FD; } }
-#define BITS_PER_BYTE 8
-
-#define streq(a, b) (strcmp((a), (b)) == 0) /* clearer shorthand */
#define strcaseeq(a, b) (strcasecmp((a), (b)) == 0) /* clearer shorthand */
/* set type with room for at least 64 elements for ALG opts (was 32 in stock FS) */
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
index 70d075263..add131ca9 100644
--- a/src/pluto/crl.c
+++ b/src/pluto/crl.c
@@ -536,7 +536,7 @@ check_revocation(const x509crl_t *crl, chunk_t serial
{
/* compare serial numbers */
if (revokedCert->userCertificate.len == serial.len &&
- memcmp(revokedCert->userCertificate.ptr, serial.ptr, serial.len) == 0)
+ memeq(revokedCert->userCertificate.ptr, serial.ptr, serial.len))
{
*revocationDate = revokedCert->revocationDate;
*revocationReason = revokedCert->revocationReason;
diff --git a/src/pluto/defs.h b/src/pluto/defs.h
index 44e012665..30a152120 100644
--- a/src/pluto/defs.h
+++ b/src/pluto/defs.h
@@ -32,10 +32,6 @@
# define USED_BY_DEBUG UNUSED
#endif
-/* Length of temporary buffers */
-
-#define BUF_LEN 512
-
/* type of serial number of a state object
* Needed in connections.h and state.h; here to simplify dependencies.
*/
@@ -118,9 +114,6 @@ typedef struct {
int fd;
} prompt_pass_t;
-/* no time defined in time_t */
-#define UNDEFINED_TIME 0
-
/* size of timetoa string buffer */
#define TIMETOA_BUF 30
diff --git a/src/pluto/demux.c b/src/pluto/demux.c
index 4a28367e1..94a7f714d 100644
--- a/src/pluto/demux.c
+++ b/src/pluto/demux.c
@@ -1713,7 +1713,7 @@ process_packet(struct msg_digest **mdp)
if (st != NULL
&& st->st_rpacket.ptr != NULL
&& st->st_rpacket.len == pbs_room(&md->packet_pbs)
- && memcmp(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len) == 0)
+ && memeq(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len))
{
if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE)
{
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c
index 284ade0d1..e33de6168 100644
--- a/src/pluto/fetch.c
+++ b/src/pluto/fetch.c
@@ -905,7 +905,7 @@ add_distribution_points(const generalName_t *newPoints ,generalName_t **distribu
{
if (gn->kind == newPoints->kind
&& gn->name.len == newPoints->name.len
- && memcmp(gn->name.ptr, newPoints->name.ptr, gn->name.len) == 0)
+ && memeq(gn->name.ptr, newPoints->name.ptr, gn->name.len))
{
/* skip if the distribution point is already present */
add = FALSE;
diff --git a/src/pluto/id.c b/src/pluto/id.c
index 6c27baac0..c21bab7b2 100644
--- a/src/pluto/id.c
+++ b/src/pluto/id.c
@@ -423,7 +423,7 @@ same_id(const struct id *a, const struct id *b)
case ID_KEY_ID:
return a->name.len == b->name.len
- && memcmp(a->name.ptr, b->name.ptr, a->name.len) == 0;
+ && memeq(a->name.ptr, b->name.ptr, a->name.len);
default:
bad_case(a->kind);
diff --git a/src/pluto/ike_alg.c b/src/pluto/ike_alg.c
index 4f8b88170..5e34b272d 100644
--- a/src/pluto/ike_alg.c
+++ b/src/pluto/ike_alg.c
@@ -464,8 +464,8 @@ ike_hash_test(const struct hash_desc *desc)
desc->hash_update(&ctx, desc->hash_testvectors[i].msg
,desc->hash_testvectors[i].msg_size);
desc->hash_final(digest, &ctx);
- result = memcmp(digest, desc->hash_testvectors[i].msg_digest
- , desc->hash_digest_size) == 0;
+ result = memeq(digest, desc->hash_testvectors[i].msg_digest
+ , desc->hash_digest_size);
DBG(DBG_CRYPT,
DBG_log(" hash testvector %d: %s", i, result ? "ok":"failed")
)
@@ -495,8 +495,8 @@ ike_hash_test(const struct hash_desc *desc)
hmac_update(&ctx, desc->hmac_testvectors[i].msg
,desc->hmac_testvectors[i].msg_size);
hmac_final(digest, &ctx);
- result = memcmp(digest, desc->hmac_testvectors[i].hmac
- , desc->hash_digest_size) == 0;
+ result = memeq(digest, desc->hmac_testvectors[i].hmac
+ , desc->hash_digest_size);
DBG(DBG_CRYPT,
DBG_log(" hmac testvector %d: %s", i, result ? "ok":"failed")
)
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
index 09b4bbaaf..98841bcee 100644
--- a/src/pluto/kernel.c
+++ b/src/pluto/kernel.c
@@ -2955,7 +2955,7 @@ was_eroute_idle(struct state *st, time_t idle_max, time_t *idle_time)
break;
}
- if (strncmp(line, text_said, strlen(text_said)) == 0)
+ if (strneq(line, text_said, strlen(text_said)))
{
/* we found a match, now try to find idle= */
char *p = strstr(line, idle);
diff --git a/src/pluto/keys.c b/src/pluto/keys.c
index 6cdf169d8..0c9f53929 100644
--- a/src/pluto/keys.c
+++ b/src/pluto/keys.c
@@ -253,7 +253,7 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
{
case PPK_PSK:
same = s->u.preshared_secret.len == best->u.preshared_secret.len
- && memcmp(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len) == 0;
+ && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len);
break;
case PPK_RSA:
/* Dirty trick: since we have code to compare
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c
index 967a0b2a5..45c7230bc 100644
--- a/src/pluto/modecfg.c
+++ b/src/pluto/modecfg.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <freeswan.h>
+#include <settings.h>
#include "constants.h"
#include "defs.h"
@@ -42,6 +43,8 @@
#include "xauth.h"
#define MAX_XAUTH_TRIES 3
+#define DNS_SERVER_MAX 2
+#define NBNS_SERVER_MAX 2
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
| LELEM(INTERNAL_IP4_NETMASK) \
@@ -54,6 +57,8 @@
#define UNITY_BANNER_STR "Welcome to strongSwan - the Linux VPN Solution!\n"
+extern settings_t *settings;
+
/*
* Addresses assigned (usually via ModeCfg) to the Initiator
*/
@@ -67,8 +72,8 @@ struct internal_addr
/* ModeCfg variables */
ip_address ipaddr;
- ip_address dns[2];
- ip_address wins[2];
+ ip_address dns[DNS_SERVER_MAX];
+ ip_address nbns[NBNS_SERVER_MAX];
char *unity_banner;
@@ -84,6 +89,8 @@ struct internal_addr
static void
init_internal_addr(internal_addr_t *ia)
{
+ int i;
+
ia->attr_set = LEMPTY;
ia->xauth_attr_set = LEMPTY;
ia->xauth_secret.user_name = empty_chunk;
@@ -94,10 +101,18 @@ init_internal_addr(internal_addr_t *ia)
ia->unity_banner = NULL;
anyaddr(AF_INET, &ia->ipaddr);
- anyaddr(AF_INET, &ia->dns[0]);
- anyaddr(AF_INET, &ia->dns[1]);
- anyaddr(AF_INET, &ia->wins[0]);
- anyaddr(AF_INET, &ia->wins[1]);
+
+ /* initialize DNS server information */
+ for (i = 0; i < DNS_SERVER_MAX; i++)
+ {
+ anyaddr(AF_INET, &ia->dns[i]);
+ }
+
+ /* initialize WINS server information */
+ for (i = 0; i < NBNS_SERVER_MAX; i++)
+ {
+ anyaddr(AF_INET, &ia->nbns[i]);
+ }
}
/*
@@ -106,6 +121,8 @@ init_internal_addr(internal_addr_t *ia)
static void
get_internal_addr(struct connection *c, internal_addr_t *ia)
{
+ int i, dns_idx = 0, nbns_idx = 0;
+
if (isanyaddr(&c->spd.that.host_srcip))
{
/* not defined in connection - fetch it from LDAP */
@@ -130,13 +147,60 @@ get_internal_addr(struct connection *c, internal_addr_t *ia)
| LELEM(INTERNAL_IP4_NETMASK);
}
- if (!isanyaddr(&ia->dns[0])) /* We got DNS addresses, send them */
- ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
+ /* assign DNS servers */
+ for (i = 1; i <= DNS_SERVER_MAX; i++)
+ {
+ char dns_key[16], *dns_str;
+
+ snprintf(dns_key, sizeof(dns_key), "pluto.dns%d", i);
+ dns_str = settings->get_str(settings, dns_key, NULL);
+ if (dns_str)
+ {
+ err_t ugh;
+ sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET;
- if (!isanyaddr(&ia->wins[0])) /* We got WINS addresses, send them */
- ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
+ ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]);
+ if (ugh != NULL)
+ {
+ plog("error in DNS server address: %s", ugh);
+ continue;
+ }
+ plog("assigning DNS server %s to peer", dns_str);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
+ dns_idx++;
+ }
+ }
+
+ /* assign WINS servers */
+ for (i = 1; i <= NBNS_SERVER_MAX; i++)
+ {
+ char nbns_key[16], *nbns_str;
+
+ snprintf(nbns_key, sizeof(nbns_key), "pluto.nbns%d", i);
+ nbns_str = settings->get_str(settings, nbns_key, NULL);
+ if (nbns_str)
+ {
+ err_t ugh;
+ sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET;
+
+ ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]);
+ if (ugh != NULL)
+ {
+ plog("error in WINS server address: %s", ugh);
+ continue;
+ }
+ plog("assigning NBNS server %s to peer", nbns_str);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
+ nbns_idx++;
+ }
+ }
}
+
/*
* Set srcip and client subnet to internal IP address
*/
@@ -218,8 +282,8 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
struct isakmp_mode_attr attrh;
struct isakmp_attribute attr;
pb_stream strattr,attrval;
- int attr_type;
- int dns_idx, wins_idx;
+ int attr_type, dns_attr_type, nbns_attr_type;
+ int dns_idx, nbns_idx;
bool dont_advance;
bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY;
bool is_unity_attr_set = ia->unity_attr_set != LEMPTY;
@@ -230,11 +294,12 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
attrh.isama_identifier = ap_id;
if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
+ {
return STF_INTERNAL_ERROR;
-
+ }
attr_type = 0;
dns_idx = 0;
- wins_idx = 0;
+ nbns_idx = 0;
while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set)
{
@@ -272,6 +337,20 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
attr.isaat_lv = ia->xauth_status;
}
+ else if (attr_type == INTERNAL_IP4_DNS && !isanyaddr(&ia->dns[dns_idx]))
+ {
+ dns_attr_type = (addrtypeof(&ia->dns[dns_idx]) == AF_INET) ?
+ INTERNAL_IP4_DNS : INTERNAL_IP6_DNS;
+ attr.isaat_af_type = dns_attr_type | ISAKMP_ATTR_AF_TLV;
+
+ }
+ else if (attr_type == INTERNAL_IP4_NBNS && !isanyaddr(&ia->nbns[nbns_idx]))
+ {
+ nbns_attr_type = (addrtypeof(&ia->nbns[nbns_idx]) == AF_INET) ?
+ INTERNAL_IP4_NBNS : INTERNAL_IP6_NBNS;
+ attr.isaat_af_type = nbns_attr_type | ISAKMP_ATTR_AF_TLV;
+
+ }
else
{
attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
@@ -303,10 +382,14 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
}
#endif
if (st->st_connection->spd.this.client.maskbits == 0)
+ {
mask = 0;
+ }
else
+ {
mask = 0xffffffff * 1;
out_raw(&mask, 4, &attrval, "IP4_mask");
+ }
}
break;
case INTERNAL_IP4_SUBNET:
@@ -318,13 +401,12 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
for (t = 0; t < 4; t++)
{
- if (m < 8)
- mask[t] = bits[m];
- else
- mask[t] = 0xff;
+ mask[t] = (m < 8) ? bits[m] : 0xff;
m -= 8;
if (m < 0)
+ {
m = 0;
+ }
}
len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);
out_raw(byte_ptr, len, &attrval, "IP4_subnet");
@@ -332,23 +414,25 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
}
break;
case INTERNAL_IP4_DNS:
+ case INTERNAL_IP6_DNS:
if (!isanyaddr(&ia->dns[dns_idx]))
{
len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_dns");
+ out_raw(byte_ptr, len, &attrval, "IP_dns");
}
- if (dns_idx < 2 && !isanyaddr(&ia->dns[dns_idx]))
+ if (dns_idx < DNS_SERVER_MAX && !isanyaddr(&ia->dns[dns_idx]))
{
dont_advance = TRUE;
}
break;
case INTERNAL_IP4_NBNS:
- if (!isanyaddr(&ia->wins[wins_idx]))
+ case INTERNAL_IP6_NBNS:
+ if (!isanyaddr(&ia->nbns[nbns_idx]))
{
- len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_wins");
+ len = addrbytesptr(&ia->nbns[nbns_idx++], &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP_nbns");
}
- if (wins_idx < 2 && !isanyaddr(&ia->wins[wins_idx]))
+ if (nbns_idx < NBNS_SERVER_MAX && !isanyaddr(&ia->nbns[nbns_idx]))
{
dont_advance = TRUE;
}
@@ -619,7 +703,9 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
}
if (stat != STF_OK)
+ {
return stat;
+ }
}
return STF_IGNORE;
}
@@ -642,7 +728,9 @@ modecfg_send_request(struct state *st)
st->st_state = STATE_MODE_CFG_I1;
stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
if (stat == STF_OK)
+ {
st->st_modecfg.started = TRUE;
+ }
return stat;
}
@@ -662,10 +750,11 @@ modecfg_inR0(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
+ }
want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
-
init_internal_addr(&ia);
get_internal_addr(st->st_connection, &ia);
@@ -682,8 +771,9 @@ modecfg_inR0(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
st->st_msgid = 0;
return STF_OK;
}
@@ -705,8 +795,9 @@ modecfg_inI1(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
st->st_msgid = 0;
return STF_OK;
@@ -734,7 +825,9 @@ modecfg_send_set(struct state *st)
st->st_state = STATE_MODE_CFG_R3;
stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
if (stat == STF_OK)
+ {
st->st_modecfg.started = TRUE;
+ }
return stat;
}
@@ -756,8 +849,9 @@ modecfg_inI0(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
/* prepare ModeCfg ack which sends zero length attributes */
@@ -774,8 +868,9 @@ modecfg_inI0(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
st->st_msgid = 0;
return STF_OK;
}
@@ -797,8 +892,9 @@ modecfg_inR3(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_msgid = 0;
return STF_OK;
}
@@ -820,7 +916,9 @@ xauth_send_request(struct state *st)
st->st_state = STATE_XAUTH_R1;
stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
if (stat == STF_OK)
+ {
st->st_xauth.started = TRUE;
+ }
return stat;
}
@@ -842,8 +940,10 @@ xauth_inI0(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
+
/* check XAUTH attributes */
xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY;
@@ -890,7 +990,9 @@ xauth_inI0(struct msg_digest *md)
ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
| LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
if (xauth_type_present)
+ {
ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE);
+ }
}
else
{
@@ -905,8 +1007,9 @@ xauth_inI0(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
if (stat == STF_OK)
{
st->st_xauth.started = TRUE;
@@ -942,8 +1045,10 @@ xauth_inR1(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
+
/* did the client return an XAUTH FAIL status? */
if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY)
{
@@ -997,7 +1102,9 @@ xauth_inR1(struct msg_digest *md)
stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
if (stat_build != STF_OK)
+ {
return stat_build;
+ }
return STF_OK;
}
@@ -1033,8 +1140,9 @@ xauth_inI1(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
if (st->st_xauth.status)
{
st->st_msgid = 0;
@@ -1069,8 +1177,9 @@ xauth_inR2(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_msgid = 0;
if (st->st_xauth.status)
{
diff --git a/src/pluto/nat_traversal.c b/src/pluto/nat_traversal.c
index 5566d3d25..1a5085eeb 100644
--- a/src/pluto/nat_traversal.c
+++ b/src/pluto/nat_traversal.c
@@ -237,7 +237,7 @@ void nat_traversal_natd_lookup(struct msg_digest *md)
&(md->iface->addr), ntohs(st->st_connection->spd.this.host_port));
if (!(pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
- memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len) == 0))
+ memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)))
{
#ifdef NAT_D_DEBUG
DBG(DBG_NATT,
@@ -258,7 +258,7 @@ void nat_traversal_natd_lookup(struct msg_digest *md)
for (p = p->next, i=0 ; p != NULL; p = p->next)
{
if (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len &&
- memcmp(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len) == 0)
+ memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len))
{
i++;
}
diff --git a/src/pluto/pem.c b/src/pluto/pem.c
index 14792d49f..396eb3d1c 100644
--- a/src/pluto/pem.c
+++ b/src/pluto/pem.c
@@ -45,7 +45,7 @@ present(const char* pattern, chunk_t* ch)
{
u_int pattern_len = strlen(pattern);
- if (ch->len >= pattern_len && strncmp(ch->ptr, pattern, pattern_len) == 0)
+ if (ch->len >= pattern_len && strneq(ch->ptr, pattern, pattern_len))
{
ch->ptr += pattern_len;
ch->len -= pattern_len;
@@ -60,8 +60,7 @@ present(const char* pattern, chunk_t* ch)
static bool
match(const char *pattern, const chunk_t *ch)
{
- return ch->len == strlen(pattern) &&
- strncmp(pattern, ch->ptr, ch->len) == 0;
+ return ch->len == strlen(pattern) && strneq(pattern, ch->ptr, ch->len);
}
/*
diff --git a/src/pluto/pgp.c b/src/pluto/pgp.c
index aab9bff67..f6744fd8a 100644
--- a/src/pluto/pgp.c
+++ b/src/pluto/pgp.c
@@ -521,7 +521,7 @@ static bool
same_pgpcert(pgpcert_t *a, pgpcert_t *b)
{
return a->certificate.len == b->certificate.len &&
- memcmp(a->certificate.ptr, b->certificate.ptr, b->certificate.len) == 0;
+ memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len);
}
/*
@@ -531,7 +531,9 @@ void
share_pgpcert(pgpcert_t *cert)
{
if (cert != NULL)
+ {
cert->count++;
+ }
}
/*
diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c
index b7bb8df98..eedbf2532 100644
--- a/src/pluto/plutomain.c
+++ b/src/pluto/plutomain.c
@@ -38,6 +38,7 @@
#endif /* CAPABILITIES */
#include <freeswan.h>
+#include <settings.h>
#include <pfkeyv2.h>
#include <pfkey.h>
@@ -197,6 +198,9 @@ delete_lock(void)
}
}
+/* settings defined by strongswan.conf */
+settings_t *settings;
+
/* by default pluto sends certificate requests to its peers */
bool no_cr_send = FALSE;
@@ -239,6 +243,9 @@ main(int argc, char **argv)
int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
#endif /* CAPABILITIES */
+ /* getting settings from strongswan.conf */
+ settings = settings_create(STRONGSWAN_CONF);
+
/* handle arguments */
for (;;)
{
@@ -703,6 +710,7 @@ exit_pluto(int status)
free_ifaces();
scx_finalize(); /* finalize and unload PKCS #11 module */
xauth_finalize(); /* finalize and unload XAUTH module */
+ settings->destroy(settings);
stop_adns();
free_md_pool();
delete_lock();
diff --git a/src/pluto/server.c b/src/pluto/server.c
index c14f72698..cae16294e 100644
--- a/src/pluto/server.c
+++ b/src/pluto/server.c
@@ -544,8 +544,10 @@ process_raw_ifaces(struct raw_iface *rifaces)
struct raw_iface *vfp;
/* ignore if virtual (ipsec*) interface */
- if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0)
+ if (strneq(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1))
+ {
continue;
+ }
for (vfp = rifaces; vfp != NULL; vfp = vfp->next)
{
@@ -558,7 +560,7 @@ process_raw_ifaces(struct raw_iface *rifaces)
/* Different entries with matching IP addresses.
* Many interesting cases.
*/
- if (strncmp(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0)
+ if (strneq(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1))
{
if (v != NULL && !streq(v->name, vfp->name))
{
diff --git a/src/pluto/smartcard.c b/src/pluto/smartcard.c
index a458d528a..64c36c7c9 100644
--- a/src/pluto/smartcard.c
+++ b/src/pluto/smartcard.c
@@ -787,7 +787,7 @@ scx_finalize(void)
bool
scx_on_smartcard(const char *filename)
{
- return strncmp(filename, SCX_TOKEN, strlen(SCX_TOKEN)) == 0;
+ return strneq(filename, SCX_TOKEN, strlen(SCX_TOKEN));
}
#ifdef SMARTCARD
@@ -1619,7 +1619,7 @@ scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op
if (keyid != NULL)
{
- number_slot_id = (strncmp(keyid, SCX_TOKEN, strlen(SCX_TOKEN)) == 0)
+ number_slot_id = (strneq(keyid, SCX_TOKEN, strlen(SCX_TOKEN)))
? keyid + strlen(SCX_TOKEN) : keyid;
}
diff --git a/src/pluto/state.c b/src/pluto/state.c
index d1587a1a5..0b223e615 100644
--- a/src/pluto/state.c
+++ b/src/pluto/state.c
@@ -578,14 +578,19 @@ find_state(const u_char *icookie
struct state *st = *state_hash(icookie, rcookie, peer);
while (st != (struct state *) NULL)
+ {
if (sameaddr(peer, &st->st_connection->spd.that.host_addr)
- && memcmp(icookie, st->st_icookie, COOKIE_SIZE) == 0
- && memcmp(rcookie, st->st_rcookie, COOKIE_SIZE) == 0
+ && memeq(icookie, st->st_icookie, COOKIE_SIZE)
+ && memeq(rcookie, st->st_rcookie, COOKIE_SIZE)
&& msgid == st->st_msgid)
+ {
break;
+ }
else
+ {
st = st->st_hashchain_next;
-
+ }
+ }
DBG(DBG_CONTROL,
if (st == NULL)
DBG_log("state object not found");
@@ -607,13 +612,20 @@ find_sender(size_t packet_len, u_char *packet)
struct state *st;
if (packet_len >= sizeof(struct isakmp_hdr))
+ {
for (i = 0; i < STATE_TABLE_SIZE; i++)
+ {
for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ {
if (st->st_tpacket.ptr != NULL
&& st->st_tpacket.len == packet_len
- && memcmp(st->st_tpacket.ptr, packet, packet_len) == 0)
+ && memeq(st->st_tpacket.ptr, packet, packet_len))
+ {
return st;
-
+ }
+ }
+ }
+ }
return NULL;
}
diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c
index 4f0e6d43a..609366452 100644
--- a/src/pluto/vendor.c
+++ b/src/pluto/vendor.c
@@ -497,7 +497,7 @@ handle_vendorid (struct msg_digest *md, const char *vid, size_t len)
{
if (pvid->vid_len == len)
{
- if (memcmp(pvid->vid, vid, len) == 0)
+ if (memeq(pvid->vid, vid, len))
{
handle_known_vendorid(md, vid, len, pvid);
return;
@@ -505,7 +505,7 @@ handle_vendorid (struct msg_digest *md, const char *vid, size_t len)
}
else if ((pvid->vid_len < len) && (pvid->flags & VID_SUBSTRING))
{
- if (memcmp(pvid->vid, vid, pvid->vid_len) == 0)
+ if (memeq(pvid->vid, vid, pvid->vid_len))
{
handle_known_vendorid(md, vid, len, pvid);
return;
diff --git a/src/pluto/virtual.c b/src/pluto/virtual.c
index cf036cc7b..9deceb224 100644
--- a/src/pluto/virtual.c
+++ b/src/pluto/virtual.c
@@ -54,11 +54,11 @@ _read_subnet(const char *src, size_t len, ip_subnet *dst, ip_subnet *dstko,
bool ok;
int af;
- if ((len > 4) && (strncmp(src, "%v4:", 4)==0))
+ if ((len > 4) && (strneq(src, "%v4:", 4)))
{
af = AF_INET;
}
- else if ((len > 4) && (strncmp(src, "%v6:", 4)==0))
+ else if ((len > 4) && (strneq(src, "%v6:", 4)))
{
af = AF_INET6;
}
@@ -196,12 +196,12 @@ struct virtual_t
if (!string || string[0] == '\0')
return NULL;
- if (strlen(string) >= 6 && strncmp(string,"vhost:",6) == 0)
+ if (strlen(string) >= 6 && strneq(string,"vhost:",6))
{
flags |= F_VIRTUAL_HOST;
str += 6;
}
- else if (strlen(string) >= 5 && strncmp(string,"vnet:",5) == 0)
+ else if (strlen(string) >= 5 && strneq(string,"vnet:",5))
str += 5;
else
goto fail;
@@ -213,17 +213,17 @@ struct virtual_t
{
next = strchr(str,',');
if (!next) next = str + strlen(str);
- if (next-str == 3 && strncmp(str, "%no", 3) == 0)
+ if (next-str == 3 && strneq(str, "%no", 3))
flags |= F_VIRTUAL_NO;
#if 0
- else if (next-str == 4 && strncmp(str, "%ike", 4) == 0)
+ else if (next-str == 4 && strneq(str, "%ike", 4))
flags |= F_VIRTUAL_IKE_CONFIG;
- else if (next-str == 5 && strncmp(str, "%dhcp", 5) == 0)
+ else if (next-str == 5 && strneq(str, "%dhcp", 5))
flags |= F_VIRTUAL_DHCP;
#endif
- else if (next-str == 5 && strncmp(str, "%priv", 5) == 0)
+ else if (next-str == 5 && strneq(str, "%priv", 5))
flags |= F_VIRTUAL_PRIVATE;
- else if (next-str == 4 && strncmp(str, "%all", 4) == 0)
+ else if (next-str == 4 && strneq(str, "%all", 4))
flags |= F_VIRTUAL_ALL;
else if (_read_subnet(str, next-str, &sub, NULL, NULL))
{
diff --git a/src/pluto/x509.c b/src/pluto/x509.c
index 3c6d85f07..e6f7b24e0 100644
--- a/src/pluto/x509.c
+++ b/src/pluto/x509.c
@@ -423,8 +423,9 @@ init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
rdn->len = asn1_length(&dn);
if (rdn->len == ASN1_INVALID_LENGTH)
+ {
return "Invalid RDN length";
-
+ }
rdn->ptr = dn.ptr;
/* are there any RDNs ? */
@@ -451,13 +452,15 @@ get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value
{
/* an RDN is a SET OF attributeTypeAndValue */
if (*rdn->ptr != ASN1_SET)
+ {
return "RDN is not a SET";
-
+ }
attribute->len = asn1_length(rdn);
if (attribute->len == ASN1_INVALID_LENGTH)
+ {
return "Invalid attribute length";
-
+ }
attribute->ptr = rdn->ptr;
/* advance to start of next RDN */
@@ -467,14 +470,17 @@ get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value
/* an attributeTypeAndValue is a SEQUENCE */
if (*attribute->ptr != ASN1_SEQUENCE)
+ {
return "attributeTypeAndValue is not a SEQUENCE";
+ }
/* extract the attribute body */
body.len = asn1_length(attribute);
if (body.len == ASN1_INVALID_LENGTH)
+ {
return "Invalid attribute body length";
-
+ }
body.ptr = attribute->ptr;
/* advance to start of next attribute */
@@ -483,14 +489,17 @@ get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value
/* attribute type is an OID */
if (*body.ptr != ASN1_OID)
+ {
return "attributeType is not an OID";
+ }
/* extract OID */
oid->len = asn1_length(&body);
- if (oid->len == ASN1_INVALID_LENGTH)
+ if (oid->len == ASN1_INVALID_LENGTH)
+ {
return "Invalid attribute OID length";
-
+ }
oid->ptr = body.ptr;
/* advance to the attribute value */
@@ -504,8 +513,9 @@ get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value
value->len = asn1_length(&body);
if (value->len == ASN1_INVALID_LENGTH)
+ {
return "Invalid attribute string length";
-
+ }
value->ptr = body.ptr;
/* are there any RDNs left? */
@@ -529,27 +539,39 @@ dn_parse(chunk_t dn, chunk_t *str)
err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
if (ugh != NULL) /* a parsing error has occured */
+ {
return ugh;
+ }
while (next)
{
ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
if (ugh != NULL) /* a parsing error has occured */
+ {
return ugh;
+ }
if (first) /* first OID/value pair */
+ {
first = FALSE;
+ }
else /* separate OID/value pair by a comma */
+ {
update_chunk(str, snprintf(str->ptr,str->len,", "));
+ }
/* print OID */
oid_code = known_oid(oid);
if (oid_code == OID_UNKNOWN) /* OID not found in list */
+ {
hex_str(oid, str);
+ }
else
+ {
update_chunk(str, snprintf(str->ptr,str->len,"%s",
oid_names[oid_code].name));
+ }
/* print value */
update_chunk(str, snprintf(str->ptr,str->len,"=%.*s",
@@ -572,16 +594,22 @@ dn_count_wildcards(chunk_t dn)
err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
if (ugh != NULL) /* a parsing error has occured */
+ {
return -1;
+ }
while (next)
{
ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
if (ugh != NULL) /* a parsing error has occured */
+ {
return -1;
+ }
if (value.len == 1 && *value.ptr == '*')
+ {
wildcards++; /* we have found a wildcard RDN */
+ }
}
return wildcards;
}
@@ -631,9 +659,13 @@ int
dntoa_or_null(char *dst, size_t dstlen, chunk_t dn, const char* null_dn)
{
if (dn.ptr == NULL)
+ {
return snprintf(dst, dstlen, "%s", null_dn);
+ }
else
+ {
return dntoa(dst, dstlen, dn);
+ }
}
/* Converts an LDAP-style human-readable ASCII-encoded
@@ -692,14 +724,18 @@ atodn(char *src, chunk_t *dn)
break;
case READ_OID:
if (*src != ' ' && *src != '=')
+ {
oid.len++;
+ }
else
{
for (pos = 0; pos < X501_RDN_ROOF; pos++)
{
if (strlen(x501rdns[pos].name) == oid.len &&
strncasecmp(x501rdns[pos].name, oid.ptr, oid.len) == 0)
+ {
break; /* found a valid OID */
+ }
}
if (pos == X501_RDN_ROOF)
{
@@ -728,9 +764,13 @@ atodn(char *src, chunk_t *dn)
{
name.len++;
if (*src == ' ')
+ {
whitespace++;
+ }
else
+ {
whitespace = 0;
+ }
}
else
{
@@ -796,16 +836,22 @@ same_dn(chunk_t a, chunk_t b)
/* same lengths for the DNs */
if (a.len != b.len)
+ {
return FALSE;
+ }
/* try a binary comparison first */
- if (memcmp(a.ptr, b.ptr, b.len) == 0)
+ if (memeq(a.ptr, b.ptr, b.len))
+ {
return TRUE;
-
+ }
+
/* initialize DN parsing */
if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
|| init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
+ {
return FALSE;
+ }
/* fetch next RDN pair */
while (next_a && next_b)
@@ -819,28 +865,38 @@ same_dn(chunk_t a, chunk_t b)
/* OIDs must agree */
if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
+ {
return FALSE;
+ }
/* same lengths for values */
if (value_a.len != value_b.len)
+ {
return FALSE;
+ }
/* printableStrings and email RDNs require uppercase comparison */
if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
(type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
{
if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
return FALSE;
+ }
}
else
{
if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
return FALSE;
+ }
}
}
/* both DNs must have same number of RDNs */
if (next_a || next_b)
+ {
return FALSE;
+ }
/* the two DNs are equal! */
return TRUE;
@@ -864,7 +920,9 @@ match_dn(chunk_t a, chunk_t b, int *wildcards)
/* initialize DN parsing */
if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
|| init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
+ {
return FALSE;
+ }
/* fetch next RDN pair */
while (next_a && next_b)
@@ -878,7 +936,9 @@ match_dn(chunk_t a, chunk_t b, int *wildcards)
/* OIDs must agree */
if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
+ {
return FALSE;
+ }
/* does rdn_b contain a wildcard? */
if (value_b.len == 1 && *value_b.ptr == '*')
@@ -889,24 +949,33 @@ match_dn(chunk_t a, chunk_t b, int *wildcards)
/* same lengths for values */
if (value_a.len != value_b.len)
+ {
return FALSE;
+ }
/* printableStrings and email RDNs require uppercase comparison */
if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
(type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))
{
if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
return FALSE;
+ }
}
else
{
if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
+ {
return FALSE;
+ }
}
}
+
/* both DNs must have same number of RDNs */
if (next_a || next_b)
+ {
return FALSE;
+ }
/* the two DNs match! */
return TRUE;
@@ -928,7 +997,9 @@ void
share_x509cert(x509cert_t *cert)
{
if (cert != NULL)
+ {
cert->count++;
+ }
}
/*
@@ -1009,8 +1080,9 @@ bool
same_keyid(chunk_t a, chunk_t b)
{
if (a.ptr == NULL || b.ptr == NULL)
+ {
return FALSE;
-
+ }
return same_chunk(a, b);
}
@@ -1022,8 +1094,9 @@ same_serial(chunk_t a, chunk_t b)
{
/* do not compare serial numbers if one of them is not defined */
if (a.ptr == NULL || b.ptr == NULL)
+ {
return TRUE;
-
+ }
return same_chunk(a, b);
}
@@ -1175,7 +1248,9 @@ release_x509cert(x509cert_t *cert)
{
x509cert_t **pp = &x509certs;
while (*pp != cert)
+ {
pp = &(*pp)->next;
+ }
*pp = cert->next;
free_x509cert(cert);
}
@@ -1215,7 +1290,9 @@ store_x509certs(x509cert_t **firstcert, bool strict)
}
}
else
+ {
pp = &cert->next;
+ }
}
/* now verify the candidate CA certs */
@@ -1330,9 +1407,13 @@ check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg
DBG(DBG_PARSING,
if (digest_alg != OID_UNKNOWN)
+ {
DBG_log("signature digest algorithm: '%s'",oid_names[digest_alg].name);
+ }
else
+ {
DBG_log("unknown signature digest algorithm");
+ }
)
if (!compute_digest(tbs, digest_alg, &digest))
@@ -1349,9 +1430,13 @@ check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg
DBG(DBG_PARSING,
if (enc_alg != OID_UNKNOWN)
+ {
DBG_log("signature encryption algorithm: '%s'",oid_names[enc_alg].name);
+ }
else
+ {
DBG_log("unknown signature encryption algorithm");
+ }
)
if (!decrypt_sig(sig, enc_alg, issuer_cert, &decrypted))
@@ -1361,7 +1446,7 @@ check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg
}
/* check if digests are equal */
- return !memcmp(decrypted.ptr, digest.ptr, digest.len);
+ return memeq(decrypted.ptr, digest.ptr, digest.len);
}
/*
@@ -1382,8 +1467,9 @@ parse_basicConstraints(chunk_t blob, int level0)
if (!extract_object(basicConstraintsObjects, &objectID,
&object,&level, &ctx))
+ {
break;
-
+ }
if (objectID == BASIC_CONSTRAINTS_CA)
{
isCA = object.len && *object.ptr;
@@ -1460,7 +1546,9 @@ parse_otherName(chunk_t blob, int level0)
while (objectID < ON_OBJ_ROOF)
{
if (!extract_object(otherNameObjects, &objectID, &object, &level, &ctx))
+ {
return FALSE;
+ }
switch (objectID)
{
@@ -1505,7 +1593,9 @@ parse_generalName(chunk_t blob, int level0)
bool valid_gn = FALSE;
if (!extract_object(generalNameObjects, &objectID, &object, &level, &ctx))
+ {
return NULL;
+ }
switch (objectID) {
case GN_OBJ_RFC822_NAME:
@@ -1574,8 +1664,9 @@ parse_generalNames(chunk_t blob, int level0, bool implicit)
while (objectID < GENERAL_NAMES_ROOF)
{
if (!extract_object(generalNamesObjects, &objectID, &object, &level, &ctx))
+ {
return NULL;
-
+ }
if (objectID == GENERAL_NAMES_GN)
{
generalName_t *gn = parse_generalName(object, level+1);
@@ -1599,10 +1690,10 @@ chunk_t get_directoryName(chunk_t blob, int level, bool implicit)
generalName_t * gn = parse_generalNames(blob, level, implicit);
if (gn != NULL && gn->kind == GN_DIRECTORY_NAME)
+ {
name= gn->name;
-
+ }
free_generalNames(gn, FALSE);
-
return name;
}
@@ -1622,8 +1713,9 @@ parse_time(chunk_t blob, int level0)
while (objectID < TIME_ROOF)
{
if (!extract_object(timeObjects, &objectID, &object, &level, &ctx))
+ {
return UNDEFINED_TIME;
-
+ }
if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
{
return asn1totime(&object, (objectID == TIME_UTC)
@@ -1668,9 +1760,11 @@ parse_authorityKeyIdentifier(chunk_t blob, int level0
while (objectID < AUTH_KEY_ID_ROOF)
{
if (!extract_object(authorityKeyIdentifierObjects, &objectID, &object, &level, &ctx))
+ {
return;
-
- switch (objectID) {
+ }
+ switch (objectID)
+ {
case AUTH_KEY_ID_KEY_ID:
*authKeyID = parse_keyIdentifier(object, level+1, TRUE);
break;
@@ -1708,9 +1802,12 @@ parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation)
while (objectID < AUTH_INFO_ACCESS_ROOF)
{
if (!extract_object(authorityInfoAccessObjects, &objectID, &object, &level, &ctx))
+ {
return;
+ }
- switch (objectID) {
+ switch (objectID)
+ {
case AUTH_INFO_ACCESS_METHOD:
accessMethod = known_oid(object);
break;
@@ -1722,8 +1819,9 @@ parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation)
if (*object.ptr == ASN1_CONTEXT_S_6)
{
if (asn1_length(&object) == ASN1_INVALID_LENGTH)
+ {
return;
-
+ }
DBG(DBG_PARSING,
DBG_log(" '%.*s'",(int)object.len, object.ptr)
)
@@ -1768,11 +1866,14 @@ parse_extendedKeyUsage(chunk_t blob, int level0)
{
if (!extract_object(extendedKeyUsageObjects, &objectID
, &object, &level, &ctx))
+ {
return FALSE;
-
+ }
if (objectID == EXT_KEY_USAGE_PURPOSE_ID
&& known_oid(object) == OID_OCSP_SIGNING)
+ {
return TRUE;
+ }
objectID++;
}
return FALSE;
@@ -1798,8 +1899,9 @@ parse_crlDistributionPoints(chunk_t blob, int level0)
{
if (!extract_object(crlDistributionPointsObjects, &objectID,
&object, &level, &ctx))
+ {
return NULL;
-
+ }
if (objectID == CRL_DIST_POINTS_FULLNAME)
{
generalName_t *gn = parse_generalNames(object, level+1, TRUE);
@@ -1836,7 +1938,9 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
while (objectID < X509_OBJ_ROOF)
{
if (!extract_object(certObjects, &objectID, &object, &level, &ctx))
+ {
return FALSE;
+ }
/* those objects which will parsed further need the next higher level */
level++;
@@ -1882,7 +1986,9 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert)
break;
case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM:
if (parse_algorithmIdentifier(object, level, NULL) == OID_RSA_ENCRYPTION)
+ {
cert->subjectPublicKeyAlgorithm = PUBKEY_ALG_RSA;
+ }
else
{
plog(" unsupported public key algorithm");
@@ -2003,14 +2109,22 @@ check_validity(const x509cert_t *cert, time_t *until)
DBG_log(" not after : %s", timetoa(&cert->notAfter, TRUE));
)
- if (cert->notAfter < *until) *until = cert->notAfter;
-
+ if (cert->notAfter < *until)
+ {
+ *until = cert->notAfter;
+ }
if (current_time < cert->notBefore)
+ {
return "certificate is not valid yet";
+ }
if (current_time > cert->notAfter)
+ {
return "certificate has expired";
+ }
else
+ {
return NULL;
+ }
}
/*
@@ -2126,7 +2240,9 @@ verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
* lifetime as the validity of the ocsp status or crl lifetime
*/
if (strict && nextUpdate < *until)
+ {
*until = nextUpdate;
+ }
break;
case CERT_REVOKED:
plog("certificate was revoked on %s, reason: %s"
diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am
index 8a9ba54c9..e9c707c2b 100644
--- a/src/starter/Makefile.am
+++ b/src/starter/Makefile.am
@@ -5,7 +5,14 @@ starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
keywords.c files.h keywords.h cmp.c starter.c cmp.h exec.c invokecharon.c \
exec.h invokecharon.h lex.yy.c loglite.c klips.c klips.h
-INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/pluto -I$(top_srcdir)/src/whack -I$(top_srcdir)/src/stroke
+INCLUDES = \
+-I${linuxdir} \
+-I$(top_srcdir)/src/libstrongswan \
+-I$(top_srcdir)/src/libfreeswan \
+-I$(top_srcdir)/src/pluto \
+-I$(top_srcdir)/src/whack \
+-I$(top_srcdir)/src/stroke
+
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" -DIPSEC_EAPDIR=\"${eapdir}\" -DDEBUG
starter_LDADD = defs.o $(top_builddir)/src/libfreeswan/libfreeswan.a
EXTRA_DIST = parser.l parser.y keywords.txt ipsec.conf
diff --git a/src/starter/args.c b/src/starter/args.c
index b5f716069..825824586 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -249,11 +249,16 @@ static const token_info_t token_info[] =
{ ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool },
{ ARG_STR, offsetof(starter_end_t, updown), NULL },
+ { ARG_STR, offsetof(starter_end_t, auth), NULL },
+ { ARG_STR, offsetof(starter_end_t, auth2), NULL },
{ ARG_STR, offsetof(starter_end_t, id), NULL },
+ { ARG_STR, offsetof(starter_end_t, id2), NULL },
{ ARG_STR, offsetof(starter_end_t, rsakey), NULL },
{ ARG_STR, offsetof(starter_end_t, cert), NULL },
+ { ARG_STR, offsetof(starter_end_t, cert2), NULL },
{ ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert },
{ ARG_STR, offsetof(starter_end_t, ca), NULL },
+ { ARG_STR, offsetof(starter_end_t, ca2), NULL },
{ ARG_STR, offsetof(starter_end_t, groups), NULL },
{ ARG_STR, offsetof(starter_end_t, iface), NULL }
};
diff --git a/src/starter/confread.h b/src/starter/confread.h
index ed344fe6f..3d4829ea1 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -20,7 +20,6 @@
#ifndef _FREESWAN_H
#include <freeswan.h>
-#include "../pluto/constants.h"
#endif
#include "parser.h"
@@ -57,10 +56,15 @@ typedef struct starter_end starter_end_t;
struct starter_end {
lset_t seen;
+ char *auth;
+ char *auth2;
char *id;
+ char *id2;
char *rsakey;
char *cert;
+ char *cert2;
char *ca;
+ char *ca2;
char *groups;
char *iface;
ip_address addr;
diff --git a/src/starter/invokecharon.c b/src/starter/invokecharon.c
index 1cce4e41d..a511f55dd 100644
--- a/src/starter/invokecharon.c
+++ b/src/starter/invokecharon.c
@@ -109,7 +109,7 @@ starter_stop_charon (void)
int
-starter_start_charon (starter_config_t *cfg, bool no_fork)
+starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb)
{
struct stat stb;
int pid, i;
@@ -121,7 +121,14 @@ starter_start_charon (starter_config_t *cfg, bool no_fork)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-
+
+ if (attach_gdb)
+ {
+ argc = 0;
+ arg[argc++] = "/usr/bin/gdb";
+ arg[argc++] = "--args";
+ arg[argc++] = CHARON_CMD;
+ }
if (!no_fork)
{
arg[argc++] = "--use-syslog";
diff --git a/src/starter/invokecharon.h b/src/starter/invokecharon.h
index f62221da6..03c592f1e 100644
--- a/src/starter/invokecharon.h
+++ b/src/starter/invokecharon.h
@@ -25,7 +25,7 @@
extern void starter_charon_sigchild (pid_t pid);
extern pid_t starter_charon_pid (void);
extern int starter_stop_charon (void);
-extern int starter_start_charon(struct starter_config *cfg, bool debug);
+extern int starter_start_charon(struct starter_config *cfg, bool no_fork, bool attach_gdb);
#endif /* _STARTER_CHARON_H_ */
diff --git a/src/starter/invokepluto.c b/src/starter/invokepluto.c
index 6fdf46ffd..5e840bac2 100644
--- a/src/starter/invokepluto.c
+++ b/src/starter/invokepluto.c
@@ -121,7 +121,7 @@ starter_stop_pluto (void)
}
int
-starter_start_pluto (starter_config_t *cfg, bool no_fork)
+starter_start_pluto (starter_config_t *cfg, bool no_fork, bool attach_gdb)
{
struct stat stb;
int i;
@@ -137,7 +137,15 @@ starter_start_pluto (starter_config_t *cfg, bool no_fork)
};
printf ("starter_start_pluto entered\n");
-
+
+ if (attach_gdb)
+ {
+ argc = 0;
+ arg[argc++] = "/usr/bin/gdb";
+ arg[argc++] = "--args";
+ arg[argc++] = PLUTO_CMD;
+ arg[argc++] = "--nofork";
+ }
if (cfg->setup.plutostderrlog || no_fork)
{
arg[argc++] = "--stderrlog";
diff --git a/src/starter/invokepluto.h b/src/starter/invokepluto.h
index 6366d1f50..768bec28c 100644
--- a/src/starter/invokepluto.h
+++ b/src/starter/invokepluto.h
@@ -22,7 +22,7 @@
extern void starter_pluto_sigchild (pid_t pid);
extern pid_t starter_pluto_pid (void);
extern int starter_stop_pluto (void);
-extern int starter_start_pluto (struct starter_config *cfg, bool debug);
+extern int starter_start_pluto (struct starter_config *cfg, bool no_fork, bool attach_gdb);
#endif /* _STARTER_PLUTO_H_ */
diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5
index c9074868a..2567dfe7e 100644
--- a/src/starter/ipsec.conf.5
+++ b/src/starter/ipsec.conf.5
@@ -246,20 +246,17 @@ for RSA digital signatures (the default),
for either, and
.B never
if negotiation is never to be attempted or accepted (useful for shunt-only conns).
-Digital signatures are superior in every way to shared secrets. In IKEv2, the
-two ends must not agree on this parameter, it is relevant for the
-outbound authentication method only.
+Digital signatures are superior in every way to shared secrets.
IKEv1 additionally supports the values
.B xauthpsk
and
.B xauthrsasig
that will enable eXtended AUTHentication (XAUTH) in addition to IKEv1 main mode
based on shared secrets or digital RSA signatures, respectively.
-IKEv2 additionally supports the value
-.B eap,
-which indicates an initiator to request EAP authentication. The EAP method to
-use is selected by the server (see
-.B eap).
+This parameter is deprecated for IKEv2 connections, as two peers do not need
+to agree on an authentication method. Use the
+.B leftauth
+parameter instead to define authentication methods in IKEv2.
.TP
.B auto
what operation, if any, should be done automatically at IPsec startup;
@@ -350,25 +347,9 @@ in case of inactivity. This only applies to IKEv1, in IKEv2 the default
retransmission timeout applies, as every exchange is used to detect dead peers.
.TP
.B eap
-defines the EAP type to propose as server if the client has
-.B authby=eap
-selected. Acceptable values are
-.B aka
-for EAP-AKA,
-.B sim
-for EAP-SIM,
-.B gtc
-for EAP-GTC,
-.B md5
-for EAP-MD5, and
-.B mschapv2
-for EAP-MS-CHAPv2.
-Additionally, IANA assigned EAP method numbers are accepted, or a definition
-in the form
-.B eap=type-vendor
-(e.g.
-.B eap=7-12345
-) can be used to specify vendor specific EAP types.
+defines the EAP type to propose as server if the client requests EAP
+authentication. This parameter is deprecated in the favour of
+.B leftauth.
To forward EAP authentication to a RADIUS server using the EAP-RADIUS plugin,
set
@@ -509,11 +490,46 @@ and
.B no
(the default).
.TP
+.B leftauth
+Authentication method to use (local) or require (remote) in this connection.
+This parameter is supported in IKEv2 only. Acceptable values are
+.B pubkey
+for public key authentication (RSA/ECDSA),
+.B psk
+for pre-shared key authentication and
+.B eap
+to (require the) use of the Extensible Authentication Protocol. In the case
+of
+.B eap,
+an optional EAP method can be appended. Currently defined methods are
+.B eap-aka, eap-sim, eap-gtc, eap-md5
+and
+.B eap-mschapv2.
+Alternatively, IANA assigned EAP method numbers are accepted. Vendor specific
+EAP methods are defined in the form
+.B eap-type-vendor
+(e.g.
+.B eap-7-12345
+).
+.TP
+.B leftauth2
+Same as
+.B leftauth,
+but defines an additional authentication exchange. IKEv2 supports multiple
+authentication rounds using "Multiple Authentication Exchanges" defined
+in RFC4739. This allows, for example, separated authentication
+of host and user (IKEv2 only).
+.TP
.B leftca
the distinguished name of a certificate authority which is required to
lie in the trust path going from the left participant's certificate up
to the root certification authority.
.TP
+.B leftca2
+Same as
+.B leftca,
+but for the second authentication round (IKEv2 only).
+.TP
.B leftcert
the path to the left participant's X.509 certificate. The file can be coded either in
PEM or DER format. OpenPGP certificates are supported as well.
@@ -529,6 +545,11 @@ The left participant's ID can be overriden by specifying a
.B leftid
value which must be certified by the certificate, though.
.TP
+.B leftcert2
+Same as
+.B leftcert,
+but for the second authentication round (IKEv2 only).
+.TP
.B leftfirewall
whether the left participant is doing forwarding-firewalling
(including masquerading) using iptables for traffic from \fIleftsubnet\fR,
@@ -594,6 +615,11 @@ or a fully-qualified domain name preceded by
.B @
(which is used as a literal string and not resolved).
.TP
+.B leftid2
+identity to use for a second authentication for the left participant
+(IKEv2 only); defaults to
+.BR leftid .
+.TP
.B leftnexthop
this parameter is not needed any more because the NETKEY IPsec stack does
not require explicit routing entries for the traffic to be tunneled.
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index 17789d9bd..3b6704450 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -147,11 +147,16 @@ typedef enum {
KW_LEFTHOSTACCESS,
KW_LEFTALLOWANY,
KW_LEFTUPDOWN,
+ KW_LEFTAUTH,
+ KW_LEFTAUTH2,
KW_LEFTID,
+ KW_LEFTID2,
KW_LEFTRSASIGKEY,
KW_LEFTCERT,
+ KW_LEFTCERT2,
KW_LEFTSENDCERT,
KW_LEFTCA,
+ KW_LEFTCA2,
KW_LEFTGROUPS,
#define KW_LEFT_FIRST KW_LEFT
@@ -169,11 +174,16 @@ typedef enum {
KW_RIGHTHOSTACCESS,
KW_RIGHTALLOWANY,
KW_RIGHTUPDOWN,
+ KW_RIGHTAUTH,
+ KW_RIGHTAUTH2,
KW_RIGHTID,
+ KW_RIGHTID2,
KW_RIGHTRSASIGKEY,
KW_RIGHTCERT,
+ KW_RIGHTCERT2,
KW_RIGHTSENDCERT,
KW_RIGHTCA,
+ KW_RIGHTCA2,
KW_RIGHTGROUPS,
#define KW_RIGHT_FIRST KW_RIGHT
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index d834fe425..be8f305fe 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -104,10 +104,15 @@ lefthostaccess, KW_LEFTHOSTACCESS
leftallowany, KW_LEFTALLOWANY
leftupdown, KW_LEFTUPDOWN
leftid, KW_LEFTID
+leftid2, KW_LEFTID2
+leftauth, KW_LEFTAUTH
+leftauth2, KW_LEFTAUTH2
leftrsasigkey, KW_LEFTRSASIGKEY
leftcert, KW_LEFTCERT,
+leftcert2, KW_LEFTCERT2,
leftsendcert, KW_LEFTSENDCERT
leftca, KW_LEFTCA
+leftca2, KW_LEFTCA2
leftgroups, KW_LEFTGROUPS
right, KW_RIGHT
rightnexthop, KW_RIGHTNEXTHOP
@@ -121,10 +126,15 @@ righthostaccess, KW_RIGHTHOSTACCESS
rightallowany, KW_RIGHTALLOWANY
rightupdown, KW_RIGHTUPDOWN
rightid, KW_RIGHTID
+rightid2, KW_RIGHTID2
+rightauth, KW_RIGHTAUTH
+rightauth2, KW_RIGHTAUTH2
rightrsasigkey, KW_RIGHTRSASIGKEY
rightcert, KW_RIGHTCERT
+rightcert2, KW_RIGHTCERT2
rightsendcert, KW_RIGHTSENDCERT
rightca, KW_RIGHTCA
+rightca2, KW_RIGHTCA2
rightgroups, KW_RIGHTGROUPS
also, KW_ALSO
auto, KW_AUTO
diff --git a/src/starter/starter.c b/src/starter/starter.c
index de8567583..a299d5671 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -224,6 +224,7 @@ int main (int argc, char **argv)
unsigned long auto_update = 0;
time_t last_reload;
bool no_fork = FALSE;
+ bool attach_gdb = FALSE;
/* global variables defined in log.h */
log_to_stderr = TRUE;
@@ -248,6 +249,11 @@ int main (int argc, char **argv)
{
no_fork = TRUE;
}
+ else if (streq(argv[i], "--attach-gdb"))
+ {
+ no_fork = TRUE;
+ attach_gdb = TRUE;
+ }
else if (streq(argv[i], "--auto-update") && i+1 < argc)
{
auto_update = atoi(argv[++i]);
@@ -571,7 +577,7 @@ int main (int argc, char **argv)
DBG_log("Attempting to start pluto...")
);
- if (starter_start_pluto(cfg, no_fork) == 0)
+ if (starter_start_pluto(cfg, no_fork, attach_gdb) == 0)
{
starter_whack_listen();
}
@@ -606,7 +612,7 @@ int main (int argc, char **argv)
DBG(DBG_CONTROL,
DBG_log("Attempting to start charon...")
);
- if (starter_start_charon(cfg, no_fork))
+ if (starter_start_charon(cfg, no_fork, attach_gdb))
{
/* schedule next try */
alarm(PLUTO_RESTART_DELAY);
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 9ce7edee3..a695feb46 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -164,9 +164,14 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
{
char buffer[INET6_ADDRSTRLEN];
+ msg_end->auth = push_string(msg, conn_end->auth);
+ msg_end->auth2 = push_string(msg, conn_end->auth2);
msg_end->id = push_string(msg, conn_end->id);
+ msg_end->id2 = push_string(msg, conn_end->id2);
msg_end->cert = push_string(msg, conn_end->cert);
+ msg_end->cert2 = push_string(msg, conn_end->cert2);
msg_end->ca = push_string(msg, conn_end->ca);
+ msg_end->ca2 = push_string(msg, conn_end->ca2);
msg_end->groups = push_string(msg, conn_end->groups);
msg_end->updown = push_string(msg, conn_end->updown);
ip_address2string(&conn_end->addr, buffer, sizeof(buffer));
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 3061e2da5..42cbf97a1 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -123,9 +123,15 @@ typedef struct stroke_end_t stroke_end_t;
* definition of a peer in a stroke message
*/
struct stroke_end_t {
+ char *auth;
+ char *auth2;
char *id;
+ char *id2;
+ char *eap_id;
char *cert;
+ char *cert2;
char *ca;
+ char *ca2;
char *groups;
char *updown;
char *address;
@@ -206,6 +212,7 @@ struct stroke_msg_t {
struct {
char *name;
int ikev2;
+ /* next three are deprecated, use stroke_end_t.auth instead */
int auth_method;
u_int32_t eap_type;
u_int32_t eap_vendor;
diff --git a/src/whack/Makefile.am b/src/whack/Makefile.am
index 985245026..69cc11afe 100644
--- a/src/whack/Makefile.am
+++ b/src/whack/Makefile.am
@@ -1,7 +1,12 @@
ipsec_PROGRAMS = whack
whack_SOURCES = whack.c whack.h
-INCLUDES = -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/pluto
+
+INCLUDES = \
+-I$(top_srcdir)/src/libstrongswan \
+-I$(top_srcdir)/src/libfreeswan \
+-I$(top_srcdir)/src/pluto
+
whack_LDADD = $(top_builddir)/src/libfreeswan/libfreeswan.a
AM_CFLAGS = -DDEBUG