http post fetching using libcurl implemented
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 7 Mar 2007 19:28:03 +0000 (19:28 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 7 Mar 2007 19:28:03 +0000 (19:28 -0000)
src/charon/Makefile.am
src/charon/daemon.c
src/libstrongswan/crypto/ocsp.c
src/libstrongswan/utils/fetcher.c
src/libstrongswan/utils/fetcher.h
src/pluto/fetch.c

index e370874..692ffeb 100644 (file)
@@ -71,3 +71,8 @@ threads/thread_pool.h threads/receiver.h threads/stroke_interface.h
 INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke
 AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" -DIPSEC_EAPDIR=\"${eapdir}\"
 charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lgmp -lpthread -lm -ldl
+
+if USE_LIBCURL
+   charon_LDADD += -lcurl
+endif
+
index 4a14340..1e6e18b 100644 (file)
@@ -39,6 +39,7 @@
 #include "daemon.h"
 
 #include <library.h>
+#include <utils/fetcher.h>
 #include <config/credentials/local_credential_store.h>
 #include <config/connections/local_connection_store.h>
 #include <config/policies/local_policy_store.h>
@@ -268,6 +269,9 @@ static void initialize(private_daemon_t *this, bool strict, bool syslog,
        this->public.policies = (policy_store_t*)local_policy_store_create();
        this->public.credentials = (credential_store_t*)local_credential_store_create(strict);
 
+       /* initialize fetcher_t class */
+       fetcher_initialize();
+
        /* load secrets, ca certificates and crls */
        credentials = this->public.credentials;
        credentials->load_ca_certificates(credentials);
index b5112ef..0fe24c8 100644 (file)
@@ -33,6 +33,7 @@
 #include <asn1/asn1.h>
 #include <utils/identification.h>
 #include <utils/randomizer.h>
+#include <utils/fetcher.h>
 #include <debug.h>
 
 #include "hashers/hasher.h"
@@ -455,6 +456,8 @@ static chunk_t ocsp_build_request(private_ocsp_t *this)
 static void fetch(private_ocsp_t *this, certinfo_t *certinfo)
 {
        chunk_t request;
+       chunk_t reply;
+       bool fetched = FALSE;
 
        if (this->uris->get_count(this->uris) == 0)
        {
@@ -467,14 +470,33 @@ static void fetch(private_ocsp_t *this, certinfo_t *certinfo)
        {
                iterator_t *iterator = this->uris->create_iterator(this->uris, TRUE);
                identification_t *uri;
-
+               
                while (iterator->iterate(iterator, (void**)&uri))
                {
-                       DBG1("sending ocsp request to location '%D'", uri);
+                       fetcher_t *fetcher;
+                       char uri_string[BUF_LEN];
+                       chunk_t uri_chunk = uri->get_encoding(uri);
+
+                       snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr);
+                       fetcher = fetcher_create(uri_string);
+                       
+                       reply = fetcher->post(fetcher, "application/ocsp-request", request);
+                       fetcher->destroy(fetcher);
+                       if (reply.ptr != NULL)
+                       {
+                               fetched = TRUE;
+                               break;
+                       }
                }
                iterator->destroy(iterator);
        }
        free(request.ptr);
+
+       if (!fetched)
+       {
+               return;
+       }
+       DBG3("ocsp reply: %B", &reply);
 }
 
 /**
index 2cabf9d..6cc89a0 100644 (file)
  * for more details.
  */
 
+#ifdef LIBCURL
+#include <curl/curl.h>
+#endif
+
+#include <library.h>
+#include <debug.h>
+
 #include "fetcher.h"
 
 typedef struct private_fetcher_t private_fetcher_t;
@@ -32,15 +39,96 @@ struct private_fetcher_t {
         * Public data
         */
        fetcher_t public;
+
+       /**
+        * URI of the information source
+        */
+       const char *uri;
+
+#ifdef LIBCURL
+       /**
+        * we use libcurl from http://curl.haxx.se/ as a fetcher
+        */
+       CURL* curl;
+#endif /* LIBCURL */
        
 };
 
 /**
+ * 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)
+{
+    size_t realsize = size * nmemb;
+    chunk_t *mem = (chunk_t*)data;
+
+    mem->ptr = (u_char *)realloc(mem->ptr, mem->len + realsize);
+    if (mem->ptr) {
+       memcpy(&(mem->ptr[mem->len]), ptr, realsize);
+       mem->len += realsize;
+    }
+    return realsize;
+}
+
+/**
  * Implements fetcher_t.get
  */
-static chunk_t get(private_fetcher_t *this, chunk_t uri)
+static chunk_t get(private_fetcher_t *this, const char *uri)
 {
-       
+       return chunk_empty;
+}
+
+/**
+ * Implements fetcher_t.post
+ */
+static chunk_t post(private_fetcher_t *this, const char *request_type, chunk_t request)
+{
+       chunk_t response = chunk_empty;
+
+#ifdef LIBCURL
+       if (this->curl)
+       {
+               CURLcode res;
+               struct curl_slist *headers = NULL;
+               chunk_t curl_response = chunk_empty;
+               char curl_error_buffer[CURL_ERROR_SIZE];
+               char content_type[BUF_LEN];
+
+               /* set content type header */
+               snprintf(content_type, BUF_LEN, "Content-Type: %s", request_type);
+               headers = curl_slist_append(headers, content_type);
+
+               /* set options */
+               curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers);
+               curl_easy_setopt(this->curl, CURLOPT_URL, this->uri);
+               curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, curl_write_buffer);
+               curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void *)&curl_response);
+               curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, request.ptr);
+               curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, request.len);
+               curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, &curl_error_buffer);
+               curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
+               curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT);
+
+               DBG2("sending http post request to '%s'", this->uri);
+               res = curl_easy_perform(this->curl);
+
+               if (res == CURLE_OK)
+               {
+               DBG2("received valid http response");
+                       response = chunk_clone(curl_response);
+               }
+               else
+               {
+               DBG1("http post request to '%s' using libcurl failed: %s",
+                                 this->uri, curl_error_buffer);
+               }
+               curl_free(curl_response.ptr);
+       }
+#else
+       DBG1("warning: libcurl fetching not compiled in");
+#endif  /* LIBCURL */
+       return response;
 }
 
 /**
@@ -48,21 +136,49 @@ static chunk_t get(private_fetcher_t *this, chunk_t uri)
  */
 static void destroy(private_fetcher_t *this)
 {
+       curl_easy_cleanup(this->curl);
        free(this);
 }
 
 /*
  * Described in header.
  */
-fetcher_t *fetcher_create(void)
+fetcher_t *fetcher_create(const char *uri)
 {
        private_fetcher_t *this = malloc_thing(private_fetcher_t);
        
        /* initialize */
+       this->uri = uri;
+#ifdef LIBCURL
+    this->curl = curl_easy_init();
+       if (this->curl == NULL)
+       {
+               DBG1("curl_easy_init_failed()");
+       }
+#endif /* LIBCURL */
 
        /* public functions */
-       this->public.get = (chunk_t (*) (fetcher_t*,chunk_t))get;
+       this->public.get = (chunk_t (*) (fetcher_t*,const char*))get;
+       this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))post;
        this->public.destroy = (void (*) (fetcher_t*))destroy;
 
        return &this->public;
 }
+
+/**
+ * Described in header.
+ */
+void fetcher_initialize(void)
+{
+ #ifdef LIBCURL
+       CURLcode res;
+
+       /* init libcurl */
+       DBG1("initializing libcurl");
+       res = curl_global_init(CURL_GLOBAL_NOTHING);
+       if (res != CURLE_OK)
+       {
+               DBG1("libcurl could not be initialized: %s", curl_easy_strerror(res));
+    }
+#endif /* LIBCURL */
+}
index dbe0ff9..ca39186 100644 (file)
@@ -27,6 +27,8 @@ typedef struct fetcher_t fetcher_t;
 
 #include <chunk.h>
 
+#define FETCHER_TIMEOUT        10      /* seconds */
+
 /**
  * @brief Fetches information from an URI (http, file, ftp, etc.)
  *
@@ -38,10 +40,21 @@ struct fetcher_t {
         * @brief Get information via a get request.
         * 
         * @param this                          calling object
-        * @param uri                           uri specifying where to get information from
+        * @param uri                           uri specifying the information source
+        * @return                                      chunk_t containing the information
+        */
+       chunk_t (*get) (fetcher_t *this, const char *uri);
+
+       /**
+        * @brief Get information via a get request.
+        * 
+        * @param this                          calling object
+        * @param uri                           uri specifying the information source
+        * @param type                          content type of http post request
+        * @param request                       binary data for http post request
         * @return                                      chunk_t containing the information
         */
-       chunk_t (*get) (fetcher_t *this, chunk_t uri);
+       chunk_t (*post) (fetcher_t *this, const char *type, chunk_t request);
 
        /**
         * @brief Destroys the fetcher_t object.
@@ -57,8 +70,17 @@ struct fetcher_t {
  * 
  * @return                     created fetcher_t object
  * 
- * @ingroup transforms
+ * @ingroup utils
+ */
+fetcher_t* fetcher_create(const char *uri);
+
+/**
+ * @brief Initializes the fetcher_t class
+ *
+ * call this function only once in the main program
+ *
+ * @ingroup utils
  */
-fetcher_t *fetcher_create(void);
+void fetcher_initialize(void);
 
 #endif /*FETCHER_H_*/
index 4bfb603..d979828 100644 (file)
@@ -827,7 +827,7 @@ init_fetch(void)
 #ifdef LIBCURL
     /* init curl */
     status = curl_global_init(CURL_GLOBAL_NOTHING);
-    if (status != 0)
+    if (status != CURLE_OK)
     {
        plog("libcurl could not be initialized, status = %d", status);
     }