|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2012 KU Leuven
|
|
Packit Service |
4684c1 |
* Copyright (C) 2013 Christian Grothoff
|
|
Packit Service |
4684c1 |
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of libdane.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The libdane library is free software; you can redistribute it
|
|
Packit Service |
4684c1 |
* and/or modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
4684c1 |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
4684c1 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <config.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <stdio.h>
|
|
Packit Service |
4684c1 |
#include <stdlib.h>
|
|
Packit Service |
4684c1 |
#include <string.h>
|
|
Packit Service |
4684c1 |
#include <errno.h>
|
|
Packit Service |
4684c1 |
#include <arpa/inet.h>
|
|
Packit Service |
4684c1 |
#include <unbound.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/dane.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/x509.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/abstract.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/crypto.h>
|
|
Packit Service |
4684c1 |
#include "../lib/gnutls_int.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define MAX_DATA_ENTRIES 100
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#undef gnutls_assert
|
|
Packit Service |
4684c1 |
#undef gnutls_assert_val
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifdef DEBUG
|
|
Packit Service |
4684c1 |
#define gnutls_assert() fprintf(stderr, "ASSERT: %s: %d\n", __FILE__, __LINE__);
|
|
Packit Service |
4684c1 |
#define gnutls_assert_val(x) gnutls_assert_val_int(x, __FILE__, __LINE__)
|
|
Packit Service |
4684c1 |
static int gnutls_assert_val_int(int val, const char *file, int line)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf(stderr, "ASSERT: %s: %d\n", file, line);
|
|
Packit Service |
4684c1 |
return val;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#else
|
|
Packit Service |
4684c1 |
#define gnutls_assert()
|
|
Packit Service |
4684c1 |
#define gnutls_assert_val(x) (x)
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct dane_state_st {
|
|
Packit Service |
4684c1 |
struct ub_ctx *ctx;
|
|
Packit Service |
4684c1 |
unsigned int flags;
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct dane_query_st {
|
|
Packit Service |
4684c1 |
struct ub_result *result;
|
|
Packit Service |
4684c1 |
unsigned int data_entries;
|
|
Packit Service |
4684c1 |
dane_cert_usage_t usage[MAX_DATA_ENTRIES];
|
|
Packit Service |
4684c1 |
dane_cert_type_t type[MAX_DATA_ENTRIES];
|
|
Packit Service |
4684c1 |
dane_match_type_t match[MAX_DATA_ENTRIES];
|
|
Packit Service |
4684c1 |
gnutls_datum_t data[MAX_DATA_ENTRIES];
|
|
Packit Service |
4684c1 |
unsigned int flags;
|
|
Packit Service |
4684c1 |
dane_query_status_t status;
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_query_status:
|
|
Packit Service |
4684c1 |
* @q: The query result structure
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will return the status of the query response.
|
|
Packit Service |
4684c1 |
* See %dane_query_status_t for the possible types.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: The status type.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
dane_query_status_t dane_query_status(dane_query_t q)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return q->status;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_query_entries:
|
|
Packit Service |
4684c1 |
* @q: The query result structure
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will return the number of entries in a query.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: The number of entries.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
unsigned int dane_query_entries(dane_query_t q)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return q->data_entries;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_query_data:
|
|
Packit Service |
4684c1 |
* @q: The query result structure
|
|
Packit Service |
4684c1 |
* @idx: The index of the query response.
|
|
Packit Service |
4684c1 |
* @usage: The certificate usage (see %dane_cert_usage_t)
|
|
Packit Service |
4684c1 |
* @type: The certificate type (see %dane_cert_type_t)
|
|
Packit Service |
4684c1 |
* @match: The DANE matching type (see %dane_match_type_t)
|
|
Packit Service |
4684c1 |
* @data: The DANE data.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will provide the DANE data from the query
|
|
Packit Service |
4684c1 |
* response.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_query_data(dane_query_t q, unsigned int idx,
|
|
Packit Service |
4684c1 |
unsigned int *usage, unsigned int *type,
|
|
Packit Service |
4684c1 |
unsigned int *match, gnutls_datum_t * data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (idx >= q->data_entries)
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (usage)
|
|
Packit Service |
4684c1 |
*usage = q->usage[idx];
|
|
Packit Service |
4684c1 |
if (type)
|
|
Packit Service |
4684c1 |
*type = q->type[idx];
|
|
Packit Service |
4684c1 |
if (match)
|
|
Packit Service |
4684c1 |
*match = q->match[idx];
|
|
Packit Service |
4684c1 |
if (data) {
|
|
Packit Service |
4684c1 |
data->data = q->data[idx].data;
|
|
Packit Service |
4684c1 |
data->size = q->data[idx].size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return DANE_E_SUCCESS;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_query_to_raw_tlsa:
|
|
Packit Service |
4684c1 |
* @q: The query result structure
|
|
Packit Service |
4684c1 |
* @data_entries: Pointer set to the number of entries in the query
|
|
Packit Service |
4684c1 |
* @dane_data: Pointer to contain an array of DNS rdata items, terminated with a NULL pointer;
|
|
Packit Service |
4684c1 |
* caller must guarantee that the referenced data remains
|
|
Packit Service |
4684c1 |
* valid until dane_query_deinit() is called.
|
|
Packit Service |
4684c1 |
* @dane_data_len: Pointer to contain the length n bytes of the dane_data items
|
|
Packit Service |
4684c1 |
* @secure: Pointer set true if the result is validated securely, false if
|
|
Packit Service |
4684c1 |
* validation failed or the domain queried has no security info
|
|
Packit Service |
4684c1 |
* @bogus: Pointer set true if the result was not secure due to a security failure
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will provide the DANE data from the query
|
|
Packit Service |
4684c1 |
* response.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The pointers dane_data and dane_data_len are allocated with gnutls_malloc()
|
|
Packit Service |
4684c1 |
* to contain the data from the query result structure (individual
|
|
Packit Service |
4684c1 |
* @dane_data items simply point to the original data and are not allocated separately).
|
|
Packit Service |
4684c1 |
* The returned @dane_data are only valid during the lifetime of @q.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_query_to_raw_tlsa(dane_query_t q, unsigned int *data_entries,
|
|
Packit Service |
4684c1 |
char ***dane_data, int **dane_data_len, int *secure, int *bogus)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
size_t data_sz;
|
|
Packit Service |
4684c1 |
char *data_buf;
|
|
Packit Service |
4684c1 |
unsigned int idx;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*data_entries = 0;
|
|
Packit Service |
4684c1 |
*dane_data = NULL;
|
|
Packit Service |
4684c1 |
*dane_data_len = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (secure) {
|
|
Packit Service |
4684c1 |
if (q->status & DANE_QUERY_DNSSEC_VERIFIED)
|
|
Packit Service |
4684c1 |
*secure = 1;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
*secure = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bogus) {
|
|
Packit Service |
4684c1 |
if (q->status & DANE_QUERY_BOGUS)
|
|
Packit Service |
4684c1 |
*bogus = 1;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
*bogus = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* pack dane_data pointer list followed by dane_data contents */
|
|
Packit Service |
4684c1 |
data_sz = sizeof (**dane_data) * (q->data_entries + 1);
|
|
Packit Service |
4684c1 |
for (idx = 0; idx < q->data_entries; idx++)
|
|
Packit Service |
4684c1 |
data_sz += 3 + q->data[idx].size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*dane_data = gnutls_calloc (1, data_sz);
|
|
Packit Service |
4684c1 |
if (*dane_data == NULL)
|
|
Packit Service |
4684c1 |
return DANE_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
data_buf = (char *)*dane_data;
|
|
Packit Service |
4684c1 |
data_buf += sizeof (**dane_data) * (q->data_entries + 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*dane_data_len = gnutls_calloc (q->data_entries + 1, sizeof (**dane_data_len));
|
|
Packit Service |
4684c1 |
if (*dane_data_len == NULL) {
|
|
Packit Service |
4684c1 |
free(*dane_data);
|
|
Packit Service |
4684c1 |
*dane_data = NULL;
|
|
Packit Service |
4684c1 |
return DANE_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (idx = 0; idx < q->data_entries; idx++) {
|
|
Packit Service |
4684c1 |
(*dane_data)[idx] = data_buf;
|
|
Packit Service |
4684c1 |
(*dane_data)[idx][0] = q->usage[idx];
|
|
Packit Service |
4684c1 |
(*dane_data)[idx][1] = q->type[idx];
|
|
Packit Service |
4684c1 |
(*dane_data)[idx][2] = q->match[idx];
|
|
Packit Service |
4684c1 |
memcpy(&(*dane_data)[idx][3], q->data[idx].data, q->data[idx].size);
|
|
Packit Service |
4684c1 |
(*dane_data_len)[idx] = 3 + q->data[idx].size;
|
|
Packit Service |
4684c1 |
data_buf += 3 + q->data[idx].size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
(*dane_data)[idx] = NULL;
|
|
Packit Service |
4684c1 |
(*dane_data_len)[idx] = 0;
|
|
Packit Service |
4684c1 |
*data_entries = q->data_entries;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return DANE_E_SUCCESS;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_state_init:
|
|
Packit Service |
4684c1 |
* @s: The structure to be initialized
|
|
Packit Service |
4684c1 |
* @flags: flags from the %dane_state_flags enumeration
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will initialize the backend resolver. It is
|
|
Packit Service |
4684c1 |
* intended to be used in scenarios where multiple resolvings
|
|
Packit Service |
4684c1 |
* occur, to optimize against multiple re-initializations.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int dane_state_init(dane_state_t * s, unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
struct ub_ctx *ctx;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*s = calloc(1, sizeof(struct dane_state_st));
|
|
Packit Service |
4684c1 |
if (*s == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ctx = ub_ctx_create();
|
|
Packit Service |
4684c1 |
if (!ctx) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_INITIALIZATION_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
ub_ctx_debugout(ctx, stderr);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(flags & DANE_F_IGNORE_LOCAL_RESOLVER)) {
|
|
Packit Service |
4684c1 |
if ((ret = ub_ctx_resolvconf(ctx, NULL)) != 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_INITIALIZATION_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ret = ub_ctx_hosts(ctx, NULL)) != 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_INITIALIZATION_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* read public keys for DNSSEC verification */
|
|
Packit Service |
4684c1 |
if (!(flags & DANE_F_IGNORE_DNSSEC)) {
|
|
Packit Service |
4684c1 |
if ((ret =
|
|
Packit Service |
4684c1 |
ub_ctx_add_ta_file(ctx,
|
|
Packit Service |
4684c1 |
(char *) UNBOUND_ROOT_KEY_FILE)) !=
|
|
Packit Service |
4684c1 |
0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_INITIALIZATION_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(*s)->ctx = ctx;
|
|
Packit Service |
4684c1 |
(*s)->flags = flags;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return DANE_E_SUCCESS;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ctx)
|
|
Packit Service |
4684c1 |
ub_ctx_delete(ctx);
|
|
Packit Service |
4684c1 |
free(*s);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_state_deinit:
|
|
Packit Service |
4684c1 |
* @s: The structure to be deinitialized
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will deinitialize a DANE query structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void dane_state_deinit(dane_state_t s)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ub_ctx_delete(s->ctx);
|
|
Packit Service |
4684c1 |
free(s);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_state_set_dlv_file:
|
|
Packit Service |
4684c1 |
* @s: The structure to be deinitialized
|
|
Packit Service |
4684c1 |
* @file: The file holding the DLV keys.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will set a file with trusted keys
|
|
Packit Service |
4684c1 |
* for DLV (DNSSEC Lookaside Validation).
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int dane_state_set_dlv_file(dane_state_t s, const char *file)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
ub_ctx_set_option(s->ctx, (char *) "dlv-anchor-file:",
|
|
Packit Service |
4684c1 |
(void *) file);
|
|
Packit Service |
4684c1 |
if (ret != 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_FILE_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_query_deinit:
|
|
Packit Service |
4684c1 |
* @q: The structure to be deinitialized
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will deinitialize a DANE query result structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void dane_query_deinit(dane_query_t q)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (q->result)
|
|
Packit Service |
4684c1 |
ub_resolve_free(q->result);
|
|
Packit Service |
4684c1 |
free(q);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_raw_tlsa:
|
|
Packit Service |
4684c1 |
* @s: The DANE state structure
|
|
Packit Service |
4684c1 |
* @r: A structure to place the result
|
|
Packit Service |
4684c1 |
* @dane_data: array of DNS rdata items, terminated with a NULL pointer;
|
|
Packit Service |
4684c1 |
* caller must guarantee that the referenced data remains
|
|
Packit Service |
4684c1 |
* valid until dane_query_deinit() is called.
|
|
Packit Service |
4684c1 |
* @dane_data_len: the length n bytes of the dane_data items
|
|
Packit Service |
4684c1 |
* @secure: true if the result is validated securely, false if
|
|
Packit Service |
4684c1 |
* validation failed or the domain queried has no security info
|
|
Packit Service |
4684c1 |
* @bogus: if the result was not secure (secure = 0) due to a security failure,
|
|
Packit Service |
4684c1 |
* and the result is due to a security failure, bogus is true.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will fill in the TLSA (DANE) structure from
|
|
Packit Service |
4684c1 |
* the given raw DNS record data. The @dane_data must be valid
|
|
Packit Service |
4684c1 |
* during the lifetime of the query.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_raw_tlsa(dane_state_t s, dane_query_t * r, char *const *dane_data,
|
|
Packit Service |
4684c1 |
const int *dane_data_len, int secure, int bogus)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret = DANE_E_SUCCESS;
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*r = calloc(1, sizeof(struct dane_query_st));
|
|
Packit Service |
4684c1 |
if (*r == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(*r)->data_entries = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_DATA_ENTRIES; i++) {
|
|
Packit Service |
4684c1 |
if (dane_data[i] == NULL)
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (dane_data_len[i] <= 3)
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val
|
|
Packit Service |
4684c1 |
(DANE_E_RECEIVED_CORRUPT_DATA);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(*r)->usage[i] = dane_data[i][0];
|
|
Packit Service |
4684c1 |
(*r)->type[i] = dane_data[i][1];
|
|
Packit Service |
4684c1 |
(*r)->match[i] = dane_data[i][2];
|
|
Packit Service |
4684c1 |
(*r)->data[i].data = (void *) &dane_data[i][3];
|
|
Packit Service |
4684c1 |
(*r)->data[i].size = dane_data_len[i] - 3;
|
|
Packit Service |
4684c1 |
(*r)->data_entries++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(s->flags & DANE_F_INSECURE) && !secure) {
|
|
Packit Service |
4684c1 |
if (bogus)
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_INVALID_DNSSEC_SIG);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_NO_DNSSEC_SIG);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* show security status */
|
|
Packit Service |
4684c1 |
if (secure) {
|
|
Packit Service |
4684c1 |
(*r)->status = DANE_QUERY_DNSSEC_VERIFIED;
|
|
Packit Service |
4684c1 |
} else if (bogus) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
(*r)->status = DANE_QUERY_BOGUS;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
(*r)->status = DANE_QUERY_NO_DNSSEC;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_query_tlsa:
|
|
Packit Service |
4684c1 |
* @s: The DANE state structure
|
|
Packit Service |
4684c1 |
* @r: A structure to place the result
|
|
Packit Service |
4684c1 |
* @host: The host name to resolve.
|
|
Packit Service |
4684c1 |
* @proto: The protocol type (tcp, udp, etc.)
|
|
Packit Service |
4684c1 |
* @port: The service port number (eg. 443).
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will query the DNS server for the TLSA (DANE)
|
|
Packit Service |
4684c1 |
* data for the given host.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_query_tlsa(dane_state_t s, dane_query_t * r, const char *host,
|
|
Packit Service |
4684c1 |
const char *proto, unsigned int port)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
char ns[1024];
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
struct ub_result *result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(ns, sizeof(ns), "_%u._%s.%s", port, proto, host);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* query for webserver */
|
|
Packit Service |
4684c1 |
ret = ub_resolve(s->ctx, ns, 52, 1, &result);
|
|
Packit Service |
4684c1 |
if (ret != 0) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_RESOLVING_ERROR);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* show first result */
|
|
Packit Service |
4684c1 |
if (!result->havedata) {
|
|
Packit Service |
4684c1 |
ub_resolve_free(result);
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_NO_DANE_DATA);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
dane_raw_tlsa(s, r, result->data, result->len, result->secure,
|
|
Packit Service |
4684c1 |
result->bogus);
|
|
Packit Service |
4684c1 |
if (*r == NULL) {
|
|
Packit Service |
4684c1 |
ub_resolve_free(result);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
(*r)->result = result;
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static unsigned int
|
|
Packit Service |
4684c1 |
matches(const gnutls_datum_t * raw1, const gnutls_datum_t * raw2,
|
|
Packit Service |
4684c1 |
dane_match_type_t match)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t digest[64];
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (match == DANE_MATCH_EXACT) {
|
|
Packit Service |
4684c1 |
if (raw1->size != raw2->size)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (memcmp(raw1->data, raw2->data, raw1->size) != 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
} else if (match == DANE_MATCH_SHA2_256) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (raw2->size != 32)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_hash_fast(GNUTLS_DIG_SHA256, raw1->data,
|
|
Packit Service |
4684c1 |
raw1->size, digest);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (memcmp(digest, raw2->data, 32) != 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
} else if (match == DANE_MATCH_SHA2_512) {
|
|
Packit Service |
4684c1 |
if (raw2->size != 64)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_hash_fast(GNUTLS_DIG_SHA512, raw1->data,
|
|
Packit Service |
4684c1 |
raw1->size, digest);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (memcmp(digest, raw2->data, 64) != 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
crt_to_pubkey(const gnutls_datum_t * raw_crt, gnutls_datum_t * out)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_pubkey_t pub = NULL;
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t crt = NULL;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
out->data = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_PUBKEY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_init(&pub;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_PUBKEY_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_import(crt, raw_crt, GNUTLS_X509_FMT_DER);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_PUBKEY_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_import_x509(pub, crt, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_PUBKEY_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pubkey_export2(pub, GNUTLS_X509_FMT_DER, out);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = DANE_E_PUBKEY_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
goto clean_certs;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
free(out->data);
|
|
Packit Service |
4684c1 |
out->data = NULL;
|
|
Packit Service |
4684c1 |
clean_certs:
|
|
Packit Service |
4684c1 |
if (pub)
|
|
Packit Service |
4684c1 |
gnutls_pubkey_deinit(pub);
|
|
Packit Service |
4684c1 |
if (crt)
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
verify_ca(const gnutls_datum_t * raw_crt, unsigned raw_crt_size,
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_t crt_type,
|
|
Packit Service |
4684c1 |
dane_cert_type_t ctype,
|
|
Packit Service |
4684c1 |
dane_match_type_t match, gnutls_datum_t * data,
|
|
Packit Service |
4684c1 |
unsigned int *verify)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_datum_t pubkey = { NULL, 0 };
|
|
Packit Service |
4684c1 |
int ret, i;
|
|
Packit Service |
4684c1 |
unsigned int vstatus = 0;
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t crt = NULL, ca = NULL;
|
|
Packit Service |
4684c1 |
unsigned is_ok = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (raw_crt_size < 2) /* we cannot verify the CA */
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
|
|
Packit Service |
4684c1 |
is_ok = 0;
|
|
Packit Service |
4684c1 |
for (i=raw_crt_size-1;i>=1;i--) {
|
|
Packit Service |
4684c1 |
if (matches(&raw_crt[i], data, match)) {
|
|
Packit Service |
4684c1 |
is_ok = 1;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (is_ok == 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
*verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
} else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
|
|
Packit Service |
4684c1 |
is_ok = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=raw_crt_size-1;i>=1;i--) {
|
|
Packit Service |
4684c1 |
ret = crt_to_pubkey(&raw_crt[i], &pubkey);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (matches(&pubkey, data, match)) {
|
|
Packit Service |
4684c1 |
is_ok = 1;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
free(pubkey.data);
|
|
Packit Service |
4684c1 |
pubkey.data = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (is_ok == 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
*verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* check if the certificate chain is actually a chain */
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_CERT_ERROR);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_import(crt, &raw_crt[0], GNUTLS_X509_FMT_DER);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_CERT_ERROR);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=raw_crt_size-1;i>=1;i--) {
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_init(&ca);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_CERT_ERROR);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_import(ca, &raw_crt[i], GNUTLS_X509_FMT_DER);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_CERT_ERROR);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_check_issuer(crt, ca);
|
|
Packit Service |
4684c1 |
if (ret != 0)
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(ca);
|
|
Packit Service |
4684c1 |
ca = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ca == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
*verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_verify(crt, &ca, 1, 0, &vstatus);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_CERT_ERROR);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (vstatus != 0)
|
|
Packit Service |
4684c1 |
*verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
free(pubkey.data);
|
|
Packit Service |
4684c1 |
if (crt != NULL)
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
if (ca != NULL)
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(ca);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
verify_ee(const gnutls_datum_t * raw_crt,
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_t crt_type, dane_cert_type_t ctype,
|
|
Packit Service |
4684c1 |
dane_match_type_t match, gnutls_datum_t * data,
|
|
Packit Service |
4684c1 |
unsigned int *verify)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_datum_t pubkey = { NULL, 0 };
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!matches(raw_crt, data, match)) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
*verify |= DANE_VERIFY_CERT_DIFFERS;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
} else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = crt_to_pubkey(raw_crt, &pubkey);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!matches(&pubkey, data, match)) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
*verify |= DANE_VERIFY_CERT_DIFFERS;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
free(pubkey.data);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define CHECK_VRET(ret, checked, record_status, status) \
|
|
Packit Service |
4684c1 |
if (ret == DANE_E_UNKNOWN_DANE_DATA) { \
|
|
Packit Service |
4684c1 |
/* skip that entry */ \
|
|
Packit Service |
4684c1 |
continue; \
|
|
Packit Service |
4684c1 |
} else if (ret < 0) { \
|
|
Packit Service |
4684c1 |
gnutls_assert(); \
|
|
Packit Service |
4684c1 |
goto cleanup; \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
checked = 1; \
|
|
Packit Service |
4684c1 |
if (record_status == 0) { \
|
|
Packit Service |
4684c1 |
status = 0; \
|
|
Packit Service |
4684c1 |
break; \
|
|
Packit Service |
4684c1 |
} else { \
|
|
Packit Service |
4684c1 |
status |= record_status; \
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_verify_crt_raw:
|
|
Packit Service |
4684c1 |
* @s: A DANE state structure (may be NULL)
|
|
Packit Service |
4684c1 |
* @chain: A certificate chain
|
|
Packit Service |
4684c1 |
* @chain_size: The size of the chain
|
|
Packit Service |
4684c1 |
* @chain_type: The type of the certificate chain
|
|
Packit Service |
4684c1 |
* @r: DANE data to check against
|
|
Packit Service |
4684c1 |
* @sflags: Flags for the initialization of @s (if NULL)
|
|
Packit Service |
4684c1 |
* @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
|
|
Packit Service |
4684c1 |
* @verify: An OR'ed list of %dane_verify_status_t.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This is the low-level function of dane_verify_crt(). See the
|
|
Packit Service |
4684c1 |
* high level function for documentation.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function does not perform any resolving, it utilizes
|
|
Packit Service |
4684c1 |
* cached entries from @r.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: a negative error code on error and %DANE_E_SUCCESS (0)
|
|
Packit Service |
4684c1 |
* when the DANE entries were successfully parsed, irrespective of
|
|
Packit Service |
4684c1 |
* whether they were verified (see @verify for that information). If
|
|
Packit Service |
4684c1 |
* no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
|
|
Packit Service |
4684c1 |
* will be returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_verify_crt_raw(dane_state_t s,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * chain, unsigned chain_size,
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_t chain_type,
|
|
Packit Service |
4684c1 |
dane_query_t r,
|
|
Packit Service |
4684c1 |
unsigned int sflags, unsigned int vflags,
|
|
Packit Service |
4684c1 |
unsigned int *verify)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
unsigned checked = 0;
|
|
Packit Service |
4684c1 |
unsigned int usage, type, match, idx;
|
|
Packit Service |
4684c1 |
gnutls_datum_t data;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (chain_type != GNUTLS_CRT_X509)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (chain_size == 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_NO_CERT);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*verify = 0;
|
|
Packit Service |
4684c1 |
idx = 0;
|
|
Packit Service |
4684c1 |
do {
|
|
Packit Service |
4684c1 |
unsigned int record_verify = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
dane_query_data(r, idx++, &usage, &type, &match,
|
|
Packit Service |
4684c1 |
&data);
|
|
Packit Service |
4684c1 |
if (ret == DANE_E_REQUESTED_DATA_NOT_AVAILABLE)
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(vflags & DANE_VFLAG_ONLY_CHECK_EE_USAGE)
|
|
Packit Service |
4684c1 |
&& (usage == DANE_CERT_USAGE_LOCAL_CA
|
|
Packit Service |
4684c1 |
|| usage == DANE_CERT_USAGE_CA)) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
verify_ca(chain, chain_size, chain_type, type,
|
|
Packit Service |
4684c1 |
match, &data, &record_verify);
|
|
Packit Service |
4684c1 |
CHECK_VRET(ret, checked, record_verify, *verify);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
} else if (!(vflags & DANE_VFLAG_ONLY_CHECK_CA_USAGE)
|
|
Packit Service |
4684c1 |
&& (usage == DANE_CERT_USAGE_LOCAL_EE
|
|
Packit Service |
4684c1 |
|| usage == DANE_CERT_USAGE_EE)) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
verify_ee(&chain[0], chain_type, type, match,
|
|
Packit Service |
4684c1 |
&data, &record_verify);
|
|
Packit Service |
4684c1 |
CHECK_VRET(ret, checked, record_verify, *verify);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
while (1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((vflags & DANE_VFLAG_FAIL_IF_NOT_CHECKED) && checked == 0) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
Packit Service |
4684c1 |
} else if (checked == 0) {
|
|
Packit Service |
4684c1 |
*verify |= DANE_VERIFY_UNKNOWN_DANE_INFO;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_verify_crt:
|
|
Packit Service |
4684c1 |
* @s: A DANE state structure (may be NULL)
|
|
Packit Service |
4684c1 |
* @chain: A certificate chain
|
|
Packit Service |
4684c1 |
* @chain_size: The size of the chain
|
|
Packit Service |
4684c1 |
* @chain_type: The type of the certificate chain
|
|
Packit Service |
4684c1 |
* @hostname: The hostname associated with the chain
|
|
Packit Service |
4684c1 |
* @proto: The protocol of the service connecting (e.g. tcp)
|
|
Packit Service |
4684c1 |
* @port: The port of the service connecting (e.g. 443)
|
|
Packit Service |
4684c1 |
* @sflags: Flags for the initialization of @s (if NULL)
|
|
Packit Service |
4684c1 |
* @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
|
|
Packit Service |
4684c1 |
* @verify: An OR'ed list of %dane_verify_status_t.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will verify the given certificate chain against the
|
|
Packit Service |
4684c1 |
* CA constrains and/or the certificate available via DANE.
|
|
Packit Service |
4684c1 |
* If no information via DANE can be obtained the flag %DANE_VERIFY_NO_DANE_INFO
|
|
Packit Service |
4684c1 |
* is set. If a DNSSEC signature is not available for the DANE
|
|
Packit Service |
4684c1 |
* record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Due to the many possible options of DANE, there is no single threat
|
|
Packit Service |
4684c1 |
* model countered. When notifying the user about DANE verification results
|
|
Packit Service |
4684c1 |
* it may be better to mention: DANE verification did not reject the certificate,
|
|
Packit Service |
4684c1 |
* rather than mentioning a successful DANE verication.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Note that this function is designed to be run in addition to
|
|
Packit Service |
4684c1 |
* PKIX - certificate chain - verification. To be run independently
|
|
Packit Service |
4684c1 |
* the %DANE_VFLAG_ONLY_CHECK_EE_USAGE flag should be specified;
|
|
Packit Service |
4684c1 |
* then the function will check whether the key of the peer matches the
|
|
Packit Service |
4684c1 |
* key advertized in the DANE entry.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: a negative error code on error and %DANE_E_SUCCESS (0)
|
|
Packit Service |
4684c1 |
* when the DANE entries were successfully parsed, irrespective of
|
|
Packit Service |
4684c1 |
* whether they were verified (see @verify for that information). If
|
|
Packit Service |
4684c1 |
* no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
|
|
Packit Service |
4684c1 |
* will be returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_verify_crt(dane_state_t s,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * chain, unsigned chain_size,
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_t chain_type,
|
|
Packit Service |
4684c1 |
const char *hostname, const char *proto, unsigned int port,
|
|
Packit Service |
4684c1 |
unsigned int sflags, unsigned int vflags,
|
|
Packit Service |
4684c1 |
unsigned int *verify)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
dane_state_t state = NULL;
|
|
Packit Service |
4684c1 |
dane_query_t r = NULL;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*verify = 0;
|
|
Packit Service |
4684c1 |
if (s == NULL) {
|
|
Packit Service |
4684c1 |
ret = dane_state_init(&state, sflags);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else
|
|
Packit Service |
4684c1 |
state = s;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = dane_query_tlsa(state, &r, hostname, proto, port);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
ret = dane_verify_crt_raw(state, chain, chain_size, chain_type,
|
|
Packit Service |
4684c1 |
r, sflags, vflags, verify);
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (state != s)
|
|
Packit Service |
4684c1 |
dane_state_deinit(state);
|
|
Packit Service |
4684c1 |
if (r != NULL)
|
|
Packit Service |
4684c1 |
dane_query_deinit(r);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_verify_session_crt:
|
|
Packit Service |
4684c1 |
* @s: A DANE state structure (may be NULL)
|
|
Packit Service |
4684c1 |
* @session: A gnutls session
|
|
Packit Service |
4684c1 |
* @hostname: The hostname associated with the chain
|
|
Packit Service |
4684c1 |
* @proto: The protocol of the service connecting (e.g. tcp)
|
|
Packit Service |
4684c1 |
* @port: The port of the service connecting (e.g. 443)
|
|
Packit Service |
4684c1 |
* @sflags: Flags for the initialization of @s (if NULL)
|
|
Packit Service |
4684c1 |
* @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
|
|
Packit Service |
4684c1 |
* @verify: An OR'ed list of %dane_verify_status_t.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will verify session's certificate chain against the
|
|
Packit Service |
4684c1 |
* CA constrains and/or the certificate available via DANE.
|
|
Packit Service |
4684c1 |
* See dane_verify_crt() for more information.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This will not verify the chain for validity; unless the DANE
|
|
Packit Service |
4684c1 |
* verification is restricted to end certificates, this must be
|
|
Packit Service |
4684c1 |
* be performed separately using gnutls_certificate_verify_peers3().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: a negative error code on error and %DANE_E_SUCCESS (0)
|
|
Packit Service |
4684c1 |
* when the DANE entries were successfully parsed, irrespective of
|
|
Packit Service |
4684c1 |
* whether they were verified (see @verify for that information). If
|
|
Packit Service |
4684c1 |
* no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
|
|
Packit Service |
4684c1 |
* will be returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_verify_session_crt(dane_state_t s,
|
|
Packit Service |
4684c1 |
gnutls_session_t session,
|
|
Packit Service |
4684c1 |
const char *hostname, const char *proto,
|
|
Packit Service |
4684c1 |
unsigned int port, unsigned int sflags,
|
|
Packit Service |
4684c1 |
unsigned int vflags, unsigned int *verify)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const gnutls_datum_t *cert_list;
|
|
Packit Service |
4684c1 |
unsigned int cert_list_size = 0;
|
|
Packit Service |
4684c1 |
unsigned int type;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
|
|
Packit Service |
4684c1 |
if (cert_list_size == 0) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(DANE_E_NO_CERT);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
type = gnutls_certificate_type_get(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* this list may be incomplete, try to get the self-signed CA if any */
|
|
Packit Service |
4684c1 |
if (cert_list_size > 0) {
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t crt, ca;
|
|
Packit Service |
4684c1 |
gnutls_certificate_credentials_t sc;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_init(&crt;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto failsafe;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_import(crt, &cert_list[cert_list_size-1], GNUTLS_X509_FMT_DER);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
goto failsafe;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* if it is already self signed continue normally */
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_check_issuer(crt, crt);
|
|
Packit Service |
4684c1 |
if (ret != 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
goto failsafe;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* chain does not finish in a self signed cert, try to obtain the issuer */
|
|
Packit Service |
4684c1 |
ret = gnutls_credentials_get(session, GNUTLS_CRD_CERTIFICATE, (void**)&sc);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
goto failsafe;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_certificate_get_issuer(sc, crt, &ca, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
goto failsafe;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* make the new list */
|
|
Packit Service |
4684c1 |
gnutls_datum_t *new_cert_list;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
new_cert_list = gnutls_malloc((cert_list_size + 1) * sizeof(gnutls_datum_t));
|
|
Packit Service |
4684c1 |
if (new_cert_list == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
goto failsafe;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(new_cert_list, cert_list, cert_list_size*sizeof(gnutls_datum_t));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_export2(ca, GNUTLS_X509_FMT_DER, &new_cert_list[cert_list_size]);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
free(new_cert_list);
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(crt);
|
|
Packit Service |
4684c1 |
goto failsafe;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = dane_verify_crt(s, new_cert_list, cert_list_size+1, type,
|
|
Packit Service |
4684c1 |
hostname, proto, port, sflags, vflags,
|
|
Packit Service |
4684c1 |
verify);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
gnutls_free(new_cert_list[cert_list_size].data);
|
|
Packit Service |
4684c1 |
free(new_cert_list);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
failsafe:
|
|
Packit Service |
4684c1 |
return dane_verify_crt(s, cert_list, cert_list_size, type,
|
|
Packit Service |
4684c1 |
hostname, proto, port, sflags, vflags,
|
|
Packit Service |
4684c1 |
verify);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* dane_verification_status_print:
|
|
Packit Service |
4684c1 |
* @status: The status flags to be printed
|
|
Packit Service |
4684c1 |
* @type: The certificate type
|
|
Packit Service |
4684c1 |
* @out: Newly allocated datum with (0) terminated string.
|
|
Packit Service |
4684c1 |
* @flags: should be zero
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will pretty print the status of a verification
|
|
Packit Service |
4684c1 |
* process -- eg. the one obtained by dane_verify_crt().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The output @out needs to be deallocated using gnutls_free().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
dane_verification_status_print(unsigned int status,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * out, unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_buffer_st str;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_buffer_init(&str);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (status == 0)
|
|
Packit Service |
4684c1 |
_gnutls_buffer_append_str(&str,
|
|
Packit Service |
4684c1 |
_("Certificate matches. "));
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
_gnutls_buffer_append_str(&str,
|
|
Packit Service |
4684c1 |
_("Verification failed. "));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (status & DANE_VERIFY_CA_CONSTRAINTS_VIOLATED)
|
|
Packit Service |
4684c1 |
_gnutls_buffer_append_str(&str,
|
|
Packit Service |
4684c1 |
_
|
|
Packit Service |
4684c1 |
("CA constrains were violated. "));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (status & DANE_VERIFY_CERT_DIFFERS)
|
|
Packit Service |
4684c1 |
_gnutls_buffer_append_str(&str,
|
|
Packit Service |
4684c1 |
_("The certificate differs. "));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (status & DANE_VERIFY_NO_DANE_INFO)
|
|
Packit Service |
4684c1 |
_gnutls_buffer_append_str(&str,
|
|
Packit Service |
4684c1 |
_
|
|
Packit Service |
4684c1 |
("There were no DANE information. "));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return _gnutls_buffer_to_datum(&str, out, 1);
|
|
Packit Service |
4684c1 |
}
|