summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbeck <>2018-04-06 07:08:20 +0000
committerbeck <>2018-04-06 07:08:20 +0000
commitcbd1d6a8808038e6f357e956a343f70ecaf110f4 (patch)
tree3f536dd9c6701ce8c8c9a5fa0d5c883caa5222e2
parenta0522cf10ae4b806e95c44e85e22fae53f9228d6 (diff)
downloadopenbsd-cbd1d6a8808038e6f357e956a343f70ecaf110f4.tar.gz
openbsd-cbd1d6a8808038e6f357e956a343f70ecaf110f4.tar.bz2
openbsd-cbd1d6a8808038e6f357e956a343f70ecaf110f4.zip
poison for X509_VERIFY_PARAM's
Tighten up checks for various X509_VERIFY_PARAM functions, and allow for the verify param to be poisoned (preculding future successful cert validation) if the setting of host, ip, or email for certificate validation fails. (since many callers do not check the return code in the wild and blunder along anyway) Inspired by some discussions with Adam Langley. ok jsing@
-rw-r--r--src/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.367
-rw-r--r--src/lib/libcrypto/x509/vpm_int.h3
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c13
-rw-r--r--src/lib/libcrypto/x509/x509_vpm.c69
4 files changed, 107 insertions, 45 deletions
diff --git a/src/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3 b/src/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3
index 4f3261c975..9c0150700d 100644
--- a/src/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3
+++ b/src/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3
@@ -1,4 +1,4 @@
1.\" $OpenBSD: X509_VERIFY_PARAM_set_flags.3,v 1.12 2018/03/23 14:26:40 schwarze Exp $ 1.\" $OpenBSD: X509_VERIFY_PARAM_set_flags.3,v 1.13 2018/04/06 07:08:20 beck Exp $
2.\" full merge up to: OpenSSL d33def66 Feb 9 14:17:13 2016 -0500 2.\" full merge up to: OpenSSL d33def66 Feb 9 14:17:13 2016 -0500
3.\" selective merge up to: OpenSSL 48e5119a Jan 19 10:49:22 2018 +0100 3.\" selective merge up to: OpenSSL 48e5119a Jan 19 10:49:22 2018 +0100
4.\" 4.\"
@@ -68,7 +68,7 @@
68.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 68.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
69.\" OF THE POSSIBILITY OF SUCH DAMAGE. 69.\" OF THE POSSIBILITY OF SUCH DAMAGE.
70.\" 70.\"
71.Dd $Mdocdate: March 23 2018 $ 71.Dd $Mdocdate: April 6 2018 $
72.Dt X509_VERIFY_PARAM_SET_FLAGS 3 72.Dt X509_VERIFY_PARAM_SET_FLAGS 3
73.Os 73.Os
74.Sh NAME 74.Sh NAME
@@ -344,14 +344,14 @@ is
344.Dv NULL 344.Dv NULL
345or empty, the list of hostnames is cleared, and name checks are not 345or empty, the list of hostnames is cleared, and name checks are not
346performed on the peer certificate. 346performed on the peer certificate.
347If 347.Fa namelen
348should be set to the length of
349.Fa name .
350For historical compatibility, if
348.Fa name 351.Fa name
349is NUL-terminated, 352is NUL-terminated,
350.Fa namelen 353.Fa namelen
351may be zero, otherwise 354may be specified as zero.
352.Fa namelen
353must be set to the length of
354.Fa name .
355When a hostname is specified, certificate verification automatically 355When a hostname is specified, certificate verification automatically
356invokes 356invokes
357.Xr X509_check_host 3 357.Xr X509_check_host 3
@@ -360,6 +360,10 @@ with flags equal to the
360argument given to 360argument given to
361.Fn X509_VERIFY_PARAM_set_hostflags 361.Fn X509_VERIFY_PARAM_set_hostflags
362(default zero). 362(default zero).
363.Fn X509_VERIFY_PARAM_set1_host
364will fail if
365.Fa name
366contains any embedded 0 bytes.
363.Pp 367.Pp
364.Fn X509_VERIFY_PARAM_add1_host 368.Fn X509_VERIFY_PARAM_add1_host
365adds 369adds
@@ -376,6 +380,18 @@ No change is made if
376is 380is
377.Dv NULL 381.Dv NULL
378or empty. 382or empty.
383.Fa namelen
384should be set to the length of
385.Fa name .
386For historical compatibility, if
387.Fa name
388is NUL-terminated,
389.Fa namelen
390may be specified as zero.
391.Fn X509_VERIFY_PARAM_add1_host
392will fail if
393.Fa name
394contains any embedded 0 bytes.
379When multiple names are configured, the peer is considered verified when 395When multiple names are configured, the peer is considered verified when
380any name matches. 396any name matches.
381.Pp 397.Pp
@@ -390,14 +406,18 @@ identifier respectively.
390.Fn X509_VERIFY_PARAM_set1_email 406.Fn X509_VERIFY_PARAM_set1_email
391sets the expected RFC822 email address to 407sets the expected RFC822 email address to
392.Fa email . 408.Fa email .
393If 409.Fa emaillen
410should be set to the length of
411.Fa email .
412For historical compatibility, if
394.Fa email 413.Fa email
395is NUL-terminated, 414is NUL-terminated,
396.Fa emaillen 415.Fa emaillen
397may be zero, otherwise 416may be specified as zero,
398.Fa emaillen 417.Fn X509_VERIFY_PARAM_set1_email
399must be set to the length of 418will fail if
400.Fa email . 419.Fa email
420is NULL, an empty string, or contains embedded 0 bytes.
401When an email address is specified, certificate verification 421When an email address is specified, certificate verification
402automatically invokes 422automatically invokes
403.Xr X509_check_email 3 . 423.Xr X509_check_email 3 .
@@ -410,6 +430,12 @@ The
410argument is in binary format, in network byte-order, and 430argument is in binary format, in network byte-order, and
411.Fa iplen 431.Fa iplen
412must be set to 4 for IPv4 and 16 for IPv6. 432must be set to 4 for IPv4 and 16 for IPv6.
433.Fn X509_VERIFY_PARAM_set1_ip
434will fail if
435.Fa ip
436is NULL or if
437.Fa iplen
438is not 4 or 16.
413When an IP address is specified, 439When an IP address is specified,
414certificate verification automatically invokes 440certificate verification automatically invokes
415.Xr X509_check_ip 3 . 441.Xr X509_check_ip 3 .
@@ -422,6 +448,10 @@ The
422argument is a NUL-terminal ASCII string: 448argument is a NUL-terminal ASCII string:
423dotted decimal quad for IPv4 and colon-separated hexadecimal for IPv6. 449dotted decimal quad for IPv4 and colon-separated hexadecimal for IPv6.
424The condensed "::" notation is supported for IPv6 addresses. 450The condensed "::" notation is supported for IPv6 addresses.
451.Fn X509_VERIFY_PARAM_set1_ip_asc
452will fail if
453.Fa ipasc
454is unparsable.
425.Pp 455.Pp
426.Fn X509_VERIFY_PARAM_add0_table 456.Fn X509_VERIFY_PARAM_add0_table
427adds 457adds
@@ -476,14 +506,23 @@ on allocation failure.
476.Fn X509_VERIFY_PARAM_set_trust , 506.Fn X509_VERIFY_PARAM_set_trust ,
477.Fn X509_VERIFY_PARAM_add0_policy , 507.Fn X509_VERIFY_PARAM_add0_policy ,
478.Fn X509_VERIFY_PARAM_set1_policies , 508.Fn X509_VERIFY_PARAM_set1_policies ,
509and
510.Fn X509_VERIFY_PARAM_add0_table
511return 1 for success or 0 for failure.
512.Pp
479.Fn X509_VERIFY_PARAM_set1_host , 513.Fn X509_VERIFY_PARAM_set1_host ,
480.Fn X509_VERIFY_PARAM_add1_host , 514.Fn X509_VERIFY_PARAM_add1_host ,
481.Fn X509_VERIFY_PARAM_set1_email , 515.Fn X509_VERIFY_PARAM_set1_email ,
482.Fn X509_VERIFY_PARAM_set1_ip , 516.Fn X509_VERIFY_PARAM_set1_ip ,
483.Fn X509_VERIFY_PARAM_set1_ip_asc ,
484and 517and
485.Fn X509_VERIFY_PARAM_add0_table 518.Fn X509_VERIFY_PARAM_set1_ip_asc ,
486return 1 for success or 0 for failure. 519return 1 for success or 0 for failure.
520A failure from these routines will poison
521the
522.Vt X509_VERIFY_PARAM
523object so that future calls to
524.Xr X509_verify_cert
525using the poisoned object will fail.
487.Pp 526.Pp
488.Fn X509_VERIFY_PARAM_get_flags 527.Fn X509_VERIFY_PARAM_get_flags
489returns the current verification flags. 528returns the current verification flags.
diff --git a/src/lib/libcrypto/x509/vpm_int.h b/src/lib/libcrypto/x509/vpm_int.h
index 6c8061c847..7fc9fef761 100644
--- a/src/lib/libcrypto/x509/vpm_int.h
+++ b/src/lib/libcrypto/x509/vpm_int.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: vpm_int.h,v 1.3 2016/12/21 15:49:29 jsing Exp $ */ 1/* $OpenBSD: vpm_int.h,v 1.4 2018/04/06 07:08:20 beck Exp $ */
2/* 2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 * 2013. 4 * 2013.
@@ -69,6 +69,7 @@ struct X509_VERIFY_PARAM_ID_st {
69 size_t emaillen; 69 size_t emaillen;
70 unsigned char *ip; /* If not NULL IP address to match */ 70 unsigned char *ip; /* If not NULL IP address to match */
71 size_t iplen; /* Length of IP address */ 71 size_t iplen; /* Length of IP address */
72 int poisoned;
72}; 73};
73 74
74__END_HIDDEN_DECLS 75__END_HIDDEN_DECLS
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index c8ccae5029..8392f509e7 100644
--- a/src/lib/libcrypto/x509/x509_vfy.c
+++ b/src/lib/libcrypto/x509/x509_vfy.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_vfy.c,v 1.68 2018/02/22 17:11:30 jsing Exp $ */ 1/* $OpenBSD: x509_vfy.c,v 1.69 2018/04/06 07:08:20 beck Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -182,10 +182,13 @@ check_id_error(X509_STORE_CTX *ctx, int errcode)
182static int 182static int
183check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id) 183check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id)
184{ 184{
185 size_t i; 185 size_t i, n;
186 size_t n = sk_OPENSSL_STRING_num(id->hosts);
187 char *name; 186 char *name;
188 187
188 if (id->poisoned)
189 return 0;
190
191 n = sk_OPENSSL_STRING_num(id->hosts);
189 free(id->peername); 192 free(id->peername);
190 id->peername = NULL; 193 id->peername = NULL;
191 194
@@ -205,6 +208,10 @@ check_id(X509_STORE_CTX *ctx)
205 X509_VERIFY_PARAM_ID *id = vpm->id; 208 X509_VERIFY_PARAM_ID *id = vpm->id;
206 X509 *x = ctx->cert; 209 X509 *x = ctx->cert;
207 210
211 if (id->poisoned)
212 if (!check_id_error(ctx, X509_V_ERR_INVALID_CALL))
213 return 0;
214
208 if (id->hosts && check_hosts(x, id) <= 0) { 215 if (id->hosts && check_hosts(x, id) <= 0) {
209 if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) 216 if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
210 return 0; 217 return 0;
diff --git a/src/lib/libcrypto/x509/x509_vpm.c b/src/lib/libcrypto/x509/x509_vpm.c
index 0897137697..baebcf7bca 100644
--- a/src/lib/libcrypto/x509/x509_vpm.c
+++ b/src/lib/libcrypto/x509/x509_vpm.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_vpm.c,v 1.17 2018/03/22 15:54:46 beck Exp $ */ 1/* $OpenBSD: x509_vpm.c,v 1.18 2018/04/06 07:08:20 beck Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2004. 3 * project 2004.
4 */ 4 */
@@ -125,7 +125,7 @@ sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void)
125} 125}
126 126
127static int 127static int
128int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode, 128x509_param_set_hosts_internal(X509_VERIFY_PARAM_ID *id, int mode,
129 const char *name, size_t namelen) 129 const char *name, size_t namelen)
130{ 130{
131 char *copy; 131 char *copy;
@@ -134,7 +134,6 @@ int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
134 namelen = strlen(name); 134 namelen = strlen(name);
135 /* 135 /*
136 * Refuse names with embedded NUL bytes. 136 * Refuse names with embedded NUL bytes.
137 * XXX: Do we need to push an error onto the error stack?
138 */ 137 */
139 if (name && memchr(name, '\0', namelen)) 138 if (name && memchr(name, '\0', namelen))
140 return 0; 139 return 0;
@@ -197,6 +196,7 @@ x509_verify_param_zero(X509_VERIFY_PARAM *param)
197 free(paramid->ip); 196 free(paramid->ip);
198 paramid->ip = NULL; 197 paramid->ip = NULL;
199 paramid->iplen = 0; 198 paramid->iplen = 0;
199 paramid->poisoned = 0;
200} 200}
201 201
202X509_VERIFY_PARAM * 202X509_VERIFY_PARAM *
@@ -367,24 +367,28 @@ X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from)
367} 367}
368 368
369static int 369static int
370int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src, 370x509_param_set1_internal(char **pdest, size_t *pdestlen, const char *src,
371 size_t srclen) 371 size_t srclen, int nonul)
372{ 372{
373 char *tmp; 373 char *tmp;
374 if (src) { 374
375 if (srclen == 0) { 375 if (src == NULL)
376 if ((tmp = strdup(src)) == NULL) 376 return 0;
377 return 0; 377
378 srclen = strlen(src); 378 if (srclen == 0) {
379 } else { 379 srclen = strlen(src);
380 if ((tmp = malloc(srclen)) == NULL) 380 if (srclen == 0)
381 return 0; 381 return 0;
382 memcpy(tmp, src, srclen); 382 if ((tmp = strdup(src)) == NULL)
383 } 383 return 0;
384 } else { 384 } else {
385 tmp = NULL; 385 if (nonul && memchr(src, '\0', srclen))
386 srclen = 0; 386 return 0;
387 if ((tmp = malloc(srclen)) == NULL)
388 return 0;
389 memcpy(tmp, src, srclen);
387 } 390 }
391
388 if (*pdest) 392 if (*pdest)
389 free(*pdest); 393 free(*pdest);
390 *pdest = tmp; 394 *pdest = tmp;
@@ -505,14 +509,20 @@ int
505X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, 509X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
506 const char *name, size_t namelen) 510 const char *name, size_t namelen)
507{ 511{
508 return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen); 512 if (x509_param_set_hosts_internal(param->id, SET_HOST, name, namelen))
513 return 1;
514 param->id->poisoned = 1;
515 return 0;
509} 516}
510 517
511int 518int
512X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, 519X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
513 const char *name, size_t namelen) 520 const char *name, size_t namelen)
514{ 521{
515 return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen); 522 if (x509_param_set_hosts_internal(param->id, ADD_HOST, name, namelen))
523 return 1;
524 param->id->poisoned = 1;
525 return 0;
516} 526}
517 527
518void 528void
@@ -531,18 +541,25 @@ int
531X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, 541X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
532 size_t emaillen) 542 size_t emaillen)
533{ 543{
534 return int_x509_param_set1(&param->id->email, &param->id->emaillen, 544 if (x509_param_set1_internal(&param->id->email, &param->id->emaillen,
535 email, emaillen); 545 email, emaillen, 1))
546 return 1;
547 param->id->poisoned = 1;
548 return 0;
536} 549}
537 550
538int 551int
539X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip, 552X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
540 size_t iplen) 553 size_t iplen)
541{ 554{
542 if (iplen != 0 && iplen != 4 && iplen != 16) 555 if (iplen != 4 && iplen != 16)
543 return 0; 556 goto err;
544 return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen, 557 if (x509_param_set1_internal((char **)&param->id->ip, &param->id->iplen,
545 (char *)ip, iplen); 558 (char *)ip, iplen, 0))
559 return 1;
560 err:
561 param->id->poisoned = 1;
562 return 0;
546} 563}
547 564
548int 565int
@@ -552,8 +569,6 @@ X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
552 size_t iplen; 569 size_t iplen;
553 570
554 iplen = (size_t)a2i_ipadd(ipout, ipasc); 571 iplen = (size_t)a2i_ipadd(ipout, ipasc);
555 if (iplen == 0)
556 return 0;
557 return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen); 572 return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
558} 573}
559 574