diff options
author | Leorize <leorize+oss@disroot.org> | 2020-06-03 17:02:18 -0500 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2020-06-06 21:11:53 +0200 |
commit | 1fb2a58674dd8136b246c7499cd295e85484d8c3 (patch) | |
tree | 4361bf2c3a6b815870ffe53325fb895dc92fe18f | |
parent | 6cb94b5da6ac409915cc0ca3f50c50214edee0ef (diff) | |
download | Nim-1fb2a58674dd8136b246c7499cd295e85484d8c3.tar.gz |
net: use a secure cipher list by default
Previously, the `net` module use the blanket "ALL" as the default cipher list. This list may contain security ciphers that are weak and/or outdated according to the current standard. This commit introduces a new module `ssl_config` that contains the latest OpenSSL configurations as recommended by Mozilla OpSec, and make the `net` module use the cipher list targeting `intermediate` compatibility level as the default.
-rw-r--r-- | changelog.md | 9 | ||||
-rw-r--r-- | lib/pure/net.nim | 3 | ||||
-rw-r--r-- | lib/pure/ssl_config.nim | 51 | ||||
-rw-r--r-- | tools/ssl_config_parser.nim | 62 | ||||
-rw-r--r-- | tools/ssl_config_parser.nims | 1 |
5 files changed, 125 insertions, 1 deletions
diff --git a/changelog.md b/changelog.md index 25fc3535c..e20077feb 100644 --- a/changelog.md +++ b/changelog.md @@ -99,6 +99,15 @@ - `osproc.execCmdEx` now takes an optional `input` for stdin, `workingDir` and `env` parameters. +- Add `ssl_config` module containing lists of secure ciphers as recommended by + [Mozilla OpSec](https://wiki.mozilla.org/Security/Server_Side_TLS) + +- `net.newContext` now uses the list of ciphers targeting + ["Intermediate compatibility"](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29) + per Mozilla's recommendation instead of `ALL`. This change should protect + users from the use of weak and insecure ciphers while still provides + adequate compatiblity with the majority of the Internet. + ## Language changes - In the newruntime it is now allowed to assign discriminator field without restrictions as long as case object doesn't have custom destructor. Discriminator value doesn't have to be a constant either. If you have custom destructor for case object and you do want to freely assign discriminator fields, it is recommended to refactor object into 2 objects like this: diff --git a/lib/pure/net.nim b/lib/pure/net.nim index af66c3a15..a5643330e 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -68,6 +68,7 @@ import std/private/since import nativesockets, os, strutils, times, sets, options, std/monotimes from ssl_certs import scanSSLCertificates +import ssl_config export nativesockets.Port, nativesockets.`$`, nativesockets.`==` export Domain, SockType, Protocol @@ -533,7 +534,7 @@ when defineSsl: raiseSSLError("Verification of private key file failed.") proc newContext*(protVersion = protSSLv23, verifyMode = CVerifyPeer, - certFile = "", keyFile = "", cipherList = "ALL", + certFile = "", keyFile = "", cipherList = CiphersIntermediate, caDir = "", caFile = ""): SSLContext = ## Creates an SSL context. ## diff --git a/lib/pure/ssl_config.nim b/lib/pure/ssl_config.nim new file mode 100644 index 000000000..14f66ede4 --- /dev/null +++ b/lib/pure/ssl_config.nim @@ -0,0 +1,51 @@ +# This file was automatically generated by tools/ssl_config_parser on 2020-06-03T22:02:05Z. DO NOT EDIT. + +## This module contains SSL configuration parameters obtained from +## `Mozilla OpSec <https://wiki.mozilla.org/Security/Server_Side_TLS>`_. +## +## The configuration file used to generate this module: https://ssl-config.mozilla.org/guidelines/5.4.json + +const CiphersModern* = "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" + ## An OpenSSL-compatible list of secure ciphers for ``modern`` compatibility + ## per Mozilla's recommendations. + ## + ## Oldest clients supported by this list: + ## * Firefox 63 + ## * Android 10.0 + ## * Chrome 70 + ## * Edge 75 + ## * Java 11 + ## * OpenSSL 1.1.1 + ## * Opera 57 + ## * Safari 12.1 + +const CiphersIntermediate* = "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384" + ## An OpenSSL-compatible list of secure ciphers for ``intermediate`` compatibility + ## per Mozilla's recommendations. + ## + ## Oldest clients supported by this list: + ## * Firefox 27 + ## * Android 4.4.2 + ## * Chrome 31 + ## * Edge + ## * IE 11 on Windows 7 + ## * Java 8u31 + ## * OpenSSL 1.0.1 + ## * Opera 20 + ## * Safari 9 + +const CiphersOld* = "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA" + ## An OpenSSL-compatible list of secure ciphers for ``old`` compatibility + ## per Mozilla's recommendations. + ## + ## Oldest clients supported by this list: + ## * Firefox 1 + ## * Android 2.3 + ## * Chrome 1 + ## * Edge 12 + ## * IE8 on Windows XP + ## * Java 6 + ## * OpenSSL 0.9.8 + ## * Opera 5 + ## * Safari 1 + diff --git a/tools/ssl_config_parser.nim b/tools/ssl_config_parser.nim new file mode 100644 index 000000000..d13ea1ee2 --- /dev/null +++ b/tools/ssl_config_parser.nim @@ -0,0 +1,62 @@ +# +# +# SSL configuration generator +# (c) Copyright 2020 Leorize <leorize+oss@disroot.org> +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +import httpclient, json, net, strformat, strutils, sequtils, times + +const + ConfigSource = "https://ssl-config.mozilla.org/guidelines/latest.json" + OutputFile = "ssl_config.nim" + +func appendToList(list, str: string): string = + if list.len == 0: + result = str + elif str.len == 0: + result = list + else: + result = list & ':' & str + +proc main() = + let + client = newHttpClient(sslContext = newContext(verifyMode = CVerifyPeer)) + resp = client.get(ConfigSource) + defer: client.close() + if not resp.code.is2xx: + quit "Couldn't fetch configuration, server returned: " & $resp.code + + let configs = resp.bodyStream.parseJson("ssl-config.json") + + let generationTime = now().utc() + let output = open(OutputFile, fmWrite) + echo "Generating ", OutputFile + output.writeLine(&""" +# This file was automatically generated by tools/ssl_config_parser on {generationTime}. DO NOT EDIT. + +## This module contains SSL configuration parameters obtained from +## `Mozilla OpSec <https://wiki.mozilla.org/Security/Server_Side_TLS>`_. +## +## The configuration file used to generate this module: {configs["href"].getStr} +""") + + for name, config in configs["configurations"]: + let + constantName = "Ciphers" & name[0].toUpperAscii & name[1..^1] + ciphers = config["ciphersuites"].foldl(a.appendToList b.getStr, "").appendToList( + config["ciphers"]["openssl"].foldl(a.appendToList b.getStr, "") + ) + oldestClients = config["oldest_clients"].foldl(a & "\n ## * " & b.getStr, "") + + output.writeLine(&""" +const {constantName}* = "{ciphers}" + ## An OpenSSL-compatible list of secure ciphers for ``{name}`` compatibility + ## per Mozilla's recommendations. + ## + ## Oldest clients supported by this list:{oldestClients} +""") + +when isMainModule: main() diff --git a/tools/ssl_config_parser.nims b/tools/ssl_config_parser.nims new file mode 100644 index 000000000..796d18894 --- /dev/null +++ b/tools/ssl_config_parser.nims @@ -0,0 +1 @@ +--d:ssl |