diff options
author | beck <> | 2017-01-03 05:34:48 +0000 |
---|---|---|
committer | beck <> | 2017-01-03 05:34:48 +0000 |
commit | 9f4657d603430aebe13903d7dbdb5cd15e512f95 (patch) | |
tree | 5fc8e0a7bc7848b74f6b48f6f81b8b56ec43c714 /src/lib | |
parent | 5652b8a711562263678662d609ce7925015bce4d (diff) | |
download | openbsd-9f4657d603430aebe13903d7dbdb5cd15e512f95.tar.gz openbsd-9f4657d603430aebe13903d7dbdb5cd15e512f95.tar.bz2 openbsd-9f4657d603430aebe13903d7dbdb5cd15e512f95.zip |
bring in boring's internal check_trust function to fix a bug introduced
when we went to alternate cert chains. this correctly does not clobber
the ctx->error when using an alt chain.
ok jsing@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 103 |
1 files changed, 79 insertions, 24 deletions
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index abd5c65e31..3d4121ed2a 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.52 2016/11/06 10:37:38 beck Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.53 2017/01/03 05:34:48 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 | * |
@@ -775,32 +775,87 @@ check_name_constraints(X509_STORE_CTX *ctx) | |||
775 | return 1; | 775 | return 1; |
776 | } | 776 | } |
777 | 777 | ||
778 | static int | 778 | /* Given a certificate try and find an exact match in the store */ |
779 | check_trust(X509_STORE_CTX *ctx) | 779 | |
780 | static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) | ||
780 | { | 781 | { |
781 | #ifdef OPENSSL_NO_CHAIN_VERIFY | 782 | STACK_OF(X509) *certs; |
782 | return 1; | 783 | X509 *xtmp = NULL; |
783 | #else | 784 | size_t i; |
784 | int i, ok; | ||
785 | X509 *x; | ||
786 | int (*cb)(int xok, X509_STORE_CTX *xctx); | ||
787 | 785 | ||
788 | cb = ctx->verify_cb; | 786 | /* Lookup all certs with matching subject name */ |
789 | /* For now just check the last certificate in the chain */ | 787 | certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); |
790 | i = sk_X509_num(ctx->chain) - 1; | 788 | if (certs == NULL) |
791 | x = sk_X509_value(ctx->chain, i); | 789 | return NULL; |
792 | ok = X509_check_trust(x, ctx->param->trust, 0); | 790 | |
793 | if (ok == X509_TRUST_TRUSTED) | 791 | /* Look for exact match */ |
794 | return 1; | 792 | for (i = 0; i < sk_X509_num(certs); i++) { |
795 | ctx->error_depth = i; | 793 | xtmp = sk_X509_value(certs, i); |
796 | ctx->current_cert = x; | 794 | if (!X509_cmp(xtmp, x)) |
797 | if (ok == X509_TRUST_REJECTED) | 795 | break; |
798 | ctx->error = X509_V_ERR_CERT_REJECTED; | 796 | } |
797 | |||
798 | if (i < sk_X509_num(certs)) | ||
799 | X509_up_ref(xtmp); | ||
799 | else | 800 | else |
800 | ctx->error = X509_V_ERR_CERT_UNTRUSTED; | 801 | xtmp = NULL; |
801 | ok = cb(0, ctx); | 802 | |
802 | return ok; | 803 | sk_X509_pop_free(certs, X509_free); |
803 | #endif | 804 | return xtmp; |
805 | } | ||
806 | |||
807 | static int check_trust(X509_STORE_CTX *ctx) | ||
808 | { | ||
809 | size_t i; | ||
810 | int ok; | ||
811 | X509 *x = NULL; | ||
812 | int (*cb) (int xok, X509_STORE_CTX *xctx); | ||
813 | |||
814 | cb = ctx->verify_cb; | ||
815 | /* Check all trusted certificates in chain */ | ||
816 | for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) { | ||
817 | x = sk_X509_value(ctx->chain, i); | ||
818 | ok = X509_check_trust(x, ctx->param->trust, 0); | ||
819 | |||
820 | /* If explicitly trusted return trusted */ | ||
821 | if (ok == X509_TRUST_TRUSTED) | ||
822 | return X509_TRUST_TRUSTED; | ||
823 | /* | ||
824 | * If explicitly rejected notify callback and reject if not | ||
825 | * overridden. | ||
826 | */ | ||
827 | if (ok == X509_TRUST_REJECTED) { | ||
828 | ctx->error_depth = i; | ||
829 | ctx->current_cert = x; | ||
830 | ctx->error = X509_V_ERR_CERT_REJECTED; | ||
831 | ok = cb(0, ctx); | ||
832 | if (!ok) | ||
833 | return X509_TRUST_REJECTED; | ||
834 | } | ||
835 | } | ||
836 | /* | ||
837 | * If we accept partial chains and have at least one trusted certificate | ||
838 | * return success. | ||
839 | */ | ||
840 | if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { | ||
841 | X509 *mx; | ||
842 | if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain)) | ||
843 | return X509_TRUST_TRUSTED; | ||
844 | x = sk_X509_value(ctx->chain, 0); | ||
845 | mx = lookup_cert_match(ctx, x); | ||
846 | if (mx) { | ||
847 | (void)sk_X509_set(ctx->chain, 0, mx); | ||
848 | X509_free(x); | ||
849 | ctx->last_untrusted = 0; | ||
850 | return X509_TRUST_TRUSTED; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * If no trusted certs in chain at all return untrusted and allow | ||
856 | * standard (no issuer cert) etc errors to be indicated. | ||
857 | */ | ||
858 | return X509_TRUST_UNTRUSTED; | ||
804 | } | 859 | } |
805 | 860 | ||
806 | static int | 861 | static int |