support of ldap-based crl fetching
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 6 Apr 2007 09:44:06 +0000 (09:44 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 6 Apr 2007 09:44:06 +0000 (09:44 -0000)
src/libstrongswan/Makefile.am
src/libstrongswan/crypto/ca.c
src/libstrongswan/utils/fetcher.c
src/pluto/Makefile.am
src/pluto/constants.c
src/pluto/fetch.c

index 0236ba3..b103be1 100644 (file)
@@ -58,6 +58,10 @@ if USE_LIBCURL
   libstrongswan_la_LIBADD += -lcurl
 endif
 
+if USE_LIBLDAP
+  libstrongswan_la_LIBADD += -lldap -llber
+endif
+
 asn1/oid.c :   asn1/oid.txt asn1/oid.pl
                cd asn1 && $(PERL) oid.pl
 
index 4ec8c84..9633c77 100644 (file)
@@ -191,12 +191,12 @@ static void add_crl(private_ca_info_t *this, crl_t *crl)
                {
                        this->crl->destroy(this->crl);
                        this->crl = crl;
-                       DBG1("  thisUpdate is newer - existing crl replaced");
+                       DBG1("  this crl is newer - existing crl replaced");
                }
                else
                {
                        crl->destroy(crl);
-                       DBG1("  thisUpdate is not newer - existing crl retained");
+                       DBG1("  this crl is older - existing crl retained");
                }
        }
        else
@@ -500,12 +500,12 @@ static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo
                                {
                                        this->crl->destroy(this->crl);
                                        this->crl = crl;
-                                       DBG1(" thisUpdate is newer - existing crl replaced");
+                                       DBG1("this crl is newer - existing crl replaced");
                                }
                                else
                                {
                                        crl->destroy(crl);
-                                       DBG1("thisUpdate is not newer - existing crl retained");
+                                       DBG1("this crl is older - existing crl retained");
                                        continue;
                                }
                                if (crl->is_valid(crl))
index cf83adb..d728f0d 100644 (file)
 #include <curl/curl.h>
 #endif /* LIBCURL */
 
+#ifdef LIBLDAP
+#include <ldap.h>
+#endif /* LIBLDAP */
+
 #include <library.h>
 #include <debug.h>
 
@@ -52,13 +56,20 @@ struct private_fetcher_t {
        CURL* curl;
 #endif /* LIBCURL */
        
+#ifdef LIBLDAP
+       /**
+        * we use libldap from http://www.openssl.org/ as a fetcher
+        */
+       LDAP *ldap;
+       LDAPURLDesc *lurl;
+#endif /* LIBLDAP */
 };
 
 /**
  * writes data into a dynamically resizeable chunk_t
  * needed for libcurl responses
  */
-size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data)
+static size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data)
 {
     size_t realsize = size * nmemb;
     chunk_t *mem = (chunk_t*)data;
@@ -72,9 +83,9 @@ size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data)
 }
 
 /**
- * Implements fetcher_t.get
+ * Implements fetcher_t.get for http[s] and file URIs
  */
-static chunk_t get(private_fetcher_t *this)
+static chunk_t curl_get(private_fetcher_t *this)
 {
        chunk_t response = chunk_empty;
 
@@ -93,17 +104,17 @@ static chunk_t get(private_fetcher_t *this)
                curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT);
                curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
 
-               DBG1("sending http get request to '%s'...", this->uri);
+               DBG1("sending curl request to '%s'...", this->uri);
                res = curl_easy_perform(this->curl);
 
                if (res == CURLE_OK)
                {
-               DBG1("received valid http response");
+               DBG1("received valid curl response");
                        response = chunk_clone(curl_response);
                }
                else
                {
-               DBG1("http get request to '%s' using libcurl failed: %s",
+               DBG1("curl request to '%s' failed: %s",
                                  this->uri, curl_error_buffer);
                }
                curl_free(curl_response.ptr);
@@ -115,9 +126,9 @@ static chunk_t get(private_fetcher_t *this)
 }
 
 /**
- * Implements fetcher_t.post
+ * Implements fetcher_t.post.
  */
-static chunk_t post(private_fetcher_t *this, const char *request_type, chunk_t request)
+static chunk_t http_post(private_fetcher_t *this, const char *request_type, chunk_t request)
 {
        chunk_t response = chunk_empty;
 
@@ -168,14 +179,146 @@ static chunk_t post(private_fetcher_t *this, const char *request_type, chunk_t r
        return response;
 }
 
+#ifdef LIBLDAP
+/**
+ * parses the result returned by an ldap query
+ */
+static chunk_t ldap_parse(LDAP *ldap, LDAPMessage *result)
+{
+       chunk_t response = chunk_empty;
+
+       LDAPMessage *entry = ldap_first_entry(ldap, result);
+       if (entry != NULL)
+       {
+               BerElement *ber = NULL;
+               char *attr;
+
+               attr = ldap_first_attribute(ldap, entry, &ber);
+
+               if (attr != NULL)
+               {
+                       struct berval **values = ldap_get_values_len(ldap, entry, attr);
+
+                       if (values != NULL)
+                       {
+                               if (values[0] != NULL)
+                               {
+                                       response.len = values[0]->bv_len;
+                                       response.ptr = malloc(response.len);
+                                       memcpy(response.ptr, values[0]->bv_val, response.len);
+                                       if (values[1] != NULL)
+                                       {
+                                               DBG1("ldap: more than one value was fetched from LDAP URL");
+                                       }
+                               }
+                               else
+                               {
+                                       DBG1("ldap: no values in attribute");
+                               }
+                               ldap_value_free_len(values);
+                       }
+                       else
+                       {
+                               DBG1("ldap: %s", ldap_err2string(ldap_result2error(ldap, entry, 0)));
+                       }
+                       ldap_memfree(attr);
+               }
+               else
+               {
+                       DBG1("ldap: %s", ldap_err2string(ldap_result2error(ldap, entry, 0)));
+               }
+               ber_free(ber, 0);
+       }
+       else
+       {
+               DBG1("ldap: %s", ldap_err2string(ldap_result2error(ldap, result, 0)));
+       }
+       return response;
+}
+#endif  /* LIBLDAP */
+
+/**
+ * fetches a binary blob from an ldap url
+ */
+static chunk_t ldap_get(private_fetcher_t *this)
+{
+       chunk_t response = chunk_empty;
+
+#ifdef LIBLDAP
+       if (this->ldap)
+       {
+               int rc;
+               int ldap_version = LDAP_VERSION3;
+
+               struct timeval timeout;
+
+               timeout.tv_sec  = FETCHER_TIMEOUT;
+               timeout.tv_usec = 0;
+
+               ldap_set_option(this->ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
+               ldap_set_option(this->ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout);
+
+               DBG1("sending ldap request to '%s'...", this->uri);
+
+               rc = ldap_simple_bind_s(this->ldap, NULL, NULL);
+               if (rc == LDAP_SUCCESS)
+               {
+                       LDAPMessage *result;
+
+                       timeout.tv_sec = FETCHER_TIMEOUT;
+                       timeout.tv_usec = 0;
+
+                       rc = ldap_search_st(this->ldap, this->lurl->lud_dn,
+                                                                                       this->lurl->lud_scope,
+                                                                                       this->lurl->lud_filter,
+                                                                                       this->lurl->lud_attrs,
+                                                                                       0, &timeout, &result);
+
+                       if (rc == LDAP_SUCCESS)
+                       {
+                               response = ldap_parse(this->ldap, result);
+                               if (response.ptr)
+                               {
+                               DBG1("received valid ldap response");
+                               }
+                               ldap_msgfree(result);
+                       }
+                       else
+                       {
+                               DBG1("ldap: %s", ldap_err2string(rc));
+                       }
+               }
+               else
+               {
+                       DBG1("ldap: %s", ldap_err2string(rc));
+               }
+               ldap_unbind_s(this->ldap);
+       }
+#else   /* !LIBLDAP */
+       DBG1("warning: libldap fetching not compiled in");
+#endif  /* !LIBLDAP */
+    return response;
+}
+
 /**
  * Implements fetcher_t.destroy
  */
 static void destroy(private_fetcher_t *this)
 {
 #ifdef LIBCURL
-       curl_easy_cleanup(this->curl);
+       if (this->curl)
+       {
+               curl_easy_cleanup(this->curl);
+       }
 #endif /* LIBCURL */
+
+#ifdef LIBLDAP
+       if (this->lurl)
+       {
+               ldap_free_urldesc(this->lurl);
+       }
+#endif /* LIBLDAP */
+
        free(this);
 }
 
@@ -188,17 +331,48 @@ fetcher_t *fetcher_create(const char *uri)
        
        /* initialize */
        this->uri = uri;
+
 #ifdef LIBCURL
-    this->curl = curl_easy_init();
-       if (this->curl == NULL)
+       this->curl = NULL;
+#endif /* LIBCURL */
+
+#ifdef LIBLDAP
+               this->lurl = NULL;
+               this->ldap = NULL;
+#endif /* LIBLDAP */
+
+       if (strlen(uri) >= 4 && strncasecmp(uri, "ldap", 4) == 0)
        {
-               DBG1("curl_easy_init_failed()");
+#ifdef LIBLDAP
+               int rc = ldap_url_parse(uri, &this->lurl);
+
+               if (rc == LDAP_SUCCESS)
+               {
+                       this->ldap = ldap_init(this->lurl->lud_host,
+                                                                  this->lurl->lud_port);
+               }
+               else
+               {
+                       DBG1("ldap: %s", ldap_err2string(rc));
+                       this->ldap = NULL;
+               }
+#endif /* LIBLDAP */
+               this->public.get = (chunk_t (*) (fetcher_t*))ldap_get;
        }
+       else
+       {
+#ifdef LIBCURL
+               this->curl = curl_easy_init();
+               if (this->curl == NULL)
+               {
+                       DBG1("curl_easy_init_failed()");
+               }
 #endif /* LIBCURL */
+               this->public.get = (chunk_t (*) (fetcher_t*))curl_get;
+       }
 
        /* public functions */
-       this->public.get = (chunk_t (*) (fetcher_t*))get;
-       this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))post;
+       this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))http_post;
        this->public.destroy = (void (*) (fetcher_t*))destroy;
 
        return &this->public;
@@ -209,7 +383,7 @@ fetcher_t *fetcher_create(const char *uri)
  */
 void fetcher_initialize(void)
 {
- #ifdef LIBCURL
+#ifdef LIBCURL
        CURLcode res;
 
        /* initialize libcurl */
@@ -227,7 +401,7 @@ void fetcher_initialize(void)
  */
 void fetcher_finalize(void)
 {
- #ifdef LIBCURL
+#ifdef LIBCURL
        /* finalize libcurl */
        DBG1("finalizing libcurl");
        curl_global_cleanup();
index 208dea1..b1b848c 100644 (file)
@@ -123,7 +123,7 @@ if USE_LIBCURL
 endif
 
 # This compile option activates dynamic LDAP CRL fetching
-if USE_LDAP
+if USE_LIBLDAP
   pluto_LDADD += -lldap -llber
 endif
 
index 1fc5ec4..e7d7216 100644 (file)
@@ -41,12 +41,8 @@ const char compile_time_interop_options[] = ""
 #ifdef LIBCURL
        " LIBCURL"
 #endif
-#ifdef LDAP_VER
-#if LDAP_VER == 2
-       " LDAP_V2"
-#else
-       " LDAP_V3"
-#endif
+#ifdef LIBLDAP
+       " LIBLDAP"
 #endif
 #ifdef SMARTCARD
        " SMARTCARD"
index d3d922f..e3e56d3 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <freeswan.h>
 
-#ifdef LDAP_VER
+#ifdef LIBLDAP
 #include <ldap.h>
 #endif
 
@@ -347,7 +347,7 @@ fetch_curl(char *url, chunk_t *blob)
 #endif  /* !LIBCURL */
 }
 
-#ifdef LDAP_VER
+#ifdef LIBLDAP
 /*
  * parses the result returned by an ldap query
  */
@@ -428,7 +428,7 @@ fetch_ldap_url(char *url, chunk_t *blob)
 
        if (ldap != NULL)
        {
-           int ldap_version = (LDAP_VER == 2)? LDAP_VERSION2 : LDAP_VERSION3;
+           int ldap_version = LDAP_VERSION3;
            struct timeval timeout;
 
            timeout.tv_sec  = FETCH_CMD_TIMEOUT;
@@ -479,13 +479,13 @@ fetch_ldap_url(char *url, chunk_t *blob)
     }
     return ugh;
 }
-#else   /* !LDAP_VER */
+#else   /* !LIBLDAP */
 static err_t
 fetch_ldap_url(char *url, chunk_t *blob)
 {
     return "LDAP URL fetching not activated in pluto source code";
 }
-#endif  /* !LDAP_VER */
+#endif  /* !LIBLDAP */
 
 /*
  * fetch an ASN.1 blob coded in PEM or DER format from a URL