Add OpenSSL 3 support (#19814)
* Minor refactor * Add OpenSSL 3 support Remove symbols noOpenSSLHacksq and openssl10 * Drop loading of older openssl versions * Add library path * Use only versioned libssl soname os OSX * Update .github/workflows/ci_packages.yml Co-authored-by: Hein Thant <official.heinthanth@gmail.com> * On Mac OS X CI, link OpenSSL in /usr/local/lib/ * Install OpenSSL on Mac OS X on azure pipeline * Remove DYLD_LIBRARY_PATH Co-authored-by: Hein Thant <official.heinthanth@gmail.com> Co-authored-by: Andreas Rumpf <rumpf_a@web.de> Co-authored-by: Hein Thant <official.heinthanth@gmail.com>
This commit is contained in:
parent
d1d141b135
commit
2dcfd73260
5 changed files with 117 additions and 139 deletions
|
|
@ -7,27 +7,30 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## OpenSSL support
|
||||
## OpenSSL wrapper. Supports OpenSSL >= 1.1.0 dynamically (as default) or statically linked
|
||||
## using `--dynlibOverride:ssl`.
|
||||
##
|
||||
## When OpenSSL is dynamically linked, the wrapper provides partial forward and backward
|
||||
## compatibility for OpenSSL versions above and below 1.1.0
|
||||
##
|
||||
## OpenSSL can also be statically linked using `--dynlibOverride:ssl` for OpenSSL >= 1.1.0.
|
||||
## If you want to statically link against OpenSSL 1.0.x, you now have to
|
||||
## define the `openssl10` symbol via `-d:openssl10`.
|
||||
## To use openSSL 3 set the symbol: -d:sslVersion=3
|
||||
##
|
||||
## Build and test examples:
|
||||
##
|
||||
## .. code-block::
|
||||
## ./bin/nim c -d:ssl -p:. -r tests/stdlib/tssl.nim
|
||||
## ./bin/nim c -d:ssl --threads:on -p:. -r tests/stdlib/thttpclient_ssl.nim
|
||||
## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
|
||||
## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passl:-lcrypto --passl:-lssl -r tests/untestable/tssl.nim
|
||||
## ./bin/nim r --putenv:NIM_TESTAMENT_REMOTE_NETWORKING:1 -d:ssl -p:testament/lib --threads:on tests/untestable/thttpclient_ssl_remotenetwork.nim
|
||||
|
||||
# https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html
|
||||
#
|
||||
from strutils import startsWith
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.push styleChecks: off.}
|
||||
|
||||
const useWinVersion = defined(windows) or defined(nimdoc)
|
||||
|
||||
# To force openSSL version use -d:sslVersion=1.0.0
|
||||
# To force openSSL version use -d:sslVersion=1.2.3
|
||||
# See: #10281, #10230
|
||||
# General issue:
|
||||
# Other dynamic libraries (like libpg) load different openSSL version then what nim loads.
|
||||
|
|
@ -52,7 +55,7 @@ when sslVersion != "":
|
|||
from posix import SocketHandle
|
||||
|
||||
elif useWinVersion:
|
||||
when defined(openssl10) or defined(nimOldDlls):
|
||||
when defined(nimOldDlls):
|
||||
when defined(cpu64):
|
||||
const
|
||||
DLLSSLName* = "(ssleay32|ssleay64).dll"
|
||||
|
|
@ -72,10 +75,11 @@ elif useWinVersion:
|
|||
|
||||
from winlean import SocketHandle
|
||||
else:
|
||||
when defined(osx):
|
||||
const versions = "(.1.1|.38|.39|.41|.43|.44|.45|.46|.47|.48|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
|
||||
when defined(macosx):
|
||||
# use only versioned soname
|
||||
const versions = ".1.1"
|
||||
else:
|
||||
const versions = "(.1.1|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|.48|.47|.46|.45|.44|.43|.41|.39|.38|.10|)"
|
||||
const versions = "(.1.1|.48|.47|.46|.45|.44|.43|.41|.39|.38|.10|)"
|
||||
|
||||
when defined(macosx):
|
||||
const
|
||||
|
|
@ -268,40 +272,24 @@ proc TLSv1_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
|||
# and support SSLv3, TLSv1, TLSv1.1 and TLSv1.2
|
||||
# SSLv23_method(), SSLv23_server_method(), SSLv23_client_method() are removed in 1.1.0
|
||||
|
||||
when compileOption("dynlibOverride", "ssl") or defined(noOpenSSLHacks):
|
||||
when compileOption("dynlibOverride", "ssl"):
|
||||
# Static linking
|
||||
|
||||
when defined(openssl10):
|
||||
proc SSL_library_init*(): cint {.cdecl, dynlib: DLLSSLName, importc, discardable.}
|
||||
proc SSL_load_error_strings*() {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSLv23_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSLeay(): culong {.cdecl, dynlib: DLLUtilName, importc.}
|
||||
proc TLS_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc getOpenSSLVersion*(): culong =
|
||||
SSLeay()
|
||||
else:
|
||||
proc OPENSSL_init_ssl*(opts: uint64, settings: uint8): cint {.cdecl, dynlib: DLLSSLName, importc, discardable.}
|
||||
proc SSL_library_init*(): cint {.discardable.} =
|
||||
## Initialize SSL using OPENSSL_init_ssl for OpenSSL >= 1.1.0
|
||||
return OPENSSL_init_ssl(0.uint64, 0.uint8)
|
||||
proc OpenSSL_version_num(): culong {.cdecl, dynlib: DLLUtilName, importc.}
|
||||
|
||||
proc TLS_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSLv23_method*(): PSSL_METHOD =
|
||||
TLS_method()
|
||||
proc getOpenSSLVersion*(): culong =
|
||||
## Return OpenSSL version as unsigned long
|
||||
OpenSSL_version_num()
|
||||
|
||||
proc OpenSSL_version_num(): culong {.cdecl, dynlib: DLLUtilName, importc.}
|
||||
proc SSL_load_error_strings*() =
|
||||
## Removed from OpenSSL 1.1.0
|
||||
# This proc prevents breaking existing code calling SslLoadErrorStrings
|
||||
# Static linking against OpenSSL < 1.1.0 is not supported
|
||||
discard
|
||||
|
||||
proc getOpenSSLVersion*(): culong =
|
||||
## Return OpenSSL version as unsigned long
|
||||
OpenSSL_version_num()
|
||||
|
||||
proc SSL_load_error_strings*() =
|
||||
## Removed from OpenSSL 1.1.0
|
||||
# This proc prevents breaking existing code calling SslLoadErrorStrings
|
||||
# Static linking against OpenSSL < 1.1.0 is not supported
|
||||
discard
|
||||
|
||||
when defined(libressl) or defined(openssl10):
|
||||
when defined(libressl):
|
||||
proc SSL_state(ssl: SslPtr): cint {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSL_in_init*(ssl: SslPtr): cint {.inline.} =
|
||||
SSl_state(ssl) and SSL_ST_INIT
|
||||
|
|
@ -311,12 +299,8 @@ when compileOption("dynlibOverride", "ssl") or defined(noOpenSSLHacks):
|
|||
|
||||
template OpenSSL_add_all_algorithms*() = discard
|
||||
|
||||
proc SSLv23_client_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSLv2_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSLv3_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
else:
|
||||
# Here we're trying to stay compatible with openssl 1.0.* and 1.1.*. Some
|
||||
# Here we're trying to stay compatible with openssl 1.1.*. Some
|
||||
# symbols are loaded dynamically and we don't use them if not found.
|
||||
proc thisModule(): LibHandle {.inline.} =
|
||||
var thisMod {.global.}: LibHandle
|
||||
|
|
@ -324,9 +308,12 @@ else:
|
|||
|
||||
result = thisMod
|
||||
|
||||
proc sslModule(): LibHandle {.inline.} =
|
||||
proc sslModule(): LibHandle {.inline, raises: [LibraryError], tags:[RootEffect].} =
|
||||
var sslMod {.global.}: LibHandle
|
||||
if sslMod.isNil: sslMod = loadLibPattern(DLLSSLName)
|
||||
try:
|
||||
if sslMod.isNil: sslMod = loadLibPattern(DLLSSLName)
|
||||
except:
|
||||
raise newException(LibraryError, "Could not load SSL using " & DLLSSLName)
|
||||
|
||||
result = sslMod
|
||||
|
||||
|
|
@ -351,63 +338,37 @@ else:
|
|||
if result.isNil and alternativeName.len > 0:
|
||||
result = symAddr(thisDynlib, alternativeName)
|
||||
|
||||
proc sslSymNullable(name: string, alternativeName = ""): pointer =
|
||||
proc sslSymNullable(name: string, alternativeName = ""): pointer {.raises: [LibraryError], tags:[RootEffect].} =
|
||||
sslModule().symNullable(name, alternativeName)
|
||||
|
||||
proc sslSymThrows(name: string, alternativeName = ""): pointer =
|
||||
proc sslSymThrows(name: string, alternativeName = ""): pointer {.raises: [LibraryError].} =
|
||||
result = sslSymNullable(name, alternativeName)
|
||||
if result.isNil: raiseInvalidLibrary(name)
|
||||
|
||||
proc utilSymNullable(name: string, alternativeName = ""): pointer =
|
||||
utilModule().symNullable(name, alternativeName)
|
||||
|
||||
proc loadPSSLMethod(method1, method2: string): PSSL_METHOD =
|
||||
proc loadPSSLMethod(method1, method2: string): PSSL_METHOD {.raises: [LibraryError], tags:[RootEffect].} =
|
||||
## Load <method1> from OpenSSL if available, otherwise <method2>
|
||||
##
|
||||
let methodSym = sslSymNullable(method1, method2)
|
||||
if methodSym.isNil:
|
||||
raise newException(LibraryError, "Could not load " & method1 & " nor " & method2)
|
||||
|
||||
let method2Proc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](methodSym)
|
||||
let method2Proc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe, raises: [].}](methodSym)
|
||||
return method2Proc()
|
||||
|
||||
proc SSL_library_init*(): cint {.discardable.} =
|
||||
## Initialize SSL using OPENSSL_init_ssl for OpenSSL >= 1.1.0 otherwise
|
||||
## SSL_library_init
|
||||
let newInitSym = sslSymNullable("OPENSSL_init_ssl")
|
||||
if not newInitSym.isNil:
|
||||
let newInitProc =
|
||||
cast[proc(opts: uint64, settings: uint8): cint {.cdecl.}](newInitSym)
|
||||
return newInitProc(0, 0)
|
||||
let olderProc = cast[proc(): cint {.cdecl.}](sslSymThrows("SSL_library_init"))
|
||||
if not olderProc.isNil: result = olderProc()
|
||||
|
||||
proc SSL_load_error_strings*() =
|
||||
# TODO: Are we ignoring this on purpose? SSL GitHub CI fails otherwise.
|
||||
let theProc = cast[proc() {.cdecl.}](sslSymNullable("SSL_load_error_strings"))
|
||||
if not theProc.isNil: theProc()
|
||||
|
||||
proc SSLv23_client_method*(): PSSL_METHOD =
|
||||
loadPSSLMethod("SSLv23_client_method", "TLS_client_method")
|
||||
|
||||
proc SSLv23_method*(): PSSL_METHOD =
|
||||
loadPSSLMethod("SSLv23_method", "TLS_method")
|
||||
|
||||
proc SSLv2_method*(): PSSL_METHOD =
|
||||
loadPSSLMethod("SSLv2_method", "TLS_method")
|
||||
|
||||
proc SSLv3_method*(): PSSL_METHOD =
|
||||
loadPSSLMethod("SSLv3_method", "TLS_method")
|
||||
|
||||
proc TLS_method*(): PSSL_METHOD =
|
||||
loadPSSLMethod("TLS_method", "SSLv23_method")
|
||||
|
||||
proc TLS_client_method*(): PSSL_METHOD =
|
||||
loadPSSLMethod("TLS_client_method", "SSLv23_client_method")
|
||||
|
||||
proc TLS_server_method*(): PSSL_METHOD =
|
||||
loadPSSLMethod("TLS_server_method", "SSLv23_server_method")
|
||||
|
||||
proc OpenSSL_add_all_algorithms*() =
|
||||
# TODO: Are we ignoring this on purpose? SSL GitHub CI fails otherwise.
|
||||
let theProc = cast[proc() {.cdecl.}](sslSymNullable("OPENSSL_add_all_algorithms_conf"))
|
||||
|
|
@ -441,7 +402,11 @@ else:
|
|||
theProc = cast[typeof(theProc)](sslSymThrows("SSL_CTX_set_ciphersuites"))
|
||||
theProc(ctx, str)
|
||||
|
||||
proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLUtilName, importc.}
|
||||
|
||||
proc OPENSSL_init_ssl*(opts: uint64, settings: uint8): cint {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc TLS_client_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
|
||||
proc SSL_new*(context: SslCtx): SslPtr{.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSL_free*(ssl: SslPtr){.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
|
@ -804,8 +769,17 @@ when defined(nimHasStyleChecks):
|
|||
# On old openSSL version some of these symbols are not available
|
||||
when not defined(nimDisableCertificateValidation) and not defined(windows):
|
||||
|
||||
proc SSL_get_peer_certificate*(ssl: SslCtx): PX509{.cdecl, dynlib: DLLSSLName,
|
||||
importc.}
|
||||
# proc SSL_get_peer_certificate*(ssl: SslCtx): PX509 =
|
||||
# loadPSSLMethod("SSL_get_peer_certificate", "SSL_get1_peer_certificate")
|
||||
|
||||
when sslVersion.startsWith('3'):
|
||||
proc SSL_get1_peer_certificate*(ssl: SslCtx): PX509 {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSL_get_peer_certificate*(ssl: SslCtx): PX509 =
|
||||
SSL_get1_peer_certificate(ssl)
|
||||
|
||||
else:
|
||||
proc SSL_get_peer_certificate*(ssl: SslCtx): PX509 {.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
|
||||
proc X509_get_subject_name*(a: PX509): PX509_NAME{.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue