summaryrefslogtreecommitdiffstats
path: root/doc/examples/ex-verify.c
blob: a4f6ebec9eb647666a42ecff5b0a866f55df55a1 (plain)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* 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;
}