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
|
/*
* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2010 Free Software
* Foundation, Inc.
* Copyright (C) 2002 Andrew McDonald
*
* This file is part of GnuTLS.
*
* The GnuTLS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA
*
*/
#include <gnutls_int.h>
#include <gnutls_str.h>
#include <x509_int.h>
#include <common.h>
#include <gnutls_errors.h>
/**
* gnutls_x509_crt_check_hostname:
* @cert: should contain an gnutls_x509_crt_t structure
* @hostname: A null terminated string that contains a DNS name
*
* This function will check if the given certificate's subject matches
* the given hostname. This is a basic implementation of the matching
* described in RFC2818 (HTTPS), which takes into account wildcards,
* and the DNSName/IPAddress subject alternative name PKIX extension.
*
* Returns: non zero for a successful match, and zero on failure.
**/
int
gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname)
{
char dnsname[MAX_CN];
size_t dnsnamesize;
int found_dnsname = 0;
int ret = 0;
int i = 0;
/* try matching against:
* 1) a DNS name as an alternative name (subjectAltName) extension
* in the certificate
* 2) the common name (CN) in the certificate
*
* either of these may be of the form: *.domain.tld
*
* only try (2) if there is no subjectAltName extension of
* type dNSName
*/
/* Check through all included subjectAltName extensions, comparing
* against all those of type dNSName.
*/
for (i = 0; !(ret < 0); i++)
{
dnsnamesize = sizeof (dnsname);
ret = gnutls_x509_crt_get_subject_alt_name (cert, i,
dnsname, &dnsnamesize,
NULL);
if (ret == GNUTLS_SAN_DNSNAME)
{
found_dnsname = 1;
if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
{
return 1;
}
}
else if (ret == GNUTLS_SAN_IPADDRESS)
{
found_dnsname = 1; /* RFC 2818 is unclear whether the CN
should be compared for IP addresses
too, but we won't do it. */
if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
{
return 1;
}
}
}
if (!found_dnsname)
{
/* not got the necessary extension, use CN instead
*/
dnsnamesize = sizeof (dnsname);
if (gnutls_x509_crt_get_dn_by_oid (cert, OID_X520_COMMON_NAME, 0,
0, dnsname, &dnsnamesize) < 0)
{
/* got an error, can't find a name
*/
return 0;
}
if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
{
return 1;
}
}
/* not found a matching name
*/
return 0;
}
|