In our setup we've been sharing a SSL_CTX between different threads
(I'll admit that I don't quite know whether that is allowed) and have
run into the following problem:
X509_STORE_get_by_subject is called to load a CA cert by both thread 1
and thread 2. It checks for the certs existence in the cert store in
both 1 & 2. Since no locks are taken at the X509_STORE_get_by_subject
level, both test return not found and both threads read the credential
and try to add it to the store. Adding is serialized by a lock so one of
these adds will fail with X509_R_CERT_ALREADY_IN_HASH_TABLE, which seems
to cause a handshake failure. The attached patch fixes this, but again,
maybe it's illegal to share SSL_CTX between threads. A better solution
may also be to take the SSL_CTX mutex in either
X509_STORE_get_by_subject or its callers.
/Sam
Index: by_file.c
===================================================================
RCS file: /home/globdev/CVS/globus-packages/gsi/openssl_gpt/crypto/x509/by_file.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 by_file.c
--- by_file.c 2002/03/01 15:25:50 1.1.1.1
+++ by_file.c 2002/09/19 06:05:59
@@ -163,7 +163,18 @@
}
}
i=X509_STORE_add_cert(ctx->store_ctx,x);
- if (!i) goto err;
+ if (!i)
+ {
+ if ((ERR_GET_REASON(ERR_peek_error()) ==
+ X509_R_CERT_ALREADY_IN_HASH_TABLE))
+ {
+ ERR_clear_error();
+ }
+ else
+ {
+ goto err;
+ }
+ }
count++;
X509_free(x);
x=NULL;
@@ -179,8 +190,19 @@
goto err;
}
i=X509_STORE_add_cert(ctx->store_ctx,x);
- if (!i) goto err;
- ret=i;
+ if (!i)
+ {
+ if ((ERR_GET_REASON(ERR_peek_error()) ==
+ X509_R_CERT_ALREADY_IN_HASH_TABLE))
+ {
+ ERR_clear_error();
+ }
+ else
+ {
+ goto err;
+ }
+ }
+ ret=1;
}
else
{