diff options
author | Tharanga Gamaethige <tgamaethige@netflix.com> | 2018-11-30 17:44:33 -0800 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2019-04-15 21:36:18 -0700 |
commit | ee1cfe3bf9384d1a93545fc942e25bed6437d910 (patch) | |
tree | 2e880ddd3d263b85f2cf6de73b8eb15d14d02e37 /t/lib | |
parent | d2dcfff7edd28baf3587ab103d6fbac322335a68 (diff) | |
download | memcached-ee1cfe3bf9384d1a93545fc942e25bed6437d910.tar.gz |
Basic implementation of TLS for memcached.1.5.13
Most of the work done by Tharanga. Some commits squashed in by
dormando. Also reviewed by dormando.
Tested, working, but experimental implementation of TLS for memcached.
Enable with ./configure --enable-tls
Requires OpenSSL 1.1.0 or better.
See `memcached -h` output for usage.
Diffstat (limited to 't/lib')
-rw-r--r-- | t/lib/MemcachedTest.pm | 86 |
1 files changed, 80 insertions, 6 deletions
diff --git a/t/lib/MemcachedTest.pm b/t/lib/MemcachedTest.pm index 416daaf..72ebe08 100644 --- a/t/lib/MemcachedTest.pm +++ b/t/lib/MemcachedTest.pm @@ -15,7 +15,22 @@ my @unixsockets = (); @EXPORT = qw(new_memcached sleep mem_get_is mem_gets mem_gets_is mem_stats supports_sasl free_port supports_drop_priv supports_extstore - wait_ext_flush); + wait_ext_flush, supports_tls, enabled_tls_testing); + +use constant MAX_READ_WRITE_SIZE => 16384; +use constant SRV_CRT => "server_crt.pem"; +use constant SRV_KEY => "server_key.pem"; +use constant CLIENT_CRT => "client_crt.pem"; +use constant CLIENT_KEY => "client_key.pem"; +use constant CA_CRT => "cacert.pem"; + +my $testdir = $builddir . "/t/"; +my $client_crt = $testdir. CLIENT_CRT; +my $client_key = $testdir. CLIENT_KEY; +my $server_crt = $testdir . SRV_CRT; +my $server_key = $testdir . SRV_KEY; + +my $tls_checked = 0; sub sleep { my $n = shift; @@ -149,10 +164,20 @@ sub free_port { my $port; while (!$sock) { $port = int(rand(20000)) + 30000; - $sock = IO::Socket::INET->new(LocalAddr => '127.0.0.1', + if (enabled_tls_testing()) { + $sock = eval qq{ IO::Socket::SSL->new(LocalAddr => '127.0.0.1', + LocalPort => $port, + Proto => '$type', + ReuseAddr => 1, + SSL_verify_mode => SSL_VERIFY_NONE); + }; + die $@ if $@; # sanity check. + } else { + $sock = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => $port, Proto => $type, ReuseAddr => 1); + } } return $port; } @@ -175,6 +200,23 @@ sub supports_extstore { return 0; } +sub supports_tls { + my $output = `$builddir/memcached-debug -h`; + return 1 if $output =~ /enable-ssl/i; + return 0; +} + +sub enabled_tls_testing { + if ($tls_checked) { + return 1; + } elsif (supports_tls() && $ENV{SSL_TEST}) { + eval "use IO::Socket::SSL"; + croak("IO::Socket::SSL not installed or failed to load, cannot run SSL tests as requested") if $@; + $tls_checked = 1; + return 1; + } +} + sub supports_drop_priv { my $output = `$builddir/memcached-debug -h`; return 1 if $output =~ /no_drop_privileges/i; @@ -185,10 +227,21 @@ sub new_memcached { my ($args, $passed_port) = @_; my $port = $passed_port; my $host = '127.0.0.1'; + my $ssl_enabled = enabled_tls_testing(); if ($ENV{T_MEMD_USE_DAEMON}) { my ($host, $port) = ($ENV{T_MEMD_USE_DAEMON} =~ m/^([^:]+):(\d+)$/); - my $conn = IO::Socket::INET->new(PeerAddr => "$host:$port"); + my $conn; + if ($ssl_enabled) { + $conn = eval qq{IO::Socket::SSL->new(PeerAddr => "$host:$port", + SSL_verify_mode => SSL_VERIFY_NONE, + SSL_cert_file => '$client_crt', + SSL_key_file => '$client_key'); + }; + die $@ if $@; # sanity check. + } else { + $conn = IO::Socket::INET->new(PeerAddr => "$host:$port"); + } if ($conn) { return Memcached::Handle->new(conn => $conn, host => $host, @@ -203,13 +256,18 @@ sub new_memcached { $args .= " -o relaxed_privileges"; my $udpport; - if ($args =~ /-l (\S+)/) { - $port = free_port(); + if ($args =~ /-l (\S+)/ || ($ssl_enabled && ($args !~ /-s (\S+)/))) { + if (!$port) { + $port = free_port(); + } $udpport = free_port("udp"); $args .= " -p $port"; if (supports_udp()) { $args .= " -U $udpport"; } + if ($ssl_enabled) { + $args .= " -Z -o ssl_chain_cert=$server_crt -o ssl_key=$server_key"; + } } elsif ($args !~ /-s (\S+)/) { my $num = @unixsockets; my $file = "/tmp/memcachetest.$$.$num"; @@ -246,7 +304,17 @@ sub new_memcached { # sockets for (1..20) { - my $conn = IO::Socket::INET->new(PeerAddr => "127.0.0.1:$port"); + my $conn; + if ($ssl_enabled) { + $conn = eval qq{ IO::Socket::SSL->new(PeerAddr => "127.0.0.1:$port", + SSL_verify_mode => SSL_VERIFY_NONE, + SSL_cert_file => '$client_crt', + SSL_key_file => '$client_key'); + }; + die $@ if $@; # sanity check. + } else { + $conn = IO::Socket::INET->new(PeerAddr => "127.0.0.1:$port"); + } if ($conn) { return Memcached::Handle->new(pid => $childpid, conn => $conn, @@ -299,6 +367,12 @@ sub new_sock { my $self = shift; if ($self->{domainsocket}) { return IO::Socket::UNIX->new(Peer => $self->{domainsocket}); + } elsif (MemcachedTest::enabled_tls_testing()) { + return eval qq{ IO::Socket::SSL->new(PeerAddr => "$self->{host}:$self->{port}", + SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE, + SSL_cert_file => '$client_crt', + SSL_key_file => '$client_key'); + }; } else { return IO::Socket::INET->new(PeerAddr => "$self->{host}:$self->{port}"); } |