Skip to content
Merged
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
6 changes: 6 additions & 0 deletions lib/mongo/uri.rb
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,12 @@ def validate_uri_options!
# 'tls' and 'ssl'. In order to fulfill this, we parse the values of each instance into an
# array; assuming all values in the array are the same, we replace the array with that value.
unless uri_options[:ssl].nil? || uri_options[:ssl].empty?
# A nil element means an invalid value (e.g. tls=yes) was supplied.
# Refuse it rather than silently connecting over plaintext (RUBY-3832).
if uri_options[:ssl].include?(nil)
raise_invalid_error_no_fmt!("invalid boolean value for 'tls' or 'ssl'; only 'true' and 'false' are accepted")
end

unless uri_options[:ssl].uniq.length == 1
raise_invalid_error_no_fmt!("all instances of 'tls' and 'ssl' must have the same value")
end
Expand Down
22 changes: 17 additions & 5 deletions lib/mongo/uri/options_mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,25 @@ def stringify_bool(value)

# Converts the value into a boolean and returns it wrapped in an array.
#
# @param [ String ] name Name of the URI option being processed.
# tls and ssl are the only repeated_bool options. An invalid value is
# preserved as a nil element rather than warned-and-dropped, so that
# URI#validate_uri_options! can detect it and raise instead of silently
# falling back to a plaintext connection (RUBY-3832).
#
# @param [ String ] _name Name of the URI option being processed.
# @param [ String ] value URI option value.
#
Comment thread
comandeo-mongo marked this conversation as resolved.
# @return [ Array<true | false> | nil ] The boolean value parsed and wraped
# in an array.
def convert_repeated_bool(name, value)
[ convert_bool(name, value) ]
# @return [ Array<true | false | nil> ] The boolean value parsed and
# wrapped in an array.
def convert_repeated_bool(_name, value)
case value
when true, 'true', 'TRUE'
[ true ]
when false, 'false', 'FALSE'
[ false ]
else
[ nil ]
end
end

# Reverts a repeated boolean type.
Expand Down
19 changes: 17 additions & 2 deletions spec/mongo/uri_option_parsing_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@
end
end

# TLS boolean options must fail loudly on an invalid value: an unrecognized
# value such as 'yes' or '1' would otherwise be discarded and the connection
# would silently fall back to plaintext (RUBY-3832).
shared_examples_for 'a strict boolean option' do
it_behaves_like 'a boolean option'

%w[ yes no 1 0 on off invalid ].each do |bad_value|
context "is #{bad_value}" do
let(:string) { "mongodb://example.com/?#{uri_option}=#{bad_value}" }

it_behaves_like 'raises parse error'
end
end
end

shared_examples_for 'an inverted boolean option' do
let(:string) { "mongodb://example.com/?#{uri_option}=true" }

Expand Down Expand Up @@ -460,14 +475,14 @@
let(:uri_option) { 'ssl' }
let(:ruby_option) { :ssl }

it_behaves_like 'a boolean option'
it_behaves_like 'a strict boolean option'
end

context 'tls' do
let(:uri_option) { 'tls' }
let(:ruby_option) { :ssl }

it_behaves_like 'a boolean option'
it_behaves_like 'a strict boolean option'
end

context 'tlsAllowInvalidCertificates' do
Expand Down
Loading