Skip to content
Closed
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
23 changes: 19 additions & 4 deletions lib/plug/ssl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,25 @@ defmodule Plug.SSL do
end

defp set_strong_tls_defaults(options) do
options
|> set_managed_tls_defaults
|> keynew(:ciphers, 0, {:ciphers, @strong_tls_ciphers})
|> keynew(:versions, 0, {:versions, [:"tlsv1.3"]})
options =
options
|> set_managed_tls_defaults
|> keynew(:ciphers, 0, {:ciphers, @strong_tls_ciphers})
|> keynew(:versions, 0, {:versions, [:"tlsv1.3"]})

# secure_renegotiate and reuse_sessions are TLS 1.2 and earlier options.
# They must be removed for TLS 1.3-only configurations because OTP 28+
# validates that these options are not set when only TLS 1.3 is enabled.
# Only remove them if the final versions list has no pre-TLS 1.3 versions.
versions = options[:versions]

if Enum.any?([:tlsv1, :"tlsv1.1", :"tlsv1.2"], &(&1 in versions)) do
options
else
options
|> List.keydelete(:secure_renegotiate, 0)
|> List.keydelete(:reuse_sessions, 0)
end
end

defp set_compatible_tls_defaults(options) do
Expand Down
19 changes: 19 additions & 0 deletions test/plug/ssl_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ defmodule Plug.SSLTest do
assert opts[:honor_cipher_order] == true
assert opts[:eccs] == [:x25519, :secp256r1, :secp384r1, :secp521r1]
assert opts[:versions] == [:"tlsv1.3"]
# secure_renegotiate and reuse_sessions must NOT be set for TLS 1.3-only
# configurations, as OTP 28+ rejects these options with TLS 1.3
assert opts[:secure_renegotiate] == nil
assert opts[:reuse_sessions] == nil

assert opts[:ciphers] == [
~c"TLS_AES_256_GCM_SHA384",
Expand All @@ -50,6 +54,21 @@ defmodule Plug.SSLTest do
]
end

test "sets cipher suite to strong but preserves secure_renegotiate when TLS 1.2 is included" do
# When user overrides versions to include TLS 1.2, secure_renegotiate should be preserved
assert {:ok, opts} =
configure(
key: "abcdef",
cert: "ghijkl",
cipher_suite: :strong,
versions: [:"tlsv1.3", :"tlsv1.2"]
)

assert opts[:versions] == [:"tlsv1.3", :"tlsv1.2"]
assert opts[:secure_renegotiate] == true
assert opts[:reuse_sessions] == true
end

test "sets cipher suite to compatible" do
assert {:ok, opts} = configure(key: "abcdef", cert: "ghijkl", cipher_suite: :compatible)
assert opts[:cipher_suite] == nil
Expand Down