From e67197a7f9c55fde4f9342d4a96ef2800241e0e3 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Wed, 29 Apr 2009 08:09:35 +0000 Subject: [PATCH] pluto and scepclient use the curl and ldap fetcher plugins --- src/libstrongswan/fetcher/fetcher.h | 12 + src/libstrongswan/fetcher/fetcher_manager.c | 4 + src/libstrongswan/plugins/curl/curl_fetcher.c | 39 +- src/pluto/Makefile.am | 18 +- src/pluto/constants.c | 6 - src/pluto/fetch.c | 581 ++++-------------- src/pluto/plutomain.c | 2 +- src/scepclient/Makefile.am | 12 +- src/scepclient/scep.c | 163 ++--- src/scepclient/scep.h | 2 +- src/scepclient/scepclient.c | 29 +- 11 files changed, 246 insertions(+), 622 deletions(-) diff --git a/src/libstrongswan/fetcher/fetcher.h b/src/libstrongswan/fetcher/fetcher.h index 9a7cc315e..70d14bf97 100644 --- a/src/libstrongswan/fetcher/fetcher.h +++ b/src/libstrongswan/fetcher/fetcher.h @@ -45,6 +45,18 @@ enum fetcher_option_t { */ FETCH_REQUEST_TYPE, + /** + * HTTP header to be sent with with the fetch request. + * Additional argument is a char*. + */ + FETCH_REQUEST_HEADER, + + /** + * Use HTTP Version 1.0 instead of 1.1. + * No additional argument is needed. + */ + FETCH_HTTP_VERSION_1_0, + /** * Timeout to use for fetch, in seconds. * Additional argument is u_int diff --git a/src/libstrongswan/fetcher/fetcher_manager.c b/src/libstrongswan/fetcher/fetcher_manager.c index dc4a2db3e..0f478a41e 100644 --- a/src/libstrongswan/fetcher/fetcher_manager.c +++ b/src/libstrongswan/fetcher/fetcher_manager.c @@ -101,8 +101,12 @@ static status_t fetch(private_fetcher_manager_t *this, good = fetcher->set_option(fetcher, opt, va_arg(args, chunk_t)); continue; case FETCH_REQUEST_TYPE: + case FETCH_REQUEST_HEADER: good = fetcher->set_option(fetcher, opt, va_arg(args, char*)); continue; + case FETCH_HTTP_VERSION_1_0: + good = fetcher->set_option(fetcher, opt); + continue; case FETCH_TIMEOUT: good = fetcher->set_option(fetcher, opt, va_arg(args, u_int)); continue; diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c index b213c7b47..d48e50a55 100644 --- a/src/libstrongswan/plugins/curl/curl_fetcher.c +++ b/src/libstrongswan/plugins/curl/curl_fetcher.c @@ -42,9 +42,9 @@ struct private_curl_fetcher_t { CURL* curl; /** - * request type, as set with FETCH_REQUEST_TYPE + * Optional HTTP headers */ - char *request_type; + struct curl_slist *headers; }; /** @@ -68,9 +68,8 @@ static size_t append(void *ptr, size_t size, size_t nmemb, chunk_t *data) */ static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result) { - struct curl_slist *headers = NULL; char error[CURL_ERROR_SIZE]; - char buf[256];; + char buf[256]; status_t status; *result = chunk_empty; @@ -85,14 +84,12 @@ static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result) curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT); curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)append); curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void*)result); - if (this->request_type) + if (this->headers) { - snprintf(buf, sizeof(buf), "Content-Type: %s", this->request_type); - headers = curl_slist_append(headers, buf); - curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, this->headers); } - DBG2("sending http request to '%s'...", uri); + DBG2(" sending http request to '%s'...", uri); switch (curl_easy_perform(this->curl)) { case CURLE_UNSUPPORTED_PROTOCOL: @@ -106,7 +103,6 @@ static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result) status = FAILED; break; } - curl_slist_free_all(headers); return status; } @@ -123,13 +119,31 @@ static bool set_option(private_curl_fetcher_t *this, fetcher_option_t option, .. case FETCH_REQUEST_DATA: { chunk_t data = va_arg(args, chunk_t); + curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, (char*)data.ptr); curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, data.len); return TRUE; } case FETCH_REQUEST_TYPE: { - this->request_type = va_arg(args, char*); + char header[BUF_LEN]; + char *request_type = va_arg(args, char*); + + snprintf(header, BUF_LEN, "Content-Type: %s", request_type); + this->headers = curl_slist_append(this->headers, header); + return TRUE; + } + case FETCH_REQUEST_HEADER: + { + char *header = va_arg(args, char*); + + this->headers = curl_slist_append(this->headers, header); + return TRUE; + } + case FETCH_HTTP_VERSION_1_0: + { + curl_easy_setopt(this->curl, CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_1_0); return TRUE; } case FETCH_TIMEOUT: @@ -148,6 +162,7 @@ static bool set_option(private_curl_fetcher_t *this, fetcher_option_t option, .. */ static void destroy(private_curl_fetcher_t *this) { + curl_slist_free_all(this->headers); curl_easy_cleanup(this->curl); free(this); } @@ -165,7 +180,7 @@ curl_fetcher_t *curl_fetcher_create() free(this); return NULL; } - this->request_type = NULL; + this->headers = NULL; this->public.interface.fetch = (status_t(*)(fetcher_t*,char*,chunk_t*))fetch; this->public.interface.set_option = (bool(*)(fetcher_t*, fetcher_option_t option, ...))set_option; diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am index 2e46de924..f360a27c7 100644 --- a/src/pluto/Makefile.am +++ b/src/pluto/Makefile.am @@ -84,6 +84,7 @@ AM_CFLAGS = \ -DIPSEC_PIDDIR=\"${piddir}\" \ -DSHARED_SECRETS_FILE=\"${confdir}/ipsec.secrets\" \ -DIPSEC_PLUGINDIR=\"${plugindir}\" \ +-DPLUGINS=\""${pluto_plugins}\"" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ -DKERNEL26_SUPPORT -DKERNEL26_HAS_KAME_DUPLICATES \ -DPLUTO -DKLIPS -DDEBUG @@ -100,11 +101,6 @@ $(LIBFREESWANDIR)/libfreeswan.a \ dist_man_MANS = pluto.8 ipsec.secrets.5 -# This compile option activates the memory leak detective -if USE_LEAK_DETECTIVE - AM_CFLAGS += -DLEAK_DETECTIVE -endif - # This compile option activates the sending of a strongSwan VID if USE_VENDORID AM_CFLAGS += -DVENDORID @@ -125,18 +121,6 @@ if USE_NAT_TRANSPORT AM_CFLAGS += -DI_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT endif -# This compile option activates dynamic URL fetching using libcurl -if USE_CURL - pluto_LDADD += -lcurl - AM_CFLAGS += -DLIBCURL -endif - -# This compile option activates dynamic LDAP CRL fetching -if USE_LDAP - pluto_LDADD += -lldap -llber - AM_CFLAGS += -DLIBLDAP -endif - # This compile option activates smartcard support if USE_SMARTCARD AM_CFLAGS += -DSMARTCARD diff --git a/src/pluto/constants.c b/src/pluto/constants.c index a302777dd..0099c803d 100644 --- a/src/pluto/constants.c +++ b/src/pluto/constants.c @@ -38,12 +38,6 @@ const char compile_time_interop_options[] = "" #ifdef THREADS " THREADS" #endif -#ifdef LIBCURL - " LIBCURL" -#endif -#ifdef LIBLDAP - " LIBLDAP" -#endif #ifdef SMARTCARD " SMARTCARD" #endif diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c index a8919e630..62d729716 100644 --- a/src/pluto/fetch.c +++ b/src/pluto/fetch.c @@ -25,20 +25,11 @@ #include #endif -#ifdef LIBCURL -#include -#endif - #include -#ifdef LIBLDAP -#ifndef LDAP_DEPRECATED -#define LDAP_DEPRECATED 1 -#endif -#include -#endif - -#include "asn1/asn1.h" +#include +#include +#include #include "constants.h" #include "defs.h" @@ -80,11 +71,10 @@ static pthread_mutex_t ocsp_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t fetch_wake_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t fetch_wake_cond = PTHREAD_COND_INITIALIZER; -/* +/** * lock access to my certs and keys */ -void -lock_certs_and_keys(const char *who) +void lock_certs_and_keys(const char *who) { pthread_mutex_lock(&certs_and_keys_mutex); DBG(DBG_CONTROLMORE, @@ -92,11 +82,10 @@ lock_certs_and_keys(const char *who) ) } -/* - * unlock access to my certs and keys +/** + * Unlock access to my certs and keys */ -void -unlock_certs_and_keys(const char *who) +void unlock_certs_and_keys(const char *who) { DBG(DBG_CONTROLMORE, DBG_log("certs and keys unlocked by '%s'", who) @@ -104,11 +93,10 @@ unlock_certs_and_keys(const char *who) pthread_mutex_unlock(&certs_and_keys_mutex); } -/* - * lock access to the chained authcert list +/** + * Lock access to the chained authcert list */ -void -lock_authcert_list(const char *who) +void lock_authcert_list(const char *who) { pthread_mutex_lock(&authcert_list_mutex); DBG(DBG_CONTROLMORE, @@ -116,11 +104,10 @@ lock_authcert_list(const char *who) ) } -/* - * unlock access to the chained authcert list +/** + * Unlock access to the chained authcert list */ -void -unlock_authcert_list(const char *who) +void unlock_authcert_list(const char *who) { DBG(DBG_CONTROLMORE, DBG_log("authcert list unlocked by '%s'", who) @@ -128,11 +115,10 @@ unlock_authcert_list(const char *who) pthread_mutex_unlock(&authcert_list_mutex); } -/* - * lock access to the chained crl list +/** + * Lock access to the chained crl list */ -void -lock_crl_list(const char *who) +void lock_crl_list(const char *who) { pthread_mutex_lock(&crl_list_mutex); DBG(DBG_CONTROLMORE, @@ -140,11 +126,10 @@ lock_crl_list(const char *who) ) } -/* - * unlock access to the chained crl list +/** + * Unlock access to the chained crl list */ -void -unlock_crl_list(const char *who) +void unlock_crl_list(const char *who) { DBG(DBG_CONTROLMORE, DBG_log("crl list unlocked by '%s'", who) @@ -152,11 +137,10 @@ unlock_crl_list(const char *who) pthread_mutex_unlock(&crl_list_mutex); } -/* - * lock access to the ocsp cache +/** + * Lock access to the ocsp cache */ -extern void -lock_ocsp_cache(const char *who) +extern void lock_ocsp_cache(const char *who) { pthread_mutex_lock(&ocsp_cache_mutex); DBG(DBG_CONTROLMORE, @@ -164,11 +148,10 @@ lock_ocsp_cache(const char *who) ) } -/* - * unlock access to the ocsp cache +/** + * Unlock access to the ocsp cache */ -extern void -unlock_ocsp_cache(const char *who) +extern void unlock_ocsp_cache(const char *who) { DBG(DBG_CONTROLMORE, DBG_log("ocsp cache unlocked by '%s'", who) @@ -176,11 +159,10 @@ unlock_ocsp_cache(const char *who) pthread_mutex_unlock(&ocsp_cache_mutex); } -/* - * lock access to the ca info list +/** + * Lock access to the ca info list */ -extern void -lock_ca_info_list(const char *who) +extern void lock_ca_info_list(const char *who) { pthread_mutex_lock(&ca_info_list_mutex); DBG(DBG_CONTROLMORE, @@ -188,11 +170,10 @@ lock_ca_info_list(const char *who) ) } -/* - * unlock access to the ca info list +/** + * Unlock access to the ca info list */ -extern void -unlock_ca_info_list(const char *who) +extern void unlock_ca_info_list(const char *who) { DBG(DBG_CONTROLMORE, DBG_log("ca info list unlocked by '%s'", who) @@ -200,11 +181,10 @@ unlock_ca_info_list(const char *who) pthread_mutex_unlock(&ca_info_list_mutex); } -/* - * lock access to the chained crl fetch request list +/** + * Lock access to the chained crl fetch request list */ -static void -lock_crl_fetch_list(const char *who) +static void lock_crl_fetch_list(const char *who) { pthread_mutex_lock(&crl_fetch_list_mutex); DBG(DBG_CONTROLMORE, @@ -212,11 +192,10 @@ lock_crl_fetch_list(const char *who) ) } -/* - * unlock access to the chained crl fetch request list +/** + * Unlock access to the chained crl fetch request list */ -static void -unlock_crl_fetch_list(const char *who) +static void unlock_crl_fetch_list(const char *who) { DBG(DBG_CONTROLMORE, DBG_log("crl fetch request list unlocked by '%s'", who) @@ -224,11 +203,10 @@ unlock_crl_fetch_list(const char *who) pthread_mutex_unlock(&crl_fetch_list_mutex); } -/* - * lock access to the chained ocsp fetch request list +/** + * Lock access to the chained ocsp fetch request list */ -static void -lock_ocsp_fetch_list(const char *who) +static void lock_ocsp_fetch_list(const char *who) { pthread_mutex_lock(&ocsp_fetch_list_mutex); DBG(DBG_CONTROLMORE, @@ -236,11 +214,10 @@ lock_ocsp_fetch_list(const char *who) ) } -/* - * unlock access to the chained ocsp fetch request list +/** + * Unlock access to the chained ocsp fetch request list */ -static void -unlock_ocsp_fetch_list(const char *who) +static void unlock_ocsp_fetch_list(const char *who) { DBG(DBG_CONTROLMORE, DBG_log("ocsp fetch request list unlocked by '%s'", who) @@ -248,11 +225,10 @@ unlock_ocsp_fetch_list(const char *who) pthread_mutex_unlock(&ocsp_fetch_list_mutex); } -/* - * wakes up the sleeping fetch thread +/** + * Wakes up the sleeping fetch thread */ -void -wake_fetch_thread(const char *who) +void wake_fetch_thread(const char *who) { if (crl_check_interval > 0) { @@ -271,11 +247,10 @@ wake_fetch_thread(const char *who) #define unlock_ocsp_fetch_list(who) /* do nothing */ #endif /* !THREADS */ -/* - * free the dynamic memory used to store fetch requests +/** + * Free the dynamic memory used to store fetch requests */ -static void -free_fetch_request(fetch_req_t *req) +static void free_fetch_request(fetch_req_t *req) { free(req->issuer.ptr); free(req->authKeySerialNumber.ptr); @@ -284,269 +259,53 @@ free_fetch_request(fetch_req_t *req) free(req); } -/* writes data into a dynamically resizeable chunk_t - * needed for libcurl responses - */ -size_t -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; -} - #ifdef THREADS -/* - * fetches a binary blob from a url with libcurl +/** + * Fetch an ASN.1 blob coded in PEM or DER format from a URL */ -static err_t -fetch_curl(char *url, chunk_t *blob) -{ -#ifdef LIBCURL - char errorbuffer[CURL_ERROR_SIZE] = ""; - chunk_t response = chunk_empty; - CURLcode res; - - /* get it with libcurl */ - CURL *curl = curl_easy_init(); - - if (curl != NULL) - { - DBG(DBG_CONTROL, - DBG_log("Trying cURL '%s'", url) - ) - - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); - - res = curl_easy_perform(curl); - - if (res == CURLE_OK) - { - blob->len = response.len; - blob->ptr = malloc(response.len); - memcpy(blob->ptr, response.ptr, response.len); - } - else - { - plog("fetching uri (%s) with libcurl failed: %s", url, errorbuffer); - } - curl_easy_cleanup(curl); - curl_free(response.ptr); - } - return strlen(errorbuffer) > 0 ? "libcurl error" : NULL; -#else /* !LIBCURL */ - return "warning: not compiled with libcurl support"; -#endif /* !LIBCURL */ -} - -#ifdef LIBLDAP -/* - * parses the result returned by an ldap query - */ -static err_t -parse_ldap_result(LDAP * ldap, LDAPMessage *result, chunk_t *blob) +bool fetch_asn1_blob(char *url, chunk_t *blob) { err_t ugh = NULL; - LDAPMessage * entry = ldap_first_entry(ldap, result); - - if (entry != NULL) + DBG1(" fetching crl from '%s' ...", url); + if (lib->fetcher->fetch(lib->fetcher, url, blob, FETCH_END) != SUCCESS) { - 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) - { - blob->len = values[0]->bv_len; - blob->ptr = malloc(blob->len); - memcpy(blob->ptr, values[0]->bv_val, blob->len); - if (values[1] != NULL) - { - plog("warning: more than one value was fetched from LDAP URL"); - } - } - else - { - ugh = "no values in attribute"; - } - ldap_value_free_len(values); - } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); - } - ldap_memfree(attr); - } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); - } - ber_free(ber, 0); + DBG1("crl fetching failed"); + return FALSE; } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, result, 0)); - } - return ugh; -} - -/* - * fetches a binary blob from an ldap url - */ -static err_t -fetch_ldap_url(char *url, chunk_t *blob) -{ - LDAPURLDesc *lurl; - err_t ugh = NULL; - int rc; - - DBG(DBG_CONTROL, - DBG_log("Trying LDAP URL '%s'", url) - ) - - rc = ldap_url_parse(url, &lurl); - - if (rc == LDAP_SUCCESS) - { - LDAP *ldap = ldap_init(lurl->lud_host, lurl->lud_port); - - if (ldap != NULL) - { - int ldap_version = LDAP_VERSION3; - struct timeval timeout; - - timeout.tv_sec = FETCH_CMD_TIMEOUT; - timeout.tv_usec = 0; - ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); - ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout); - - rc = ldap_simple_bind_s(ldap, NULL, NULL); - - if (rc == LDAP_SUCCESS) - { - LDAPMessage *result; - - timeout.tv_sec = FETCH_CMD_TIMEOUT; - timeout.tv_usec = 0; - - rc = ldap_search_st(ldap, lurl->lud_dn - , lurl->lud_scope - , lurl->lud_filter - , lurl->lud_attrs - , 0, &timeout, &result); - - if (rc == LDAP_SUCCESS) - { - ugh = parse_ldap_result(ldap, result, blob); - ldap_msgfree(result); - } - else - { - ugh = ldap_err2string(rc); - } - } - else - { - ugh = ldap_err2string(rc); - } - ldap_unbind_s(ldap); - } - else - { - ugh = "ldap init"; - } - ldap_free_urldesc(lurl); - } - else - { - ugh = ldap_err2string(rc); - } - return ugh; -} -#else /* !LIBLDAP */ -static err_t -fetch_ldap_url(char *url, chunk_t *blob) -{ - return "LDAP URL fetching not activated in pluto source code"; -} -#endif /* !LIBLDAP */ - -/* - * fetch an ASN.1 blob coded in PEM or DER format from a URL - */ -static err_t -fetch_asn1_blob(char *url, chunk_t *blob) -{ - err_t ugh = NULL; - - if (strlen(url) >= 4 && strncasecmp(url, "ldap", 4) == 0) - { - ugh = fetch_ldap_url(url, blob); - } - else - { - ugh = fetch_curl(url, blob); - } - if (ugh != NULL) - return ugh; if (is_asn1(*blob)) { - DBG(DBG_PARSING, - DBG_log(" fetched blob coded in DER format") - ) + DBG2(" fetched blob coded in DER format"); } else { bool pgp = FALSE; ugh = pemtobin(blob, NULL, "", &pgp); - if (ugh == NULL) + if (ugh != NULL) { - if (is_asn1(*blob)) - { - DBG(DBG_PARSING, - DBG_log(" fetched blob coded in PEM format") - ) - } - else - { - ugh = "blob coded in unknown format"; - free(blob->ptr); - } + free(blob->ptr); + return FALSE; + }; + if (is_asn1(*blob)) + { + DBG2(" fetched blob coded in PEM format"); } else { + DBG1("crl fetched successfully but data coded in unknown format"); free(blob->ptr); + return FALSE; } } - return ugh; + return TRUE; } -/* - * complete a distributionPoint URI with ca information +/** + * Complete a distributionPoint URI with ca information */ -static char* -complete_uri(chunk_t distPoint, const char *ldaphost) +static char* complete_uri(chunk_t distPoint, const char *ldaphost) { char *uri; char *ptr = distPoint.ptr; @@ -589,11 +348,10 @@ complete_uri(chunk_t distPoint, const char *ldaphost) return uri; } -/* - * try to fetch the crls defined by the fetch requests +/** + * Try to fetch the crls defined by the fetch requests */ -static void -fetch_crls(bool cache_crls) +static void fetch_crls(bool cache_crls) { fetch_req_t *req; fetch_req_t **reqp; @@ -619,14 +377,7 @@ fetch_crls(bool cache_crls) { char *uri = complete_uri(gn->name, ldaphost); - err_t ugh = fetch_asn1_blob(uri, &blob); - free(uri); - - if (ugh != NULL) - { - plog("fetch failed: %s", ugh); - } - else + if (fetch_asn1_blob(uri, &blob)) { chunk_t crl_uri = chunk_clone(gn->name); @@ -636,9 +387,11 @@ fetch_crls(bool cache_crls) DBG_log("we have a valid crl") ) valid_crl = TRUE; + free(uri); break; } } + free(uri); gn = gn->next; } @@ -664,73 +417,33 @@ fetch_crls(bool cache_crls) unlock_crl_fetch_list("fetch_crls"); } -static void -fetch_ocsp_status(ocsp_location_t* location) +static void fetch_ocsp_status(ocsp_location_t* location) { -#ifdef LIBCURL - chunk_t request; - chunk_t response = chunk_empty; - - CURL* curl; - CURLcode res; + chunk_t request, response; + char *uri; request = build_ocsp_request(location); + response = chunk_empty; - DBG(DBG_CONTROL, - DBG_log("sending ocsp request to location '%.*s'" - , (int)location->uri.len, location->uri.ptr) - ) - DBG(DBG_RAW, - DBG_dump_chunk("OCSP request", request) - ) + /* we need a null terminated string for curl */ + uri = malloc(location->uri.len + 1); + memcpy(uri, location->uri.ptr, location->uri.len); + *(uri + location->uri.len) = '\0'; - /* send via http post using libcurl */ - curl = curl_easy_init(); - - if (curl != NULL) + DBG1(" requesting ocsp status from '%s' ...", uri); + if (lib->fetcher->fetch(lib->fetcher, uri, &response, + FETCH_REQUEST_DATA, request, + FETCH_REQUEST_TYPE, "application/ocsp-request", + FETCH_END) == SUCCESS) { - char errorbuffer[CURL_ERROR_SIZE]; - struct curl_slist *headers = NULL; - char* uri = malloc(location->uri.len + 1); - - /* we need a null terminated string for curl */ - memcpy(uri, location->uri.ptr, location->uri.len); - *(uri + location->uri.len) = '\0'; - - /* set content type header */ - headers = curl_slist_append(headers, "Content-Type: application/ocsp-request"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - - curl_easy_setopt(curl, CURLOPT_URL, uri); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*)request.ptr); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, request.len); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); - - res = curl_easy_perform(curl); - - if (res == CURLE_OK) - { - DBG(DBG_CONTROL, - DBG_log("received ocsp response") - ) - DBG(DBG_RAW, - DBG_dump_chunk("OCSP response:\n", response) - ) - parse_ocsp(location, response); - } - else - { - plog("failed to fetch ocsp status from '%s': %s", uri, errorbuffer); - } - curl_slist_free_all(headers); - curl_easy_cleanup(curl); - free(uri); - curl_free(response.ptr); + parse_ocsp(location, response); } + else + { + DBG1("ocsp request to %s failed", uri); + } + + free(uri); free(request.ptr); chunk_free(&location->nonce); @@ -744,17 +457,12 @@ fetch_ocsp_status(ocsp_location_t* location) certinfo = certinfo->next; } } - return; -#else /* !LIBCURL */ - plog("ocsp error: pluto wasn't compiled with libcurl support"); -#endif /* !LIBCURL */ } -/* - * try to fetch the necessary ocsp information +/** + * Try to fetch the necessary ocsp information */ -static void -fetch_ocsp(void) +static void fetch_ocsp(void) { ocsp_location_t *location; @@ -765,15 +473,16 @@ fetch_ocsp(void) while (location != NULL) { if (location->certinfo != NULL) + { fetch_ocsp_status(location); + } location = location->next; } unlock_ocsp_fetch_list("fetch_ocsp"); } -static void* -fetch_thread(void *arg) +static void* fetch_thread(void *arg) { struct timespec wait_interval; @@ -817,29 +526,16 @@ fetch_thread(void *arg) } #endif /* THREADS*/ -/* - * initializes curl and starts the fetching thread +/** + * Initializes curl and starts the fetching thread */ -void -init_fetch(void) +void init_fetch(void) { -#if defined(LIBCURL) || defined (THREADS) - int status; -#endif - -#ifdef LIBCURL - /* init curl */ - status = curl_global_init(CURL_GLOBAL_NOTHING); - if (status != CURLE_OK) - { - plog("libcurl could not be initialized, status = %d", status); - } -#endif /* LIBCURL */ - if (crl_check_interval > 0) { #ifdef THREADS - status = pthread_create( &thread, NULL, fetch_thread, NULL); + int status = pthread_create( &thread, NULL, fetch_thread, NULL); + if (status != 0) { plog("fetching thread could not be started, status = %d", status); @@ -850,8 +546,7 @@ init_fetch(void) } } -void -free_crl_fetch(void) +void free_crl_fetch(void) { lock_crl_fetch_list("free_crl_fetch"); @@ -863,21 +558,12 @@ free_crl_fetch(void) } unlock_crl_fetch_list("free_crl_fetch"); - -#ifdef LIBCURL - if (crl_check_interval > 0) - { - /* cleanup curl */ - curl_global_cleanup(); - } -#endif /* LIBCURL */ } -/* - * free the chained list of ocsp requests +/** + * Free the chained list of ocsp requests */ -void -free_ocsp_fetch(void) +void free_ocsp_fetch(void) { lock_ocsp_fetch_list("free_ocsp_fetch"); free_ocsp_locations(&ocsp_fetch_reqs); @@ -885,11 +571,10 @@ free_ocsp_fetch(void) } -/* - * add additional distribution points +/** + * Add additional distribution points */ -void -add_distribution_points(const generalName_t *newPoints ,generalName_t **distributionPoints) +void add_distribution_points(const generalName_t *newPoints ,generalName_t **distributionPoints) { while (newPoints != NULL) { @@ -927,9 +612,8 @@ add_distribution_points(const generalName_t *newPoints ,generalName_t **distribu } } -fetch_req_t* -build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber -, chunk_t authKeyID, const generalName_t *gn) +fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber, + chunk_t authKeyID, const generalName_t *gn) { fetch_req_t *req = malloc_thing(fetch_req_t); *req = empty_fetch_req; @@ -948,11 +632,10 @@ build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber return req; } -/* - * add a crl fetch request to the chained list +/** + * Add a crl fetch request to the chained list */ -void -add_crl_fetch_request(fetch_req_t *req) +void add_crl_fetch_request(fetch_req_t *req) { fetch_req_t *r; @@ -990,11 +673,10 @@ add_crl_fetch_request(fetch_req_t *req) unlock_crl_fetch_list("add_crl_fetch_request"); } -/* - * add an ocsp fetch request to the chained list +/** + * Add an ocsp fetch request to the chained list */ -void -add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber) +void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber) { ocsp_certinfo_t certinfo; @@ -1005,11 +687,10 @@ add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber) unlock_ocsp_fetch_list("add_ocsp_fetch_request"); } -/* - * list all distribution points +/** + * List all distribution points */ -void -list_distribution_points(const generalName_t *gn) +void list_distribution_points(const generalName_t *gn) { bool first_gn = TRUE; @@ -1022,11 +703,10 @@ list_distribution_points(const generalName_t *gn) } } -/* - * list all fetch requests in the chained list +/** + * List all fetch requests in the chained list */ -void -list_crl_fetch_requests(bool utc) +void list_crl_fetch_requests(bool utc) { fetch_req_t *req; @@ -1066,8 +746,7 @@ list_crl_fetch_requests(bool utc) unlock_crl_fetch_list("list_crl_fetch_requests"); } -void -list_ocsp_fetch_requests(bool utc) +void list_ocsp_fetch_requests(bool utc) { lock_ocsp_fetch_list("list_ocsp_fetch_requests"); list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE); diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index 34fa2f764..2e350c896 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -631,7 +631,7 @@ int main(int argc, char **argv) /* load plugins, further infrastructure may need it */ lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR, - lib->settings->get_str(lib->settings, "pluto.load", "")); + lib->settings->get_str(lib->settings, "pluto.load", PLUGINS)); print_plugins(); init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am index 2661bc318..f12e6e0f2 100644 --- a/src/scepclient/Makefile.am +++ b/src/scepclient/Makefile.am @@ -18,6 +18,7 @@ INCLUDES = \ AM_CFLAGS = \ -DIPSEC_CONFDIR=\"${confdir}\" \ -DIPSEC_PLUGINDIR=\"${plugindir}\" \ +-DPLUGINS=\""${pluto_plugins}\"" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ -DDEBUG -DNO_PLUTO @@ -34,23 +35,12 @@ $(LIBFREESWANBUILDDIR)/libfreeswan.a \ $(LIBCRYPTOBUILDDIR)/libcrypto.a \ -lgmp -# This compile option activates the memory leak detective -if USE_LEAK_DETECTIVE - AM_CFLAGS += -DLEAK_DETECTIVE -endif - # This compile option activates smartcard support if USE_SMARTCARD AM_CFLAGS += -DSMARTCARD scepclient_LDADD += -ldl endif -# This compile option activates dynamic URL fetching using libcurl -if USE_CURL - AM_CFLAGS += -DLIBCURL - scepclient_LDADD += -lcurl -endif - dist_man_MANS = scepclient.8 ca.o : $(PLUTODIR)/ca.c $(PLUTODIR)/ca.h diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c index f880fe734..84292975d 100644 --- a/src/scepclient/scep.c +++ b/src/scepclient/scep.c @@ -25,14 +25,11 @@ #include +#include #include #include #include -#ifdef LIBCURL -#include -#endif - #include "../pluto/constants.h" #include "../pluto/defs.h" #include "../pluto/rnd.h" @@ -264,11 +261,11 @@ end: return success; } -/* generates a unique fingerprint of the pkcs10 request +/** + * Generates a unique fingerprint of the pkcs10 request * by computing an MD5 hash over it */ -void -scep_generate_pkcs10_fingerprint(chunk_t pkcs10, chunk_t *fingerprint) +void scep_generate_pkcs10_fingerprint(chunk_t pkcs10, chunk_t *fingerprint) { char buf[MD5_DIGEST_SIZE]; chunk_t digest = { buf, sizeof(buf) }; @@ -280,12 +277,12 @@ scep_generate_pkcs10_fingerprint(chunk_t pkcs10, chunk_t *fingerprint) datatot(digest.ptr, digest.len, 16, fingerprint->ptr, fingerprint->len + 1); } -/* generate a transaction id as the MD5 hash of an public key +/** + * Generate a transaction id as the MD5 hash of an public key * the transaction id is also used as a unique serial number */ -void -scep_generate_transaction_id(const RSA_public_key_t *rsak -, chunk_t *transID, chunk_t *serialNumber) +void scep_generate_transaction_id(const RSA_public_key_t *rsak, + chunk_t *transID, chunk_t *serialNumber) { char buf[MD5_DIGEST_SIZE]; @@ -319,11 +316,10 @@ scep_generate_transaction_id(const RSA_public_key_t *rsak datatot(digest.ptr, digest.len, 16, transID->ptr, transID->len + 1); } -/* - * builds a transId attribute +/** + * Builds a transId attribute */ -chunk_t -scep_transId_attribute(chunk_t transID) +chunk_t scep_transId_attribute(chunk_t transID) { return asn1_wrap(ASN1_SEQUENCE, "cm" , ASN1_transId_oid @@ -333,11 +329,10 @@ scep_transId_attribute(chunk_t transID) ); } -/* - * builds a messageType attribute +/** + * Builds a messageType attribute */ -chunk_t -scep_messageType_attribute(scep_msg_t m) +chunk_t scep_messageType_attribute(scep_msg_t m) { chunk_t msgType = { (u_char*)msgType_values[m], @@ -352,11 +347,10 @@ scep_messageType_attribute(scep_msg_t m) ); } -/* - * builds a senderNonce attribute +/** + * Builds a senderNonce attribute */ -chunk_t -scep_senderNonce_attribute(void) +chunk_t scep_senderNonce_attribute(void) { const size_t nonce_len = 16; u_char nonce_buf[nonce_len]; @@ -372,14 +366,13 @@ scep_senderNonce_attribute(void) ); } -/* - * builds a pkcs7 enveloped and signed scep request +/** + * Builds a pkcs7 enveloped and signed scep request */ -chunk_t -scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg -, const x509cert_t *enc_cert, int enc_alg -, const x509cert_t *signer_cert, int digest_alg -, const RSA_private_key_t *private_key) +chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, + const x509cert_t *enc_cert, int enc_alg, + const x509cert_t *signer_cert, int digest_alg, + const RSA_private_key_t *private_key) { chunk_t envelopedData, attributes, request; @@ -400,12 +393,11 @@ scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg return request; } -#ifdef LIBCURL -/* converts a binary request to base64 with 64 characters per line +/** + * Converts a binary request to base64 with 64 characters per line * newline and '+' characters are escaped by %0A and %2B, respectively */ -static char* -escape_http_request(chunk_t req) +static char* escape_http_request(chunk_t req) { char *escaped_req = NULL; char *p1, *p2; @@ -460,70 +452,58 @@ escape_http_request(chunk_t req) free(encoded_req); return escaped_req; } -#endif -/* - * send a SCEP request via HTTP and wait for a response +/** + * Send a SCEP request via HTTP and wait for a response */ -bool -scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op -, fetch_request_t req_type, chunk_t *response) +bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, + bool http_get_request, chunk_t *response) { -#ifdef LIBCURL - char errorbuffer[CURL_ERROR_SIZE] = ""; + int len; + status_t status; char *complete_url = NULL; - struct curl_slist *headers = NULL; - CURL *curl; - CURLcode res; /* initialize response */ *response = chunk_empty; - /* initialize curl context */ - curl = curl_easy_init(); - if (curl == NULL) - { - plog("could not initialize curl context"); - return FALSE; - } + DBG(DBG_CONTROL, + DBG_log("sending scep request to '%s'", url) + ) if (op == SCEP_PKI_OPERATION) { const char operation[] = "PKIOperation"; - if (req_type == FETCH_GET) + if (http_get_request) { char *escaped_req = escape_http_request(pkcs7); /* form complete url */ - int len = strlen(url) + 20 + strlen(operation) + strlen(escaped_req) + 1; - + len = strlen(url) + 20 + strlen(operation) + strlen(escaped_req) + 1; complete_url = malloc(len); snprintf(complete_url, len, "%s?operation=%s&message=%s" , url, operation, escaped_req); free(escaped_req); - curl_easy_setopt(curl, CURLOPT_HTTPGET, TRUE); - headers = curl_slist_append(headers, "Pragma:"); - headers = curl_slist_append(headers, "Host:"); - headers = curl_slist_append(headers, "Accept:"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + status = lib->fetcher->fetch(lib->fetcher, complete_url, response, + FETCH_HTTP_VERSION_1_0, + FETCH_REQUEST_HEADER, "Pragma:", + FETCH_REQUEST_HEADER, "Host:", + FETCH_REQUEST_HEADER, "Accept:", + FETCH_END); } else /* HTTP_POST */ { /* form complete url */ - int len = strlen(url) + 11 + strlen(operation) + 1; - + len = strlen(url) + 11 + strlen(operation) + 1; complete_url = malloc(len); snprintf(complete_url, len, "%s?operation=%s", url, operation); - curl_easy_setopt(curl, CURLOPT_HTTPGET, FALSE); - headers = curl_slist_append(headers, "Content-Type:"); - headers = curl_slist_append(headers, "Expect:"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char*)pkcs7.ptr); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, pkcs7.len); + status = lib->fetcher->fetch(lib->fetcher, complete_url, response, + FETCH_REQUEST_DATA, pkcs7, + FETCH_REQUEST_TYPE, "", + FETCH_REQUEST_HEADER, "Expect:", + FETCH_END); } } else /* SCEP_GET_CA_CERT */ @@ -531,54 +511,21 @@ scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op const char operation[] = "GetCACert"; /* form complete url */ - int len = strlen(url) + 32 + strlen(operation) + 1; - + len = strlen(url) + 32 + strlen(operation) + 1; complete_url = malloc(len); snprintf(complete_url, len, "%s?operation=%s&message=CAIdentifier" , url, operation); - curl_easy_setopt(curl, CURLOPT_HTTPGET, TRUE); + status = lib->fetcher->fetch(lib->fetcher, complete_url, response, + FETCH_END); } - curl_easy_setopt(curl, CURLOPT_URL, complete_url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); - - DBG(DBG_CONTROL, - DBG_log("sending scep request to '%s'", url) - ) - res = curl_easy_perform(curl); - - if (res == CURLE_OK) - { - DBG(DBG_CONTROL, - DBG_log("received scep response") - ) - DBG(DBG_RAW, - DBG_dump_chunk("SCEP response:\n", *response) - ) - } - else - { - plog("failed to fetch scep response from '%s': %s", url, errorbuffer); - } - curl_slist_free_all(headers); - curl_easy_cleanup(curl); free(complete_url); - - return (res == CURLE_OK); -#else /* !LIBCURL */ - plog("scep error: pluto wasn't compiled with libcurl support"); - return FALSE; -#endif /* !LIBCURL */ + return (status == SUCCESS); } -err_t -scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data -, scep_attributes_t *attrs, x509cert_t *signer_cert) +err_t scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data, + scep_attributes_t *attrs, x509cert_t *signer_cert) { chunk_t attributes; diff --git a/src/scepclient/scep.h b/src/scepclient/scep.h index 0586a29cb..2a11a246e 100644 --- a/src/scepclient/scep.h +++ b/src/scepclient/scep.h @@ -86,7 +86,7 @@ extern chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg , const x509cert_t *signer_cert, int digest_alg , const RSA_private_key_t *private_key); extern bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op - , fetch_request_t request_type, chunk_t *response); + , bool http_get_request, chunk_t *response); extern err_t scep_parse_response(chunk_t response, chunk_t transID , contentInfo_t *data, scep_attributes_t *attrs, x509cert_t *signer_cert); diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 9c352c2ca..ae57de1c0 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -48,7 +48,6 @@ #include "../pluto/pkcs1.h" #include "../pluto/pkcs7.h" #include "../pluto/certs.h" -#include "../pluto/fetch.h" #include "../pluto/rnd.h" #include "rsakey.h" @@ -355,17 +354,17 @@ int main(int argc, char **argv) /* symmetric encryption algorithm used by pkcs7, default is 3DES */ int pkcs7_symmetric_cipher = OID_3DES_EDE_CBC; - /* digest algorithm used by pkcs7, default is MD5 */ - int pkcs7_digest_alg = OID_MD5; + /* digest algorithm used by pkcs7, default is SHA-1 */ + int pkcs7_digest_alg = OID_SHA1; - /* signature algorithm used by pkcs10, default is MD5 with RSA encryption */ - int pkcs10_signature_alg = OID_MD5; + /* signature algorithm used by pkcs10, default is SHA-1 with RSA encryption */ + int pkcs10_signature_alg = OID_SHA1; /* URL of the SCEP-Server */ char *scep_url = NULL; /* http request method, default is GET */ - fetch_request_t request_type = FETCH_GET; + bool http_get_request = TRUE; /* poll interval time in manual mode in seconds */ u_int poll_interval = DEFAULT_POLL_INTERVAL; @@ -669,13 +668,13 @@ int main(int argc, char **argv) continue; case 'm': /* --method */ - if (strcaseeq("post", optarg)) + if (strcaseeq("get", optarg)) { - request_type = FETCH_POST; + http_get_request = TRUE; } - else if (strcaseeq("get", optarg)) + else if (strcaseeq("post", optarg)) { - request_type = FETCH_GET; + http_get_request = FALSE; } else { @@ -745,7 +744,7 @@ int main(int argc, char **argv) /* load plugins, further infrastructure may need it */ lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR, - lib->settings->get_str(lib->settings, "scepclient.load", "")); + lib->settings->get_str(lib->settings, "scepclient.load", PLUGINS)); print_plugins(); init_rnd_pool(); @@ -1006,8 +1005,8 @@ int main(int argc, char **argv) exit_scepclient("could not load signature cacert file '%s'", path); x509_ca_sig = cert.u.x509; - if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION - , request_type, &scep_response)) + if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION, + http_get_request, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } @@ -1053,8 +1052,8 @@ int main(int argc, char **argv) , x509_ca_enc, pkcs7_symmetric_cipher , x509_signer, pkcs7_digest_alg, private_key); - if (!scep_http_request(scep_url, getCertInitial, SCEP_PKI_OPERATION - , request_type, &scep_response)) + if (!scep_http_request(scep_url, getCertInitial, SCEP_PKI_OPERATION, + http_get_request, &scep_response)) { exit_scepclient("did not receive a valid scep response"); }