support of CA-based ipsec policies
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 18 May 2007 12:25:37 +0000 (12:25 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 18 May 2007 12:25:37 +0000 (12:25 -0000)
src/charon/config/backend_manager.c
src/charon/config/backend_manager.h
src/charon/config/backends/backend.h
src/charon/config/backends/local_backend.c
src/charon/config/credentials/local_credential_store.c
src/charon/control/interfaces/stroke_interface.c
src/charon/sa/authenticators/rsa_authenticator.c
src/charon/sa/tasks/ike_auth.c
src/libstrongswan/credential_store.h

index 186273b..0434f70 100644 (file)
@@ -82,16 +82,14 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
  */                    
 static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this,
                                                                identification_t *my_id, identification_t *other_id,
-                                                               identification_t *other_ca, char *other_group,
-                                                           host_t *my_host, host_t *other_host)
+                                                               ca_info_t *other_ca_info)
 {
        backend_t *backend;
        peer_cfg_t *config = NULL;
        iterator_t *iterator = this->backends->create_iterator(this->backends, TRUE);
        while (config == NULL && iterator->iterate(iterator, (void**)&backend))
        {
-               config = backend->get_peer_cfg(backend, my_id, other_id, other_ca,
-                                                                          other_group, my_host, other_host);
+               config = backend->get_peer_cfg(backend, my_id, other_id, other_ca_info);
        }
        iterator->destroy(iterator);
        return config;
@@ -227,11 +225,11 @@ backend_manager_t *backend_manager_create()
 {
        private_backend_manager_t *this = malloc_thing(private_backend_manager_t);
        
-       this->public.get_ike_cfg = (ike_cfg_t*(*)(backend_manager_t*, host_t *, host_t *))get_ike_cfg;
-       this->public.get_peer_cfg = (peer_cfg_t*(*)(backend_manager_t*, identification_t *, identification_t *))get_peer_cfg;
-       this->public.add_peer_cfg = (void(*)(backend_manager_t*, peer_cfg_t*))add_peer_cfg;
-       this->public.create_iterator = (iterator_t*(*)(backend_manager_t*))create_iterator;
-       this->public.destroy = (void(*)(backend_manager_t*))destroy;
+       this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg;
+       this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg;
+       this->public.add_peer_cfg = (void (*)(backend_manager_t*,peer_cfg_t*))add_peer_cfg;
+       this->public.create_iterator = (iterator_t* (*)(backend_manager_t*))create_iterator;
+       this->public.destroy = (void (*)(backend_manager_t*))destroy;
        
        this->backends = linked_list_create();
        this->writeable = linked_list_create();
index 4c00e4b..22a19a2 100644 (file)
@@ -71,19 +71,21 @@ struct backend_manager_t {
         * @param other_host            address of remote host
         * @return                                      matching ike_config, or NULL if none found
         */
-       ike_cfg_t *(*get_ike_cfg)(backend_manager_t *this, 
+       ike_cfg_t(*get_ike_cfg)(backend_manager_t *this, 
                                                          host_t *my_host, host_t *other_host);
        
        /**
-        * @brief Get a peer_config identified by two IDs.
+        * @brief Get a peer_config identified by two IDs and the peer's certificate issuer
         *
         * @param this                          calling object
         * @param my_id                         own ID
-        * @param other_id                      peers ID
+        * @param other_id                      peer ID
+        * @param other_ca_info         info record on issuer of peer certificate
         * @return                                      matching peer_config, or NULL if none found
         */
-       peer_cfg_t *(*get_peer_cfg)(backend_manager_t *this, identification_t *my_id,
-                                                               identification_t *other_id);
+       peer_cfg_t* (*get_peer_cfg)(backend_manager_t *this,
+                                                               identification_t *my_id, identification_t *other_id,
+                                                               ca_info_t *other_ca_info);
        
        /**
         * @brief Add a peer_config to the first found writable backend.
@@ -116,7 +118,7 @@ struct backend_manager_t {
  *
  * @ingroup config
  */
-backend_manager_t *backend_manager_create(void);
+backend_manager_tbackend_manager_create(void);
 
 #endif /*BACKEND_MANAGER_H_*/
 
index 14ab215..acab660 100644 (file)
@@ -58,21 +58,17 @@ struct backend_t {
        /**
         * @brief Get a peer_cfg identified by two IDs.
         * 
-        * Select a config for two IDs, the others certificate issuer, and
-        * a AC certificate group. The hosts are just a hint to select the
-        * correct config if multiple configs match.
+        * Select a config based on the two IDs and the other's certificate issuer
         *
         * @param this                          calling object
         * @param my_id                         own ID
-        * @param other_id                      peers ID
-        * @param my_host                       address of own host
-        * @param other_host            address of remote host
+        * @param other_id                      peer ID
+        * @param other_ca_info         info record on issuer of peer certificate
         * @return                                      matching peer_config, or NULL if none found
         */
        peer_cfg_t *(*get_peer_cfg)(backend_t *this,
                                                                identification_t *my_id, identification_t *other_id,
-                                                               identification_t *other_ca, char *other_group,
-                                                           host_t *my_host, host_t *other_host);
+                                                               ca_info_t *other_ca_info);
        
        /**
         * @brief Check if a backend is writable and implements writable_backend_t.
index 4100af8..2e80cc8 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <daemon.h>
 #include <utils/linked_list.h>
+#include <crypto/ca.h>
 
 
 typedef struct private_local_backend_t private_local_backend_t;
@@ -115,18 +116,19 @@ static ike_cfg_t *get_ike_cfg(private_local_backend_t *this,
        return found;
 }
 
+#define PRIO_NO_MATCH_FOUND            256
+
 /**
  * implements backend_t.get_peer.
  */                    
 static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
                                                                identification_t *my_id, identification_t *other_id,
-                                                               identification_t *other_ca, char *other_group,
-                                                           host_t *my_host, host_t *other_host)
+                                                               ca_info_t *other_ca_info)
 {
        peer_cfg_t *current, *found = NULL;
        iterator_t *iterator;
        identification_t *my_candidate, *other_candidate;
-       int best = 2 * MAX_WILDCARDS + 1;
+       int best = PRIO_NO_MATCH_FOUND;
        
        DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id);
        
@@ -137,19 +139,68 @@ static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
 
                my_candidate = current->get_my_id(current);
                other_candidate = current->get_other_id(current);
-               
-               if (my_candidate->matches(my_candidate, my_id, &wc1) &&
-                       other_id->matches(other_id, other_candidate, &wc2))
+
+               if (my_candidate->matches(my_candidate, my_id, &wc1)
+               &&      other_id->matches(other_id, other_candidate, &wc2))
                {
-                       int prio = wc1 + wc2;
-                       
-                       DBG2(DBG_CFG, "  candidate '%s': %D...%D, prio %d",
-                                current->get_name(current), my_candidate, other_candidate, prio);
-                       
-                       if (prio < best)
+                       int prio = (wc1 + wc2) * (MAX_CA_PATH_LEN + 1);
+                       int pathlen = 0;
+                       identification_t *other_candidate_ca = current->get_other_ca(current);
+
+                       /* are there any ca constraints? */
+                       if (other_candidate_ca->get_type(other_candidate_ca) != ID_ANY)
                        {
-                               found = current;
-                               best = prio;
+                               ca_info_t *ca_info = other_ca_info;
+
+                               for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
+                               {
+                                       if (ca_info == NULL)
+                                       {
+                                               prio = PRIO_NO_MATCH_FOUND;
+                                               break;
+                                       }
+                                       else
+                                       {
+                                               x509_t *cacert = ca_info->get_certificate(ca_info);
+                                               identification_t *other_ca = cacert->get_subject(cacert);
+
+                                               if (other_candidate_ca->equals(other_candidate_ca, other_ca))
+                                               {
+                                                       /* found a ca match */
+                                                       break;
+                                               }
+                                               if (cacert->is_self_signed(cacert))
+                                               {
+                                                       /* reached the root ca without a match */
+                                                       prio = PRIO_NO_MATCH_FOUND;
+                                                       break;
+                                               }
+                                               /* move a level upward in the trust path hierarchy */
+                                               ca_info = charon->credentials->get_issuer(charon->credentials, cacert); 
+                                       }
+                               }
+                               if (pathlen == MAX_CA_PATH_LEN)
+                               {
+                                       DBG1(DBG_CFG, "maximum ca path length of %d levels reached", MAX_CA_PATH_LEN);
+                                       prio = PRIO_NO_MATCH_FOUND;
+                               }
+                       }
+                       if (prio == PRIO_NO_MATCH_FOUND)
+                       {
+                               DBG2(DBG_CFG, "  candidate '%s': %D...%D, no ca match",
+                                       current->get_name(current), my_candidate, other_candidate);
+                       }
+                       else
+                       {
+                               prio += pathlen;
+                               DBG2(DBG_CFG, "  candidate '%s': %D...%D, prio %d",
+                                       current->get_name(current), my_candidate, other_candidate, prio);
+                       
+                               if (prio < best)
+                               {
+                                       found = current;
+                                       best = prio;
+                               }
                        }
                }
        }
@@ -208,12 +259,12 @@ backend_t *backend_create(void)
 {
        private_local_backend_t *this = malloc_thing(private_local_backend_t);
        
-       this->public.backend.backend.get_ike_cfg = (ike_cfg_t*(*)(backend_t*, host_t *, host_t *))get_ike_cfg;
-       this->public.backend.backend.get_peer_cfg = (peer_cfg_t*(*)(backend_t*,identification_t*,identification_t*,identification_t*,char*,host_t*,host_t*))get_peer_cfg;
-    this->public.backend.backend.is_writeable = (bool(*)(backend_t*))is_writeable;
-    this->public.backend.backend.destroy = (void(*)(backend_t*))destroy;
-       this->public.backend.create_iterator = (iterator_t*(*)(writeable_backend_t*))create_iterator;
-    this->public.backend.add_cfg = (void(*)(writeable_backend_t*, peer_cfg_t *))add_cfg;
+       this->public.backend.backend.get_ike_cfg = (ike_cfg_t* (*)(backend_t*, host_t*, host_t*))get_ike_cfg;
+       this->public.backend.backend.get_peer_cfg = (peer_cfg_t* (*)(backend_t*,identification_t*,identification_t*,ca_info_t*))get_peer_cfg;
+    this->public.backend.backend.is_writeable = (bool(*) (backend_t*))is_writeable;
+    this->public.backend.backend.destroy = (void (*)(backend_t*))destroy;
+       this->public.backend.create_iterator = (iterator_t* (*)(writeable_backend_t*))create_iterator;
+    this->public.backend.add_cfg = (void (*)(writeable_backend_t*,peer_cfg_t*))add_cfg;
     
        /* private variables */
        this->cfgs = linked_list_create();
index ca39a58..58026a9 100644 (file)
@@ -40,7 +40,6 @@
 #include "local_credential_store.h"
 
 #define PATH_BUF                       256
-#define MAX_CA_PATH_LEN                7
 
 typedef struct shared_key_t shared_key_t;
 
@@ -304,21 +303,24 @@ static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *th
  */
 static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_t *cert)
 {
-       ca_info_t *found = NULL;
-       ca_info_t *ca_info;
-
-       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
+       ca_info_t *found = cert->get_ca_info(cert);
 
-       while (iterator->iterate(iterator, (void**)&ca_info))
+       if (found == NULL)
        {
-               if (ca_info->is_cert_issuer(ca_info, cert))
+               iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
+               ca_info_t *ca_info;
+
+               while (iterator->iterate(iterator, (void**)&ca_info))
                {
-                       found = ca_info;
-                       break;
+                       if (ca_info->is_cert_issuer(ca_info, cert))
+                       {
+                               found = ca_info;
+                               cert->set_ca_info(cert, found);
+                               break;
+                       }
                }
+               iterator->destroy(iterator);
        }
-       iterator->destroy(iterator);
-
        return found;
 }
 
@@ -749,38 +751,31 @@ static status_t verify_signature(private_local_credential_store_t *this,
                                        DBG1(DBG_CFG, "candidate peer certificate was not successfully verified");
                                        continue;
                                }
-                               if (!cert->is_self_signed(cert))
-                               {
-                                       *issuer_p = get_issuer(this, cert);
-                               }
+                               *issuer_p = get_issuer(this, cert);
                        }
                        else
                        {
+                               ca_info_t *issuer = get_issuer(this, cert);
                                chunk_t keyid = public_key->get_keyid(public_key);
 
                                DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
                                DBG2(DBG_CFG, "issuer:  '%D'", cert->get_issuer(cert));
                                DBG2(DBG_CFG, "keyid:    %#B", &keyid);
 
-                               if (!cert->is_self_signed(cert))
+                               if (issuer == NULL)
                                {
-                                       ca_info_t *issuer = get_issuer(this, cert);
-
-                                       if (issuer == NULL)
-                                       {
-                                               DBG1(DBG_CFG, "candidate peer certificate has no retrievable issuer");
-                                               sig_status = NOT_FOUND;
-                                               continue;
-                                       }
-                                       if (cert_status == CERT_REVOKED || cert_status == CERT_UNTRUSTED
-                                       || ((issuer)->is_strict(issuer) && cert_status != CERT_GOOD))
-                                       {
-                                               DBG1(DBG_CFG, "candidate peer certificate has an inacceptable status: %N", cert_status_names, cert_status);
-                                               sig_status = VERIFY_ERROR;
-                                               continue;
-                                       }
-                                       *issuer_p = issuer;
+                                       DBG1(DBG_CFG, "candidate peer certificate has no retrievable issuer");
+                                       sig_status = NOT_FOUND;
+                                       continue;
                                }
+                               if (cert_status == CERT_REVOKED || cert_status == CERT_UNTRUSTED
+                               || ((issuer)->is_strict(issuer) && cert_status != CERT_GOOD))
+                               {
+                                       DBG1(DBG_CFG, "candidate peer certificate has an inacceptable status: %N", cert_status_names, cert_status);
+                                       sig_status = VERIFY_ERROR;
+                                       continue;
+                               }
+                               *issuer_p = issuer;
                        }
                        sig_status = public_key->verify_emsa_pkcs1_signature(public_key, hash, sig);
                        if (sig_status == SUCCESS)
@@ -828,7 +823,7 @@ static x509_t* add_certificate(linked_list_t *certs, x509_t *cert)
 /**
  * Add a unique ca info record to a linked list
  */
-static void add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_info)
+static ca_info_t* add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_info)
 {
        ca_info_t *current_ca_info;
        ca_info_t *found_ca_info = NULL;
@@ -849,11 +844,13 @@ static void add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_in
        {
                current_ca_info->add_info(current_ca_info, ca_info);
                ca_info->destroy(ca_info);
+               ca_info = found_ca_info;
        }
        else
        {
                this->ca_infos->insert_last(this->ca_infos, (void*)ca_info);
        }
+       return ca_info;
 }
 
 /**
@@ -1020,12 +1017,15 @@ static void load_ca_certificates(private_local_credential_store_t *this)
 
                while (iterator->iterate(iterator, (void **)&ca_info))
                {
-                       x509_t *cacert = ca_info->get_certificate(ca_info);
-                       ca_info_t *issuer = get_issuer(this, cacert);
-
-                       if (issuer)
+                       if (ca_info->is_ca(ca_info))
                        {
-                               add_uris(issuer, cacert);
+                               x509_t *cacert = ca_info->get_certificate(ca_info);
+                               ca_info_t *issuer = get_issuer(this, cacert);
+
+                               if (issuer)
+                               {
+                                       add_uris(issuer, cacert);
+                               }
                        }
                }
                iterator->destroy(iterator);
@@ -1119,7 +1119,7 @@ static void add_crl(private_local_credential_store_t *this, crl_t *crl, const ch
 
        while (iterator->iterate(iterator, (void**)&ca_info))
        {
-               if (ca_info->is_crl_issuer(ca_info, crl))
+               if (ca_info->is_ca(ca_info) && ca_info->is_crl_issuer(ca_info, crl))
                {
                        char buffer[BUF_LEN];
                        chunk_t uri = { buffer, 7 + strlen(path) };
@@ -1466,7 +1466,7 @@ local_credential_store_t * local_credential_store_create(void)
        this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify;
        this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate;
        this->public.credential_store.add_auth_certificate = (x509_t* (*) (credential_store_t*,x509_t*,u_int))add_auth_certificate;
-       this->public.credential_store.add_ca_info = (void (*) (credential_store_t*,ca_info_t*))add_ca_info;
+       this->public.credential_store.add_ca_info = (ca_info_t* (*) (credential_store_t*,ca_info_t*))add_ca_info;
        this->public.credential_store.release_ca_info = (status_t (*) (credential_store_t*,const char*))release_ca_info;
        this->public.credential_store.create_cert_iterator = (iterator_t* (*) (credential_store_t*))create_cert_iterator;
        this->public.credential_store.create_auth_cert_iterator = (iterator_t* (*) (credential_store_t*))create_auth_cert_iterator;
index bbbed24..4a77b11 100755 (executable)
@@ -400,22 +400,56 @@ static void stroke_add_conn(private_stroke_interface_t *this,
        {
                x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id);
 
-               if (my_ca == NULL && !my_ca_same && cert)
+               if (cert)
                {
-                       identification_t *issuer = cert->get_issuer(cert);
+                       ca_info_t *ca_info;
 
-                       my_ca = issuer->clone(issuer);
+                       if (cert->is_self_signed(cert))
+                       {
+                               /* a self-signed certificate is its own ca */
+                               ca_info = ca_info_create(NULL, cert);
+                               ca_info = charon->credentials->add_ca_info(charon->credentials, ca_info);
+                               cert->set_ca_info(cert, ca_info);
+                       }
+                       else
+                       {
+                               /* get_issuer() automatically sets cert->ca_info */
+                               ca_info = charon->credentials->get_issuer(charon->credentials, cert);
+                       }
+                       if (my_ca == NULL && !my_ca_same)
+                       {
+                               identification_t *issuer = cert->get_issuer(cert);
+
+                               my_ca = issuer->clone(issuer);
+                       }
                }
        }
        if (msg->add_conn.other.cert)
        {
                x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id);
 
-               if (other_ca == NULL && !other_ca_same && cert)
+               if (cert)
                {
-                       identification_t *issuer = cert->get_issuer(cert);
+                       ca_info_t *ca_info;
 
-                       other_ca = issuer->clone(issuer);
+                       if (cert->is_self_signed(cert))
+                       {
+                               /* a self-signed certificate is its own ca */
+                               ca_info = ca_info_create(NULL, cert);
+                               ca_info = charon->credentials->add_ca_info(charon->credentials, ca_info);
+                               cert->set_ca_info(cert, ca_info);
+                       }
+                       else
+                       {
+                               /* get_issuer() automatically sets cert->ca_info */
+                               ca_info = charon->credentials->get_issuer(charon->credentials, cert);
+                       }
+                       if (other_ca == NULL && !other_ca_same)
+                       {
+                               identification_t *issuer = cert->get_issuer(cert);
+
+                               other_ca = issuer->clone(issuer);
+                       }
                }
        }
        if (other_ca_same && my_ca)
@@ -443,13 +477,14 @@ static void stroke_add_conn(private_stroke_interface_t *this,
        while (iterator->iterate(iterator, (void**)&peer_cfg))
        {
                ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
-               if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg)) &&
-                       other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg)) &&
-                       my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg)) &&
-                       other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg)) &&
-                       peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) &&
-                       peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method &&
-                       peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type)
+               if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg))
+               &&      other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg))
+               &&      my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg))
+               &&      other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg))
+               &&      other_ca->equals(other_ca, peer_cfg->get_other_ca(peer_cfg))
+               &&      peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1)
+               &&      peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method
+               &&      peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type)
                {
                        DBG1(DBG_CFG, "reusing existing configuration '%s'",
                                 peer_cfg->get_name(peer_cfg));
@@ -1215,6 +1250,17 @@ static void stroke_status(private_stroke_interface_t *this,
                        fprintf(out, "%12s:  %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg),
                                        ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg),
                                        ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg));
+                       {
+                               identification_t *my_ca = peer_cfg->get_my_ca(peer_cfg);
+                               identification_t *other_ca = peer_cfg->get_other_ca(peer_cfg);
+
+                               if (my_ca->get_type(my_ca) != ID_ANY
+                               ||  other_ca->get_type(other_ca) != ID_ANY)
+                               {
+                                       fprintf(out, "%12s:    CAs: '%D'...'%D'\n", peer_cfg->get_name(peer_cfg),
+                                                       my_ca, other_ca);
+                               }
+                       }
                        children = peer_cfg->create_child_cfg_iterator(peer_cfg);
                        while (children->iterate(children, (void**)&child_cfg))
                        {
@@ -1341,17 +1387,22 @@ static void stroke_list(private_stroke_interface_t *this,
        if (msg->list.flags & LIST_CAINFOS)
        {
                ca_info_t *ca_info;
+               bool first = TRUE;
 
                iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
-               if (iterator->get_count(iterator))
-               {
-                       fprintf(out, "\n");
-                       fprintf(out, "List of X.509 CA Information Records:\n");
-                       fprintf(out, "\n");
-               }
                while (iterator->iterate(iterator, (void**)&ca_info))
                {
-                       ca_info->list(ca_info, out, msg->list.utc);
+                       if (ca_info->is_ca(ca_info))
+                       {
+                               if (first)
+                               {
+                                       fprintf(out, "\n");
+                                       fprintf(out, "List of X.509 CA Information Records:\n");
+                                       fprintf(out, "\n");
+                                       first = FALSE;
+                               }
+                               ca_info->list(ca_info, out, msg->list.utc);
+                       }
                }
                iterator->destroy(iterator);
        }
@@ -1359,11 +1410,11 @@ static void stroke_list(private_stroke_interface_t *this,
        {
         ca_info_t *ca_info;
         bool first = TRUE;
-        
+
         iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
         while (iterator->iterate(iterator, (void **)&ca_info))
         {
-            if (ca_info->has_crl(ca_info))
+            if (ca_info->is_ca(ca_info) && ca_info->has_crl(ca_info))
             {
                 if (first)
                 {
@@ -1385,7 +1436,7 @@ static void stroke_list(private_stroke_interface_t *this,
         iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
         while (iterator->iterate(iterator, (void **)&ca_info))
         {
-            if (ca_info->has_certinfos(ca_info))
+            if (ca_info->is_ca(ca_info) && ca_info->has_certinfos(ca_info))
             {
                 if (first)
                 {
@@ -1434,7 +1485,10 @@ static void stroke_purge(private_stroke_interface_t *this,
 
                while (iterator->iterate(iterator, (void**)&ca_info))
                {
-                       ca_info->purge_ocsp(ca_info);
+                       if (ca_info->is_ca(ca_info))
+                       {
+                               ca_info->purge_ocsp(ca_info);
+                       }
                }
                iterator->destroy(iterator);
        }
index 5a1a3a5..e5c5cd6 100644 (file)
@@ -80,6 +80,7 @@ static status_t verify(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
        
        if (status == SUCCESS)
        {
+               this->ike_sa->set_other_ca(this->ike_sa, issuer);
                DBG1(DBG_IKE, "authentication of '%D' with %N successful",
                                           other_id, auth_method_names, AUTH_RSA);
        }
index 4eaf1b0..d0dd49a 100644 (file)
@@ -511,15 +511,6 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
                return NEED_MORE;
        }
        
-       config = charon->backends->get_peer_cfg(charon->backends,
-                                                                       this->ike_sa->get_my_id(this->ike_sa),
-                                                                       this->ike_sa->get_other_id(this->ike_sa));
-       if (config)
-       {
-               this->ike_sa->set_peer_cfg(this->ike_sa, config);
-               config->destroy(config);
-       }
-       
        switch (process_auth(this, message))
        {
                case SUCCESS:
@@ -532,6 +523,17 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
                default:
                        break;
        }
+
+       config = charon->backends->get_peer_cfg(charon->backends,
+                                                                       this->ike_sa->get_my_id(this->ike_sa),
+                                                                       this->ike_sa->get_other_id(this->ike_sa),
+                                                                       this->ike_sa->get_other_ca(this->ike_sa));
+       if (config)
+       {
+               this->ike_sa->set_peer_cfg(this->ike_sa, config);
+               config->destroy(config);
+       }
+       
        return NEED_MORE;
 }
 
index dce8d60..b34a66d 100755 (executable)
@@ -199,8 +199,9 @@ struct credential_store_t {
         *
         * @param this          calling object
         * @param ca_info       ca info record to be added
+        * @return                      pointer to the added or already existing ca_info_t record
         */
-       void (*add_ca_info) (credential_store_t *this, ca_info_t *ca_info);
+       ca_info_t* (*add_ca_info) (credential_store_t *this, ca_info_t *ca_info);
 
        /**
         * @brief Release a ca info record with a given name.