summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorLeorize <leorize+oss@disroot.org>2020-06-03 17:02:18 -0500
committerAndreas Rumpf <rumpf_a@web.de>2020-06-06 21:11:53 +0200
commit1fb2a58674dd8136b246c7499cd295e85484d8c3 (patch)
tree4361bf2c3a6b815870ffe53325fb895dc92fe18f
parent6cb94b5da6ac409915cc0ca3f50c50214edee0ef (diff)
downloadNim-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.md9
-rw-r--r--lib/pure/net.nim3
-rw-r--r--lib/pure/ssl_config.nim51
-rw-r--r--tools/ssl_config_parser.nim62
-rw-r--r--tools/ssl_config_parser.nims1
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