diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index e37087486..692ffeb12 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -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 + diff --git a/src/charon/daemon.c b/src/charon/daemon.c index 4a1434014..1e6e18b47 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -39,6 +39,7 @@ #include "daemon.h" #include +#include #include #include #include @@ -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); diff --git a/src/libstrongswan/crypto/ocsp.c b/src/libstrongswan/crypto/ocsp.c index b5112ef29..0fe24c89b 100644 --- a/src/libstrongswan/crypto/ocsp.c +++ b/src/libstrongswan/crypto/ocsp.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #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); } /** diff --git a/src/libstrongswan/utils/fetcher.c b/src/libstrongswan/utils/fetcher.c index 2cabf9d83..6cc89a009 100644 --- a/src/libstrongswan/utils/fetcher.c +++ b/src/libstrongswan/utils/fetcher.c @@ -20,6 +20,13 @@ * for more details. */ +#ifdef LIBCURL +#include +#endif + +#include +#include + #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 */ +} diff --git a/src/libstrongswan/utils/fetcher.h b/src/libstrongswan/utils/fetcher.h index dbe0ff98c..ca3918697 100644 --- a/src/libstrongswan/utils/fetcher.h +++ b/src/libstrongswan/utils/fetcher.h @@ -27,6 +27,8 @@ typedef struct fetcher_t fetcher_t; #include +#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, chunk_t uri); + 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 (*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(void); +fetcher_t* fetcher_create(const char *uri); + +/** + * @brief Initializes the fetcher_t class + * + * call this function only once in the main program + * + * @ingroup utils + */ +void fetcher_initialize(void); #endif /*FETCHER_H_*/ diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c index 4bfb6031b..d9798284d 100644 --- a/src/pluto/fetch.c +++ b/src/pluto/fetch.c @@ -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); }