Modify verify code to handle self signed certificates.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 17 Nov 1999 01:20:29 +0000 (01:20 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 17 Nov 1999 01:20:29 +0000 (01:20 +0000)
CHANGES
apps/verify.c
crypto/x509/x509_vfy.c

diff --git a/CHANGES b/CHANGES
index 289342b..c22cd3f 100644 (file)
--- 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" <pocheng@nst.com.tw>, slightly modified by Steve Henson]
+     [Po-Cheng Chen <pocheng@nst.com.tw>, 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
index 093fe09..840fda9 100644 (file)
@@ -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();
index def60ef..97984ca 100644 (file)
@@ -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
                        {