#include <asn1/asn1.h>
#include <utils/identification.h>
#include <utils/randomizer.h>
+#include <utils/fetcher.h>
#include <debug.h>
#include "hashers/hasher.h"
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)
{
{
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);
}
/**
* 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;
* 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;
}
/**
*/
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 */
+}
#include <chunk.h>
+#define FETCHER_TIMEOUT 10 /* seconds */
+
/**
* @brief Fetches information from an URI (http, file, ftp, etc.)
*
* @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.
*
* @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_*/