From f76d8c47470094a5cb14e937ef3c30db1d97389b Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 17 Nov 1999 01:20:29 +0000 Subject: [PATCH] Modify verify code to handle self signed certificates. --- CHANGES | 15 ++++++++++++++- apps/verify.c | 25 +++++++++++-------------- crypto/x509/x509_vfy.c | 34 +++++++++++++++++++++++++++------- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/CHANGES b/CHANGES index 289342b987..c22cd3f734 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,19 @@ Changes between 0.9.4 and 0.9.5 [xx XXX 1999] + *) First update to verify code. Change the verify utility + so it warns if it is passed a self signed certificate: + for consistency with the normal behaviour. X509_verify + has been modified to it will now verify a self signed + certificate if *exactly* the same certificate appears + in the store: it was previously impossible to trust a + single self signed certificate. This means that: + openssl verify ss.pem + now gives a warning about a self signed certificate but + openssl verify -CAfile ss.pem ss.pem + is OK. + [Steve Henson] + *) For servers, store verify_result in SSL_SESSION data structure (and add it to external session representation). This is needed when client certificate verifications fails, @@ -18,7 +31,7 @@ *) Fix a bug in the new PKCS#7 code: it didn't consider the case in PKCS7_dataInit() where the signed PKCS7 structure didn't contain any existing data because it was being created. - [Po-Cheng Chen" , slightly modified by Steve Henson] + [Po-Cheng Chen , slightly modified by Steve Henson] *) Add a salt to the key derivation routines in enc.c. This forms the first 8 bytes of the encrypted file. Also add a diff --git a/apps/verify.c b/apps/verify.c index 093fe09f2c..840fda9561 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -206,21 +206,18 @@ static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) if (!ok) { - /* since we are just checking the certificates, it is - * ok if they are self signed. */ - if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) - ok=1; - else - { - X509_NAME_oneline( + X509_NAME_oneline( X509_get_subject_name(ctx->current_cert),buf,256); - printf("%s\n",buf); - printf("error %d at %d depth lookup:%s\n",ctx->error, - ctx->error_depth, - X509_verify_cert_error_string(ctx->error)); - if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) - ok=1; - } + printf("%s\n",buf); + printf("error %d at %d depth lookup:%s\n",ctx->error, + ctx->error_depth, + X509_verify_cert_error_string(ctx->error)); + if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1; + /* since we are just checking the certificates, it is + * ok if they are self signed. But we should still warn + * the user. + */ + if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; } if (!v_verbose) ERR_clear_error(); diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index def60ef23e..97984cade4 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -125,7 +125,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) ctx->last_untrusted=1; } - /* We use a temporary so we can chop and hack at it */ + /* We use a temporary STACK so we can chop and hack at it */ if (ctx->untrusted != NULL && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL) { @@ -182,17 +182,37 @@ int X509_verify_cert(X509_STORE_CTX *ctx) i=sk_X509_num(ctx->chain); x=sk_X509_value(ctx->chain,i-1); - if (X509_NAME_cmp(X509_get_subject_name(x),X509_get_issuer_name(x)) + xn = X509_get_subject_name(x); + if (X509_NAME_cmp(xn,X509_get_issuer_name(x)) == 0) { /* we have a self signed certificate */ if (sk_X509_num(ctx->chain) == 1) { - ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - ctx->current_cert=x; - ctx->error_depth=i-1; - ok=cb(0,ctx); - if (!ok) goto end; + /* We have a single self signed certificate: see if + * we can find it in the store. We must have an exact + * match to avoid possible impersonation. + */ + ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj); + if ((ok != X509_LU_X509) || X509_cmp(x, obj.data.x509)) + { + ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + ctx->current_cert=x; + ctx->error_depth=i-1; + if(ok == X509_LU_X509) X509_OBJECT_free_contents(&obj); + ok=cb(0,ctx); + if (!ok) goto end; + } + else + { + /* We have a match: replace certificate with store version + * so we get any trust settings. + */ + X509_free(x); + x = obj.data.x509; + sk_X509_set(ctx->chain, i - 1, x); + ctx->last_untrusted=0; + } } else { -- GitLab