I appologize if this comes through twice. I haven't seen the first come through the list yet and it was sent Friday, so I presume it's been gobbled up somewhere :)


I'm working on an application that needs to work with a lot of
simultaneous SSL connections to the same remote host. It spawns a
thread for each connection and handles each connection entirely in that
thread. These connections each last anywhere from half a second to a
minute, and as soon as the connection is finished, it's closed and the
thread is terminated (and often another thread started to process
another request).
The OpenSSL library is initialized prior to any connection handling thread starting. Apparently thread safety is a FAQ, but the answer on the www.openssl.org FAQ and related links falls far short of helpful and borders on just plain inaccurate.
Initially I tried using a single SSL_CTX for all connections, so that while no SSL objects were being shared across threads, one SSL_CTX
object was being used to all calls to SSL_new(). This failed miserably.
SSL connections failed randomly and frequently during the negotation
phase. The SSL_CTX ended up getting freed on some test runs during the
middle of the run. Although there are suggestions that a single SSL_CTX
is meant to be shared between multiple connections, there isn't any
specific mention of wether that is supposed to work with connections
handled by different threads, so I suppose it's not (well it appears not
to at least).
I moved to making a new SSL_CTX for each thread as well. This had somewhat better luck, but randomly during startup one of the calls to SSL_CTX_new() would fail with "error:140A90A1:SSL
routines:SSL_CTX_new:library has no ciphers". After a bit of digging it
appears that SSL_CTX_new() is not really threadsafe either. It calls
ssl_create_cipher_list() which checks the status of an unmutexed global
variable init_ciphers (ssl/ssl_ciph.c). If the value is its
initialization value of 1, then load_ciphers() is called.
load_ciphers() sets init_ciphers to 0 and then procedes to load various
ciphers for the library to use.
Unfortunately, since this value isn't protected by a mutex it's not unlikely that in the event of two threads "racing" through SSL_CTX_new() that the lead thread will clear init_ciphers and then be interrupted before it can actually perform any loading.
For the time being I've worked around this by creating a SSL_CTX prior to starting any threads that has no point other than to prompt cipher loading before any potential race conditions.


Fixes:
I'm not sure about the SSL_CTX shared between threads, but it would be nice if the settings (CA files particularly) didn't have to be loaded from disk for each thread spawned in this scenario.
Protect init_ciphers with a mutex. Or at least move init_ciphers=0 to the end of the load_ciphers() function so that the worst case condition becomes multiple calls to load_ciphers() instead of a tiny chance of multiple calls and a larger chance of a"library has no ciphers" error.


Andrew




______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List [EMAIL PROTECTED] Automated List Manager [EMAIL PROTECTED]

Reply via email to