Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Always build the OpenSSL shim in portable mode on macOS.
Browse files Browse the repository at this point in the history
  • Loading branch information
bartonjs committed Jan 6, 2020
1 parent 1730016 commit 70396aa
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 56 deletions.
48 changes: 21 additions & 27 deletions src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@ set(NATIVECRYPTO_SOURCES
pal_x509ext.c
)

if (FEATURE_DISTRO_AGNOSTIC_SSL)
if (NOT CMAKE_SYSTEM_NAME STREQUAL Linux)
message(FATAL_ERROR "FEATURE_DISTRO_AGNOSTIC_SSL can only be enabled for Linux")
endif()
# Always build portable on macOS because OpenSSL is not a system component
# and our prebuilts should not assume a specific ABI version for the types
# that use OpenSSL at runtime.
if (APPLE)
set(FEATURE_DISTRO_AGNOSTIC_SSL True)
endif()

if (FEATURE_DISTRO_AGNOSTIC_SSL)
list(APPEND NATIVECRYPTO_SOURCES
opensslshim.c
)
Expand All @@ -82,13 +85,20 @@ set_target_properties(System.Security.Cryptography.Native.OpenSsl-Static PROPERT
set_target_properties(System.Security.Cryptography.Native.OpenSsl-Static PROPERTIES OUTPUT_NAME System.Security.Cryptography.Native.OpenSsl CLEAN_DIRECT_OUTPUT 1)

if (FEATURE_DISTRO_AGNOSTIC_SSL)
add_custom_command(TARGET System.Security.Cryptography.Native.OpenSsl POST_BUILD
COMMENT "Verifying System.Security.Cryptography.Native.OpenSsl.so dependencies"
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-so.sh
$<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
"Verification failed. System.Security.Cryptography.Native.OpenSsl.so has undefined dependencies. These are likely OpenSSL APIs that need to be added to opensslshim.h"
VERBATIM
)
# on macOS the link step fails with undefined symbols, and the script doesn't run.
# if the build succeeds, the script would succeed, except it uses a Linux-only command.
#
# on Linux, the build will succeed with undefined symbols, then the script reports them
# and fails the build for us.
if (NOT APPLE)
add_custom_command(TARGET System.Security.Cryptography.Native.OpenSsl POST_BUILD
COMMENT "Verifying System.Security.Cryptography.Native.OpenSsl.so dependencies"
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-so.sh
$<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
"Verification failed. System.Security.Cryptography.Native.OpenSsl.so has undefined dependencies. These are likely OpenSSL APIs that need to be added to opensslshim.h"
VERBATIM
)
endif()

# Link with libdl.so to get the dlopen / dlsym / dlclose
target_link_libraries(System.Security.Cryptography.Native.OpenSsl
Expand All @@ -99,22 +109,6 @@ else()
${OPENSSL_CRYPTO_LIBRARY}
${OPENSSL_SSL_LIBRARY}
)

# On OS X every library emits the manner in which it should be referenced.
# All of our libraries are referenced via @rpath, which is similar to how Linux and Windows
# libraries are loaded. The homebrew installation of OpenSSL (libcrypto, libssl) uses the
# full path to the library installation. This means that this library is not flexible to
# users installing newer libcrypto in the working directory, or to systems which do not
# install to the same path as homebrew does.
#
# So, after compiling, rewrite the references to libcrypto to be more flexible.
if (APPLE)
add_custom_command(TARGET System.Security.Cryptography.Native.OpenSsl POST_BUILD
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib @rpath/libcrypto.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change /usr/local/opt/openssl/lib/libssl.1.0.0.dylib @rpath/libssl.1.0.0.dylib $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @loader_path $<TARGET_FILE:System.Security.Cryptography.Native.OpenSsl>
)
endif()
endif()

include(configure.cmake)
Expand Down
23 changes: 0 additions & 23 deletions src/Native/Unix/System.Security.Cryptography.Native/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1159,24 +1159,6 @@ static void LockingCallback(int mode, int n, const char* file, int line)
#pragma clang diagnostic pop
}

#ifdef __APPLE__
/*
Function:
GetCurrentThreadId
Called back by OpenSSL to get the current thread id.
This is necessary because OSX uses an earlier version of
OpenSSL, which requires setting the CRYPTO_set_id_callback.
*/
static unsigned long GetCurrentThreadId()
{
uint64_t tid;
pthread_threadid_np(pthread_self(), &tid);
return tid;
}
#endif // __APPLE__

/*
Function:
EnsureOpenSslInitialized
Expand Down Expand Up @@ -1239,11 +1221,6 @@ static int32_t EnsureOpenSsl10Initialized()
// Initialize the callback
CRYPTO_set_locking_callback(LockingCallback);

#ifdef __APPLE__
// OSX uses an earlier version of OpenSSL which requires setting the CRYPTO_set_id_callback
CRYPTO_set_id_callback(GetCurrentThreadId);
#endif

// Initialize the random number generator seed
randPollResult = RAND_poll();
if (randPollResult < 1)
Expand Down
39 changes: 33 additions & 6 deletions src/Native/Unix/System.Security.Cryptography.Native/opensslshim.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
//

#include <assert.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdbool.h>
Expand All @@ -27,10 +28,27 @@ FOR_ALL_OPENSSL_FUNCTIONS

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
#define SONAME_BASE "libssl.so."

static void* libssl = NULL;

#ifdef __APPLE__
#define DYLIBNAME_PREFIX "libssl."
#define DYLIBNAME_SUFFIX ".dylib"
#define MAKELIB(v) DYLIBNAME_PREFIX v DYLIBNAME_SUFFIX
#else
#define SONAME_BASE "libssl.so."
#define MAKELIB(v) SONAME_BASE v
#endif

static void DlOpen(const char* libraryName)
{
assert(libssl == NULL);
libssl = dlopen(libraryName, RTLD_LAZY);
#ifdef DEBUG_LIBRARY_LOAD
printf("Attempting load of %s ... %s\n", libraryName, libssl == NULL ? "failed." : "succeeded!");
#endif
}

static bool OpenLibrary()
{
// If there is an override of the version specified using the CLR_OPENSSL_VERSION_OVERRIDE
Expand All @@ -41,36 +59,45 @@ static bool OpenLibrary()

if ((versionOverride != NULL) && strnlen(versionOverride, MaxVersionStringLength + 1) <= MaxVersionStringLength)
{
#if __APPLE__
char soName[sizeof(DYLIBNAME_PREFIX) + MaxVersionStringLength + sizeof(DYLIBNAME_SUFFIX)] =
DYLIBNAME_PREFIX;

strcat(soName, versionOverride);
strcat(soName, DYLIBNAME_SUFFIX);
#else
char soName[sizeof(SONAME_BASE) + MaxVersionStringLength] = SONAME_BASE;

strcat(soName, versionOverride);
libssl = dlopen(soName, RTLD_LAZY);
#endif

DlOpen(soName);
}

if (libssl == NULL)
{
// Prefer OpenSSL 1.1.x
libssl = dlopen("libssl.so.1.1", RTLD_LAZY);
DlOpen(MAKELIB("1.1"));
}

if (libssl == NULL)
{
// Debian 9 has dropped support for SSLv3 and so they have bumped their soname. Let's try it
// before trying the version 1.0.0 to make it less probable that some of our other dependencies
// end up loading conflicting version of libssl.
libssl = dlopen("libssl.so.1.0.2", RTLD_LAZY);
DlOpen(MAKELIB("1.0.2"));
}

if (libssl == NULL)
{
// Now try the default versioned so naming as described in the OpenSSL doc
libssl = dlopen("libssl.so.1.0.0", RTLD_LAZY);
DlOpen(MAKELIB("1.0.0"));
}

if (libssl == NULL)
{
// Fedora derived distros use different naming for the version 1.0.0
libssl = dlopen("libssl.so.10", RTLD_LAZY);
DlOpen(MAKELIB("10"));
}

return libssl != NULL;
Expand Down

0 comments on commit 70396aa

Please sign in to comment.