merged multi-auth branch back into trunk
authorMartin Willi <martin@strongswan.org>
Tue, 14 Apr 2009 10:34:24 +0000 (10:34 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 14 Apr 2009 10:34:24 +0000 (10:34 -0000)
234 files changed:
src/_copyright/Makefile.am
src/charon/Makefile.am
src/charon/bus/bus.c
src/charon/bus/bus.h
src/charon/config/attributes/attribute_manager.c
src/charon/config/attributes/attribute_manager.h
src/charon/config/attributes/attribute_provider.h
src/charon/config/auth_cfg.c [new file with mode: 0644]
src/charon/config/auth_cfg.h [new file with mode: 0644]
src/charon/config/backend.h
src/charon/config/backend_manager.c
src/charon/config/backend_manager.h
src/charon/config/peer_cfg.c
src/charon/config/peer_cfg.h
src/charon/config/proposal.c
src/charon/config/proposal_keywords.h [new file with mode: 0644]
src/charon/config/proposal_keywords.txt [new file with mode: 0644]
src/charon/credentials/auth_info.c [deleted file]
src/charon/credentials/auth_info.h [deleted file]
src/charon/credentials/credential_manager.c
src/charon/credentials/credential_manager.h
src/charon/credentials/sets/auth_cfg_wrapper.c [new file with mode: 0644]
src/charon/credentials/sets/auth_cfg_wrapper.h [new file with mode: 0644]
src/charon/credentials/sets/auth_info_wrapper.c [deleted file]
src/charon/credentials/sets/auth_info_wrapper.h [deleted file]
src/charon/encoding/generator.c
src/charon/encoding/message.c
src/charon/encoding/message.h
src/charon/plugins/eap_mschapv2/eap_mschapv2.c
src/charon/plugins/eap_sim_file/eap_sim_file_card.c
src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c
src/charon/plugins/load_tester/load_tester_config.c
src/charon/plugins/nm/nm_creds.c
src/charon/plugins/nm/nm_service.c
src/charon/plugins/smp/smp.c
src/charon/plugins/sql/pool.c
src/charon/plugins/sql/sql_attribute.c
src/charon/plugins/sql/sql_config.c
src/charon/plugins/stroke/stroke_attribute.c
src/charon/plugins/stroke/stroke_config.c
src/charon/plugins/stroke/stroke_cred.c
src/charon/plugins/stroke/stroke_list.c
src/charon/plugins/stroke/stroke_socket.c
src/charon/plugins/uci/uci_config.c
src/charon/plugins/uci/uci_control.c
src/charon/plugins/uci/uci_creds.c
src/charon/plugins/unit_tester/tests/test_auth_info.c
src/charon/plugins/unit_tester/tests/test_med_db.c
src/charon/plugins/unit_tester/tests/test_pool.c
src/charon/processing/jobs/initiate_mediation_job.c
src/charon/sa/authenticators/authenticator.c
src/charon/sa/authenticators/authenticator.h
src/charon/sa/authenticators/eap/eap_manager.c
src/charon/sa/authenticators/eap/eap_method.c
src/charon/sa/authenticators/eap/eap_method.h
src/charon/sa/authenticators/eap/sim_manager.h
src/charon/sa/authenticators/eap_authenticator.c
src/charon/sa/authenticators/eap_authenticator.h
src/charon/sa/authenticators/psk_authenticator.c
src/charon/sa/authenticators/psk_authenticator.h
src/charon/sa/authenticators/pubkey_authenticator.c
src/charon/sa/authenticators/pubkey_authenticator.h
src/charon/sa/connect_manager.c
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/ike_sa_manager.c
src/charon/sa/task_manager.c
src/charon/sa/tasks/child_create.c
src/charon/sa/tasks/child_delete.c
src/charon/sa/tasks/child_rekey.c
src/charon/sa/tasks/ike_auth.c
src/charon/sa/tasks/ike_auth_lifetime.c
src/charon/sa/tasks/ike_cert_post.c
src/charon/sa/tasks/ike_cert_pre.c
src/charon/sa/tasks/ike_config.c
src/charon/sa/tasks/ike_init.c
src/charon/sa/tasks/ike_me.c
src/charon/sa/tasks/ike_mobike.c
src/charon/sa/tasks/ike_natd.c
src/charon/sa/tasks/ike_rekey.c
src/libfreeswan/Makefile.am
src/libfreeswan/freeswan.h
src/libstrongswan/credentials/certificates/certificate.c
src/libstrongswan/credentials/certificates/certificate.h
src/libstrongswan/plugins/curl/curl_fetcher.c
src/libstrongswan/settings.h
src/libstrongswan/utils/enumerator.h
src/libstrongswan/utils/identification.c
src/libstrongswan/utils/identification.h
src/libstrongswan/utils/linked_list.h
src/pluto/Makefile.am
src/pluto/ac.c
src/pluto/alg_info.c
src/pluto/constants.c
src/pluto/constants.h
src/pluto/crl.c
src/pluto/defs.h
src/pluto/demux.c
src/pluto/fetch.c
src/pluto/id.c
src/pluto/ike_alg.c
src/pluto/kernel.c
src/pluto/keys.c
src/pluto/modecfg.c
src/pluto/nat_traversal.c
src/pluto/pem.c
src/pluto/pgp.c
src/pluto/plutomain.c
src/pluto/server.c
src/pluto/smartcard.c
src/pluto/state.c
src/pluto/vendor.c
src/pluto/virtual.c
src/pluto/x509.c
src/starter/Makefile.am
src/starter/args.c
src/starter/confread.h
src/starter/invokecharon.c
src/starter/invokecharon.h
src/starter/invokepluto.c
src/starter/invokepluto.h
src/starter/ipsec.conf.5
src/starter/keywords.h
src/starter/keywords.txt
src/starter/starter.c
src/starter/starterstroke.c
src/stroke/stroke_msg.h
src/whack/Makefile.am
testing/hosts/winnetou/etc/openssl/index.txt
testing/hosts/winnetou/etc/openssl/index.txt.old
testing/hosts/winnetou/etc/openssl/newcerts/15.pem [new file with mode: 0644]
testing/hosts/winnetou/etc/openssl/serial
testing/hosts/winnetou/etc/openssl/serial.old
testing/scripts/function.sh
testing/scripts/start-bridges [new file with mode: 0755]
testing/scripts/start-switches [deleted file]
testing/scripts/stop-bridges [new file with mode: 0755]
testing/start-testing
testing/stop-testing
testing/testing.conf
testing/tests/ikev1/dpd-restart/evaltest.dat
testing/tests/ikev1/protoport-route/evaltest.dat
testing/tests/ikev1/protoport-route/pretest.dat
testing/tests/ikev2/any-interface/hosts/alice/etc/strongswan.conf
testing/tests/ikev2/any-interface/hosts/bob/etc/strongswan.conf
testing/tests/ikev2/any-interface/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/any-interface/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/crl-revoked/evaltest.dat
testing/tests/ikev2/host2host-transport/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/host2host-transport/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/description.txt [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/evaltest.dat [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/alice/etc/raddb/clients.conf [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/alice/etc/raddb/eap.conf [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/alice/etc/raddb/proxy.conf [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/alice/etc/raddb/radiusd.conf [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/alice/etc/raddb/sites-available/default [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/alice/etc/raddb/triplets.dat [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/alice/etc/raddb/users [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/carol/etc/ipsec.conf [new file with mode: 0755]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/carol/etc/ipsec.d/triplets.dat [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/carol/etc/ipsec.secrets [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/carol/etc/strongswan.conf [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/dave/etc/ipsec.conf [new file with mode: 0755]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/dave/etc/ipsec.d/triplets.dat [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/dave/etc/ipsec.secrets [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/dave/etc/strongswan.conf [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/moon/etc/init.d/iptables [new file with mode: 0755]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/moon/etc/ipsec.conf [new file with mode: 0755]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/moon/etc/ipsec.secrets [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/hosts/moon/etc/strongswan.conf [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/posttest.dat [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/pretest.dat [new file with mode: 0644]
testing/tests/ikev2/mult-auth-rsa-eap-sim-id/test.conf [new file with mode: 0644]
testing/tests/ikev2/multi-level-ca-cr-init/description.txt
testing/tests/ikev2/multi-level-ca-cr-init/hosts/moon/etc/ipsec.conf
testing/tests/ikev2/multi-level-ca-cr-resp/description.txt
testing/tests/ikev2/multi-level-ca-cr-resp/evaltest.dat
testing/tests/ikev2/multi-level-ca-cr-resp/hosts/moon/etc/ipsec.conf
testing/tests/ikev2/multi-level-ca-ldap/evaltest.dat
testing/tests/ikev2/multi-level-ca-loop/evaltest.dat
testing/tests/ikev2/multi-level-ca-revoked/evaltest.dat
testing/tests/ikev2/multi-level-ca-strict/description.txt
testing/tests/ikev2/multi-level-ca/evaltest.dat
testing/tests/ikev2/net2net-cert/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/net2net-cert/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/net2net-psk/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/net2net-psk/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/net2net-route/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/net2net-route/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/net2net-start/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/net2net-start/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/ocsp-no-signer-cert/evaltest.dat
testing/tests/ikev2/ocsp-strict-ifuri/evaltest.dat
testing/tests/ikev2/ocsp-untrusted-cert/evaltest.dat
testing/tests/ikev2/reauth-late/evaltest.dat
testing/tests/ikev2/rw-eap-aka-id-rsa/evaltest.dat
testing/tests/ikev2/rw-eap-aka-rsa/evaltest.dat
testing/tests/ikev2/rw-eap-md5-id-radius/evaltest.dat
testing/tests/ikev2/rw-eap-md5-radius/evaltest.dat
testing/tests/ikev2/rw-eap-mschapv2-id-rsa/evaltest.dat
testing/tests/ikev2/rw-eap-sim-id-radius/description.txt
testing/tests/ikev2/rw-eap-sim-id-radius/evaltest.dat
testing/tests/ikev2/rw-eap-sim-id-radius/hosts/alice/etc/raddb/triplets.dat
testing/tests/ikev2/rw-eap-sim-id-radius/hosts/carol/etc/ipsec.conf
testing/tests/ikev2/rw-eap-sim-radius/evaltest.dat
testing/tests/ikev2/two-certs/description.txt
testing/tests/ikev2/two-certs/evaltest.dat
testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.conf
testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/certs/carolCert-002.pem [new file with mode: 0644]
testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/private/carolKey-002.pem [new file with mode: 0644]
testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.secrets [new file with mode: 0644]
testing/tests/ikev2/two-certs/hosts/dave/etc/ipsec.conf [deleted file]
testing/tests/ikev2/two-certs/hosts/dave/etc/strongswan.conf [deleted file]
testing/tests/ikev2/two-certs/hosts/moon/etc/ipsec.conf
testing/tests/ikev2/two-certs/hosts/moon/etc/ipsec.d/certs/carolRevokedCert.pem [deleted file]
testing/tests/ikev2/two-certs/hosts/moon/etc/ipsec.d/certs/daveCert.der [deleted file]
testing/tests/ikev2/two-certs/posttest.dat
testing/tests/ikev2/two-certs/pretest.dat
testing/tests/ikev2/two-certs/test.conf
testing/tests/openssl/alg-blowfish/description.txt [new file with mode: 0644]
testing/tests/openssl/alg-blowfish/evaltest.dat [new file with mode: 0644]
testing/tests/openssl/alg-blowfish/hosts/carol/etc/ipsec.conf [new file with mode: 0755]
testing/tests/openssl/alg-blowfish/hosts/carol/etc/strongswan.conf [new file with mode: 0644]
testing/tests/openssl/alg-blowfish/hosts/dave/etc/ipsec.conf [new file with mode: 0755]
testing/tests/openssl/alg-blowfish/hosts/dave/etc/strongswan.conf [new file with mode: 0644]
testing/tests/openssl/alg-blowfish/hosts/moon/etc/ipsec.conf [new file with mode: 0755]
testing/tests/openssl/alg-blowfish/hosts/moon/etc/strongswan.conf [new file with mode: 0644]
testing/tests/openssl/alg-blowfish/posttest.dat [new file with mode: 0644]
testing/tests/openssl/alg-blowfish/pretest.dat [new file with mode: 0644]
testing/tests/openssl/alg-blowfish/test.conf [new file with mode: 0644]
testing/tests/openssl/rw-cert/hosts/moon/etc/strongswan.conf
testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/ipsec.d/data.sql
testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/ipsec.d/data.sql

index 00d5fb2..8b46f11 100644 (file)
@@ -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
index 9da2b23..cc1cffd 100644 (file)
@@ -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
 #################
 
index 670c535..c0b8e45 100644 (file)
@@ -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();
index 90ad201..5c479b6 100644 (file)
@@ -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
index a069c95..f0ae4ff 100644 (file)
@@ -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;
index aef6e7b..0ac37e7 100644 (file)
@@ -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.
index 5d563e8..cbd0075 100644 (file)
@@ -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 (file)
index 0000000..90fe987
--- /dev/null
@@ -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 (file)
index 0000000..c6bc195
--- /dev/null
@@ -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_ @}*/
index 4673d39..42633f7 100644 (file)
@@ -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
index c31df8d..28e50ef 100644 (file)
@@ -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;
index 1fd921c..b3c74fb 100644 (file)
@@ -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.
         *
index 398244f..5d9db1b 100644 (file)
@@ -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;
index 3a77692..7cfe612 100644 (file)
@@ -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,
index da69739..7bddff1 100644 (file)
@@ -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 (file)
index 0000000..ae10d34
--- /dev/null
@@ -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 (file)
index 0000000..e195b1f
--- /dev/null
@@ -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 (file)
index 62d5ea9..0000000
+++ /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 (file)
index f480a6e..0000000
+++ /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_ @}*/
index 2721edc..3cd4e35 100644 (file)
@@ -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;
index 23f43cf..c628e7e 100644 (file)
@@ -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_cfg_wrapper.c b/src/charon/credentials/sets/auth_cfg_wrapper.c
new file mode 100644 (file)
index 0000000..2e93cc5
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2008-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 <daemon.h>
+
+#include "auth_cfg_wrapper.h"
+
+typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t;
+
+/**
+ * private data of auth_cfg_wrapper
+ */
+struct private_auth_cfg_wrapper_t {
+
+       /**
+        * public functions
+        */
+       auth_cfg_wrapper_t public;
+       
+       /**
+        * wrapped auth info
+        */
+       auth_cfg_t *auth;
+};
+
+/**
+ * enumerator for auth_cfg_wrapper_t.create_cert_enumerator()
+ */
+typedef struct {
+       /** implements enumerator_t */
+       enumerator_t public;
+       /** inner enumerator from auth_cfg */
+       enumerator_t *inner;
+       /** wrapped auth round */
+       auth_cfg_t *auth;
+       /** enumerated cert type */
+       certificate_type_t cert;
+       /** enumerated key type */
+       key_type_t key;
+       /** enumerated id */
+       identification_t *id;
+} wrapper_enumerator_t;
+
+/**
+ * Tries to fetch a certificate that was supplied as "Hash and URL"
+ * (replaces rule type and value in place).
+ */
+static bool fetch_cert(wrapper_enumerator_t *enumerator,
+                                          auth_rule_t *rule, void **value)
+{
+       char *url = (char*)*value;
+       if (!url)
+       {
+               /* fetching the certificate previously failed */
+               return FALSE;
+       }
+       
+       chunk_t data;
+       certificate_t *cert;
+       
+       DBG1(DBG_CFG, "  fetching certificate from '%s' ...", url);
+       if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS)
+       {
+               DBG1(DBG_CFG, "  fetching certificate failed");
+               /* we set the item to NULL, so we can skip it */
+               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);
+       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(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);
+       
+       if (*rule == AUTH_HELPER_IM_HASH_URL)
+       {
+               *rule = AUTH_HELPER_IM_CERT;
+       }
+       else
+       {
+               *rule = AUTH_HELPER_SUBJECT_CERT;
+       }
+       *value = cert;
+       enumerator->auth->replace(enumerator->auth, enumerator->inner,
+                                                         *rule, cert->get_ref(cert));
+       return TRUE;
+}
+
+/**
+ * enumerate function for wrapper_enumerator_t
+ */
+static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
+{
+       auth_rule_t rule;
+       certificate_t *current;
+       public_key_t *public;
+
+       while (this->inner->enumerate(this->inner, &rule, &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 (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;
+               }
+               public = current->get_public_key(current);
+               if (this->key != KEY_ANY && !public)
+               {       /* key type requested, but no public key */
+                       DESTROY_IF(public);
+                       continue;
+               }
+               if (this->key != KEY_ANY && public && this->key != public->get_type(public))
+               {       /* key type requested, but public key has another type */
+                       DESTROY_IF(public);
+                       continue;
+               }
+               DESTROY_IF(public);
+               if (this->id && !current->has_subject(current, this->id))
+               {       /* subject requested, but does not match */
+                       continue;
+               }
+               *cert = current;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/**
+ * destroy function for wrapper_enumerator_t
+ */
+static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
+{
+       this->inner->destroy(this->inner);
+       free(this);
+}
+
+/**
+ * implementation of auth_cfg_wrapper_t.set.create_cert_enumerator
+ */
+static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this,
+                                                                          certificate_type_t cert, key_type_t key, 
+                                                                          identification_t *id, bool trusted)
+{
+       wrapper_enumerator_t *enumerator;
+       
+       if (trusted)
+       {
+               return NULL;
+       }
+       enumerator = malloc_thing(wrapper_enumerator_t);
+       enumerator->auth = this->auth;
+       enumerator->cert = cert;
+       enumerator->key = key;
+       enumerator->id = id;
+       enumerator->inner = this->auth->create_enumerator(this->auth);
+       enumerator->public.enumerate = (void*)enumerate;
+       enumerator->public.destroy = (void*)wrapper_enumerator_destroy;
+       return &enumerator->public;
+}
+
+/**
+ * Implementation of auth_cfg_wrapper_t.destroy
+ */
+static void destroy(private_auth_cfg_wrapper_t *this)
+{
+       free(this);
+}
+
+/*
+ * see header file
+ */
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth)
+{
+       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_cfg_wrapper_t*))destroy;
+       
+       this->auth = auth;
+       
+       return &this->public;
+}
+
diff --git a/src/charon/credentials/sets/auth_cfg_wrapper.h b/src/charon/credentials/sets/auth_cfg_wrapper.h
new file mode 100644 (file)
index 0000000..9baf064
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008-2009 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup auth_cfg_wrapper auth_cfg_wrapper
+ * @{ @ingroup sets
+ */
+
+#ifndef AUTH_CFG_WRAPPER_H_
+#define AUTH_CFG_WRAPPER_H_
+
+#include <config/auth_cfg.h>
+#include <credentials/credential_set.h>
+
+typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t;
+
+/**
+ * A wrapper around auth_cfg_t to handle it as a credential set.
+ */
+struct auth_cfg_wrapper_t {
+
+       /**
+        * implements credential_set_t
+        */
+       credential_set_t set;
+               
+       /**
+     * Destroy a auth_cfg_wrapper instance.
+     */
+    void (*destroy)(auth_cfg_wrapper_t *this);
+};
+
+/**
+ * Create a auth_cfg_wrapper instance.
+ *
+ * @param auth         the wrapped auth info
+ * @return                     wrapper around auth
+ */
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth);
+
+#endif /** AUTH_CFG_WRAPPER_H_ @}*/
diff --git a/src/charon/credentials/sets/auth_info_wrapper.c b/src/charon/credentials/sets/auth_info_wrapper.c
deleted file mode 100644 (file)
index 7ec75be..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * $Id$
- */
-
-#include <daemon.h>
-
-#include "auth_info_wrapper.h"
-
-typedef struct private_auth_info_wrapper_t private_auth_info_wrapper_t;
-
-/**
- * private data of auth_info_wrapper
- */
-struct private_auth_info_wrapper_t {
-
-       /**
-        * public functions
-        */
-       auth_info_wrapper_t public;
-       
-       /**
-        * wrapped auth info
-        */
-       auth_info_t *auth;
-};
-
-/**
- * enumerator for auth_info_wrapper_t.create_cert_enumerator()
- */
-typedef struct {
-       /** implements enumerator_t */
-       enumerator_t public;
-       /** inner enumerator from auth_info */
-       enumerator_t *inner;
-       /** wrapped auth info */
-       auth_info_t *auth;
-       /** enumerated cert type */
-       certificate_type_t cert;
-       /** enumerated key type */
-       key_type_t key;
-       /** enumerated id */
-       identification_t *id;
-} wrapper_enumerator_t;
-
-/**
- * Tries to fetch a certificate that was supplied as "Hash and URL" (replaces the
- * item's type and value in place).
- */
-static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void **value)
-{
-       char *url = (char*)*value;
-       if (!url)
-       {
-               /* fetching the certificate previously failed */
-               return FALSE;
-       }
-       
-       chunk_t data;
-       certificate_t *cert;
-       
-       DBG1(DBG_CFG, "  fetching certificate from '%s' ...", url);
-       if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS)
-       {
-               DBG1(DBG_CFG, "  fetching certificate failed");
-               /* we set the item to NULL, so we can skip it */
-               enumerator->auth->replace_item(enumerator->inner, *type, NULL);
-               return FALSE;
-       }
-       
-       cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
-                                         BUILD_BLOB_ASN1_DER, data, BUILD_END);
-       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);
-               return FALSE;
-       }
-       
-       DBG1(DBG_CFG, "  fetched certificate \"%D\"", cert->get_subject(cert));
-       charon->credentials->cache_cert(charon->credentials, cert);
-       
-       *type = (*type == AUTHN_IM_HASH_URL) ? AUTHN_IM_CERT : AUTHN_SUBJECT_CERT;
-       *value = cert;
-       enumerator->auth->replace_item(enumerator->inner, *type, cert);
-       
-       return TRUE;
-}
-
-/**
- * enumerate function for wrapper_enumerator_t
- */
-static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
-{
-       auth_item_t type;
-       certificate_t *current;
-       public_key_t *public;
-
-       while (this->inner->enumerate(this->inner, &type, &current))
-       {
-               if (type == AUTHN_IM_HASH_URL ||
-                       type == AUTHN_SUBJECT_HASH_URL)
-               {
-                       if (!fetch_cert(this, &type, (void**)&current))
-                       {
-                               continue;
-                       }
-               }
-               else if (type != AUTHN_SUBJECT_CERT && 
-                                type != AUTHN_IM_CERT)
-               {
-                       continue;
-               }
-
-               if (this->cert != CERT_ANY && this->cert != current->get_type(current))
-               {       /* CERT type requested, but does not match */
-                       continue;
-               }
-               public = current->get_public_key(current);
-               if (this->key != KEY_ANY && !public)
-               {       /* key type requested, but no public key */
-                       DESTROY_IF(public);
-                       continue;
-               }
-               if (this->key != KEY_ANY && public && this->key != public->get_type(public))
-               {       /* key type requested, but public key has another type */
-                       DESTROY_IF(public);
-                       continue;
-               }
-               DESTROY_IF(public);
-               if (this->id && !current->has_subject(current, this->id))
-               {       /* subject requested, but does not match */
-                       continue;
-               }
-               *cert = current;
-               return TRUE;
-       }
-       return FALSE;
-}
-
-/**
- * destroy function for wrapper_enumerator_t
- */
-static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
-{
-       this->inner->destroy(this->inner);
-       free(this);
-}
-
-/**
- * implementation of auth_info_wrapper_t.set.create_cert_enumerator
- */
-static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this,
-                                                                          certificate_type_t cert, key_type_t key, 
-                                                                          identification_t *id, bool trusted)
-{
-       wrapper_enumerator_t *enumerator;
-       
-       if (trusted)
-       {
-               return NULL;
-       }
-       enumerator = malloc_thing(wrapper_enumerator_t);
-       enumerator->auth = this->auth;
-       enumerator->cert = cert;
-       enumerator->key = key;
-       enumerator->id = id;
-       enumerator->inner = this->auth->create_item_enumerator(this->auth);
-       enumerator->public.enumerate = (void*)enumerate;
-       enumerator->public.destroy = (void*)wrapper_enumerator_destroy;
-       return &enumerator->public;
-}
-
-/**
- * Implementation of auth_info_wrapper_t.destroy
- */
-static void destroy(private_auth_info_wrapper_t *this)
-{
-       free(this);
-}
-
-/*
- * see header file
- */
-auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth)
-{
-       private_auth_info_wrapper_t *this = malloc_thing(private_auth_info_wrapper_t);
-       
-       this->public.set.create_private_enumerator = (void*)return_null;
-       this->public.set.create_cert_enumerator = (void*)create_enumerator;
-       this->public.set.create_shared_enumerator = (void*)return_null;
-       this->public.set.create_cdp_enumerator = (void*)return_null;
-       this->public.set.cache_cert = (void*)nop;
-       this->public.destroy = (void(*)(auth_info_wrapper_t*))destroy;
-       
-       this->auth = auth;
-       
-       return &this->public;
-}
-
diff --git a/src/charon/credentials/sets/auth_info_wrapper.h b/src/charon/credentials/sets/auth_info_wrapper.h
deleted file mode 100644 (file)
index 9186715..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * $Id$
- */
-
-/**
- * @defgroup auth_info_wrapper auth_info_wrapper
- * @{ @ingroup sets
- */
-
-#ifndef AUTH_INFO_WRAPPER_H_
-#define AUTH_INFO_WRAPPER_H_
-
-#include <credentials/credential_set.h>
-#include <credentials/auth_info.h>
-
-typedef struct auth_info_wrapper_t auth_info_wrapper_t;
-
-/**
- * A wrapper around auth_info_t to handle it like a credential set.
- */
-struct auth_info_wrapper_t {
-
-       /**
-        * implements credential_set_t
-        */
-       credential_set_t set;
-               
-       /**
-     * Destroy a auth_info_wrapper instance.
-     */
-    void (*destroy)(auth_info_wrapper_t *this);
-};
-
-/**
- * Create a auth_info_wrapper instance.
- *
- * @param auth         the wrapped auth info
- * @return                     wrapper around auth
- */
-auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth);
-
-#endif /** AUTH_INFO_WRAPPER_H_ @}*/
index ca7cb1e..759f4ed 100644 (file)
@@ -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);
 }
 
 /**
index a605bd3..993d48b 100644 (file)
@@ -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;
index fcd206c..0953717 100644 (file)
@@ -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
index 2f276eb..9bbff81 100644 (file)
@@ -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;
                }
        }
index 7969007..cd71adf 100644 (file)
@@ -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);
index 409e9cb..9d30f89 100644 (file)
@@ -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;
                }\r
                \r
-               DBG1(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",\r
+               DBG2(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",\r
                         triplet->imsi, triplet->rand, RAND_LEN,\r
                         triplet->sres, SRES_LEN, triplet->kc, KC_LEN);
                         
index f3cd33b..25055da 100644 (file)
@@ -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);
index e7cd640..de9eb3b 100644 (file)
@@ -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);
index 72744b7..abe55eb 100644 (file)
@@ -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_