diff options
Diffstat (limited to 'src/pluto/fetch.c')
-rw-r--r-- | src/pluto/fetch.c | 1293 |
1 files changed, 479 insertions, 814 deletions
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c index c8a98cd9b..6f7f1215f 100644 --- a/src/pluto/fetch.c +++ b/src/pluto/fetch.c @@ -1,6 +1,6 @@ /* Dynamic fetching of X.509 CRLs * Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com> - * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur + * Copyright (C) 2002-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -11,8 +11,6 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * - * RCSID $Id: fetch.c 4632 2008-11-11 18:37:19Z martin $ */ #include <stdlib.h> @@ -25,24 +23,17 @@ #include <pthread.h> #endif -#ifdef LIBCURL -#include <curl/curl.h> -#endif - #include <freeswan.h> -#ifdef LIBLDAP -#ifndef LDAP_DEPRECATED -#define LDAP_DEPRECATED 1 -#endif -#include <ldap.h> -#endif +#include <library.h> +#include <debug.h> +#include <asn1/asn1.h> +#include <asn1/pem.h> #include "constants.h" #include "defs.h" #include "log.h" #include "id.h" -#include "asn1.h" #include "pem.h" #include "x509.h" #include "ca.h" @@ -52,13 +43,13 @@ #include "fetch.h" fetch_req_t empty_fetch_req = { - NULL , /* next */ - 0 , /* installed */ - 0 , /* trials */ + NULL , /* next */ + 0 , /* installed */ + 0 , /* trials */ { NULL, 0}, /* issuer */ { NULL, 0}, /* authKeyID */ { NULL, 0}, /* authKeySerialNumber */ - NULL /* distributionPoints */ + NULL /* distributionPoints */ }; /* chained list of crl fetch requests */ @@ -79,189 +70,174 @@ 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, - DBG_log("certs and keys locked by '%s'", who) - ) + pthread_mutex_lock(&certs_and_keys_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("certs and keys locked by '%s'", 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) - ) - pthread_mutex_unlock(&certs_and_keys_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("certs and keys unlocked by '%s'", 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, - DBG_log("authcert list locked by '%s'", who) - ) + pthread_mutex_lock(&authcert_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("authcert list locked by '%s'", 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) - ) - pthread_mutex_unlock(&authcert_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("authcert list unlocked by '%s'", 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, - DBG_log("crl list locked by '%s'", who) - ) + pthread_mutex_lock(&crl_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl list locked by '%s'", 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) - ) - pthread_mutex_unlock(&crl_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl list unlocked by '%s'", 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, - DBG_log("ocsp cache locked by '%s'", who) - ) + pthread_mutex_lock(&ocsp_cache_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp cache locked by '%s'", 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) - ) - pthread_mutex_unlock(&ocsp_cache_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp cache unlocked by '%s'", 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, - DBG_log("ca info list locked by '%s'", who) - ) + pthread_mutex_lock(&ca_info_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ca info list locked by '%s'", 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) - ) - pthread_mutex_unlock(&ca_info_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ca info list unlocked by '%s'", 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, - DBG_log("crl fetch request list locked by '%s'", who) - ) + pthread_mutex_lock(&crl_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl fetch request list locked by '%s'", 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) - ) - pthread_mutex_unlock(&crl_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl fetch request list unlocked by '%s'", 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, - DBG_log("ocsp fetch request list locked by '%s'", who) - ) + pthread_mutex_lock(&ocsp_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp fetch request list locked by '%s'", 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) - ) - pthread_mutex_unlock(&ocsp_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp fetch request list unlocked by '%s'", 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) - { - DBG(DBG_CONTROLMORE, - DBG_log("fetch thread wake call by '%s'", who) - ) - pthread_mutex_lock(&fetch_wake_mutex); - pthread_cond_signal(&fetch_wake_cond); - pthread_mutex_unlock(&fetch_wake_mutex); - } + if (crl_check_interval > 0) + { + DBG(DBG_CONTROLMORE, + DBG_log("fetch thread wake call by '%s'", who) + ) + pthread_mutex_lock(&fetch_wake_mutex); + pthread_cond_signal(&fetch_wake_cond); + pthread_mutex_unlock(&fetch_wake_mutex); + } } #else /* !THREADS */ #define lock_crl_fetch_list(who) /* do nothing */ @@ -270,817 +246,506 @@ 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) { - pfree(req->issuer.ptr); - pfreeany(req->authKeySerialNumber.ptr); - pfreeany(req->authKeyID.ptr); - free_generalNames(req->distributionPoints, TRUE); - pfree(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; + free(req->issuer.ptr); + free(req->authKeySerialNumber.ptr); + free(req->authKeyID.ptr); + free_generalNames(req->distributionPoints, TRUE); + free(req); } #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) +bool fetch_asn1_blob(char *url, chunk_t *blob) { -#ifdef LIBCURL - char errorbuffer[CURL_ERROR_SIZE] = ""; - chunk_t response = empty_chunk; - 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 = alloc_bytes(response.len, "curl blob"); - memcpy(blob->ptr, response.ptr, response.len); - } - else + DBG1(" fetching crl from '%s' ...", url); + if (lib->fetcher->fetch(lib->fetcher, url, blob, FETCH_END) != SUCCESS) { - plog("fetching uri (%s) with libcurl failed: %s", url, errorbuffer); + DBG1("crl fetching failed"); + return FALSE; } - curl_easy_cleanup(curl); - /* not using freeanychunk because of realloc (no leak detective) */ - 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) -{ - err_t ugh = NULL; - - 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) + if (is_asn1(*blob)) { - 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 = alloc_bytes(blob->len, "ldap blob"); - 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); + DBG2(" fetched blob coded in DER format"); } else { - ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); - } - ber_free(ber, 0); - } - 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; + bool pgp = FALSE; - 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) + if (pem_to_bin(blob, chunk_empty, &pgp) != SUCCESS) { - ugh = parse_ldap_result(ldap, result, blob); - ldap_msgfree(result); + free(blob->ptr); + return FALSE; + } + if (is_asn1(*blob)) + { + DBG2(" fetched blob coded in PEM format"); } else { - ugh = ldap_err2string(rc); + DBG1("crl fetched successfully but data coded in unknown format"); + free(blob->ptr); + return FALSE; } - } - 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") - ) - } - else - { - bool pgp = FALSE; - - ugh = pemtobin(blob, NULL, "", &pgp); - 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"; - pfree(blob->ptr); - } - } - else - { - pfree(blob->ptr); } - } - 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; - size_t len = distPoint.len; + char *uri; + char *ptr = distPoint.ptr; + size_t len = distPoint.len; - char *symbol = memchr(ptr, ':', len); + char *symbol = memchr(ptr, ':', len); - if (symbol != NULL) - { - size_t type_len = symbol - ptr; - - if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0) + if (symbol != NULL) { - ptr = symbol + 1; - len -= (type_len + 1); - - if (len > 2 && *ptr++ == '/' && *ptr++ == '/') - { - len -= 2; - symbol = memchr(ptr, '/', len); + size_t type_len = symbol - ptr; - if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL) + if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0) { - uri = alloc_bytes(distPoint.len+strlen(ldaphost)+1, "uri"); - - /* insert the ldaphost into the uri */ - sprintf(uri, "%.*s%s%.*s" - , (int)(distPoint.len - len), distPoint.ptr - , ldaphost - , (int)len, symbol); - return uri; + ptr = symbol + 1; + len -= (type_len + 1); + + if (len > 2 && *ptr++ == '/' && *ptr++ == '/') + { + len -= 2; + symbol = memchr(ptr, '/', len); + + if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL) + { + uri = malloc(distPoint.len + strlen(ldaphost) + 1); + + /* insert the ldaphost into the uri */ + sprintf(uri, "%.*s%s%.*s" + , (int)(distPoint.len - len), distPoint.ptr + , ldaphost + , (int)len, symbol); + return uri; + } + } } - } } - } - - /* default action: copy distributionPoint without change */ - uri = alloc_bytes(distPoint.len+1, "uri"); - sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr); - return uri; + + /* default action: copy distributionPoint without change */ + uri = malloc(distPoint.len + 1); + sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr); + 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; - - lock_crl_fetch_list("fetch_crls"); - req = crl_fetch_reqs; - reqp = &crl_fetch_reqs; - - while (req != NULL) - { - bool valid_crl = FALSE; - chunk_t blob = empty_chunk; - generalName_t *gn = req->distributionPoints; - const char *ldaphost; - ca_info_t *ca; + fetch_req_t *req; + fetch_req_t **reqp; - lock_ca_info_list("fetch_crls"); + lock_crl_fetch_list("fetch_crls"); + req = crl_fetch_reqs; + reqp = &crl_fetch_reqs; - ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID); - ldaphost = (ca == NULL)? NULL : ca->ldaphost; - - while (gn != NULL) + while (req != NULL) { - char *uri = complete_uri(gn->name, ldaphost); + bool valid_crl = FALSE; + chunk_t blob = chunk_empty; + generalName_t *gn = req->distributionPoints; + const char *ldaphost; + ca_info_t *ca; - err_t ugh = fetch_asn1_blob(uri, &blob); - pfree(uri); + lock_ca_info_list("fetch_crls"); - if (ugh != NULL) - { - plog("fetch failed: %s", ugh); - } - else - { - chunk_t crl_uri; + ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID); + ldaphost = (ca == NULL)? NULL : ca->ldaphost; - clonetochunk(crl_uri, gn->name.ptr, gn->name.len, "crl uri"); - if (insert_crl(blob, crl_uri, cache_crls)) + while (gn != NULL) { - DBG(DBG_CONTROL, - DBG_log("we have a valid crl") - ) - valid_crl = TRUE; - break; + char *uri = complete_uri(gn->name, ldaphost); + + if (fetch_asn1_blob(uri, &blob)) + { + chunk_t crl_uri = chunk_clone(gn->name); + + if (insert_crl(blob, crl_uri, cache_crls)) + { + DBG(DBG_CONTROL, + DBG_log("we have a valid crl") + ) + valid_crl = TRUE; + free(uri); + break; + } + } + free(uri); + gn = gn->next; } - } - gn = gn->next; - } - unlock_ca_info_list("fetch_crls"); + unlock_ca_info_list("fetch_crls"); - if (valid_crl) - { - /* delete fetch request */ - fetch_req_t *req_free = req; + if (valid_crl) + { + /* delete fetch request */ + fetch_req_t *req_free = req; - req = req->next; - *reqp = req; - free_fetch_request(req_free); - } - else - { - /* try again next time */ - req->trials++; - reqp = &req->next; - req = req->next; + req = req->next; + *reqp = req; + free_fetch_request(req_free); + } + else + { + /* try again next time */ + req->trials++; + reqp = &req->next; + req = req->next; + } } - } - unlock_crl_fetch_list("fetch_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 = empty_chunk; - - CURL* curl; - CURLcode res; - - request = build_ocsp_request(location); + chunk_t request, response; + char *uri; - 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) - ) - - /* send via http post using libcurl */ - curl = curl_easy_init(); - - if (curl != NULL) - { - char errorbuffer[CURL_ERROR_SIZE]; - struct curl_slist *headers = NULL; - char* uri = alloc_bytes(location->uri.len+1, "ocsp uri"); + request = build_ocsp_request(location); + response = chunk_empty; /* 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'; - /* 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) + 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) { - DBG(DBG_CONTROL, - DBG_log("received ocsp response") - ) - DBG(DBG_RAW, - DBG_dump_chunk("OCSP response:\n", response) - ) - parse_ocsp(location, response); + parse_ocsp(location, response); } else { - plog("failed to fetch ocsp status from '%s': %s", uri, errorbuffer); + DBG1("ocsp request to %s failed", uri); } - curl_slist_free_all(headers); - curl_easy_cleanup(curl); - pfree(uri); - /* not using freeanychunk because of realloc (no leak detective) */ - curl_free(response.ptr); - } - freeanychunk(location->nonce); - freeanychunk(request); - - /* increment the trial counter of the unresolved fetch requests */ - { - ocsp_certinfo_t *certinfo = location->certinfo; - - while (certinfo != NULL) + + free(uri); + free(request.ptr); + chunk_free(&location->nonce); + + /* increment the trial counter of the unresolved fetch requests */ { - certinfo->trials++; - certinfo = certinfo->next; + ocsp_certinfo_t *certinfo = location->certinfo; + + while (certinfo != NULL) + { + certinfo->trials++; + 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; + ocsp_location_t *location; - lock_ocsp_fetch_list("fetch_ocsp"); - location = ocsp_fetch_reqs; + lock_ocsp_fetch_list("fetch_ocsp"); + location = ocsp_fetch_reqs; - /* fetch the ocps status for all locations */ - while (location != NULL) - { - if (location->certinfo != NULL) - fetch_ocsp_status(location); - location = location->next; - } + /* fetch the ocps status for all locations */ + while (location != NULL) + { + if (location->certinfo != NULL) + { + fetch_ocsp_status(location); + } + location = location->next; + } - unlock_ocsp_fetch_list("fetch_ocsp"); + unlock_ocsp_fetch_list("fetch_ocsp"); } -static void* -fetch_thread(void *arg) +static void* fetch_thread(void *arg) { - struct timespec wait_interval; + struct timespec wait_interval; - DBG(DBG_CONTROL, - DBG_log("fetch thread started") - ) + DBG(DBG_CONTROL, + DBG_log("fetch thread started") + ) - pthread_mutex_lock(&fetch_wake_mutex); + pthread_mutex_lock(&fetch_wake_mutex); - while(1) - { - int status; + while(1) + { + int status; - wait_interval.tv_nsec = 0; - wait_interval.tv_sec = time(NULL) + crl_check_interval; + wait_interval.tv_nsec = 0; + wait_interval.tv_sec = time(NULL) + crl_check_interval; - DBG(DBG_CONTROL, - DBG_log("next regular crl check in %ld seconds", crl_check_interval) - ) - status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex - , &wait_interval); + DBG(DBG_CONTROL, + DBG_log("next regular crl check in %ld seconds", crl_check_interval) + ) + status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex + , &wait_interval); - if (status == ETIMEDOUT) - { - DBG(DBG_CONTROL, - DBG_log(" "); - DBG_log("*time to check crls and the ocsp cache") - ) - check_ocsp(); - check_crls(); - } - else - { - DBG(DBG_CONTROL, - DBG_log("fetch thread was woken up") - ) + if (status == ETIMEDOUT) + { + DBG(DBG_CONTROL, + DBG_log(" "); + DBG_log("*time to check crls and the ocsp cache") + ) + check_ocsp(); + check_crls(); + } + else + { + DBG(DBG_CONTROL, + DBG_log("fetch thread was woken up") + ) + } + fetch_ocsp(); + fetch_crls(cache_crls); } - fetch_ocsp(); - fetch_crls(cache_crls); - } } #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); - if (status != 0) + if (crl_check_interval > 0) { - plog("fetching thread could not be started, status = %d", status); - } +#ifdef THREADS + int status = pthread_create( &thread, NULL, fetch_thread, NULL); + + if (status != 0) + { + plog("fetching thread could not be started, status = %d", status); + } #else /* !THREADS */ - plog("warning: not compiled with pthread support"); + plog("warning: not compiled with pthread support"); #endif /* !THREADS */ - } + } } -void -free_crl_fetch(void) +void free_crl_fetch(void) { lock_crl_fetch_list("free_crl_fetch"); - while (crl_fetch_reqs != NULL) - { - fetch_req_t *req = crl_fetch_reqs; - crl_fetch_reqs = req->next; - free_fetch_request(req); - } - - unlock_crl_fetch_list("free_crl_fetch"); - -#ifdef LIBCURL - if (crl_check_interval > 0) - { - /* cleanup curl */ - curl_global_cleanup(); - } -#endif /* LIBCURL */ + while (crl_fetch_reqs != NULL) + { + fetch_req_t *req = crl_fetch_reqs; + crl_fetch_reqs = req->next; + free_fetch_request(req); + } + + unlock_crl_fetch_list("free_crl_fetch"); } -/* - * 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); - unlock_ocsp_fetch_list("free_ocsp_fetch"); + lock_ocsp_fetch_list("free_ocsp_fetch"); + free_ocsp_locations(&ocsp_fetch_reqs); + unlock_ocsp_fetch_list("free_ocsp_fetch"); } -/* - * 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) - { - /* skip empty distribution point */ - if (newPoints->name.len > 0) - { - bool add = TRUE; - generalName_t *gn = *distributionPoints; - - while (gn != NULL) - { - if (gn->kind == newPoints->kind - && gn->name.len == newPoints->name.len - && memcmp(gn->name.ptr, newPoints->name.ptr, gn->name.len) == 0) - { - /* skip if the distribution point is already present */ - add = FALSE; - break; - } - gn = gn->next; - } - - if (add) - { - /* clone additional distribution point */ - gn = clone_thing(*newPoints, "generalName"); - clonetochunk(gn->name, newPoints->name.ptr, newPoints->name.len - , "crl uri"); - - /* insert additional CRL distribution point */ - gn->next = *distributionPoints; - *distributionPoints = gn; - } + while (newPoints != NULL) + { + /* skip empty distribution point */ + if (newPoints->name.len > 0) + { + bool add = TRUE; + generalName_t *gn = *distributionPoints; + + while (gn != NULL) + { + if (gn->kind == newPoints->kind + && gn->name.len == newPoints->name.len + && memeq(gn->name.ptr, newPoints->name.ptr, gn->name.len)) + { + /* skip if the distribution point is already present */ + add = FALSE; + break; + } + gn = gn->next; + } + + if (add) + { + /* clone additional distribution point */ + gn = clone_thing(*newPoints); + gn->name = chunk_clone(newPoints->name); + + /* insert additional CRL distribution point */ + gn->next = *distributionPoints; + *distributionPoints = gn; + } + } + newPoints = newPoints->next; } - newPoints = newPoints->next; - } } -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 = alloc_thing(fetch_req_t, "fetch request"); - *req = empty_fetch_req; - - /* note current time */ - req->installed = time(NULL); - - /* clone fields */ - clonetochunk(req->issuer, issuer.ptr, issuer.len, "issuer"); - if (authKeySerialNumber.ptr != NULL) - { - clonetochunk(req->authKeySerialNumber, authKeySerialNumber.ptr - , authKeySerialNumber.len, "authKeySerialNumber"); - } - if (authKeyID.ptr != NULL) - { - clonetochunk(req->authKeyID, authKeyID.ptr, authKeyID.len, "authKeyID"); - } - - /* copy distribution points */ - add_distribution_points(gn, &req->distributionPoints); - - return req; + fetch_req_t *req = malloc_thing(fetch_req_t); + *req = empty_fetch_req; + + /* note current time */ + req->installed = time(NULL); + + /* clone fields */ + req->issuer = chunk_clone(issuer); + req->authKeySerialNumber = chunk_clone(authKeySerialNumber); + req->authKeyID = chunk_clone(authKeyID); + + /* copy distribution points */ + add_distribution_points(gn, &req->distributionPoints); + + 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; + fetch_req_t *r; - lock_crl_fetch_list("add_crl_fetch_request"); - r = crl_fetch_reqs; + lock_crl_fetch_list("add_crl_fetch_request"); + r = crl_fetch_reqs; - while (r != NULL) - { - if ((req->authKeyID.ptr != NULL)? same_keyid(req->authKeyID, r->authKeyID) - : (same_dn(req->issuer, r->issuer) - && same_serial(req->authKeySerialNumber, r->authKeySerialNumber))) + while (r != NULL) { - /* there is already a fetch request */ - DBG(DBG_CONTROL, - DBG_log("crl fetch request already exists") - ) + if ((req->authKeyID.ptr != NULL)? same_keyid(req->authKeyID, r->authKeyID) + : (same_dn(req->issuer, r->issuer) + && same_serial(req->authKeySerialNumber, r->authKeySerialNumber))) + { + /* there is already a fetch request */ + DBG(DBG_CONTROL, + DBG_log("crl fetch request already exists") + ) - /* there might be new distribution points */ - add_distribution_points(req->distributionPoints, &r->distributionPoints); + /* there might be new distribution points */ + add_distribution_points(req->distributionPoints, &r->distributionPoints); - unlock_crl_fetch_list("add_crl_fetch_request"); - free_fetch_request(req); - return; + unlock_crl_fetch_list("add_crl_fetch_request"); + free_fetch_request(req); + return; + } + r = r->next; } - r = r->next; - } - /* insert new fetch request at the head of the queue */ - req->next = crl_fetch_reqs; - crl_fetch_reqs = req; + /* insert new fetch request at the head of the queue */ + req->next = crl_fetch_reqs; + crl_fetch_reqs = req; - DBG(DBG_CONTROL, - DBG_log("crl fetch request added") - ) - unlock_crl_fetch_list("add_crl_fetch_request"); + DBG(DBG_CONTROL, + DBG_log("crl fetch request added") + ) + 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; + ocsp_certinfo_t certinfo; - certinfo.serialNumber = serialNumber; + certinfo.serialNumber = serialNumber; - lock_ocsp_fetch_list("add_ocsp_fetch_request"); - add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE); - unlock_ocsp_fetch_list("add_ocsp_fetch_request"); + lock_ocsp_fetch_list("add_ocsp_fetch_request"); + add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE); + 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; - - while (gn != NULL) - { - whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: " - :" ", (int)gn->name.len, gn->name.ptr); - first_gn = FALSE; - gn = gn->next; - } + bool first_gn = TRUE; + + while (gn != NULL) + { + whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: " + :" ", (int)gn->name.len, gn->name.ptr); + first_gn = FALSE; + gn = gn->next; + } } -/* - * 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; - - lock_crl_fetch_list("list_crl_fetch_requests"); - req = crl_fetch_reqs; - - if (req != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of CRL fetch requests:"); - whack_log(RC_COMMENT, " "); - } - - while (req != NULL) - { - u_char buf[BUF_LEN]; - - whack_log(RC_COMMENT, "%s, trials: %d" - , timetoa(&req->installed, utc), req->trials); - dntoa(buf, BUF_LEN, req->issuer); - whack_log(RC_COMMENT, " issuer: '%s'", buf); - if (req->authKeyID.ptr != NULL) + fetch_req_t *req; + + lock_crl_fetch_list("list_crl_fetch_requests"); + req = crl_fetch_reqs; + + if (req != NULL) { - datatot(req->authKeyID.ptr, req->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of CRL fetch requests:"); + whack_log(RC_COMMENT, " "); } - if (req->authKeySerialNumber.ptr != NULL) + + while (req != NULL) { - datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); + u_char buf[BUF_LEN]; + + whack_log(RC_COMMENT, "%T, trials: %d" + , &req->installed, utc, req->trials); + dntoa(buf, BUF_LEN, req->issuer); + whack_log(RC_COMMENT, " issuer: '%s'", buf); + if (req->authKeyID.ptr != NULL) + { + datatot(req->authKeyID.ptr, req->authKeyID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authkey: %s", buf); + } + if (req->authKeySerialNumber.ptr != NULL) + { + datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " aserial: %s", buf); + } + list_distribution_points(req->distributionPoints); + req = req->next; } - list_distribution_points(req->distributionPoints); - req = req->next; - } - unlock_crl_fetch_list("list_crl_fetch_requests"); + 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); - unlock_ocsp_fetch_list("list_ocsp_fetch_requests"); + lock_ocsp_fetch_list("list_ocsp_fetch_requests"); + list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE); + unlock_ocsp_fetch_list("list_ocsp_fetch_requests"); } |