summaryrefslogtreecommitdiff
path: root/src/pluto/fetch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/fetch.c')
-rw-r--r--src/pluto/fetch.c1293
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");
}