Fix bug where freed OIDs could be accessed in EVP_cleanup() by
authorDr. Stephen Henson <steve@openssl.org>
Tue, 28 Mar 2006 17:23:48 +0000 (17:23 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 28 Mar 2006 17:23:48 +0000 (17:23 +0000)
defering freeing in OBJ_cleanup().

CHANGES
FAQ
apps/apps.h
apps/dgst.c
crypto/evp/names.c
crypto/objects/obj_dat.c

diff --git a/CHANGES b/CHANGES
index bb006e21a13be51f0f8016d4543c1e8f19f66406..b33ec3274312c101fe07542224a9576bb85f3c8c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,10 @@
 
  Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 
+  *) Don't free up OIDs in OBJ_cleanup() if they are in use by EVP_MD or
+     EVP_CIPHER structures to avoid later problems in EVP_cleanup().
+     [Steve Henson]
+
   *) New utilities pkey and pkeyparam. These are similar to algorithm specific
      utilities such as rsa, dsa, dsaparam etc except they processes any key
      type.
diff --git a/FAQ b/FAQ
index 9f6dc63d4fcf6781834008bd958463a44182c333..a88765ef0fb85e8baf21d028518edc67c328561f 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -430,7 +430,7 @@ encryption so these certificates are now obsolete.
 
 It doesn't: this extension is often the cause of confusion.
 
-Consider a certificate chain A->B->C so that A signs, B and B signs C. Suppose
+Consider a certificate chain A->B->C so that A signs B and B signs C. Suppose
 certificate C contains AKID.
 
 The purpose of this extension is to identify the authority certificate B. This
index f7950d7a97b3e272cf17466ab88fa7e0f4016d76..7a20d066c960b3e748c771d0c5fdfa4ed8d4c6d3 100644 (file)
@@ -177,7 +177,7 @@ extern BIO *bio_err;
                        ENGINE_load_builtin_engines(); setup_ui_method(); } while(0)
 #    define apps_shutdown() \
                        do { CONF_modules_unload(1); destroy_ui_method(); \
-                       EVP_cleanup(); ENGINE_cleanup(); \
+                       OBJ_cleanup(); EVP_cleanup(); ENGINE_cleanup(); \
                        CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); \
                        ERR_free_strings(); } while(0)
 #  else
@@ -187,7 +187,7 @@ extern BIO *bio_err;
                        setup_ui_method(); } while(0)
 #    define apps_shutdown() \
                        do { CONF_modules_unload(1); destroy_ui_method(); \
-                       EVP_cleanup(); \
+                       OBJ_cleanup(); EVP_cleanup(); \
                        CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); \
                        ERR_free_strings(); } while(0)
 #  endif
index 65b2ae34ba509f92d3b22ad9f27853fea67c8f18..0c9c351ebc38584d8c5064e20192e98cb714ff96 100644 (file)
@@ -180,6 +180,7 @@ int MAIN(int argc, char **argv)
                        {
                        if (--argc < 1) break;
                        engine= *(++argv);
+                       e = setup_engine(bio_err, engine, 0);
                        }
 #endif
                else if (strcmp(*argv,"-hex") == 0)
@@ -257,10 +258,6 @@ int MAIN(int argc, char **argv)
                goto end;
                }
 
-#ifndef OPENSSL_NO_ENGINE
-        e = setup_engine(bio_err, engine, 0);
-#endif
-
        in=BIO_new(BIO_s_file());
        bmd=BIO_new(BIO_f_md());
        if (debug)
index 88c1e780dd7694c325730ef76720868beff338c1..348df71cba23f1bfee15b147c200ebe6ea3e7a74 100644 (file)
 #include <openssl/objects.h>
 #include <openssl/x509.h>
 
+extern int obj_cleanup_defer;
+extern void check_defer(int nid);
+
 int EVP_add_cipher(const EVP_CIPHER *c)
        {
        int r;
 
        r=OBJ_NAME_add(OBJ_nid2sn(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(const char *)c);
        if (r == 0) return(0);
+       check_defer(c->nid);
        r=OBJ_NAME_add(OBJ_nid2ln(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(const char *)c);
        return(r);
        }
@@ -80,6 +84,7 @@ int EVP_add_digest(const EVP_MD *md)
        name=OBJ_nid2sn(md->type);
        r=OBJ_NAME_add(name,OBJ_NAME_TYPE_MD_METH,(const char *)md);
        if (r == 0) return(0);
+       check_defer(md->type);
        r=OBJ_NAME_add(OBJ_nid2ln(md->type),OBJ_NAME_TYPE_MD_METH,(const char *)md);
        if (r == 0) return(0);
 
@@ -88,6 +93,7 @@ int EVP_add_digest(const EVP_MD *md)
                r=OBJ_NAME_add(OBJ_nid2sn(md->pkey_type),
                        OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,name);
                if (r == 0) return(0);
+               check_defer(md->pkey_type);
                r=OBJ_NAME_add(OBJ_nid2ln(md->pkey_type),
                        OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,name);
                }
@@ -120,4 +126,9 @@ void EVP_cleanup(void)
        OBJ_NAME_cleanup(-1);
 
        EVP_PBE_cleanup();
+       if (obj_cleanup_defer == 2)
+               {
+               obj_cleanup_defer = 0;
+               OBJ_cleanup();
+               }
        }
index 7a95c7795a936ec648f14dc35d2cb200ffb48c7d..aca492d1df87f430ef8e4d91a641d99bdd149c67 100644 (file)
@@ -208,8 +208,26 @@ static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ *)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ *)
 static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ *)
 
+/* The purpose of obj_cleanup_defer is to avoid EVP_cleanup() attempting
+ * to use freed up OIDs. If neccessary the actual freeing up of OIDs is
+ * delayed.
+ */
+
+int obj_cleanup_defer = 0;
+
+void check_defer(int nid)
+       {
+       if (obj_cleanup_defer && nid >= NUM_NID)
+                       obj_cleanup_defer = 1;
+       }
+
 void OBJ_cleanup(void)
        {
+       if (obj_cleanup_defer)
+               {
+               obj_cleanup_defer = 2;
+               return ;
+               }
        if (added == NULL) return;
        added->down_load=0;
        lh_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */