summaryrefslogtreecommitdiff
path: root/src/libstrongswan/crypto/ca.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/crypto/ca.c')
-rw-r--r--src/libstrongswan/crypto/ca.c813
1 files changed, 0 insertions, 813 deletions
diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c
deleted file mode 100644
index 510e3528e..000000000
--- a/src/libstrongswan/crypto/ca.c
+++ /dev/null
@@ -1,813 +0,0 @@
-/**
- * @file ca.c
- *
- * @brief Implementation of ca_info_t.
- *
- */
-
-/*
- * Copyright (C) 2007 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 <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <pthread.h>
-
-#include "x509.h"
-#include "crl.h"
-#include "ca.h"
-#include "ac.h"
-#include "certinfo.h"
-#include "ocsp.h"
-
-#include <library.h>
-#include <debug.h>
-#include <utils/linked_list.h>
-#include <utils/identification.h>
-#include <utils/fetcher.h>
-
-typedef struct private_ca_info_t private_ca_info_t;
-
-/**
- * Private data of a ca_info_t object.
- */
-struct private_ca_info_t {
- /**
- * Public interface for this ca info record
- */
- ca_info_t public;
-
- /**
- * Name of the ca info record
- */
- char *name;
-
- /**
- * Time when ca info record was installed
- */
- time_t installed;
-
- /**
- * Distinguished Name of the CA
- */
- x509_t *cacert;
-
- /**
- * List of attribute certificates
- */
- linked_list_t *attrcerts;
-
- /**
- * List of crl URIs
- */
- linked_list_t *crluris;
-
- /**
- * List of ocsp URIs
- */
- linked_list_t *ocspuris;
-
- /**
- * CRL issued by this ca
- */
- crl_t *crl;
-
- /**
- * List of certificate info records
- */
- linked_list_t *certinfos;
-
- /**
- * mutex controls access to the elements:
- * name, crluris, ocspuris, crl, and certinfos
- */
- pthread_mutex_t mutex;
-};
-
-/**
- * static options set by ca_info_set_options()
- */
-static strict_t strict_crl_policy = STRICT_NO;
-static bool cache_crls = FALSE;
-static u_int crl_check_interval = 0;
-
-/**
- * Implements ca_info_t.equals
- */
-static bool equals(const private_ca_info_t *this, const private_ca_info_t *that)
-{
- return chunk_equals(this->cacert->get_keyid(this->cacert),
- that->cacert->get_keyid(that->cacert));
-}
-
-/**
- * Implements ca_info_t.equals_name_release_info
- */
-static bool equals_name_release_info(private_ca_info_t *this, const char *name)
-{
- bool found;
-
- pthread_mutex_lock(&(this->mutex));
- found = this->name != NULL && streq(this->name, name);
-
- if (found)
- {
- this->crluris->destroy_offset(this->crluris,
- offsetof(identification_t, destroy));
- this->crluris = linked_list_create();
-
- this->ocspuris->destroy_offset(this->ocspuris,
- offsetof(identification_t, destroy));
- this->ocspuris = linked_list_create();
-
- free(this->name);
- this->name = NULL;
- }
-
- pthread_mutex_unlock(&(this->mutex));
- return found;
-}
-
-/**
- * Implements ca_info_t.is_crl_issuer
- */
-static bool is_cert_issuer(private_ca_info_t *this, const x509_t *cert)
-{
- return cert->is_issuer(cert, this->cacert);
-}
-
-/**
- * Implements ca_info_t.is_crl_issuer
- */
-static bool is_crl_issuer(private_ca_info_t *this, const crl_t *crl)
-{
- return crl->is_issuer(crl, this->cacert);
-}
-
-/**
- * Implements ca_info_t.is_ca
- */
-static bool is_ca(private_ca_info_t *this)
-{
- return this->cacert->is_ca(this->cacert);
-}
-
-/**
- * Implements ca_info_t.is_strict
- */
-static bool is_strict(private_ca_info_t *this)
-{
- bool strict = strict_crl_policy != STRICT_NO;
-
- if (strict_crl_policy == STRICT_IFURI)
- {
- pthread_mutex_lock(&(this->mutex));
- strict = this->crluris->get_count(this->crluris) > 0 ||
- this->ocspuris->get_count(this->ocspuris) > 0;
- pthread_mutex_unlock(&(this->mutex));
- }
- return strict;
-}
-
-/**
- * Implements ca_info_t.has_crl
- */
-static bool has_crl(private_ca_info_t *this)
-{
- bool found;
-
- pthread_mutex_lock(&(this->mutex));
- found = this->crl != NULL;
- pthread_mutex_unlock(&(this->mutex));
-
- return found;
-}
-
-/**
- * Implements ca_info_t.has_certinfos
- */
-static bool has_certinfos(private_ca_info_t *this)
-{
- bool found;
-
- pthread_mutex_lock(&(this->mutex));
- found = this->certinfos->get_count(this->certinfos) > 0;
- pthread_mutex_unlock(&(this->mutex));
-
- return found;
-}
-
-/**
- * Implements ca_info_t.add_crl
- */
-static void add_crl(private_ca_info_t *this, crl_t *crl)
-{
- pthread_mutex_lock(&(this->mutex));
-
- if (this->crl)
- {
- if (crl->is_newer(crl, this->crl))
- {
- this->crl->destroy(this->crl);
- this->crl = crl;
- DBG1(" this crl is newer - existing crl replaced");
- }
- else
- {
- crl->destroy(crl);
- DBG1(" this crl is not newer - existing crl retained");
- }
- }
- else
- {
- this->crl = crl;
- DBG2(" crl added");
- }
-
- pthread_mutex_unlock(&(this->mutex));
-}
-
-/**
- * Implements ca_info_t.list_crl
- */
-static void list_crl(private_ca_info_t *this, FILE *out, bool utc)
-{
- pthread_mutex_lock(&this->mutex);
- this->crl->list(this->crl, out, utc);
- pthread_mutex_unlock(&this->mutex);
-}
-
-/**
- * Implements ca_info_t.list_certinfos
- */
-static void list_certinfos(private_ca_info_t *this, FILE *out, bool utc)
-{
- iterator_t *iterator;
- certinfo_t *certinfo;
- chunk_t authkey;
-
- pthread_mutex_lock(&this->mutex);
-
- authkey = this->cacert->get_subjectKeyID(this->cacert);
- fprintf(out," authname: '%D'\n", this->cacert->get_subject(this->cacert));
- fprintf(out," authkey: %#B\n", &authkey);
-
- iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
- while (iterator->iterate(iterator, (void**)&certinfo))
- {
- time_t nextUpdate, thisUpdate, now;
- chunk_t serial;
-
- now = time(NULL);
- nextUpdate = certinfo->get_nextUpdate(certinfo);
- thisUpdate = certinfo->get_thisUpdate(certinfo);
- serial = certinfo->get_serialNumber(certinfo);
-
- fprintf(out, "%#T, until %#T, ", &thisUpdate, utc, &nextUpdate, utc);
- if (now > nextUpdate)
- {
- fprintf(out, "expired (%#V ago)\n", &now, &nextUpdate);
- }
- else
- {
- fprintf(out, "ok (expires in %#V)\n", &now, &nextUpdate);
- }
- fprintf(out, " serial: %#B, %N\n", &serial,
- cert_status_names, certinfo->get_status(certinfo));
- }
- iterator->destroy(iterator);
-
- pthread_mutex_unlock(&this->mutex);
-}
-
-/**
- * Find an exact copy of an identification in a linked list
- */
-static identification_t* find_identification(linked_list_t *list, identification_t *id)
-{
- identification_t *found_id = NULL, *current_id;
-
- iterator_t *iterator = list->create_iterator(list, TRUE);
-
- while (iterator->iterate(iterator, (void**)&current_id))
- {
- if (id->equals(id, current_id))
- {
- found_id = current_id;
- break;
- }
- }
- iterator->destroy(iterator);
-
- return found_id;
-}
-
-/**
- * Add a unique identification to a linked list
- */
-static identification_t *add_identification(linked_list_t *list, identification_t *id)
-{
- identification_t *found_id = find_identification(list, id);
-
- if (found_id)
- {
- id->destroy(id);
- return found_id;
- }
- else
- {
- list->insert_last(list, (void*)id);
- return id;
- }
-}
-
-/**
- * Implements ca_info_t.add_crluri
- */
-static void add_crluri(private_ca_info_t *this, chunk_t uri)
-{
- if (uri.len < 6 ||
- (strncasecmp(uri.ptr, "http", 4) != 0 &&
- strncasecmp(uri.ptr, "ldap", 4) != 0 &&
- strncasecmp(uri.ptr, "file", 4) != 0 &&
- strncasecmp(uri.ptr, "ftp", 3) != 0))
- {
- DBG1(" invalid crl uri '%.*s'", uri.len, uri.ptr);
- return;
- }
- else
- {
- identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
-
- pthread_mutex_lock(&(this->mutex));
- add_identification(this->crluris, crluri);
- pthread_mutex_unlock(&(this->mutex));
- }
-}
-
-/**
- * Implements ca_info_t.add_ocspuri
- */
-static void add_ocspuri(private_ca_info_t *this, chunk_t uri)
-{
- if (uri.len < 7 || strncasecmp(uri.ptr, "http", 4) != 0)
- {
- DBG1(" invalid ocsp uri '%.*s'", uri.len, uri.ptr);
- return;
- }
- else
- {
- identification_t *ocspuri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
-
- pthread_mutex_lock(&(this->mutex));
- add_identification(this->ocspuris, ocspuri);
- pthread_mutex_unlock(&(this->mutex));
- }
-}
-
-/**
- * Implements ca_info_t.add_info.
- */
-void add_info (private_ca_info_t *this, const private_ca_info_t *that)
-{
- pthread_mutex_lock(&(this->mutex));
-
- if (this->name == NULL && that->name != NULL)
- {
- this->name = strdup(that->name);
- }
-
- pthread_mutex_unlock(&(this->mutex));
-
- {
- identification_t *uri;
-
- iterator_t *iterator = that->crluris->create_iterator(that->crluris, TRUE);
-
- while (iterator->iterate(iterator, (void**)&uri))
- {
- if (uri->get_type(uri) == ID_DER_ASN1_GN_URI)
- {
- add_crluri(this, uri->get_encoding(uri));
- }
- }
- iterator->destroy(iterator);
- }
-
- {
- identification_t *uri;
-
- iterator_t *iterator = that->ocspuris->create_iterator(that->ocspuris, TRUE);
-
- while (iterator->iterate(iterator, (void**)&uri))
- {
- if (uri->get_type(uri) == ID_DER_ASN1_GN_URI)
- {
- add_ocspuri(this, uri->get_encoding(uri));
- }
- }
- iterator->destroy(iterator);
- }
-}
-
-/**
- * Implements ca_info_t.get_certificate.
- */
-static x509_t* get_certificate(private_ca_info_t* this)
-{
- return this->cacert;
-}
-
-/**
- * caches a crl by saving it to a given crl directory
- */
-void cache_crl(private_ca_info_t* this, const char *crl_dir, crl_t *crl)
-{
- char buffer[BUF_LEN];
- char *path;
- char *pos = buffer;
- int len = BUF_LEN;
- int n;
-
- chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert);
- chunk_t uri;
-
- uri.ptr = buffer;
- uri.len = 7 + strlen(crl_dir) + 1 + 2*authKeyID.len + 4;
-
- if (uri.len >= BUF_LEN)
- {
- DBG1("file uri exceeds buffer length of %d bytes - crl not saved", BUF_LEN);
- return;
- }
-
- /* print the file uri prefix */
- n = snprintf(pos, len, "file://");
- pos += n; len -= n;
-
- /* remember the start of the path string */
- path = pos;
-
- /* print the default crl directory path */
- n = snprintf(pos, len, "%s/", crl_dir);
- pos += n; len -= n;
-
- /* create and print a unique crl filename derived from the authKeyID */
- while (authKeyID.len-- > 0)
- {
- n = snprintf(pos, len, "%02x", *authKeyID.ptr++);
- pos += n; len -= n;
- }
-
- /* add the file suffix */
- n = snprintf(pos, len, ".crl");
-
- if (crl->write_to_file(crl, path, 0022, TRUE))
- {
- identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
-
- add_identification(this->crluris, crluri);
- }
-}
-
-/**
- * Implements ca_info_t.verify_by_crl.
- */
-static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo,
- const char *crl_dir)
-{
- rsa_public_key_t *issuer_public_key = this->cacert->get_public_key(this->cacert);
- bool stale;
-
- pthread_mutex_lock(&(this->mutex));
- if (this->crl == NULL)
- {
- stale = TRUE;
- DBG1("no crl is locally available");
- }
- else
- {
- stale = !this->crl->is_valid(this->crl);
- DBG1("crl is %s", stale? "stale":"valid");
- }
-
- if (stale && crl_check_interval > 0)
- {
- iterator_t *iterator = this->crluris->create_iterator(this->crluris, TRUE);
- identification_t *uri;
-
- while (iterator->iterate(iterator, (void**)&uri))
- {
- fetcher_t *fetcher;
- char uri_string[BUF_LEN];
- chunk_t uri_chunk = uri->get_encoding(uri);
- chunk_t response_chunk;
-
- snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr);
- fetcher = fetcher_create(uri_string);
-
- response_chunk = fetcher->get(fetcher);
- fetcher->destroy(fetcher);
- if (response_chunk.ptr != NULL)
- {
- crl_t *crl = crl_create_from_chunk(response_chunk);
-
- if (crl == NULL)
- {
- free(response_chunk.ptr);
- continue;
- }
- if (!is_crl_issuer(this, crl))
- {
- DBG1(" fetched crl has wrong issuer");
- crl->destroy(crl);
- continue;
- }
- if (!crl->verify(crl, issuer_public_key))
- {
- DBG1("fetched crl signature is invalid");
- crl->destroy(crl);
- continue;
- }
- DBG2("fetched crl signature is valid");
-
- if (this->crl == NULL)
- {
- this->crl = crl;
- }
- else if (crl->is_newer(crl, this->crl))
- {
- this->crl->destroy(this->crl);
- this->crl = crl;
- DBG1("this crl is newer - existing crl replaced");
- }
- else
- {
- crl->destroy(crl);
- DBG1("this crl is not newer - existing crl retained");
- continue;
- }
- if (crl->is_valid(crl))
- {
- if (cache_crls && strncasecmp(uri_string, "file", 4) != 0)
- {
- cache_crl(this, crl_dir, crl);
- }
- /* we found a valid crl and therefore exit the fetch loop */
- break;
- }
- else
- {
- DBG1("fetched crl is stale");
- }
- }
- }
- iterator->destroy(iterator);
- }
-
- if (this->crl)
- {
- if (!this->crl->verify(this->crl, issuer_public_key))
- {
- DBG1("crl signature is invalid");
- goto ret;
- }
- DBG2("crl signature is valid");
-
- this->crl->get_status(this->crl, certinfo);
- }
-
-ret:
- pthread_mutex_unlock(&(this->mutex));
- return certinfo->get_status(certinfo);
-}
-
-/**
- * Implements ca_info_t.verify_by_ocsp.
- */
-static cert_status_t verify_by_ocsp(private_ca_info_t* this,
- certinfo_t *certinfo,
- credential_store_t *credentials)
-{
- bool stale;
- iterator_t *iterator;
- certinfo_t *cached_certinfo = NULL;
- int comparison = 1;
-
- pthread_mutex_lock(&(this->mutex));
-
- /* do we support OCSP at all? */
- if (this->ocspuris->get_count(this->ocspuris) == 0)
- {
- goto ret;
- }
-
- iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
-
- /* find the list insertion point in alphabetical order */
- while(iterator->iterate(iterator, (void**)&cached_certinfo))
- {
- comparison = certinfo->compare_serialNumber(certinfo, cached_certinfo);
-
- if (comparison <= 0)
- {
- break;
- }
- }
-
- /* do we have a valid certinfo_t for this serial number in our cache? */
- if (comparison == 0)
- {
- stale = cached_certinfo->get_nextUpdate(cached_certinfo) < time(NULL);
- DBG1("ocsp status in cache is %s", stale ? "stale":"fresh");
- }
- else
- {
- stale = TRUE;
- DBG1("ocsp status is not in cache");
- }
-
- if (stale)
- {
- ocsp_t *ocsp;
-
- ocsp = ocsp_create(this->cacert, this->ocspuris);
- ocsp->fetch(ocsp, certinfo, credentials);
- if (certinfo->get_status(certinfo) != CERT_UNDEFINED)
- {
- if (comparison != 0)
- {
- cached_certinfo = certinfo_create(certinfo->get_serialNumber(certinfo));
-
- if (comparison > 0)
- {
- this->certinfos->insert_last(this->certinfos, (void *)cached_certinfo);
- }
- else
- {
- iterator->insert_before(iterator, (void *)cached_certinfo);
- }
- }
- cached_certinfo->update(cached_certinfo, certinfo);
- }
- ocsp->destroy(ocsp);
- }
- else
- {
- certinfo->update(certinfo, cached_certinfo);
- }
-
- iterator->destroy(iterator);
-
-ret:
- pthread_mutex_unlock(&(this->mutex));
- return certinfo->get_status(certinfo);
-}
-
-/**
- * Implements ca_info_t.purge_ocsp
- */
-static void purge_ocsp(private_ca_info_t *this)
-{
- pthread_mutex_lock(&(this->mutex));
-
- this->certinfos->destroy_offset(this->certinfos,
- offsetof(certinfo_t, destroy));
- this->certinfos = linked_list_create();
-
- pthread_mutex_unlock(&(this->mutex));
-}
-
-/**
- * Implements ca_info_t.destroy
- */
-static void destroy(private_ca_info_t *this)
-{
- this->attrcerts->destroy_offset(this->attrcerts,
- offsetof(x509ac_t, destroy));
- this->crluris->destroy_offset(this->crluris,
- offsetof(identification_t, destroy));
- this->ocspuris->destroy_offset(this->ocspuris,
- offsetof(identification_t, destroy));
- this->certinfos->destroy_offset(this->certinfos,
- offsetof(certinfo_t, destroy));
- DESTROY_IF(this->crl);
- free(this->name);
- free(this);
-}
-
-/**
- * list the info of this CA
- */
-static void list(private_ca_info_t* this, FILE* out, bool utc)
-{
- chunk_t chunk;
- identification_t *uri;
- iterator_t *iterator;
- bool first;
-
- pthread_mutex_lock(&(this->mutex));
- fprintf(out, "%#T", &this->installed, utc);
-
- if (this->name)
- {
- fprintf(out, ", \"%s\"\n", this->name);
- }
- else
- {
- fprintf(out, "\n");
- }
-
- fprintf(out, " authname: '%D'\n", this->cacert->get_subject(this->cacert));
- chunk = this->cacert->get_subjectKeyID(this->cacert);
- fprintf(out, " authkey: %#B\n", &chunk);
- chunk = this->cacert->get_keyid(this->cacert);
- fprintf(out, " keyid: %#B\n", &chunk);
-
- first = TRUE;
- iterator = this->crluris->create_iterator(this->crluris, TRUE);
- while (iterator->iterate(iterator, (void**)&uri))
- {
- fprintf(out, " %s '%D'\n", first ? "crluris:":" ", uri);
- first = FALSE;
- }
- iterator->destroy(iterator);
-
- first = TRUE;
- iterator = this->ocspuris->create_iterator(this->ocspuris, TRUE);
- while (iterator->iterate(iterator, (void**)&uri))
- {
- fprintf(out, " %s '%D'\n", first ? "ocspuris:":" ", uri);
- first = FALSE;
- }
- iterator->destroy(iterator);
- pthread_mutex_unlock(&(this->mutex));
-}
-
-/*
- * Described in header.
- */
-void ca_info_set_options(strict_t strict, bool cache, u_int interval)
-{
- strict_crl_policy = strict;
- cache_crls = cache;
- crl_check_interval = interval;
-}
-
-/*
- * Described in header.
- */
-ca_info_t *ca_info_create(const char *name, x509_t *cacert)
-{
- private_ca_info_t *this = malloc_thing(private_ca_info_t);
-
- /* initialize */
- this->installed = time(NULL);
- this->name = (name == NULL)? NULL:strdup(name);
- this->cacert = cacert;
- this->attrcerts = linked_list_create();
- this->crluris = linked_list_create();
- this->ocspuris = linked_list_create();
- this->certinfos = linked_list_create();
- this->crl = NULL;
-
- /* initialize the mutex */
- pthread_mutex_init(&(this->mutex), NULL);
-
- /* public functions */
- this->public.equals = (bool (*) (const ca_info_t*,const ca_info_t*))equals;
- this->public.equals_name_release_info = (bool (*) (ca_info_t*,const char*))equals_name_release_info;
- this->public.is_cert_issuer = (bool (*) (ca_info_t*,const x509_t*))is_cert_issuer;
- this->public.is_crl_issuer = (bool (*) (ca_info_t*,const crl_t*))is_crl_issuer;
- this->public.is_ca = (bool (*) (ca_info_t*))is_ca;
- this->public.is_strict = (bool (*) (ca_info_t*))is_strict;
- this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info;
- this->public.add_crl = (void (*) (ca_info_t*,crl_t*))add_crl;
- this->public.has_crl = (bool (*) (ca_info_t*))has_crl;
- this->public.has_certinfos = (bool (*) (ca_info_t*))has_certinfos;
- this->public.list = (void (*) (ca_info_t*,FILE*,bool))list;
- this->public.list_crl = (void (*) (ca_info_t*,FILE*,bool))list_crl;
- this->public.list_certinfos = (void (*) (ca_info_t*,FILE*,bool))list_certinfos;
- this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri;
- this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri;
- this->public.get_certificate = (x509_t* (*) (ca_info_t*))get_certificate;
- this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,certinfo_t*, const char*))verify_by_crl;
- this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,certinfo_t*,credential_store_t*))verify_by_ocsp;
- this->public.purge_ocsp = (void (*) (ca_info_t*))purge_ocsp;
- this->public.destroy = (void (*) (ca_info_t*))destroy;
-
- return &this->public;
-}