Hi, I'm sorry if this has all been discussed extensively before. A brief search for "DLL hell" in the archives turns up disappointingly (and surprisingly) little. I do see a thread with messages from my erstwhile colleagues at Sun/Oracle, so I know it's been discussed, e.g., here: http://www.mail-archive.com/openssl-dev@openssl.org/msg27453.html . Recent developments, like Android's failure to properly initialize OpenSSL's PRNG make me think it's time to table (in the British sense) the issue once more.
To summarize the rest of this long post (please forgive me): There should be no need for run-time, global initialization of OpenSSL (or any sub-system of it) by applications. Moreover, any existing functions for such initialization should become no-ops or do their work just once, and in a thread-safe way. As much configuration of threading and other system libraries should be done at build-time as possible; as little should be done at run-time as possible. Even for special-purpose OSes. OpenSSL requires too much explicit and global run-time initialization of it by applications in ways that preclude (or at least used to and still might cause problems for) multiple distinct callers of OpenSSL in the same process. And yet the layered software systems we've built over the past decade result in just that happening. Typical examples include: applications that use TLS and Kerberos, PAM applications (each module might need to use OpenSSL, and so might the application), systems running without nscd (the name service switch modules may need OpenSSL, and so might the app), and so on. Are there best practices for dealing with this other than "don't do that"? (We *really* can't not do that: horse, barn door, and all that.) More to the point: why are there *any* initialization requirements at all? I can understand the need for it on some embedded systems, but on modern general-purpose operating systems there should always be: - a single threading library to depend on for locking and which includes: - a way to perform one-time initialization (e.g., POSIX's pthread_once(), Win32's InitOnceExecuteOnce()); - a decent source of entropy (but even if you must gather some on your own, measuring jitter or what have you, one-time initialization should suffice). I realize that in the past there have been a multiplicity of threading libraries (e.g., Solaris' native vs. POSIX threads, Linux's LinuxThreads vs. NPTL). But in practice these have either been unified or one has been deprecated -- for the latter case you could have OpenSSL build options for special cases, but the OpenSSL distributed by distros should be linked with the standard/dominant thread library. I also realize that on special-purpose systems the builder of OpenSSL may have to provide a thread library one way or another, but even then doing so at build-time is easier than at run-time. Another source of DLL hell besides multiple initializations in one process has been multiple dependents in one process dependning on different versions of OpenSSL that are not ABI compatible with each other. There's less that OpenSSL can do about this (besides the obvious "be ABI backwards-compatible going forward"), but distros can do some things, like use -B direct (Solaris) or versioned symbols (Linux), and this can be documented. (To be fair there are still problems with multiple instances of a library in a process, on POSIX systems anyways, because of things like POSIX file locking being insane (I'm referring to the drop-locks-on-first-close nonsense), so that two libraries (of similar or different pedigree -- doesn't matter) using POSIX file locking to synchronize access to a shared file will end up stepping on each other's toes if they run in the same process concurrently. But by and large ensuring that accidental interposition (see previous paragraph) doesn't happen should suffice for many cases. In any case, OpenSSL thankfully appears not to use POSIX file locking for anything, thank goodness.) Note the self-contradicting text in the FAQ: " * Is OpenSSL thread-safe? Yes (with limitations: an SSL connection may not concurrently be used by multiple threads). On Windows and many Unix systems, OpenSSL automatically uses the multi-threaded versions of the standard libraries. If your platform is not one of these, consult the INSTALL file. Multi-threaded applications must provide two callback functions to OpenSSL by calling CRYPTO_set_locking_callback() and CRYPTO_set_id_callback(), for all versions of OpenSSL up to and including 0.9.8[abc...]. As of version 1.0.0, CRYPTO_set_id_callback() and associated APIs are deprecated by CRYPTO_THREADID_set_callback() and friends. This is described in the threads(3) manpage. " Huh? Which is it? Must apps call CRYPTO_THREADID_set_callback() even though "[o]n Windows and many Unix systems, OpenSSL automatically uses the multi-threaded versions of the standard libraries"? Why? One would think that the "multi-threaded versions of the standard libraries" on such OSes would provide all that OpenSSL needs. I don't get it. I'll note that this: int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) { if (threadid_callback) return 0; threadid_callback = func; return 1; } is not terribly thread-safe. In practice any threads racing to call this will (hopefully) be setting callbacks that produce the same results anyways so that nothing bad should ever happen. But this really gets to the above points: more build-time / less run-time configuration would make it easier to use OpenSSL in safe ways. Also, CRYPTO_THREADID_current() seems to have a reasonable default when CRYPTO_THREADID_set_callback() has not been called. That seems to contradict part of the above FAQ text. Is the FAQ wrong? The manpage does describe the sane default behavior. It'd be better to document that there is no need to call it at all on the relevant OSes. Finally, what can I do to help? What fixes might be welcomed? Would patches to automatically initialize the PRNG on first use (and so on) be welcomed? Would patches to the docs/FAQ indicating that applications should NOT call the thread callback setting functions be welcomed? Would patches making those functions no-ops (when the build system finds/is to use standard ones) be welcomed? Nico -- ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org