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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
#include <stdio.h>
#include <stdlib.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
/* 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 void verify_cert2 (gnutls_x509_crt_t crt,
gnutls_x509_crt_t issuer,
gnutls_x509_crl_t * crl_list, int crl_list_size);
static void verify_last_cert (gnutls_x509_crt_t crt,
gnutls_x509_crt_t * ca_list, int ca_list_size,
gnutls_x509_crl_t * crl_list,
int crl_list_size);
/* This function will try to verify the peer's certificate chain, and
* also check if the hostname matches, and the activation, expiration dates.
*/
void
verify_certificate_chain (gnutls_session_t session,
const char *hostname,
const gnutls_datum_t * cert_chain,
int cert_chain_length)
{
int i;
gnutls_x509_crt_t *cert;
cert = malloc (sizeof (*cert) * cert_chain_length);
/* Import all the certificates in the chain to
* native certificate format.
*/
for (i = 0; i < cert_chain_length; i++)
{
gnutls_x509_crt_init (&cert[i]);
gnutls_x509_crt_import (cert[i], &cert_chain[i], GNUTLS_X509_FMT_DER);
}
/* If the last certificate in the chain is self signed ignore it.
* That is because we want to check against our trusted certificate
* list.
*/
if (gnutls_x509_crt_check_issuer (cert[cert_chain_length - 1],
cert[cert_chain_length - 1]) > 0
&& cert_chain_length > 0)
{
cert_chain_length--;
}
/* Now verify the certificates against their issuers
* in the chain.
*/
for (i = 1; i < cert_chain_length; i++)
{
verify_cert2 (cert[i - 1], cert[i], crl_list, crl_list_size);
}
/* Here we must verify the last certificate in the chain against
* our trusted CA list.
*/
verify_last_cert (cert[cert_chain_length - 1],
ca_list, ca_list_size, crl_list, crl_list_size);
/* 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]);
return;
}
/* Verifies a certificate against an other certificate
* which is supposed to be it's issuer. Also checks the
* crl_list if the certificate is revoked.
*/
static void
verify_cert2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer,
gnutls_x509_crl_t * crl_list, int crl_list_size)
{
unsigned int output;
int ret;
time_t now = time (0);
size_t name_size;
char name[64];
/* Print information about the certificates to
* be checked.
*/
name_size = sizeof (name);
gnutls_x509_crt_get_dn (crt, name, &name_size);
fprintf (stderr, "\nCertificate: %s\n", name);
name_size = sizeof (name);
gnutls_x509_crt_get_issuer_dn (crt, name, &name_size);
fprintf (stderr, "Issued by: %s\n", name);
/* Get the DN of the issuer cert.
*/
name_size = sizeof (name);
gnutls_x509_crt_get_dn (issuer, name, &name_size);
fprintf (stderr, "Checking against: %s\n", name);
/* Do the actual verification.
*/
gnutls_x509_crt_verify (crt, &issuer, 1, 0, &output);
if (output & GNUTLS_CERT_INVALID)
{
fprintf (stderr, "Not trusted");
if (output & GNUTLS_CERT_SIGNER_NOT_FOUND)
fprintf (stderr, ": no issuer was found");
if (output & GNUTLS_CERT_SIGNER_NOT_CA)
fprintf (stderr, ": issuer is not a CA");
fprintf (stderr, "\n");
}
else
fprintf (stderr, "Trusted\n");
/* Now check the expiration dates.
*/
if (gnutls_x509_crt_get_activation_time (crt) > now)
fprintf (stderr, "Not yet activated\n");
if (gnutls_x509_crt_get_expiration_time (crt) < now)
fprintf (stderr, "Expired\n");
/* Check if the certificate is revoked.
*/
ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
if (ret == 1)
{ /* revoked */
fprintf (stderr, "Revoked\n");
}
}
/* Verifies a certificate against our trusted CA list.
* Also checks the crl_list if the certificate is revoked.
*/
static void
verify_last_cert (gnutls_x509_crt_t crt,
gnutls_x509_crt_t * ca_list, int ca_list_size,
gnutls_x509_crl_t * crl_list, int crl_list_size)
{
unsigned int output;
int ret;
time_t now = time (0);
size_t name_size;
char name[64];
/* Print information about the certificates to
* be checked.
*/
name_size = sizeof (name);
gnutls_x509_crt_get_dn (crt, name, &name_size);
fprintf (stderr, "\nCertificate: %s\n", name);
name_size = sizeof (name);
gnutls_x509_crt_get_issuer_dn (crt, name, &name_size);
fprintf (stderr, "Issued by: %s\n", name);
/* Do the actual verification.
*/
gnutls_x509_crt_verify (crt, ca_list, ca_list_size,
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &output);
if (output & GNUTLS_CERT_INVALID)
{
fprintf (stderr, "Not trusted");
if (output & GNUTLS_CERT_SIGNER_NOT_CA)
fprintf (stderr, ": Issuer is not a CA\n");
else
fprintf (stderr, "\n");
}
else
fprintf (stderr, "Trusted\n");
/* Now check the expiration dates.
*/
if (gnutls_x509_crt_get_activation_time (crt) > now)
fprintf (stderr, "Not yet activated\n");
if (gnutls_x509_crt_get_expiration_time (crt) < now)
fprintf (stderr, "Expired\n");
/* Check if the certificate is revoked.
*/
ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
if (ret == 1)
{ /* revoked */
fprintf (stderr, "Revoked\n");
}
}
|