Skip to content

Commit b157cc9

Browse files
committed
Merge pull request #2689 from jhass/tls_verify
Turn on TLS client certificate validation by default, expose OpenSSL::SSL::Context in HTTP::Client
2 parents 23bc3e8 + d7ff730 commit b157cc9

File tree

10 files changed

+401
-169
lines changed

10 files changed

+401
-169
lines changed

spec/std/http/client/client_spec.cr

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,47 @@ module HTTP
4848

4949
describe "from URI" do
5050
it "has sane defaults" do
51-
cl = Client.new(URI.parse("http://demo.com"))
52-
cl.ssl?.should be_false
51+
cl = Client.new(URI.parse("http://example.com"))
52+
cl.ssl?.should be_nil
5353
cl.port.should eq(80)
5454
end
5555

56-
it "detects ssl" do
57-
cl = Client.new(URI.parse("https://demo.com"))
58-
cl.ssl?.should be_true
59-
cl.port.should eq(443)
60-
end
56+
ifdef !without_openssl
57+
it "detects ssl" do
58+
cl = Client.new(URI.parse("https://example.com"))
59+
cl.ssl?.should be_truthy
60+
cl.port.should eq(443)
61+
end
62+
63+
it "keeps context" do
64+
ctx = OpenSSL::SSL::Context::Client.new
65+
cl = Client.new(URI.parse("https://example.com"), ctx)
66+
cl.ssl.should be(ctx)
67+
end
6168

62-
it "allows for specified ports" do
63-
cl = Client.new(URI.parse("https://demo.com:9999"))
64-
cl.ssl?.should be_true
65-
cl.port.should eq(9999)
69+
it "doesn't take context for HTTP" do
70+
ctx = OpenSSL::SSL::Context::Client.new
71+
expect_raises(ArgumentError, "SSL context given") do
72+
Client.new(URI.parse("http://example.com"), ctx)
73+
end
74+
end
75+
76+
it "allows for specified ports" do
77+
cl = Client.new(URI.parse("https://example.com:9999"))
78+
cl.ssl?.should be_truthy
79+
cl.port.should eq(9999)
80+
end
81+
else
82+
it "raises when trying to activate SSL" do
83+
expect_raises do
84+
Client.new "example.org", 443, ssl: true
85+
end
86+
end
6687
end
6788

6889
it "raises error if not http schema" do
6990
expect_raises(ArgumentError, "Unsupported scheme: ssh") do
70-
Client.new(URI.parse("ssh://demo.com"))
91+
Client.new(URI.parse("ssh://example.com"))
7192
end
7293
end
7394

spec/std/http/server/server_spec.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module HTTP
3232

3333
describe Response do
3434
it "creates default ssl context" do
35-
HTTP::Server.default_ssl_context.should be_a(OpenSSL::SSL::Context)
35+
HTTP::Server.default_ssl_context.should be_a(OpenSSL::SSL::Context::Server)
3636
end
3737

3838
it "closes" do

spec/std/openssl/ssl/context_spec.cr

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,86 +2,115 @@ require "spec"
22
require "openssl"
33

44
describe OpenSSL::SSL::Context do
5-
it "new" do
6-
OpenSSL::SSL::Context.new
7-
OpenSSL::SSL::Context.new(LibSSL.tlsv1_method)
5+
it "new for client" do
6+
ssl_context = OpenSSL::SSL::Context::Client.new
7+
ssl_context.verify_mode.should eq(OpenSSL::SSL::VerifyMode::PEER)
8+
OpenSSL::SSL::Context::Client.new(LibSSL.tlsv1_method)
9+
end
10+
11+
it "new for server" do
12+
ssl_context = OpenSSL::SSL::Context::Server.new
13+
ssl_context.verify_mode.should eq(OpenSSL::SSL::VerifyMode::NONE)
14+
OpenSSL::SSL::Context::Server.new(LibSSL.tlsv1_method)
15+
end
16+
17+
it "insecure for client" do
18+
ssl_context = OpenSSL::SSL::Context::Client.insecure
19+
ssl_context.should be_a(OpenSSL::SSL::Context::Client)
20+
ssl_context.verify_mode.should eq(OpenSSL::SSL::VerifyMode::NONE)
21+
OpenSSL::SSL::Context::Client.insecure(LibSSL.tlsv1_method)
22+
end
23+
24+
it "insecure for server" do
25+
ssl_context = OpenSSL::SSL::Context::Server.insecure
26+
ssl_context.should be_a(OpenSSL::SSL::Context::Server)
27+
ssl_context.verify_mode.should eq(OpenSSL::SSL::VerifyMode::NONE)
28+
OpenSSL::SSL::Context::Server.insecure(LibSSL.tlsv1_method)
829
end
930

1031
it "sets certificate chain" do
11-
ssl_context = OpenSSL::SSL::Context.new
32+
ssl_context = OpenSSL::SSL::Context::Client.new
1233
ssl_context.certificate_chain = File.join(__DIR__, "openssl.crt")
1334
end
1435

1536
it "fails to set certificate chain" do
16-
ssl_context = OpenSSL::SSL::Context.new
37+
ssl_context = OpenSSL::SSL::Context::Client.new
1738
expect_raises(OpenSSL::Error) { ssl_context.certificate_chain = File.join(__DIR__, "unknown.crt") }
1839
expect_raises(OpenSSL::Error) { ssl_context.certificate_chain = __FILE__ }
1940
end
2041

2142
it "sets private key" do
22-
ssl_context = OpenSSL::SSL::Context.new
43+
ssl_context = OpenSSL::SSL::Context::Client.new
2344
ssl_context.private_key = File.join(__DIR__, "openssl.key")
2445
end
2546

2647
it "fails to set private key" do
27-
ssl_context = OpenSSL::SSL::Context.new
48+
ssl_context = OpenSSL::SSL::Context::Client.new
2849
expect_raises(OpenSSL::Error) { ssl_context.private_key = File.join(__DIR__, "unknown.key") }
2950
expect_raises(OpenSSL::Error) { ssl_context.private_key = __FILE__ }
3051
end
3152

3253
it "sets ciphers" do
3354
ciphers = "EDH+aRSA DES-CBC3-SHA !RC4"
34-
ssl_context = OpenSSL::SSL::Context.new
55+
ssl_context = OpenSSL::SSL::Context::Client.new
3556
(ssl_context.ciphers = ciphers).should eq(ciphers)
3657
end
3758

3859
it "adds temporary ecdh curve (P-256)" do
39-
ssl_context = OpenSSL::SSL::Context.new
60+
ssl_context = OpenSSL::SSL::Context::Client.new
4061
ssl_context.set_tmp_ecdh_key
4162
end
4263

4364
it "adds options" do
44-
ssl_context = OpenSSL::SSL::Context.new
65+
ssl_context = OpenSSL::SSL::Context::Client.new
4566
ssl_context.remove_options(ssl_context.options) # reset
4667
ssl_context.add_options(LibSSL::Options::ALL).should eq(LibSSL::Options::ALL)
4768
ssl_context.add_options(LibSSL::Options::NO_SSLV2 | LibSSL::Options::NO_SSLV3)
4869
.should eq(LibSSL::Options::ALL | LibSSL::Options::NO_SSLV2 | LibSSL::Options::NO_SSLV3)
4970
end
5071

5172
it "removes options" do
52-
ssl_context = OpenSSL::SSL::Context.new
73+
ssl_context = OpenSSL::SSL::Context::Client.new
5374
ssl_context.add_options(LibSSL::Options::ALL | LibSSL::Options::NO_SSLV2)
5475
ssl_context.remove_options(LibSSL::Options::ALL).should eq(LibSSL::Options::NO_SSLV2)
5576
end
5677

5778
it "returns options" do
58-
ssl_context = OpenSSL::SSL::Context.new
79+
ssl_context = OpenSSL::SSL::Context::Client.new
5980
ssl_context.add_options(LibSSL::Options::ALL | LibSSL::Options::NO_SSLV2)
6081
ssl_context.options.should eq(LibSSL::Options::ALL | LibSSL::Options::NO_SSLV2)
6182
end
6283

6384
it "adds modes" do
64-
ssl_context = OpenSSL::SSL::Context.new
85+
ssl_context = OpenSSL::SSL::Context::Client.new
6586
ssl_context.add_modes(LibSSL::Modes::AUTO_RETRY).should eq(LibSSL::Modes::AUTO_RETRY)
6687
ssl_context.add_modes(LibSSL::Modes::RELEASE_BUFFERS)
6788
.should eq(LibSSL::Modes::AUTO_RETRY | LibSSL::Modes::RELEASE_BUFFERS)
6889
end
6990

7091
it "removes modes" do
71-
ssl_context = OpenSSL::SSL::Context.new
92+
ssl_context = OpenSSL::SSL::Context::Client.new
7293
ssl_context.add_modes(LibSSL::Modes::AUTO_RETRY | LibSSL::Modes::RELEASE_BUFFERS)
7394
ssl_context.remove_modes(LibSSL::Modes::AUTO_RETRY).should eq(LibSSL::Modes::RELEASE_BUFFERS)
7495
end
7596

7697
it "returns modes" do
77-
ssl_context = OpenSSL::SSL::Context.new
98+
ssl_context = OpenSSL::SSL::Context::Client.new
7899
ssl_context.add_modes(LibSSL::Modes::AUTO_RETRY | LibSSL::Modes::RELEASE_BUFFERS)
79100
ssl_context.modes.should eq(LibSSL::Modes::AUTO_RETRY | LibSSL::Modes::RELEASE_BUFFERS)
80101
end
81102

103+
it "sets the verify mode" do
104+
ssl_context = OpenSSL::SSL::Context::Client.new
105+
ssl_context.verify_mode = OpenSSL::SSL::VerifyMode::NONE
106+
ssl_context.verify_mode.should eq(OpenSSL::SSL::VerifyMode::NONE)
107+
ssl_context.verify_mode = OpenSSL::SSL::VerifyMode::PEER
108+
ssl_context.verify_mode.should eq(OpenSSL::SSL::VerifyMode::PEER)
109+
end
110+
82111
pending "alpn_protocol=" do
83112
# requires OpenSSL 1.0.2+
84-
ssl_context = OpenSSL::SSL::Context.new
113+
ssl_context = OpenSSL::SSL::Context::Client.new
85114
ssl_context.alpn_protocol = "h2"
86115
end
87116
end

0 commit comments

Comments
 (0)