Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libraries/System.Net.Http/src/System.Net.Http.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-freebsd;$(NetCoreAppCurrent)-maccatalyst;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-browser;$(NetCoreAppCurrent)-wasi;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-solaris;$(NetCoreAppCurrent)-haiku;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-freebsd;$(NetCoreAppCurrent)-openbsd;$(NetCoreAppCurrent)-maccatalyst;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-browser;$(NetCoreAppCurrent)-wasi;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-solaris;$(NetCoreAppCurrent)-haiku;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the linux/freebsd/openbsd/solaris/haiku builds any different from one another?

For cryptography we build "unix", and then special variants for macOS-nee-OSX and friends.

<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-browser;$(NetCoreAppCurrent)</TargetFrameworks>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some "platform specific" blocks:

$ git grep -niE 'linux|haiku|solaris|osx|apple|illumos|bsd' -- ':/src/libraries/System.Net.Http/src/*cs'
src/libraries/System.Net.Http/src/System/Net/Http/GlobalHttpSettings.cs:44:            [SupportedOSPlatformGuard("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/GlobalHttpSettings.cs:51:                (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS());
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs:112:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs:152:                // Resolving a non-existent hostname often leads to EAI_AGAIN/TryAgain on Linux, indicating a non-authoritative failure, eg. timeout.
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs:153:                // Getting EAGAIN/TryAgain from a TCP connect() is not possible on Windows or Mac according to the docs and indicates lack of kernel resources on Linux,
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:61:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:129:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:204:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:243:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:326:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:357:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:479:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:522:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:558:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.Http3.cs:759:#if !ILLUMOS && !SOLARIS && !HAIKU
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectionPool/HttpConnectionPool.cs:278:                // It breaks TLS resume on Linux
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs:18:    [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs:20:    [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs:47:#if !ILLUMOS && !SOLARIS && !HAIKU
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs:142:#if !ILLUMOS && !SOLARIS && !HAIKU
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs:460:#if !ILLUMOS && !SOLARIS && !HAIKU
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs:153:        [SupportedOSPlatform("linux")]
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SystemProxyInfo.OSX.cs:8:        // On OSX we get default proxy configuration from either environment variables or the OSX system proxy.
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SystemProxyInfo.Unix.cs:8:        // On Unix (except for OSX) we get default proxy configuration from environment variables. If the

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>$(DefineConstants);HTTP_DLL</DefineConstants>
<UseCompilerGeneratedDocXmlFile>false</UseCompilerGeneratedDocXmlFile>
Expand Down
105 changes: 105 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/opensslshim.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
#include <stdio.h>
#include <string.h>

#if defined(__OpenBSD__)
#include <dirent.h>
#include <limits.h>
#include <stdlib.h>
#endif

#include "opensslshim.h"
#include "pal_atomic.h"

Expand Down Expand Up @@ -54,6 +60,80 @@ static void DlOpen(const char* libraryName)
}
}

#if defined(__OpenBSD__)
// OpenBSD's base system ships LibreSSL, which does not implement the full
// OpenSSL 3.x surface the shim requires. The OpenSSL ports install in parallel
// under /usr/local/lib/eopenssl<NN>/, where <NN> is the OpenSSL version (e.g.
// eopenssl35 for OpenSSL 3.5). Each directory ships libssl with its own SONAME
// (for example libssl.so.37.0), bumped independently of the version number, so
// the SONAME is discovered within the requested directory rather than hardcoded.
// The library is opened by absolute path so the matching libcrypto resolves via
// the library's RUNPATH.
static void DlOpenEOpenSsl(const char* eopensslVersion)
{
static const char libDir[] = "/usr/local/lib";
static const char dirPrefix[] = "eopenssl";
static const char sslPrefix[] = "libssl.so.";

char dirPath[PATH_MAX];
int written = snprintf(dirPath, sizeof(dirPath), "%s/%s%s", libDir, dirPrefix, eopensslVersion);
if (written < 0 || (size_t)written >= sizeof(dirPath))
{
return;
}

DIR* dir = opendir(dirPath);
if (dir == NULL)
{
return;
}

// Pick the highest libssl.so.<major>.<minor> in case more than one is present.
char libName[NAME_MAX + 1] = { 0 };
long bestMajor = -1;
long bestMinor = -1;
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
if (strncmp(entry->d_name, sslPrefix, sizeof(sslPrefix) - 1) != 0)
{
continue;
}

const char* version = entry->d_name + sizeof(sslPrefix) - 1;
char* end;
long major = strtol(version, &end, 10);
if (end == version)
{
continue;
}

long minor = (*end == '.') ? strtol(end + 1, &end, 10) : 0;
if (major > bestMajor || (major == bestMajor && minor > bestMinor))
{
bestMajor = major;
bestMinor = minor;
strncpy(libName, entry->d_name, sizeof(libName) - 1);
}
}
closedir(dir);

if (libName[0] == '\0')
{
return;
}

char libPath[PATH_MAX];
written = snprintf(libPath, sizeof(libPath), "%s/%s", dirPath, libName);
if (written < 0 || (size_t)written >= sizeof(libPath))
{
return;
}

DlOpen(libPath);
}
#endif

static void OpenLibraryOnce(void)
{
// If there is an override of the version specified using the DOTNET_OPENSSL_VERSION_OVERRIDE
Expand All @@ -64,9 +144,14 @@ static void OpenLibraryOnce(void)

if ((versionOverride != NULL) && strnlen(versionOverride, MaxVersionStringLength + 1) <= MaxVersionStringLength)
{
#if defined(__OpenBSD__)
// On OpenBSD the override selects the eopenssl<NN> ports directory.
DlOpenEOpenSsl(versionOverride);
#else
char soName[sizeof(SONAME_BASE) + MaxVersionStringLength] = SONAME_BASE;
strcat(soName, versionOverride);
DlOpen(soName);
#endif
}

#ifdef TARGET_ANDROID
Expand Down Expand Up @@ -111,6 +196,26 @@ static void OpenLibraryOnce(void)
{
DlOpen(MAKELIB("111"));
}
#elif defined(__OpenBSD__)
// OpenBSD base is LibreSSL; load the OpenSSL ports build from /usr/local/lib/eopenssl<NN>.
// Probe the known package directories explicitly, preferring 3.x and trying 4.0 last.
if (libssl == NULL)
{
// OpenSSL 3.6 from ports
DlOpenEOpenSsl("36");
}

if (libssl == NULL)
{
// OpenSSL 3.5 from ports
DlOpenEOpenSsl("35");
}

if (libssl == NULL)
{
// OpenSSL 4.0 from ports (probed but not preferred)
DlOpenEOpenSsl("40");
}
#endif

if (libssl == NULL)
Expand Down