Doc fixes.
[gnutls:gnutls.git] / lib / x509 / rfc2818_hostname.c
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation
3  * Copyright (C) 2002 Andrew McDonald
4  *
5  * This file is part of GNUTLS.
6  *
7  * The GNUTLS library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA
21  *
22  */
23
24 #include <gnutls_int.h>
25 #include <gnutls_str.h>
26 #include <x509_int.h>
27 #include <common.h>
28 #include <gnutls_errors.h>
29
30 /**
31  * gnutls_x509_crt_check_hostname - compares the hostname with certificate's hostname
32  * @cert: should contain an gnutls_x509_crt_t structure
33  * @hostname: A null terminated string that contains a DNS name
34  *
35  * This function will check if the given certificate's subject matches
36  * the given hostname.  This is a basic implementation of the matching
37  * described in RFC2818 (HTTPS), which takes into account wildcards,
38  * and the DNSName/IPAddress subject alternative name PKIX extension.
39  *
40  * Returns: non zero for a successful match, and zero on failure.
41  **/
42 int
43 gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname)
44 {
45
46   char dnsname[MAX_CN];
47   size_t dnsnamesize;
48   int found_dnsname = 0;
49   int ret = 0;
50   int i = 0;
51
52   /* try matching against:
53    *  1) a DNS name as an alternative name (subjectAltName) extension
54    *     in the certificate
55    *  2) the common name (CN) in the certificate
56    *
57    *  either of these may be of the form: *.domain.tld
58    *
59    *  only try (2) if there is no subjectAltName extension of
60    *  type dNSName
61    */
62
63   /* Check through all included subjectAltName extensions, comparing
64    * against all those of type dNSName.
65    */
66   for (i = 0; !(ret < 0); i++)
67     {
68
69       dnsnamesize = sizeof (dnsname);
70       ret = gnutls_x509_crt_get_subject_alt_name (cert, i,
71                                                   dnsname, &dnsnamesize,
72                                                   NULL);
73
74       if (ret == GNUTLS_SAN_DNSNAME)
75         {
76           found_dnsname = 1;
77           if (_gnutls_hostname_compare (dnsname, hostname))
78             {
79               return 1;
80             }
81         }
82       else if (ret == GNUTLS_SAN_IPADDRESS)
83         {
84           found_dnsname = 1; /* RFC 2818 is unclear whether the CN
85                                 should be compared for IP addresses
86                                 too, but we won't do it.  */
87           if (_gnutls_hostname_compare (dnsname, hostname))
88             {
89               return 1;
90             }
91         }
92     }
93
94   if (!found_dnsname)
95     {
96       /* not got the necessary extension, use CN instead
97        */
98       dnsnamesize = sizeof (dnsname);
99       if (gnutls_x509_crt_get_dn_by_oid (cert, OID_X520_COMMON_NAME, 0,
100                                          0, dnsname, &dnsnamesize) < 0)
101         {
102           /* got an error, can't find a name
103            */
104           return 0;
105         }
106
107       if (_gnutls_hostname_compare (dnsname, hostname))
108         {
109           return 1;
110         }
111     }
112
113   /* not found a matching name
114    */
115   return 0;
116 }