1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/* This example code is placed in the public domain. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "examples.h"
#define CHECK(x) assert((x) >= 0)
/* All the available CRLs
*/
gnutls_x509_crl_t *crl_list;
int crl_list_size;
/* All the available trusted CAs
*/
gnutls_x509_crt_t *ca_list;
int ca_list_size;
static int print_details_func(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer,
gnutls_x509_crl_t crl,
unsigned int verification_output);
/* This function will try to verify the peer's certificate chain, and
* also check if the hostname matches.
*/
void verify_certificate_chain(const char *hostname,
const gnutls_datum_t *cert_chain,
int cert_chain_length)
{
int i;
gnutls_x509_trust_list_t tlist;
gnutls_x509_crt_t *cert;
gnutls_datum_t txt;
unsigned int output;
/* Initialize the trusted certificate list. This should be done
* once on initialization. gnutls_x509_crt_list_import2() and
* gnutls_x509_crl_list_import2() can be used to load them.
*/
CHECK(gnutls_x509_trust_list_init(&tlist, 0));
CHECK(gnutls_x509_trust_list_add_cas(tlist, ca_list, ca_list_size, 0));
CHECK(gnutls_x509_trust_list_add_crls(tlist, crl_list, crl_list_size,
GNUTLS_TL_VERIFY_CRL, 0));
cert = gnutls_calloc(cert_chain_length, sizeof(*cert));
assert(cert != NULL);
/* Import all the certificates in the chain to
* native certificate format.
*/
for (i = 0; i < cert_chain_length; i++) {
CHECK(gnutls_x509_crt_init(&cert[i]));
CHECK(gnutls_x509_crt_import(cert[i], &cert_chain[i],
GNUTLS_X509_FMT_DER));
}
CHECK(gnutls_x509_trust_list_verify_named_crt(
tlist, cert[0], hostname, strlen(hostname),
GNUTLS_VERIFY_DISABLE_CRL_CHECKS, &output, print_details_func));
/* if this certificate is not explicitly trusted verify against CAs
*/
if (output != 0) {
CHECK(gnutls_x509_trust_list_verify_crt(
tlist, cert, cert_chain_length, 0, &output,
print_details_func));
}
if (output & GNUTLS_CERT_INVALID) {
fprintf(stderr, "Not trusted\n");
CHECK(gnutls_certificate_verification_status_print(
output, GNUTLS_CRT_X509, &txt, 0));
fprintf(stderr, "Error: %s\n", txt.data);
gnutls_free(txt.data);
} else
fprintf(stderr, "Trusted\n");
/* Check if the name in the first certificate matches our destination!
*/
if (!gnutls_x509_crt_check_hostname(cert[0], hostname)) {
printf("The certificate's owner does not match hostname '%s'\n",
hostname);
}
for (i = 0; i < cert_chain_length; i++) {
gnutls_x509_crt_deinit(cert[i]);
}
gnutls_free(cert);
gnutls_x509_trust_list_deinit(tlist, 1);
return;
}
static int print_details_func(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer,
gnutls_x509_crl_t crl,
unsigned int verification_output)
{
char name[512];
char issuer_name[512];
size_t name_size;
size_t issuer_name_size;
issuer_name_size = sizeof(issuer_name);
gnutls_x509_crt_get_issuer_dn(cert, issuer_name, &issuer_name_size);
name_size = sizeof(name);
gnutls_x509_crt_get_dn(cert, name, &name_size);
fprintf(stdout, "\tSubject: %s\n", name);
fprintf(stdout, "\tIssuer: %s\n", issuer_name);
if (issuer != NULL) {
issuer_name_size = sizeof(issuer_name);
gnutls_x509_crt_get_dn(issuer, issuer_name, &issuer_name_size);
fprintf(stdout, "\tVerified against: %s\n", issuer_name);
}
if (crl != NULL) {
issuer_name_size = sizeof(issuer_name);
gnutls_x509_crl_get_issuer_dn(crl, issuer_name,
&issuer_name_size);
fprintf(stdout, "\tVerified against CRL of: %s\n", issuer_name);
}
fprintf(stdout, "\tVerification output: %x\n\n", verification_output);
return 0;
}
|