summaryrefslogtreecommitdiff
path: root/src/lib/libtls/tls_verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libtls/tls_verify.c')
-rw-r--r--src/lib/libtls/tls_verify.c84
1 files changed, 51 insertions, 33 deletions
diff --git a/src/lib/libtls/tls_verify.c b/src/lib/libtls/tls_verify.c
index 23e58ebef7..3bd1057d0c 100644
--- a/src/lib/libtls/tls_verify.c
+++ b/src/lib/libtls/tls_verify.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_verify.c,v 1.18 2016/11/04 15:32:40 jsing Exp $ */ 1/* $OpenBSD: tls_verify.c,v 1.19 2017/04/10 17:11:13 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> 3 * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
4 * 4 *
@@ -27,11 +27,6 @@
27#include <tls.h> 27#include <tls.h>
28#include "tls_internal.h" 28#include "tls_internal.h"
29 29
30static int tls_match_name(const char *cert_name, const char *name);
31static int tls_check_subject_altname(struct tls *ctx, X509 *cert,
32 const char *name);
33static int tls_check_common_name(struct tls *ctx, X509 *cert, const char *name);
34
35static int 30static int
36tls_match_name(const char *cert_name, const char *name) 31tls_match_name(const char *cert_name, const char *name)
37{ 32{
@@ -84,20 +79,28 @@ tls_match_name(const char *cert_name, const char *name)
84 return -1; 79 return -1;
85} 80}
86 81
87/* See RFC 5280 section 4.2.1.6 for SubjectAltName details. */ 82/*
83 * See RFC 5280 section 4.2.1.6 for SubjectAltName details.
84 * alt_match is set to 1 if a matching alternate name is found.
85 * alt_exists is set to 1 if any known alternate name exists in the certificate.
86 */
88static int 87static int
89tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name) 88tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name,
89 int *alt_match, int *alt_exists)
90{ 90{
91 STACK_OF(GENERAL_NAME) *altname_stack = NULL; 91 STACK_OF(GENERAL_NAME) *altname_stack = NULL;
92 union tls_addr addrbuf; 92 union tls_addr addrbuf;
93 int addrlen, type; 93 int addrlen, type;
94 int count, i; 94 int count, i;
95 int rv = -1; 95 int rv = 0;
96
97 *alt_match = 0;
98 *alt_exists = 0;
96 99
97 altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name, 100 altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name,
98 NULL, NULL); 101 NULL, NULL);
99 if (altname_stack == NULL) 102 if (altname_stack == NULL)
100 return -1; 103 return 0;
101 104
102 if (inet_pton(AF_INET, name, &addrbuf) == 1) { 105 if (inet_pton(AF_INET, name, &addrbuf) == 1) {
103 type = GEN_IPADD; 106 type = GEN_IPADD;
@@ -115,6 +118,10 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name)
115 GENERAL_NAME *altname; 118 GENERAL_NAME *altname;
116 119
117 altname = sk_GENERAL_NAME_value(altname_stack, i); 120 altname = sk_GENERAL_NAME_value(altname_stack, i);
121
122 if (altname->type == GEN_DNS || altname->type == GEN_IPADD)
123 *alt_exists = 1;
124
118 if (altname->type != type) 125 if (altname->type != type)
119 continue; 126 continue;
120 127
@@ -133,7 +140,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name)
133 "NUL byte in subjectAltName, " 140 "NUL byte in subjectAltName, "
134 "probably a malicious certificate", 141 "probably a malicious certificate",
135 name); 142 name);
136 rv = -2; 143 rv = -1;
137 break; 144 break;
138 } 145 }
139 146
@@ -143,16 +150,16 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name)
143 * dNSName must be rejected. 150 * dNSName must be rejected.
144 */ 151 */
145 if (strcmp(data, " ") == 0) { 152 if (strcmp(data, " ") == 0) {
146 tls_set_error(ctx, 153 tls_set_errorx(ctx,
147 "error verifying name '%s': " 154 "error verifying name '%s': "
148 "a dNSName of \" \" must not be " 155 "a dNSName of \" \" must not be "
149 "used", name); 156 "used", name);
150 rv = -2; 157 rv = -1;
151 break; 158 break;
152 } 159 }
153 160
154 if (tls_match_name(data, name) == 0) { 161 if (tls_match_name(data, name) == 0) {
155 rv = 0; 162 *alt_match = 1;
156 break; 163 break;
157 } 164 }
158 } else { 165 } else {
@@ -174,7 +181,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name)
174 tls_set_errorx(ctx, 181 tls_set_errorx(ctx,
175 "Unexpected negative length for an " 182 "Unexpected negative length for an "
176 "IP address: %d", datalen); 183 "IP address: %d", datalen);
177 rv = -2; 184 rv = -1;
178 break; 185 break;
179 } 186 }
180 187
@@ -184,7 +191,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name)
184 */ 191 */
185 if (datalen == addrlen && 192 if (datalen == addrlen &&
186 memcmp(data, &addrbuf, addrlen) == 0) { 193 memcmp(data, &addrbuf, addrlen) == 0) {
187 rv = 0; 194 *alt_match = 1;
188 break; 195 break;
189 } 196 }
190 } 197 }
@@ -195,13 +202,16 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name)
195} 202}
196 203
197static int 204static int
198tls_check_common_name(struct tls *ctx, X509 *cert, const char *name) 205tls_check_common_name(struct tls *ctx, X509 *cert, const char *name,
206 int *cn_match)
199{ 207{
200 X509_NAME *subject_name; 208 X509_NAME *subject_name;
201 char *common_name = NULL; 209 char *common_name = NULL;
202 union tls_addr addrbuf; 210 union tls_addr addrbuf;
203 int common_name_len; 211 int common_name_len;
204 int rv = -1; 212 int rv = 0;
213
214 *cn_match = 0;
205 215
206 subject_name = X509_get_subject_name(cert); 216 subject_name = X509_get_subject_name(cert);
207 if (subject_name == NULL) 217 if (subject_name == NULL)
@@ -225,38 +235,46 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name)
225 tls_set_errorx(ctx, "error verifying name '%s': " 235 tls_set_errorx(ctx, "error verifying name '%s': "
226 "NUL byte in Common Name field, " 236 "NUL byte in Common Name field, "
227 "probably a malicious certificate", name); 237 "probably a malicious certificate", name);
228 rv = -2; 238 rv = -1;
229 goto out; 239 goto out;
230 } 240 }
231 241
242 /*
243 * We don't want to attempt wildcard matching against IP addresses,
244 * so perform a simple comparison here.
245 */
232 if (inet_pton(AF_INET, name, &addrbuf) == 1 || 246 if (inet_pton(AF_INET, name, &addrbuf) == 1 ||
233 inet_pton(AF_INET6, name, &addrbuf) == 1) { 247 inet_pton(AF_INET6, name, &addrbuf) == 1) {
234 /*
235 * We don't want to attempt wildcard matching against IP
236 * addresses, so perform a simple comparison here.
237 */
238 if (strcmp(common_name, name) == 0) 248 if (strcmp(common_name, name) == 0)
239 rv = 0; 249 *cn_match = 1;
240 else
241 rv = -1;
242 goto out; 250 goto out;
243 } 251 }
244 252
245 if (tls_match_name(common_name, name) == 0) 253 if (tls_match_name(common_name, name) == 0)
246 rv = 0; 254 *cn_match = 1;
255
247 out: 256 out:
248 free(common_name); 257 free(common_name);
249 return rv; 258 return rv;
250} 259}
251 260
252int 261int
253tls_check_name(struct tls *ctx, X509 *cert, const char *name) 262tls_check_name(struct tls *ctx, X509 *cert, const char *name, int *match)
254{ 263{
255 int rv; 264 int alt_exists;
256 265
257 rv = tls_check_subject_altname(ctx, cert, name); 266 *match = 0;
258 if (rv == 0 || rv == -2) 267
259 return rv; 268 if (tls_check_subject_altname(ctx, cert, name, match,
269 &alt_exists) == -1)
270 return -1;
271
272 /*
273 * As per RFC 6125 section 6.4.4, if any known alternate name existed
274 * in the certificate, we do not attempt to match on the CN.
275 */
276 if (*match || alt_exists)
277 return 0;
260 278
261 return tls_check_common_name(ctx, cert, name); 279 return tls_check_common_name(ctx, cert, name, match);
262} 280}