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.c766
1 files changed, 0 insertions, 766 deletions
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c
deleted file mode 100644
index 3dfc1386f..000000000
--- a/src/pluto/fetch.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/* Dynamic fetching of X.509 CRLs
- * Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com>
- * 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
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * 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.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-#include <string.h>
-
-#ifdef THREADS
-#include <pthread.h>
-#endif
-
-#include <freeswan.h>
-
-#include <library.h>
-#include <debug.h>
-#include <asn1/asn1.h>
-#include <credentials/certificates/certificate.h>
-#ifdef THREADS
-#include <threading/thread.h>
-#endif
-
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "x509.h"
-#include "ca.h"
-#include "whack.h"
-#include "ocsp.h"
-#include "crl.h"
-#include "fetch.h"
-#include "builder.h"
-
-fetch_req_t empty_fetch_req = {
- NULL , /* next */
- 0 , /* trials */
- NULL , /* issuer */
- { NULL, 0}, /* authKeyID */
- NULL /* distributionPoints */
-};
-
-/* chained list of crl fetch requests */
-static fetch_req_t *crl_fetch_reqs = NULL;
-
-/* chained list of ocsp fetch requests */
-static ocsp_location_t *ocsp_fetch_reqs = NULL;
-
-#ifdef THREADS
-static thread_t *thread;
-static pthread_mutex_t certs_and_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t authcert_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t crl_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t ocsp_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t ca_info_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t crl_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-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)
-{
- 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
- */
-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);
-}
-
-/**
- * Lock access to the chained authcert list
- */
-void lock_authcert_list(const char *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
- */
-void unlock_authcert_list(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("authcert list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&authcert_list_mutex);
-}
-
-/**
- * Lock access to the chained crl list
- */
-void lock_crl_list(const char *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
- */
-void unlock_crl_list(const char *who)
-{
- DBG(DBG_CONTROLMORE,
- DBG_log("crl list unlocked by '%s'", who)
- )
- pthread_mutex_unlock(&crl_list_mutex);
-}
-
-/**
- * Lock access to the ocsp cache
- */
-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)
- )
-}
-
-/**
- * Unlock access to the ocsp cache
- */
-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);
-}
-
-/**
- * Lock access to the ca info list
- */
-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)
- )
-}
-
-/**
- * Unlock access to the ca info list
- */
-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);
-}
-
-/**
- * Lock access to the chained crl fetch request list
- */
-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)
- )
-}
-
-/**
- * Unlock access to the chained crl fetch request list
- */
-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);
-}
-
-/**
- * Lock access to the chained ocsp fetch request list
- */
-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)
- )
-}
-
-/**
- * Unlock access to the chained ocsp fetch request list
- */
-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);
-}
-
-/**
- * Wakes up the sleeping fetch thread
- */
-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);
- }
-}
-#else /* !THREADS */
-#define lock_crl_fetch_list(who) /* do nothing */
-#define unlock_crl_fetch_list(who) /* do nothing */
-#define lock_ocsp_fetch_list(who) /* do nothing */
-#define unlock_ocsp_fetch_list(who) /* do nothing */
-#endif /* !THREADS */
-
-/**
- * Free the dynamic memory used to store fetch requests
- */
-static void free_fetch_request(fetch_req_t *req)
-{
- req->distributionPoints->destroy_function(req->distributionPoints, free);
- DESTROY_IF(req->issuer);
- free(req->authKeyID.ptr);
- free(req);
-}
-
-#ifdef THREADS
-/**
- * Fetch an ASN.1 blob coded in PEM or DER format from a URL
- */
-x509crl_t* fetch_crl(char *url)
-{
- x509crl_t *crl;
- chunk_t blob;
-
- DBG1(DBG_LIB, " fetching crl from '%s' ...", url);
- if (lib->fetcher->fetch(lib->fetcher, url, &blob, FETCH_END) != SUCCESS)
- {
- DBG1(DBG_LIB, "crl fetching failed");
- return FALSE;
- }
- crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL,
- BUILD_BLOB_PEM, blob, BUILD_END);
- free(blob.ptr);
- if (!crl)
- {
- DBG1(DBG_LIB, "crl fetched successfully but data coded in unknown "
- "format");
- }
- return crl;
-}
-
-/**
- * Complete a distributionPoint URI with ca information
- */
-static char* complete_uri(char *distPoint, const char *ldaphost)
-{
- char *symbol = strchr(distPoint, ':');
-
- if (symbol)
- {
- int type_len = symbol - distPoint;
-
- if (type_len >= 4 && strncasecmp(distPoint, "ldap", 4) == 0)
- {
- char *ptr = symbol + 1;
- int len = strlen(distPoint) - (type_len + 1);
-
- if (len > 2 && *ptr++ == '/' && *ptr++ == '/')
- {
- len -= 2;
- symbol = strchr(ptr, '/');
-
- if (symbol && symbol - ptr == 0 && ldaphost)
- {
- char uri[BUF_LEN];
-
- /* insert the ldaphost into the uri */
- snprintf(uri, BUF_LEN, "%.*s%s%.*s",
- (int)strlen(distPoint) - len, distPoint, ldaphost,
- len, symbol);
- return strdup(uri);
- }
- }
- }
- }
-
- /* default action: copy distributionPoint without change */
- return strdup(distPoint);
-}
-
-/**
- * Try to fetch the crls defined by the fetch requests
- */
-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)
- {
- enumerator_t *enumerator;
- char *point;
- bool valid_crl = FALSE;
- const char *ldaphost;
- ca_info_t *ca;
-
- lock_ca_info_list("fetch_crls");
-
- ca = get_ca_info(req->issuer, req->authKeyID);
- ldaphost = (ca == NULL)? NULL : ca->ldaphost;
-
- enumerator = req->distributionPoints->create_enumerator(req->distributionPoints);
- while (enumerator->enumerate(enumerator, &point))
- {
- x509crl_t *crl;
- char *uri;
-
- uri = complete_uri(point, ldaphost);
- crl = fetch_crl(uri);
- free(uri);
-
- if (crl)
- {
- if (insert_crl(crl, point, cache_crls))
- {
- DBG(DBG_CONTROL,
- DBG_log("we have a valid crl")
- )
- valid_crl = TRUE;
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- unlock_ca_info_list("fetch_crls");
-
- 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;
- }
- }
- unlock_crl_fetch_list("fetch_crls");
-}
-
-static void fetch_ocsp_status(ocsp_location_t* location)
-{
- chunk_t request = build_ocsp_request(location);
- chunk_t response = chunk_empty;
-
- DBG1(DBG_LIB, " requesting ocsp status from '%s' ...", location->uri);
- if (lib->fetcher->fetch(lib->fetcher, location->uri, &response,
- FETCH_REQUEST_DATA, request,
- FETCH_REQUEST_TYPE, "application/ocsp-request",
- FETCH_END) == SUCCESS)
- {
- parse_ocsp(location, response);
- }
- else
- {
- DBG1(DBG_LIB, "ocsp request to %s failed", location->uri);
- }
-
- free(request.ptr);
- chunk_free(&location->nonce);
-
- /* increment the trial counter of the unresolved fetch requests */
- {
- ocsp_certinfo_t *certinfo = location->certinfo;
-
- while (certinfo != NULL)
- {
- certinfo->trials++;
- certinfo = certinfo->next;
- }
- }
-}
-
-/**
- * Try to fetch the necessary ocsp information
- */
-static void fetch_ocsp(void)
-{
- ocsp_location_t *location;
-
- 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;
- }
-
- unlock_ocsp_fetch_list("fetch_ocsp");
-}
-
-static void* fetch_thread(void *arg)
-{
- struct timespec wait_interval;
-
- /* the fetching thread is only cancellable while waiting for new events */
- thread_cancelability(FALSE);
-
- DBG(DBG_CONTROL,
- DBG_log("fetch thread started")
- )
-
- pthread_mutex_lock(&fetch_wake_mutex);
-
- while(1)
- {
- int status;
-
- 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)
- )
-
- thread_cancelability(TRUE);
- status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex
- , &wait_interval);
- thread_cancelability(FALSE);
-
- 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);
- }
- return NULL;
-}
-#endif /* THREADS*/
-
-/**
- * Initializes curl and starts the fetching thread
- */
-void fetch_initialize(void)
-{
- if (crl_check_interval > 0)
- {
-#ifdef THREADS
- thread = thread_create((thread_main_t)fetch_thread, NULL);
- if (thread == NULL)
- {
- plog("fetching thread could not be started");
- }
-#else /* !THREADS */
- plog("warning: not compiled with pthread support");
-#endif /* !THREADS */
- }
-}
-
-/**
- * Terminates the fetching thread
- */
-void fetch_finalize(void)
-{
- if (crl_check_interval > 0)
- {
-#ifdef THREADS
- if (thread)
- {
- thread->cancel(thread);
- thread->join(thread);
- }
-#endif
- }
-}
-
-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");
-}
-
-/**
- * Free the chained list of ocsp requests
- */
-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");
-}
-
-
-/**
- * Add an additional distribution point
- */
-void add_distribution_point(linked_list_t *points, char *new_point)
-{
- char *point;
- bool add = TRUE;
- enumerator_t *enumerator;
-
- if (new_point == NULL || *new_point == '\0')
- {
- return;
- }
-
- enumerator = points->create_enumerator(points);
- while (enumerator->enumerate(enumerator, &point))
- {
- if (streq(point, new_point))
- {
- add = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (add)
- {
- points->insert_last(points, strdup(new_point));
- }
-}
-
-/**
- * Add additional distribution points
- */
-void add_distribution_points(linked_list_t *points, linked_list_t *new_points)
-{
- char *new_point;
- enumerator_t *enumerator;
-
- enumerator = new_points->create_enumerator(new_points);
- while (enumerator->enumerate(enumerator, &new_point))
- {
- bool add = TRUE;
- char *point;
- enumerator_t *enumerator;
-
- enumerator = points->create_enumerator(points);
- while (enumerator->enumerate(enumerator, &point))
- {
- if (streq(point, new_point))
- {
- add = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- if (add)
- {
- points->insert_last(points, strdup(new_point));
- }
- }
- enumerator->destroy(enumerator);
-}
-
-fetch_req_t* build_crl_fetch_request(identification_t *issuer,
- chunk_t authKeyID,
- linked_list_t *distributionPoints)
-{
- char *point;
- enumerator_t *enumerator;
- fetch_req_t *req = malloc_thing(fetch_req_t);
-
- memset(req, 0, sizeof(fetch_req_t));
- req->distributionPoints = linked_list_create();
-
- /* clone fields */
- req->issuer = issuer->clone(issuer);
- req->authKeyID = chunk_clone(authKeyID);
-
- /* copy distribution points */
- enumerator = distributionPoints->create_enumerator(distributionPoints);
- while (enumerator->enumerate(enumerator, &point))
- {
- req->distributionPoints->insert_last(req->distributionPoints,
- strdup(point));
- }
- enumerator->destroy(enumerator);
-
- return req;
-}
-
-/**
- * Add a crl fetch request to the chained list
- */
-void add_crl_fetch_request(fetch_req_t *req)
-{
- fetch_req_t *r;
-
- lock_crl_fetch_list("add_crl_fetch_request");
- r = crl_fetch_reqs;
-
- while (r != NULL)
- {
- if (req->authKeyID.ptr ? same_keyid(req->authKeyID, r->authKeyID) :
- req->issuer->equals(req->issuer, r->issuer))
- {
- /* 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(r->distributionPoints,
- req->distributionPoints);
-
- unlock_crl_fetch_list("add_crl_fetch_request");
- free_fetch_request(req);
- return;
- }
- r = r->next;
- }
-
- /* 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");
-}
-
-/**
- * Add an ocsp fetch request to the chained list
- */
-void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber)
-{
- ocsp_certinfo_t certinfo;
-
- 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");
-}
-
-/**
- * List all distribution points
- */
-void list_distribution_points(linked_list_t *distributionPoints)
-{
- char *point;
- bool first_point = TRUE;
- enumerator_t *enumerator;
-
- enumerator = distributionPoints->create_enumerator(distributionPoints);
- while (enumerator->enumerate(enumerator, &point))
- {
- whack_log(RC_COMMENT, " %s '%s'",
- (first_point)? "distPts: " : " ", point);
- first_point = FALSE;
- }
- enumerator->destroy(enumerator);
-}
-
-/**
- * List all fetch requests in the chained list
- */
-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:");
- }
-
- while (req != NULL)
- {
- whack_log(RC_COMMENT, " ");
- whack_log(RC_COMMENT, " trials: %d", req->trials);
- whack_log(RC_COMMENT, " issuer: \"%Y\"", req->issuer);
- if (req->authKeyID.ptr)
- {
- whack_log(RC_COMMENT, " authkey: %#B", &req->authKeyID);
- }
- list_distribution_points(req->distributionPoints);
- req = req->next;
- }
- unlock_crl_fetch_list("list_crl_fetch_requests");
-}
-
-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");
-
-}