Skip to content

Commit

Permalink
openssl 3 support no longer opt in + some 1.0 support (nim-lang#20668)
Browse files Browse the repository at this point in the history
* Revert "Add OpenSSL 3 support (nim-lang#19814)"

This reverts commit 2dcfd73.

* openssl 3 support no longer opt in + some 1.0 support

* hopefully fix

* maybe fix

* final attempt

* actual fix hopefully
  • Loading branch information
metagn authored Oct 27, 2022
1 parent 27896ed commit e68a6ea
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 53 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/ci_packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ jobs:
valgrind libc6-dbg libblas-dev xorg-dev
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: |
brew install boehmgc make sfml gtk+3
run: brew install boehmgc make sfml gtk+3
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
Expand All @@ -71,5 +70,4 @@ jobs:

- name: 'koch, Run CI'
shell: bash
run: |
. ci/funs.sh && nimInternalBuildKochAndRunCI
run: . ci/funs.sh && nimInternalBuildKochAndRunCI
5 changes: 1 addition & 4 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@

- Removed the `nimIncrSeqV3` define.

- Static linking against OpenSSL versions below 1.1, previously done by
setting `-d:openssl10`, is no longer supported.

- `macros.getImpl` for `const` symbols now returns the full definition node
(as `nnkConstDef`) rather than the AST of the constant value.

Expand All @@ -98,7 +95,7 @@
## Standard library additions and changes

[//]: # "Changes:"
- OpenSSL version 3 is now supported by setting either `-d:sslVersion=3` or `-d:useOpenssl3`.
- OpenSSL 3 is now supported.
- `macros.parseExpr` and `macros.parseStmt` now accept an optional
filename argument for more informative errors.
- Module `colors` expanded with missing colors from the CSS color standard.
Expand Down
17 changes: 15 additions & 2 deletions lib/pure/net.nim
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,8 @@ when defineSsl:
caDir = "", caFile = ""): SslContext =
## Creates an SSL context.
##
## protVersion is currently unsed.
## Protocol version is currently ignored by default and TLS is used.
## With `-d:openssl10`, only SSLv23 and TLSv1 may be used.
##
## There are three options for verify mode:
## `CVerifyNone`: certificates are not verified;
Expand All @@ -651,7 +652,19 @@ when defineSsl:
## or using ECDSA:
## - `openssl ecparam -out mykey.pem -name secp256k1 -genkey`
## - `openssl req -new -key mykey.pem -x509 -nodes -days 365 -out mycert.pem`
let mtd = TLS_method()
var mtd: PSSL_METHOD
when defined(openssl10):
case protVersion
of protSSLv23:
mtd = SSLv23_method()
of protSSLv2:
raiseSSLError("SSLv2 is no longer secure and has been deprecated, use protSSLv23")
of protSSLv3:
raiseSSLError("SSLv3 is no longer secure and has been deprecated, use protSSLv23")
of protTLSv1:
mtd = TLSv1_method()
else:
mtd = TLS_method()
if mtd == nil:
raiseSSLError("Failed to create TLS context")
var newCTX = SSL_CTX_new(mtd)
Expand Down
128 changes: 85 additions & 43 deletions lib/wrappers/openssl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
## OpenSSL wrapper. Supports OpenSSL >= 1.1.0 dynamically (as default) or statically linked
## using `--dynlibOverride:ssl`.
##
## To use openSSL 3, either set `-d:sslVersion=3` or `-d:useOpenssl3`.
## `-d:sslVersion=1.2.3` can be used to force an SSL version.
## This version must be included in the library name.
## `-d:useOpenssl3` may be set for OpenSSL 3 instead.
##
## There is also limited support for OpenSSL 1.0.x which may require `-d:openssl10`.
##
## Build and test examples:
##
Expand Down Expand Up @@ -59,7 +63,7 @@ when sslVersion != "":
from posix import SocketHandle

elif useWinVersion:
when defined(nimOldDlls):
when defined(openssl10) or defined(nimOldDlls):
when defined(cpu64):
const
DLLSSLName* = "(ssleay32|ssleay64).dll"
Expand Down Expand Up @@ -276,40 +280,60 @@ 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"):
when compileOption("dynlibOverride", "ssl") or defined(noOpenSSLHacks):
# Static linking
when not useOpenssl3:

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 getOpenSSLVersion*(): culong =
SSLeay()

proc ERR_load_BIO_strings*() {.cdecl, dynlib: DLLUtilName, importc.}
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 TLS_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
proc TLS_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
proc SSLv23_method*(): PSSL_METHOD =
TLS_method()

proc OpenSSL_version_num(): culong {.cdecl, dynlib: DLLUtilName, importc.}
proc OpenSSL_version_num(): culong {.cdecl, dynlib: DLLUtilName, importc.}

proc getOpenSSLVersion*(): culong =
## Return OpenSSL version as unsigned long
OpenSSL_version_num()
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
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):
proc ERR_load_BIO_strings*() =
discard

when defined(libressl) or defined(openssl10):
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
SSL_state(ssl) and SSL_ST_INIT
else:
proc SSL_in_init*(ssl: SslPtr): cint {.cdecl, dynlib: DLLSSLName, importc.}
proc SSL_CTX_set_ciphersuites*(ctx: SslCtx, str: cstring): cint {.cdecl, dynlib: DLLSSLName, importc.}

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.1.*. Some
# Here we're trying to stay compatible between openssl versions. Some
# symbols are loaded dynamically and we don't use them if not found.
proc thisModule(): LibHandle {.inline.} =
var thisMod {.global.}: LibHandle
Expand Down Expand Up @@ -367,29 +391,47 @@ else:
let method2Proc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe, raises: [].}](methodSym)
return method2Proc()

when not useOpenssl3:
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_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 ERR_load_BIO_strings*() =
let theProc = cast[proc() {.cdecl.}](utilModule().symNullable("ERR_load_BIO_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"))
Expand Down Expand Up @@ -423,11 +465,6 @@ else:
theProc = cast[typeof(theProc)](sslSymThrows("SSL_CTX_set_ciphersuites"))
theProc(ctx, str)

proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLUtilName, 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.}
proc SSL_get_SSL_CTX*(ssl: SslPtr): SslCtx {.cdecl, dynlib: DLLSSLName, importc.}
Expand Down Expand Up @@ -535,8 +572,9 @@ const
useNimsAlloc = not defined(nimNoAllocForSSL) and not defined(gcDestructors)

when not useWinVersion and not defined(macosx) and not defined(android) and useNimsAlloc:
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl,
dynlib: DLLUtilName, importc.}
proc CRYPTO_set_mem_functions(a,b,c: pointer) =
let theProc = cast[proc(a,b,c: pointer) {.cdecl.}](utilModule().symNullable("CRYPTO_set_mem_functions"))
if not theProc.isNil: theProc(a, b, c)

proc allocWrapper(size: int): pointer {.cdecl.} = allocShared(size)
proc reallocWrapper(p: pointer; newSize: int): pointer {.cdecl.} =
Expand All @@ -547,9 +585,11 @@ when not useWinVersion and not defined(macosx) and not defined(android) and useN
proc deallocWrapper(p: pointer) {.cdecl.} =
if p != nil: deallocShared(p)

proc CRYPTO_malloc_init*() =
when not useWinVersion and not defined(macosx) and not defined(android) and useNimsAlloc:
proc CRYPTO_malloc_init*() =
CRYPTO_set_mem_functions(allocWrapper, reallocWrapper, deallocWrapper)
else:
proc CRYPTO_malloc_init*() =
discard

proc SSL_CTX_ctrl*(ctx: SslCtx, cmd: cint, larg: clong, parg: pointer): clong{.
cdecl, dynlib: DLLSSLName, importc.}
Expand Down Expand Up @@ -792,17 +832,19 @@ 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 =
# loadPSSLMethod("SSL_get_peer_certificate", "SSL_get1_peer_certificate")

# SSL_get_peer_certificate removed in 3.0
# SSL_get1_peer_certificate added in 3.0
when useOpenssl3:
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 SSL_get_peer_certificate*(ssl: SslCtx): PX509 =
let methodSym = sslSymNullable("SSL_get_peer_certificate", "SSL_get1_peer_certificate")
if methodSym.isNil:
raise newException(LibraryError, "Could not load SSL_get_peer_certificate or SSL_get1_peer_certificate")
let method2Proc = cast[proc(ssl: SslCtx): PX509 {.cdecl, gcsafe, raises: [].}](methodSym)
return method2Proc(ssl)

proc X509_get_subject_name*(a: PX509): PX509_NAME{.cdecl, dynlib: DLLSSLName, importc.}

Expand Down

0 comments on commit e68a6ea

Please sign in to comment.