summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libtls/tls_client.c14
-rw-r--r--src/lib/libtls/tls_internal.h5
-rw-r--r--src/lib/libtls/tls_peer.c9
-rw-r--r--src/lib/libtls/tls_server.c11
-rw-r--r--src/lib/libtls/tls_verify.c84
5 files changed, 76 insertions, 47 deletions
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c
index a1e2caa717..0e519684ef 100644
--- a/src/lib/libtls/tls_client.c
+++ b/src/lib/libtls/tls_client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_client.c,v 1.40 2017/01/26 12:56:37 jsing Exp $ */ 1/* $OpenBSD: tls_client.c,v 1.41 2017/04/10 17:11:13 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -289,7 +289,7 @@ int
289tls_handshake_client(struct tls *ctx) 289tls_handshake_client(struct tls *ctx)
290{ 290{
291 X509 *cert = NULL; 291 X509 *cert = NULL;
292 int ssl_ret; 292 int match, ssl_ret;
293 int rv = -1; 293 int rv = -1;
294 294
295 if ((ctx->flags & TLS_CLIENT) == 0) { 295 if ((ctx->flags & TLS_CLIENT) == 0) {
@@ -311,11 +311,11 @@ tls_handshake_client(struct tls *ctx)
311 tls_set_errorx(ctx, "no server certificate"); 311 tls_set_errorx(ctx, "no server certificate");
312 goto err; 312 goto err;
313 } 313 }
314 if ((rv = tls_check_name(ctx, cert, 314 if (tls_check_name(ctx, cert, ctx->servername, &match) == -1)
315 ctx->servername)) != 0) { 315 goto err;
316 if (rv != -2) 316 if (!match) {
317 tls_set_errorx(ctx, "name `%s' not present in" 317 tls_set_errorx(ctx, "name `%s' not present in"
318 " server certificate", ctx->servername); 318 " server certificate", ctx->servername);
319 goto err; 319 goto err;
320 } 320 }
321 } 321 }
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h
index 7bbc14ca86..bd23249e57 100644
--- a/src/lib/libtls/tls_internal.h
+++ b/src/lib/libtls/tls_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_internal.h,v 1.56 2017/04/07 08:48:30 jsing Exp $ */ 1/* $OpenBSD: tls_internal.h,v 1.57 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 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 4 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -186,7 +186,8 @@ void tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx);
186struct tls *tls_new(void); 186struct tls *tls_new(void);
187struct tls *tls_server_conn(struct tls *ctx); 187struct tls *tls_server_conn(struct tls *ctx);
188 188
189int tls_check_name(struct tls *ctx, X509 *cert, const char *servername); 189int tls_check_name(struct tls *ctx, X509 *cert, const char *servername,
190 int *match);
190int tls_configure_server(struct tls *ctx); 191int tls_configure_server(struct tls *ctx);
191 192
192int tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx); 193int tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx);
diff --git a/src/lib/libtls/tls_peer.c b/src/lib/libtls/tls_peer.c
index 1a9065dfb1..ec97a30838 100644
--- a/src/lib/libtls/tls_peer.c
+++ b/src/lib/libtls/tls_peer.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_peer.c,v 1.7 2017/04/05 03:19:22 beck Exp $ */ 1/* $OpenBSD: tls_peer.c,v 1.8 2017/04/10 17:11:13 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org> 4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
@@ -55,10 +55,15 @@ tls_peer_cert_provided(struct tls *ctx)
55int 55int
56tls_peer_cert_contains_name(struct tls *ctx, const char *name) 56tls_peer_cert_contains_name(struct tls *ctx, const char *name)
57{ 57{
58 int match;
59
58 if (ctx->ssl_peer_cert == NULL) 60 if (ctx->ssl_peer_cert == NULL)
59 return (0); 61 return (0);
60 62
61 return (tls_check_name(ctx, ctx->ssl_peer_cert, name) == 0); 63 if (tls_check_name(ctx, ctx->ssl_peer_cert, name, &match) == -1)
64 return (0);
65
66 return (match);
62} 67}
63 68
64time_t 69time_t
diff --git a/src/lib/libtls/tls_server.c b/src/lib/libtls/tls_server.c
index 51deff2510..39c6ca79e9 100644
--- a/src/lib/libtls/tls_server.c
+++ b/src/lib/libtls/tls_server.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_server.c,v 1.35 2017/01/31 15:57:43 jsing Exp $ */ 1/* $OpenBSD: tls_server.c,v 1.36 2017/04/10 17:11:13 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -75,11 +75,13 @@ tls_servername_cb(SSL *ssl, int *al, void *arg)
75 union tls_addr addrbuf; 75 union tls_addr addrbuf;
76 struct tls *conn_ctx; 76 struct tls *conn_ctx;
77 const char *name; 77 const char *name;
78 int match;
78 79
79 if ((conn_ctx = SSL_get_app_data(ssl)) == NULL) 80 if ((conn_ctx = SSL_get_app_data(ssl)) == NULL)
80 goto err; 81 goto err;
81 82
82 if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) == NULL) { 83 if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) ==
84 NULL) {
83 /* 85 /*
84 * The servername callback gets called even when there is no 86 * The servername callback gets called even when there is no
85 * TLS servername extension provided by the client. Sigh! 87 * TLS servername extension provided by the client. Sigh!
@@ -98,7 +100,10 @@ tls_servername_cb(SSL *ssl, int *al, void *arg)
98 100
99 /* Find appropriate SSL context for requested servername. */ 101 /* Find appropriate SSL context for requested servername. */
100 for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) { 102 for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) {
101 if (tls_check_name(ctx, sni_ctx->ssl_cert, name) == 0) { 103 if (tls_check_name(ctx, sni_ctx->ssl_cert, name,
104 &match) == -1)
105 goto err;
106 if (match) {
102 SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx); 107 SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx);
103 return (SSL_TLSEXT_ERR_OK); 108 return (SSL_TLSEXT_ERR_OK);
104 } 109 }
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}