|
Packit |
aea12f |
/*
|
|
Packit |
aea12f |
* Copyright (C) 2011-2016 Free Software Foundation, Inc.
|
|
Packit |
aea12f |
* Copyright (C) 2015-2016 Red Hat, Inc.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This file is part of GnuTLS.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
aea12f |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
aea12f |
* the License, or (at your option) any later version.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
aea12f |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
aea12f |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
aea12f |
* Lesser General Public License for more details.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include "gnutls_int.h"
|
|
Packit |
aea12f |
#include "errors.h"
|
|
Packit |
aea12f |
#include <libtasn1.h>
|
|
Packit |
aea12f |
#include <global.h>
|
|
Packit |
aea12f |
#include <num.h> /* MAX */
|
|
Packit |
aea12f |
#include <tls-sig.h>
|
|
Packit |
aea12f |
#include <str.h>
|
|
Packit |
aea12f |
#include <datum.h>
|
|
Packit |
aea12f |
#include <hash-pjw-bare.h>
|
|
Packit |
aea12f |
#include "x509_int.h"
|
|
Packit |
aea12f |
#include <common.h>
|
|
Packit |
aea12f |
#include <gnutls/x509-ext.h>
|
|
Packit |
aea12f |
#include "verify-high.h"
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
struct named_cert_st {
|
|
Packit |
aea12f |
gnutls_x509_crt_t cert;
|
|
Packit |
aea12f |
uint8_t name[MAX_SERVER_NAME_SIZE];
|
|
Packit |
aea12f |
unsigned int name_size;
|
|
Packit |
aea12f |
};
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
struct node_st {
|
|
Packit |
aea12f |
/* The trusted certificates */
|
|
Packit |
aea12f |
gnutls_x509_crt_t *trusted_cas;
|
|
Packit |
aea12f |
unsigned int trusted_ca_size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
struct named_cert_st *named_certs;
|
|
Packit |
aea12f |
unsigned int named_cert_size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* The trusted CRLs */
|
|
Packit |
aea12f |
gnutls_x509_crl_t *crls;
|
|
Packit |
aea12f |
unsigned int crl_size;
|
|
Packit |
aea12f |
};
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
struct gnutls_x509_trust_list_iter {
|
|
Packit |
aea12f |
unsigned int node_index;
|
|
Packit |
aea12f |
unsigned int ca_index;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
gnutls_pkcs11_obj_t* pkcs11_list;
|
|
Packit |
aea12f |
unsigned int pkcs11_index;
|
|
Packit |
aea12f |
unsigned int pkcs11_size;
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
};
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#define DEFAULT_SIZE 127
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_init:
|
|
Packit |
aea12f |
* @list: A pointer to the type to be initialized
|
|
Packit |
aea12f |
* @size: The size of the internal hash table. Use (0) for default size.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will initialize an X.509 trust list structure.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_init(gnutls_x509_trust_list_t * list,
|
|
Packit |
aea12f |
unsigned int size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_x509_trust_list_t tmp;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
FAIL_IF_LIB_ERROR;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
tmp =
|
|
Packit |
aea12f |
gnutls_calloc(1, sizeof(struct gnutls_x509_trust_list_st));
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (!tmp)
|
|
Packit |
aea12f |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (size == 0)
|
|
Packit |
aea12f |
size = DEFAULT_SIZE;
|
|
Packit |
aea12f |
tmp->size = size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
tmp->node = gnutls_calloc(1, tmp->size * sizeof(tmp->node[0]));
|
|
Packit |
aea12f |
if (tmp->node == NULL) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
gnutls_free(tmp);
|
|
Packit |
aea12f |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*list = tmp;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0; /* success */
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_deinit:
|
|
Packit |
aea12f |
* @list: The list to be deinitialized
|
|
Packit |
aea12f |
* @all: if non-zero it will deinitialize all the certificates and CRLs contained in the structure.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will deinitialize a trust list. Note that the
|
|
Packit |
aea12f |
* @all flag should be typically non-zero unless you have specified
|
|
Packit |
aea12f |
* your certificates using gnutls_x509_trust_list_add_cas() and you
|
|
Packit |
aea12f |
* want to prevent them from being deinitialized by this function.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
void
|
|
Packit |
aea12f |
gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
unsigned int all)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
unsigned int i, j;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (!list)
|
|
Packit |
aea12f |
return;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (j = 0; j < list->blacklisted_size; j++) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(list->blacklisted[j]);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
gnutls_free(list->blacklisted);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (j = 0; j < list->keep_certs_size; j++) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(list->keep_certs[j]);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
gnutls_free(list->keep_certs);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < list->size; i++) {
|
|
Packit |
aea12f |
if (all) {
|
|
Packit |
aea12f |
for (j = 0; j < list->node[i].trusted_ca_size; j++) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(list->node[i].
|
|
Packit |
aea12f |
trusted_cas[j]);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
gnutls_free(list->node[i].trusted_cas);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (all) {
|
|
Packit |
aea12f |
for (j = 0; j < list->node[i].crl_size; j++) {
|
|
Packit |
aea12f |
gnutls_x509_crl_deinit(list->node[i].
|
|
Packit |
aea12f |
crls[j]);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
gnutls_free(list->node[i].crls);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (all) {
|
|
Packit |
aea12f |
for (j = 0; j < list->node[i].named_cert_size; j++) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(list->node[i].
|
|
Packit |
aea12f |
named_certs[j].
|
|
Packit |
aea12f |
cert);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
gnutls_free(list->node[i].named_certs);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_free(list->x509_rdn_sequence.data);
|
|
Packit |
aea12f |
gnutls_free(list->node);
|
|
Packit |
aea12f |
gnutls_free(list->pkcs11_token);
|
|
Packit |
aea12f |
gnutls_free(list);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static int
|
|
Packit |
aea12f |
add_new_ca_to_rdn_seq(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t ca)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_datum_t tmp;
|
|
Packit |
aea12f |
size_t newsize;
|
|
Packit |
aea12f |
unsigned char *newdata, *p;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Add DN of the last added CAs to the RDN sequence
|
|
Packit |
aea12f |
* This will be sent to clients when a certificate
|
|
Packit |
aea12f |
* request message is sent.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
tmp.data = ca->raw_dn.data;
|
|
Packit |
aea12f |
tmp.size = ca->raw_dn.size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
newsize = list->x509_rdn_sequence.size + 2 + tmp.size;
|
|
Packit |
aea12f |
if (newsize < list->x509_rdn_sequence.size) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return GNUTLS_E_SHORT_MEMORY_BUFFER;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
newdata =
|
|
Packit |
aea12f |
gnutls_realloc_fast(list->x509_rdn_sequence.data,
|
|
Packit |
aea12f |
newsize);
|
|
Packit |
aea12f |
if (newdata == NULL) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
p = newdata + list->x509_rdn_sequence.size;
|
|
Packit |
aea12f |
_gnutls_write_uint16(tmp.size, p);
|
|
Packit |
aea12f |
if (tmp.data != NULL)
|
|
Packit |
aea12f |
memcpy(p + 2, tmp.data, tmp.size);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->x509_rdn_sequence.size = newsize;
|
|
Packit |
aea12f |
list->x509_rdn_sequence.data = newdata;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
/* Keeps the provided certificate in a structure that will be
|
|
Packit |
aea12f |
* deallocated on deinit. This is to handle get_issuer() with
|
|
Packit |
aea12f |
* pkcs11 trust modules when the GNUTLS_TL_GET_COPY flag isn't
|
|
Packit |
aea12f |
* given. It is not thread safe. */
|
|
Packit |
aea12f |
static int
|
|
Packit |
aea12f |
trust_list_add_compat(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t cert)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
list->keep_certs =
|
|
Packit |
aea12f |
gnutls_realloc_fast(list->keep_certs,
|
|
Packit |
aea12f |
(list->keep_certs_size +
|
|
Packit |
aea12f |
1) *
|
|
Packit |
aea12f |
sizeof(list->keep_certs[0]));
|
|
Packit |
aea12f |
if (list->keep_certs == NULL) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->keep_certs[list->keep_certs_size] = cert;
|
|
Packit |
aea12f |
list->keep_certs_size++;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_add_cas:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @clist: A list of CAs
|
|
Packit |
aea12f |
* @clist_size: The length of the CA list
|
|
Packit |
aea12f |
* @flags: flags from %gnutls_trust_list_flags_t
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will add the given certificate authorities
|
|
Packit |
aea12f |
* to the trusted list. The CAs in @clist must not be deinitialized
|
|
Packit |
aea12f |
* during the lifetime of @list.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If the flag %GNUTLS_TL_NO_DUPLICATES is specified, then
|
|
Packit |
aea12f |
* this function will ensure that no duplicates will be
|
|
Packit |
aea12f |
* present in the final trust list.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If the flag %GNUTLS_TL_NO_DUPLICATE_KEY is specified, then
|
|
Packit |
aea12f |
* this function will ensure that no certificates with the
|
|
Packit |
aea12f |
* same key are present in the final trust list.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If either %GNUTLS_TL_NO_DUPLICATE_KEY or %GNUTLS_TL_NO_DUPLICATES
|
|
Packit |
aea12f |
* are given, gnutls_x509_trust_list_deinit() must be called with parameter
|
|
Packit |
aea12f |
* @all being 1.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: The number of added elements is returned; that includes
|
|
Packit |
aea12f |
* duplicate entries.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
const gnutls_x509_crt_t * clist,
|
|
Packit |
aea12f |
unsigned clist_size, unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
unsigned i, j;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned exists;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < clist_size; i++) {
|
|
Packit |
aea12f |
exists = 0;
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(clist[i]->raw_dn.data,
|
|
Packit |
aea12f |
clist[i]->raw_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* avoid duplicates */
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_NO_DUPLICATES || flags & GNUTLS_TL_NO_DUPLICATE_KEY) {
|
|
Packit |
aea12f |
for (j=0;j<list->node[hash].trusted_ca_size;j++) {
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_NO_DUPLICATES)
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_equals(list->node[hash].trusted_cas[j], clist[i]);
|
|
Packit |
aea12f |
else
|
|
Packit |
aea12f |
ret = _gnutls_check_if_same_key(list->node[hash].trusted_cas[j], clist[i], 1);
|
|
Packit |
aea12f |
if (ret != 0) {
|
|
Packit |
aea12f |
exists = 1;
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (exists != 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(list->node[hash].trusted_cas[j]);
|
|
Packit |
aea12f |
list->node[hash].trusted_cas[j] = clist[i];
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->node[hash].trusted_cas =
|
|
Packit |
aea12f |
gnutls_realloc_fast(list->node[hash].trusted_cas,
|
|
Packit |
aea12f |
(list->node[hash].trusted_ca_size +
|
|
Packit |
aea12f |
1) *
|
|
Packit |
aea12f |
sizeof(list->node[hash].
|
|
Packit |
aea12f |
trusted_cas[0]));
|
|
Packit |
aea12f |
if (list->node[hash].trusted_cas == NULL) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return i;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (gnutls_x509_crt_get_version(clist[i]) >= 3 &&
|
|
Packit |
aea12f |
gnutls_x509_crt_get_ca_status(clist[i], NULL) <= 0) {
|
|
Packit |
aea12f |
gnutls_datum_t dn;
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
if (gnutls_x509_crt_get_dn2(clist[i], &dn) >= 0) {
|
|
Packit |
aea12f |
_gnutls_audit_log(NULL,
|
|
Packit |
aea12f |
"There was a non-CA certificate in the trusted list: %s.\n",
|
|
Packit |
aea12f |
dn.data);
|
|
Packit |
aea12f |
gnutls_free(dn.data);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->node[hash].trusted_cas[list->node[hash].
|
|
Packit |
aea12f |
trusted_ca_size] = clist[i];
|
|
Packit |
aea12f |
list->node[hash].trusted_ca_size++;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_USE_IN_TLS) {
|
|
Packit |
aea12f |
ret = add_new_ca_to_rdn_seq(list, clist[i]);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return i+1;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return i;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static int
|
|
Packit |
aea12f |
advance_iter(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_trust_list_iter_t iter)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
if (iter->node_index < list->size) {
|
|
Packit |
aea12f |
++iter->ca_index;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* skip entries */
|
|
Packit |
aea12f |
while (iter->node_index < list->size &&
|
|
Packit |
aea12f |
iter->ca_index >= list->node[iter->node_index].trusted_ca_size) {
|
|
Packit |
aea12f |
++iter->node_index;
|
|
Packit |
aea12f |
iter->ca_index = 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (iter->node_index < list->size)
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
if (list->pkcs11_token != NULL) {
|
|
Packit |
aea12f |
if (iter->pkcs11_list == NULL) {
|
|
Packit |
aea12f |
int ret = gnutls_pkcs11_obj_list_import_url2(&iter->pkcs11_list, &iter->pkcs11_size,
|
|
Packit |
aea12f |
list->pkcs11_token, (GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE|GNUTLS_PKCS11_OBJ_FLAG_CRT|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED), 0);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (iter->pkcs11_size > 0)
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
} else if (iter->pkcs11_index < iter->pkcs11_size) {
|
|
Packit |
aea12f |
++iter->pkcs11_index;
|
|
Packit |
aea12f |
if (iter->pkcs11_index < iter->pkcs11_size)
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_iter_get_ca:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @iter: A pointer to an iterator (initially the iterator should be %NULL)
|
|
Packit |
aea12f |
* @crt: where the certificate will be copied
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function obtains a certificate in the trust list and advances the
|
|
Packit |
aea12f |
* iterator to the next certificate. The certificate returned in @crt must be
|
|
Packit |
aea12f |
* deallocated with gnutls_x509_crt_deinit().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* When past the last element is accessed %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
|
|
Packit |
aea12f |
* is returned and the iterator is reset.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The iterator is deinitialized and reset to %NULL automatically by this
|
|
Packit |
aea12f |
* function after iterating through all elements until
|
|
Packit |
aea12f |
* %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. If the iteration is
|
|
Packit |
aea12f |
* aborted early, it must be manually deinitialized using
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_iter_deinit().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.4.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_iter_get_ca(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_trust_list_iter_t *iter,
|
|
Packit |
aea12f |
gnutls_x509_crt_t *crt)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* initialize iterator */
|
|
Packit |
aea12f |
if (*iter == NULL) {
|
|
Packit |
aea12f |
*iter = gnutls_malloc(sizeof (struct gnutls_x509_trust_list_iter));
|
|
Packit |
aea12f |
if (*iter == NULL)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
(*iter)->node_index = 0;
|
|
Packit |
aea12f |
(*iter)->ca_index = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
(*iter)->pkcs11_list = NULL;
|
|
Packit |
aea12f |
(*iter)->pkcs11_size = 0;
|
|
Packit |
aea12f |
(*iter)->pkcs11_index = 0;
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Advance iterator to the first valid entry */
|
|
Packit |
aea12f |
if (list->node[0].trusted_ca_size == 0) {
|
|
Packit |
aea12f |
ret = advance_iter(list, *iter);
|
|
Packit |
aea12f |
if (ret != 0) {
|
|
Packit |
aea12f |
gnutls_x509_trust_list_iter_deinit(*iter);
|
|
Packit |
aea12f |
*iter = NULL;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*crt = NULL;
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* obtain the certificate at the current iterator position */
|
|
Packit |
aea12f |
if ((*iter)->node_index < list->size) {
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_init(crt);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_x509_crt_cpy(*crt, list->node[(*iter)->node_index].trusted_cas[(*iter)->ca_index]);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(*crt);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
else if ( (*iter)->pkcs11_index < (*iter)->pkcs11_size) {
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_init(crt);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_import_pkcs11(*crt, (*iter)->pkcs11_list[(*iter)->pkcs11_index]);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(*crt);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
else {
|
|
Packit |
aea12f |
/* iterator is at end */
|
|
Packit |
aea12f |
gnutls_x509_trust_list_iter_deinit(*iter);
|
|
Packit |
aea12f |
*iter = NULL;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*crt = NULL;
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Move iterator to the next position.
|
|
Packit |
aea12f |
* GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned if the iterator
|
|
Packit |
aea12f |
* has been moved to the end position. That is okay, we return the
|
|
Packit |
aea12f |
* certificate that we read and when this function is called again we
|
|
Packit |
aea12f |
* report GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE to our caller. */
|
|
Packit |
aea12f |
ret = advance_iter(list, *iter);
|
|
Packit |
aea12f |
if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(*crt);
|
|
Packit |
aea12f |
*crt = NULL;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_iter_deinit:
|
|
Packit |
aea12f |
* @iter: The iterator structure to be deinitialized
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will deinitialize an iterator structure.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.4.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
void gnutls_x509_trust_list_iter_deinit(gnutls_x509_trust_list_iter_t iter)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
if (!iter)
|
|
Packit |
aea12f |
return;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
if (iter->pkcs11_size > 0) {
|
|
Packit |
aea12f |
unsigned i;
|
|
Packit |
aea12f |
for (i = 0; i < iter->pkcs11_size; ++i)
|
|
Packit |
aea12f |
gnutls_pkcs11_obj_deinit(iter->pkcs11_list[i]);
|
|
Packit |
aea12f |
gnutls_free(iter->pkcs11_list);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_free(iter);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static gnutls_x509_crt_t crt_cpy(gnutls_x509_crt_t src)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_x509_crt_t dst;
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_init(&dst);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return NULL;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_x509_crt_cpy(dst, src);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(dst);
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return NULL;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return dst;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_remove_cas:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @clist: A list of CAs
|
|
Packit |
aea12f |
* @clist_size: The length of the CA list
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will remove the given certificate authorities
|
|
Packit |
aea12f |
* from the trusted list.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Note that this function can accept certificates and authorities
|
|
Packit |
aea12f |
* not yet known. In that case they will be kept in a separate
|
|
Packit |
aea12f |
* black list that will be used during certificate verification.
|
|
Packit |
aea12f |
* Unlike gnutls_x509_trust_list_add_cas() there is no deinitialization
|
|
Packit |
aea12f |
* restriction for certificate list provided in this function.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: The number of removed elements is returned.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.1.10
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
const gnutls_x509_crt_t * clist,
|
|
Packit |
aea12f |
unsigned clist_size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int r = 0;
|
|
Packit |
aea12f |
unsigned j, i;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < clist_size; i++) {
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(clist[i]->raw_dn.data,
|
|
Packit |
aea12f |
clist[i]->raw_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
|
|
Packit |
aea12f |
if (gnutls_x509_crt_equals
|
|
Packit |
aea12f |
(clist[i],
|
|
Packit |
aea12f |
list->node[hash].trusted_cas[j]) != 0) {
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(list->node[hash].
|
|
Packit |
aea12f |
trusted_cas[j]);
|
|
Packit |
aea12f |
list->node[hash].trusted_cas[j] =
|
|
Packit |
aea12f |
list->node[hash].trusted_cas[list->
|
|
Packit |
aea12f |
node
|
|
Packit |
aea12f |
[hash].
|
|
Packit |
aea12f |
trusted_ca_size
|
|
Packit |
aea12f |
- 1];
|
|
Packit |
aea12f |
list->node[hash].trusted_ca_size--;
|
|
Packit |
aea12f |
r++;
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Add the CA (or plain) certificate to the black list as well.
|
|
Packit |
aea12f |
* This will prevent a subordinate CA from being valid, and
|
|
Packit |
aea12f |
* ensure that a server certificate will also get rejected.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
list->blacklisted =
|
|
Packit |
aea12f |
gnutls_realloc_fast(list->blacklisted,
|
|
Packit |
aea12f |
(list->blacklisted_size + 1) *
|
|
Packit |
aea12f |
sizeof(list->blacklisted[0]));
|
|
Packit |
aea12f |
if (list->blacklisted == NULL)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->blacklisted[list->blacklisted_size] = crt_cpy(clist[i]);
|
|
Packit |
aea12f |
if (list->blacklisted[list->blacklisted_size] != NULL)
|
|
Packit |
aea12f |
list->blacklisted_size++;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return r;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_add_named_crt:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @cert: A certificate
|
|
Packit |
aea12f |
* @name: An identifier for the certificate
|
|
Packit |
aea12f |
* @name_size: The size of the identifier
|
|
Packit |
aea12f |
* @flags: should be 0.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will add the given certificate to the trusted
|
|
Packit |
aea12f |
* list and associate it with a name. The certificate will not be
|
|
Packit |
aea12f |
* be used for verification with gnutls_x509_trust_list_verify_crt()
|
|
Packit |
aea12f |
* but with gnutls_x509_trust_list_verify_named_crt() or
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_verify_crt2() - the latter only since
|
|
Packit |
aea12f |
* GnuTLS 3.4.0 and if a hostname is provided.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* In principle this function can be used to set individual "server"
|
|
Packit |
aea12f |
* certificates that are trusted by the user for that specific server
|
|
Packit |
aea12f |
* but for no other purposes.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The certificate @cert must not be deinitialized during the lifetime
|
|
Packit |
aea12f |
* of the @list.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_add_named_crt(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t cert,
|
|
Packit |
aea12f |
const void *name, size_t name_size,
|
|
Packit |
aea12f |
unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (name_size >= MAX_SERVER_NAME_SIZE)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(cert->raw_issuer_dn.data,
|
|
Packit |
aea12f |
cert->raw_issuer_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->node[hash].named_certs =
|
|
Packit |
aea12f |
gnutls_realloc_fast(list->node[hash].named_certs,
|
|
Packit |
aea12f |
(list->node[hash].named_cert_size +
|
|
Packit |
aea12f |
1) *
|
|
Packit |
aea12f |
sizeof(list->node[hash].named_certs[0]));
|
|
Packit |
aea12f |
if (list->node[hash].named_certs == NULL)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->node[hash].named_certs[list->node[hash].named_cert_size].
|
|
Packit |
aea12f |
cert = cert;
|
|
Packit |
aea12f |
memcpy(list->node[hash].
|
|
Packit |
aea12f |
named_certs[list->node[hash].named_cert_size].name, name,
|
|
Packit |
aea12f |
name_size);
|
|
Packit |
aea12f |
list->node[hash].named_certs[list->node[hash].
|
|
Packit |
aea12f |
named_cert_size].name_size =
|
|
Packit |
aea12f |
name_size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->node[hash].named_cert_size++;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_add_crls:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @crl_list: A list of CRLs
|
|
Packit |
aea12f |
* @crl_size: The length of the CRL list
|
|
Packit |
aea12f |
* @flags: flags from %gnutls_trust_list_flags_t
|
|
Packit |
aea12f |
* @verification_flags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will add the given certificate revocation lists
|
|
Packit |
aea12f |
* to the trusted list. The CRLs in @crl_list must not be deinitialized
|
|
Packit |
aea12f |
* during the lifetime of @list.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function must be called after gnutls_x509_trust_list_add_cas()
|
|
Packit |
aea12f |
* to allow verifying the CRLs for validity. If the flag %GNUTLS_TL_NO_DUPLICATES
|
|
Packit |
aea12f |
* is given, then the final CRL list will not contain duplicate entries.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If the flag %GNUTLS_TL_NO_DUPLICATES is given, gnutls_x509_trust_list_deinit() must be
|
|
Packit |
aea12f |
* called with parameter @all being 1.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If flag %GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added,
|
|
Packit |
aea12f |
* and if verification fails, they will be skipped.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: The number of added elements is returned; that includes
|
|
Packit |
aea12f |
* duplicate entries.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
const gnutls_x509_crl_t * crl_list,
|
|
Packit |
aea12f |
unsigned crl_size, unsigned int flags,
|
|
Packit |
aea12f |
unsigned int verification_flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned x, i, j = 0;
|
|
Packit |
aea12f |
unsigned int vret = 0;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
gnutls_x509_crl_t *tmp;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Probably we can optimize things such as removing duplicates
|
|
Packit |
aea12f |
* etc.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
if (crl_size == 0 || crl_list == NULL)
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < crl_size; i++) {
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(crl_list[i]->raw_issuer_dn.data,
|
|
Packit |
aea12f |
crl_list[i]->raw_issuer_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_VERIFY_CRL) {
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_x509_crl_verify(crl_list[i],
|
|
Packit |
aea12f |
list->node[hash].
|
|
Packit |
aea12f |
trusted_cas,
|
|
Packit |
aea12f |
list->node[hash].
|
|
Packit |
aea12f |
trusted_ca_size,
|
|
Packit |
aea12f |
verification_flags,
|
|
Packit |
aea12f |
&vret);
|
|
Packit |
aea12f |
if (ret < 0 || vret != 0) {
|
|
Packit |
aea12f |
_gnutls_debug_log("CRL verification failed, not adding it\n");
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_NO_DUPLICATES)
|
|
Packit |
aea12f |
gnutls_x509_crl_deinit(crl_list[i]);
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_FAIL_ON_INVALID_CRL)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_CRL_VERIFICATION_ERROR);
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* If the CRL added overrides a previous one, then overwrite
|
|
Packit |
aea12f |
* the old one */
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_NO_DUPLICATES) {
|
|
Packit |
aea12f |
for (x=0;x<list->node[hash].crl_size;x++) {
|
|
Packit |
aea12f |
if (crl_list[i]->raw_issuer_dn.size == list->node[hash].crls[x]->raw_issuer_dn.size &&
|
|
Packit |
aea12f |
memcmp(crl_list[i]->raw_issuer_dn.data, list->node[hash].crls[x]->raw_issuer_dn.data, crl_list[i]->raw_issuer_dn.size) == 0) {
|
|
Packit |
aea12f |
if (gnutls_x509_crl_get_this_update(crl_list[i]) >=
|
|
Packit |
aea12f |
gnutls_x509_crl_get_this_update(list->node[hash].crls[x])) {
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_x509_crl_deinit(list->node[hash].crls[x]);
|
|
Packit |
aea12f |
list->node[hash].crls[x] = crl_list[i];
|
|
Packit |
aea12f |
goto next;
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
/* The new is older, discard it */
|
|
Packit |
aea12f |
gnutls_x509_crl_deinit(crl_list[i]);
|
|
Packit |
aea12f |
goto next;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
tmp =
|
|
Packit |
aea12f |
gnutls_realloc(list->node[hash].crls,
|
|
Packit |
aea12f |
(list->node[hash].crl_size +
|
|
Packit |
aea12f |
1) *
|
|
Packit |
aea12f |
sizeof(list->node[hash].
|
|
Packit |
aea12f |
crls[0]));
|
|
Packit |
aea12f |
if (tmp == NULL) {
|
|
Packit |
aea12f |
ret = i;
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_NO_DUPLICATES)
|
|
Packit |
aea12f |
while (i < crl_size)
|
|
Packit |
aea12f |
gnutls_x509_crl_deinit(crl_list[i++]);
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
list->node[hash].crls = tmp;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
list->node[hash].crls[list->node[hash].crl_size] =
|
|
Packit |
aea12f |
crl_list[i];
|
|
Packit |
aea12f |
list->node[hash].crl_size++;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
next:
|
|
Packit |
aea12f |
j++;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return j;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Takes a certificate list and shortens it if there are
|
|
Packit |
aea12f |
* intermedia certificates already trusted by us.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns the new size of the list or a negative number on error.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
static int shorten_clist(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t * certificate_list,
|
|
Packit |
aea12f |
unsigned int clist_size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
unsigned int j, i;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (clist_size > 1) {
|
|
Packit |
aea12f |
/* Check if the last certificate in the path is self signed.
|
|
Packit |
aea12f |
* In that case ignore it (a certificate is trusted only if it
|
|
Packit |
aea12f |
* leads to a trusted party by us, not the server's).
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This prevents from verifying self signed certificates against
|
|
Packit |
aea12f |
* themselves. This (although not bad) caused verification
|
|
Packit |
aea12f |
* failures on some root self signed certificates that use the
|
|
Packit |
aea12f |
* MD2 algorithm.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
if (gnutls_x509_crt_check_issuer
|
|
Packit |
aea12f |
(certificate_list[clist_size - 1],
|
|
Packit |
aea12f |
certificate_list[clist_size - 1]) != 0) {
|
|
Packit |
aea12f |
clist_size--;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* We want to shorten the chain by removing the cert that matches
|
|
Packit |
aea12f |
* one of the certs we trust and all the certs after that i.e. if
|
|
Packit |
aea12f |
* cert chain is A signed-by B signed-by C signed-by D (signed-by
|
|
Packit |
aea12f |
* self-signed E but already removed above), and we trust B, remove
|
|
Packit |
aea12f |
* B, C and D. */
|
|
Packit |
aea12f |
for (i = 1; i < clist_size; i++) {
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(certificate_list[i]->raw_issuer_dn.data,
|
|
Packit |
aea12f |
certificate_list[i]->raw_issuer_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
|
|
Packit |
aea12f |
if (gnutls_x509_crt_equals
|
|
Packit |
aea12f |
(certificate_list[i],
|
|
Packit |
aea12f |
list->node[hash].trusted_cas[j]) != 0) {
|
|
Packit |
aea12f |
/* cut the list at the point of first the trusted certificate */
|
|
Packit |
aea12f |
clist_size = i + 1;
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
/* clist_size may have been changed which gets out of loop */
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return clist_size;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static
|
|
Packit |
aea12f |
int trust_list_get_issuer(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t cert,
|
|
Packit |
aea12f |
gnutls_x509_crt_t * issuer,
|
|
Packit |
aea12f |
unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned int i;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(cert->raw_issuer_dn.data,
|
|
Packit |
aea12f |
cert->raw_issuer_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_x509_crt_check_issuer(cert,
|
|
Packit |
aea12f |
list->node[hash].
|
|
Packit |
aea12f |
trusted_cas[i]);
|
|
Packit |
aea12f |
if (ret != 0) {
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_GET_COPY) {
|
|
Packit |
aea12f |
*issuer = crt_cpy(list->node[hash].trusted_cas[i]);
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
*issuer = list->node[hash].trusted_cas[i];
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static
|
|
Packit |
aea12f |
int trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
const gnutls_datum_t *dn,
|
|
Packit |
aea12f |
const gnutls_datum_t *spki,
|
|
Packit |
aea12f |
gnutls_x509_crt_t * issuer,
|
|
Packit |
aea12f |
unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned int i, j;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
uint8_t tmp[256];
|
|
Packit |
aea12f |
size_t tmp_size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (dn) {
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(dn->data,
|
|
Packit |
aea12f |
dn->size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
|
|
Packit |
aea12f |
ret = _gnutls_x509_compare_raw_dn(dn, &list->node[hash].trusted_cas[i]->raw_dn);
|
|
Packit |
aea12f |
if (ret != 0) {
|
|
Packit |
aea12f |
if (spki && spki->size > 0) {
|
|
Packit |
aea12f |
tmp_size = sizeof(tmp);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_get_subject_key_id(list->node[hash].trusted_cas[i], tmp, &tmp_size, NULL);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
if (spki->size != tmp_size || memcmp(spki->data, tmp, spki->size) != 0)
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
*issuer = crt_cpy(list->node[hash].trusted_cas[i]);
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
} else if (spki) {
|
|
Packit |
aea12f |
/* search everything! */
|
|
Packit |
aea12f |
for (i = 0; i < list->size; i++) {
|
|
Packit |
aea12f |
for (j = 0; j < list->node[i].trusted_ca_size; j++) {
|
|
Packit |
aea12f |
tmp_size = sizeof(tmp);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_get_subject_key_id(list->node[i].trusted_cas[j], tmp, &tmp_size, NULL);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (spki->size != tmp_size || memcmp(spki->data, tmp, spki->size) != 0)
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*issuer = crt_cpy(list->node[i].trusted_cas[j]);
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_get_issuer:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @cert: is the certificate to find issuer for
|
|
Packit |
aea12f |
* @issuer: Will hold the issuer if any. Should be treated as constant.
|
|
Packit |
aea12f |
* @flags: flags from %gnutls_trust_list_flags_t (%GNUTLS_TL_GET_COPY is applicable)
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will find the issuer of the given certificate.
|
|
Packit |
aea12f |
* If the flag %GNUTLS_TL_GET_COPY is specified a copy of the issuer
|
|
Packit |
aea12f |
* will be returned which must be freed using gnutls_x509_crt_deinit().
|
|
Packit |
aea12f |
* In that case the provided @issuer must not be initialized.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Note that the flag %GNUTLS_TL_GET_COPY is required for this function
|
|
Packit |
aea12f |
* to work with PKCS#11 trust lists in a thread-safe way.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t cert,
|
|
Packit |
aea12f |
gnutls_x509_crt_t * issuer,
|
|
Packit |
aea12f |
unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = trust_list_get_issuer(list, cert, issuer, flags);
|
|
Packit |
aea12f |
if (ret == 0) {
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
if (ret < 0 && list->pkcs11_token) {
|
|
Packit |
aea12f |
gnutls_x509_crt_t crt;
|
|
Packit |
aea12f |
gnutls_datum_t der = {NULL, 0};
|
|
Packit |
aea12f |
/* use the token for verification */
|
|
Packit |
aea12f |
ret = gnutls_pkcs11_get_raw_issuer(list->pkcs11_token, cert, &der,
|
|
Packit |
aea12f |
GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_free(der.data);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
|
|
Packit |
aea12f |
gnutls_free(der.data);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (flags & GNUTLS_TL_GET_COPY) {
|
|
Packit |
aea12f |
*issuer = crt;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
/* we add this CA to the keep_cert list in order to make it
|
|
Packit |
aea12f |
* persistent. It will be deallocated when the trust list is.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
ret = trust_list_add_compat(list, crt);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
*issuer = crt;
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_get_issuer_by_dn:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @dn: is the issuer's DN
|
|
Packit |
aea12f |
* @issuer: Will hold the issuer if any. Should be deallocated after use.
|
|
Packit |
aea12f |
* @flags: Use zero
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will find the issuer with the given name, and
|
|
Packit |
aea12f |
* return a copy of the issuer, which must be freed using gnutls_x509_crt_deinit().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.4.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int gnutls_x509_trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
const gnutls_datum_t *dn,
|
|
Packit |
aea12f |
gnutls_x509_crt_t *issuer,
|
|
Packit |
aea12f |
unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = trust_list_get_issuer_by_dn(list, dn, NULL, issuer, flags);
|
|
Packit |
aea12f |
if (ret == 0) {
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
if (ret < 0 && list->pkcs11_token) {
|
|
Packit |
aea12f |
gnutls_x509_crt_t crt;
|
|
Packit |
aea12f |
gnutls_datum_t der = {NULL, 0};
|
|
Packit |
aea12f |
/* use the token for verification */
|
|
Packit |
aea12f |
ret = gnutls_pkcs11_get_raw_issuer_by_dn(list->pkcs11_token, dn, &der,
|
|
Packit |
aea12f |
GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_free(der.data);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
|
|
Packit |
aea12f |
gnutls_free(der.data);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*issuer = crt;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_get_issuer_by_subject_key_id:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @dn: is the issuer's DN (may be %NULL)
|
|
Packit |
aea12f |
* @spki: is the subject key ID
|
|
Packit |
aea12f |
* @issuer: Will hold the issuer if any. Should be deallocated after use.
|
|
Packit |
aea12f |
* @flags: Use zero
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will find the issuer with the given name and subject key ID, and
|
|
Packit |
aea12f |
* return a copy of the issuer, which must be freed using gnutls_x509_crt_deinit().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.4.2
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int gnutls_x509_trust_list_get_issuer_by_subject_key_id(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
const gnutls_datum_t *dn,
|
|
Packit |
aea12f |
const gnutls_datum_t *spki,
|
|
Packit |
aea12f |
gnutls_x509_crt_t *issuer,
|
|
Packit |
aea12f |
unsigned int flags)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = trust_list_get_issuer_by_dn(list, dn, spki, issuer, flags);
|
|
Packit |
aea12f |
if (ret == 0) {
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
if (ret < 0 && list->pkcs11_token) {
|
|
Packit |
aea12f |
gnutls_x509_crt_t crt;
|
|
Packit |
aea12f |
gnutls_datum_t der = {NULL, 0};
|
|
Packit |
aea12f |
/* use the token for verification */
|
|
Packit |
aea12f |
ret = gnutls_pkcs11_get_raw_issuer_by_subject_key_id(list->pkcs11_token, dn, spki, &der,
|
|
Packit |
aea12f |
GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_free(der.data);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
|
|
Packit |
aea12f |
gnutls_free(der.data);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_x509_crt_deinit(crt);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*issuer = crt;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static
|
|
Packit |
aea12f |
int check_if_in_blacklist(gnutls_x509_crt_t * cert_list, unsigned int cert_list_size,
|
|
Packit |
aea12f |
gnutls_x509_crt_t * blacklist, unsigned int blacklist_size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
unsigned i, j;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (blacklist_size == 0)
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i=0;i
|
|
Packit |
aea12f |
for (j=0;j
|
|
Packit |
aea12f |
if (gnutls_x509_crt_equals(cert_list[i], blacklist[j]) != 0) {
|
|
Packit |
aea12f |
return 1;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_verify_crt:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @cert_list: is the certificate list to be verified
|
|
Packit |
aea12f |
* @cert_list_size: is the certificate list size
|
|
Packit |
aea12f |
* @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
|
|
Packit |
aea12f |
* @voutput: will hold the certificate verification output.
|
|
Packit |
aea12f |
* @func: If non-null will be called on each chain element verification with the output.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will try to verify the given certificate and return
|
|
Packit |
aea12f |
* its status. The @voutput parameter will hold an OR'ed sequence of
|
|
Packit |
aea12f |
* %gnutls_certificate_status_t flags.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The details of the verification are the same as in gnutls_x509_trust_list_verify_crt2().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t * cert_list,
|
|
Packit |
aea12f |
unsigned int cert_list_size,
|
|
Packit |
aea12f |
unsigned int flags,
|
|
Packit |
aea12f |
unsigned int *voutput,
|
|
Packit |
aea12f |
gnutls_verify_output_function func)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
return gnutls_x509_trust_list_verify_crt2(list, cert_list, cert_list_size,
|
|
Packit |
aea12f |
NULL, 0, flags, voutput, func);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#define LAST_DN cert_list[cert_list_size-1]->raw_dn
|
|
Packit |
aea12f |
#define LAST_IDN cert_list[cert_list_size-1]->raw_issuer_dn
|
|
Packit Service |
991b93 |
/* This macro is introduced to detect a verification output which
|
|
Packit Service |
991b93 |
* indicates an unknown signer, a signer which uses an insecure
|
|
Packit Service |
991b93 |
* algorithm (e.g., sha1), a signer has expired, or something that
|
|
Packit Service |
991b93 |
* indicates a superseded signer */
|
|
Packit Service |
991b93 |
#define SIGNER_OLD_OR_UNKNOWN(output) ((output & GNUTLS_CERT_SIGNER_NOT_FOUND) || \
|
|
Packit Service |
991b93 |
(output & GNUTLS_CERT_EXPIRED) || \
|
|
Packit Service |
991b93 |
(output & GNUTLS_CERT_INSECURE_ALGORITHM))
|
|
Packit |
aea12f |
#define SIGNER_WAS_KNOWN(output) (!(output & GNUTLS_CERT_SIGNER_NOT_FOUND))
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_verify_crt2:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @cert_list: is the certificate list to be verified
|
|
Packit |
aea12f |
* @cert_list_size: is the certificate list size
|
|
Packit |
aea12f |
* @data: an array of typed data
|
|
Packit |
aea12f |
* @elements: the number of data elements
|
|
Packit |
aea12f |
* @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
|
|
Packit |
aea12f |
* @voutput: will hold the certificate verification output.
|
|
Packit |
aea12f |
* @func: If non-null will be called on each chain element verification with the output.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will attempt to verify the given certificate chain and return
|
|
Packit |
aea12f |
* its status. The @voutput parameter will hold an OR'ed sequence of
|
|
Packit |
aea12f |
* %gnutls_certificate_status_t flags.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* When a certificate chain of @cert_list_size with more than one certificates is
|
|
Packit |
aea12f |
* provided, the verification status will apply to the first certificate in the chain
|
|
Packit |
aea12f |
* that failed verification. The verification process starts from the end of the chain
|
|
Packit |
aea12f |
* (from CA to end certificate). The first certificate in the chain must be the end-certificate
|
|
Packit |
aea12f |
* while the rest of the members may be sorted or not.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Additionally a certificate verification profile can be specified
|
|
Packit |
aea12f |
* from the ones in %gnutls_certificate_verification_profiles_t by
|
|
Packit |
aea12f |
* ORing the result of GNUTLS_PROFILE_TO_VFLAGS() to the verification
|
|
Packit |
aea12f |
* flags.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Additional verification parameters are possible via the @data types; the
|
|
Packit |
aea12f |
* acceptable types are %GNUTLS_DT_DNS_HOSTNAME, %GNUTLS_DT_IP_ADDRESS and %GNUTLS_DT_KEY_PURPOSE_OID.
|
|
Packit |
aea12f |
* The former accepts as data a null-terminated hostname, and the latter a null-terminated
|
|
Packit |
aea12f |
* object identifier (e.g., %GNUTLS_KP_TLS_WWW_SERVER).
|
|
Packit |
aea12f |
* If a DNS hostname is provided then this function will compare
|
|
Packit |
aea12f |
* the hostname in the end certificate against the given. If names do not match the
|
|
Packit |
aea12f |
* %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set. In addition it
|
|
Packit |
aea12f |
* will consider certificates provided with gnutls_x509_trust_list_add_named_crt().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* If a key purpose OID is provided and the end-certificate contains the extended key
|
|
Packit |
aea12f |
* usage PKIX extension, it will be required to match the provided OID
|
|
Packit |
aea12f |
* or be marked for any purpose, otherwise verification will fail with
|
|
Packit |
aea12f |
* %GNUTLS_CERT_PURPOSE_MISMATCH status.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value. Note that verification failure will not result to an
|
|
Packit |
aea12f |
* error code, only @voutput will be updated.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.3.8
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t * cert_list,
|
|
Packit |
aea12f |
unsigned int cert_list_size,
|
|
Packit |
aea12f |
gnutls_typed_vdata_st *data,
|
|
Packit |
aea12f |
unsigned int elements,
|
|
Packit |
aea12f |
unsigned int flags,
|
|
Packit |
aea12f |
unsigned int *voutput,
|
|
Packit |
aea12f |
gnutls_verify_output_function func)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned int i;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH];
|
|
Packit |
aea12f |
const char *hostname = NULL, *purpose = NULL, *email = NULL;
|
|
Packit |
aea12f |
unsigned hostname_size = 0;
|
|
Packit |
aea12f |
unsigned have_set_name = 0;
|
|
Packit |
aea12f |
unsigned saved_output;
|
|
Packit |
aea12f |
gnutls_datum_t ip = {NULL, 0};
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (cert_list == NULL || cert_list_size < 1)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i=0;i
|
|
Packit |
aea12f |
if (data[i].type == GNUTLS_DT_DNS_HOSTNAME) {
|
|
Packit |
aea12f |
hostname = (void*)data[i].data;
|
|
Packit |
aea12f |
if (data[i].size > 0) {
|
|
Packit |
aea12f |
hostname_size = data[i].size;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
aea12f |
have_set_name = 1;
|
|
Packit |
aea12f |
} else if (data[i].type == GNUTLS_DT_IP_ADDRESS) {
|
|
Packit |
aea12f |
if (data[i].size > 0) {
|
|
Packit |
aea12f |
ip.data = data[i].data;
|
|
Packit |
aea12f |
ip.size = data[i].size;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
aea12f |
have_set_name = 1;
|
|
Packit |
aea12f |
} else if (data[i].type == GNUTLS_DT_RFC822NAME) {
|
|
Packit |
aea12f |
email = (void*)data[i].data;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
aea12f |
have_set_name = 1;
|
|
Packit |
aea12f |
} else if (data[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
|
|
Packit |
aea12f |
purpose = (void*)data[i].data;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (hostname) { /* shortcut using the named certs - if any */
|
|
Packit |
aea12f |
unsigned vtmp = 0;
|
|
Packit |
aea12f |
if (hostname_size == 0)
|
|
Packit |
aea12f |
hostname_size = strlen(hostname);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_trust_list_verify_named_crt(list,
|
|
Packit |
aea12f |
cert_list[0], hostname, hostname_size,
|
|
Packit |
aea12f |
flags, &vtmp, func);
|
|
Packit |
aea12f |
if (ret == 0 && vtmp == 0) {
|
|
Packit |
aea12f |
*voutput = vtmp;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN))
|
|
Packit |
aea12f |
cert_list = _gnutls_sort_clist(sorted, cert_list, &cert_list_size, NULL);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
cert_list_size = shorten_clist(list, cert_list, cert_list_size);
|
|
Packit |
aea12f |
if (cert_list_size <= 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.
|
|
Packit |
aea12f |
data,
|
|
Packit |
aea12f |
cert_list[cert_list_size -
|
|
Packit |
aea12f |
1]->raw_issuer_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = check_if_in_blacklist(cert_list, cert_list_size,
|
|
Packit |
aea12f |
list->blacklisted, list->blacklisted_size);
|
|
Packit |
aea12f |
if (ret != 0) {
|
|
Packit |
aea12f |
*voutput = 0;
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_REVOKED;
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*voutput =
|
|
Packit |
aea12f |
_gnutls_verify_crt_status(cert_list, cert_list_size,
|
|
Packit |
aea12f |
list->node[hash].trusted_cas,
|
|
Packit |
aea12f |
list->
|
|
Packit |
aea12f |
node[hash].trusted_ca_size,
|
|
Packit |
aea12f |
flags, purpose, func);
|
|
Packit |
aea12f |
saved_output = *voutput;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (SIGNER_OLD_OR_UNKNOWN(*voutput) &&
|
|
Packit |
aea12f |
(LAST_DN.size != LAST_IDN.size ||
|
|
Packit |
aea12f |
memcmp(LAST_DN.data, LAST_IDN.data, LAST_IDN.size) != 0)) {
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* if we couldn't find the issuer, try to see if the last
|
|
Packit |
aea12f |
* certificate is in the trusted list and try to verify against
|
|
Packit |
aea12f |
* (if it is not self signed) */
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(cert_list[cert_list_size - 1]->raw_dn.
|
|
Packit |
aea12f |
data, cert_list[cert_list_size - 1]->raw_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_debug_log("issuer in verification was not found or insecure; trying against trust list\n");
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*voutput =
|
|
Packit |
aea12f |
_gnutls_verify_crt_status(cert_list, cert_list_size,
|
|
Packit |
aea12f |
list->node[hash].trusted_cas,
|
|
Packit |
aea12f |
list->
|
|
Packit |
aea12f |
node[hash].trusted_ca_size,
|
|
Packit |
aea12f |
flags, purpose, func);
|
|
Packit |
aea12f |
if (*voutput != 0) {
|
|
Packit |
aea12f |
if (SIGNER_WAS_KNOWN(saved_output))
|
|
Packit |
aea12f |
*voutput = saved_output;
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
saved_output = *voutput;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#ifdef ENABLE_PKCS11
|
|
Packit |
aea12f |
if (SIGNER_OLD_OR_UNKNOWN(*voutput) && list->pkcs11_token) {
|
|
Packit |
aea12f |
/* use the token for verification */
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*voutput = _gnutls_pkcs11_verify_crt_status(list->pkcs11_token,
|
|
Packit |
aea12f |
cert_list, cert_list_size,
|
|
Packit |
aea12f |
purpose,
|
|
Packit |
aea12f |
flags, func);
|
|
Packit |
aea12f |
if (*voutput != 0) {
|
|
Packit |
aea12f |
if (SIGNER_WAS_KNOWN(saved_output))
|
|
Packit |
aea12f |
*voutput = saved_output;
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* End-certificate, key purpose and hostname checks. */
|
|
Packit |
aea12f |
if (purpose) {
|
|
Packit |
aea12f |
ret = _gnutls_check_key_purpose(cert_list[0], purpose, 0);
|
|
Packit |
aea12f |
if (ret != 1) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_PURPOSE_MISMATCH|GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (hostname) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_x509_crt_check_hostname2(cert_list[0], hostname, flags);
|
|
Packit |
aea12f |
if (ret == 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (ip.data) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_x509_crt_check_ip(cert_list[0], ip.data, ip.size, flags);
|
|
Packit |
aea12f |
if (ret == 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (email) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_x509_crt_check_email(cert_list[0], email, 0);
|
|
Packit |
aea12f |
if (ret == 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* CRL checks follow */
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (*voutput != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Check revocation of individual certificates.
|
|
Packit |
aea12f |
* start with the last one that we already have its hash
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_x509_crt_check_revocation(cert_list
|
|
Packit |
aea12f |
[cert_list_size - 1],
|
|
Packit |
aea12f |
list->node[hash].crls,
|
|
Packit |
aea12f |
list->node[hash].crl_size,
|
|
Packit |
aea12f |
func);
|
|
Packit |
aea12f |
if (ret == 1) { /* revoked */
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_REVOKED;
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < cert_list_size - 1; i++) {
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(cert_list[i]->raw_issuer_dn.data,
|
|
Packit |
aea12f |
cert_list[i]->raw_issuer_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_x509_crt_check_revocation(cert_list[i],
|
|
Packit |
aea12f |
list->node[hash].
|
|
Packit |
aea12f |
crls,
|
|
Packit |
aea12f |
list->node[hash].
|
|
Packit |
aea12f |
crl_size, func);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
} else if (ret == 1) { /* revoked */
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_REVOKED;
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit |
aea12f |
* gnutls_x509_trust_list_verify_named_crt:
|
|
Packit |
aea12f |
* @list: The list
|
|
Packit |
aea12f |
* @cert: is the certificate to be verified
|
|
Packit |
aea12f |
* @name: is the certificate's name
|
|
Packit |
aea12f |
* @name_size: is the certificate's name size
|
|
Packit |
aea12f |
* @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
|
|
Packit |
aea12f |
* @voutput: will hold the certificate verification output.
|
|
Packit |
aea12f |
* @func: If non-null will be called on each chain element verification with the output.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will try to find a certificate that is associated with the provided
|
|
Packit |
aea12f |
* name --see gnutls_x509_trust_list_add_named_crt(). If a match is found the
|
|
Packit |
aea12f |
* certificate is considered valid. In addition to that this function will also
|
|
Packit |
aea12f |
* check CRLs. The @voutput parameter will hold an OR'ed sequence of
|
|
Packit |
aea12f |
* %gnutls_certificate_status_t flags.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Additionally a certificate verification profile can be specified
|
|
Packit |
aea12f |
* from the ones in %gnutls_certificate_verification_profiles_t by
|
|
Packit |
aea12f |
* ORing the result of GNUTLS_PROFILE_TO_VFLAGS() to the verification
|
|
Packit |
aea12f |
* flags.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Since: 3.0.0
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t cert,
|
|
Packit |
aea12f |
const void *name,
|
|
Packit |
aea12f |
size_t name_size,
|
|
Packit |
aea12f |
unsigned int flags,
|
|
Packit |
aea12f |
unsigned int *voutput,
|
|
Packit |
aea12f |
gnutls_verify_output_function func)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned int i;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
hash =
|
|
Packit |
aea12f |
hash_pjw_bare(cert->raw_issuer_dn.data,
|
|
Packit |
aea12f |
cert->raw_issuer_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = check_if_in_blacklist(&cert, 1,
|
|
Packit |
aea12f |
list->blacklisted, list->blacklisted_size);
|
|
Packit |
aea12f |
if (ret != 0) {
|
|
Packit |
aea12f |
*voutput = 0;
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_REVOKED;
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
*voutput = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < list->node[hash].named_cert_size; i++) {
|
|
Packit |
aea12f |
if (gnutls_x509_crt_equals(cert, list->node[hash].named_certs[i].cert) != 0) { /* check if name matches */
|
|
Packit |
aea12f |
if (list->node[hash].named_certs[i].name_size ==
|
|
Packit |
aea12f |
name_size
|
|
Packit |
aea12f |
&& memcmp(list->node[hash].named_certs[i].name,
|
|
Packit |
aea12f |
name, name_size) == 0) {
|
|
Packit |
aea12f |
*voutput = 0;
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (*voutput != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Check revocation of individual certificates.
|
|
Packit |
aea12f |
* start with the last one that we already have its hash
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
ret = _gnutls_x509_crt_check_revocation(cert,
|
|
Packit |
aea12f |
list->node[hash].crls,
|
|
Packit |
aea12f |
list->node[hash].crl_size,
|
|
Packit |
aea12f |
func);
|
|
Packit |
aea12f |
if (ret == 1) { /* revoked */
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_REVOKED;
|
|
Packit |
aea12f |
*voutput |= GNUTLS_CERT_INVALID;
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* return 1 if @cert is in @list, 0 if not */
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
_gnutls_trustlist_inlist(gnutls_x509_trust_list_t list,
|
|
Packit |
aea12f |
gnutls_x509_crt_t cert)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned int i;
|
|
Packit Service |
991b93 |
size_t hash;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size);
|
|
Packit |
aea12f |
hash %= list->size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_x509_crt_equals(cert,
|
|
Packit |
aea12f |
list->node[hash].
|
|
Packit |
aea12f |
trusted_cas[i]);
|
|
Packit |
aea12f |
if (ret != 0)
|
|
Packit |
aea12f |
return 1;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|