diff options
Diffstat (limited to 't')
-rwxr-xr-x | t/binary.t | 34 | ||||
-rw-r--r-- | t/cacert.pem | 22 | ||||
-rw-r--r-- | t/cakey.pem | 30 | ||||
-rw-r--r-- | t/client_crt.pem | 68 | ||||
-rw-r--r-- | t/client_key.pem | 15 | ||||
-rw-r--r-- | t/idle-timeout.t | 8 | ||||
-rw-r--r-- | t/lib/MemcachedTest.pm | 86 | ||||
-rwxr-xr-x | t/misbehave.t | 2 | ||||
-rwxr-xr-x | t/multiversioning.t | 12 | ||||
-rw-r--r-- | t/noreply.t | 1 | ||||
-rw-r--r-- | t/server.pem | 79 | ||||
-rw-r--r-- | t/server_crt.pem | 67 | ||||
-rw-r--r-- | t/server_key.pem | 15 | ||||
-rw-r--r-- | t/ssl_cert_refresh.t | 76 | ||||
-rw-r--r-- | t/ssl_ports.t | 31 | ||||
-rw-r--r-- | t/ssl_settings.t | 36 | ||||
-rw-r--r-- | t/ssl_verify_modes.t | 22 | ||||
-rwxr-xr-x | t/stats.t | 15 |
18 files changed, 598 insertions, 21 deletions
@@ -441,7 +441,14 @@ $mc->silent_mutation(::CMD_ADDQ, 'silentadd', 'silentaddval'); my %stats = $mc->stats('settings'); is(1024, $stats{'maxconns'}); - isnt('NULL', $stats{'domain_socket'}); + # we run SSL tests over TCP; hence the domain_socket + # is expected to be NULL. + if (enabled_tls_testing()) { + is('NULL', $stats{'domain_socket'}); + } else { + isnt('NULL', $stats{'domain_socket'}); + } + is('on', $stats{'evictions'}); is('yes', $stats{'cas_enabled'}); is('yes', $stats{'flush_enabled'}); @@ -484,14 +491,14 @@ $mc->silent_mutation(::CMD_ADDQ, 'silentadd', 'silentaddval'); $data .= $mc->build_command(::CMD_SETQ, "alt_$k", "blah", 0, $extra, 0); if (length($data) > 2024) { for (my $j = 2024; $j < min(2096, length($data)); $j++) { - $mc->{socket}->send(substr($data, 0, $j)); + $mc->{socket}->syswrite(substr($data, 0, $j)); $mc->flush_socket; sleep(0.001); - $mc->{socket}->send(substr($data, $j)); + $mc->{socket}->syswrite(substr($data, $j)); $mc->flush_socket; } } else { - $mc->{socket}->send($data); + $mc->{socket}->syswrite($data); } $mc->flush_socket; $check->($k, 82, $v); @@ -571,9 +578,18 @@ sub send_command { my $full_msg = $self->build_command($cmd, $key, $val, $opaque, $extra_header, $cas); - my $sent = $self->{socket}->send($full_msg); - die("Send failed: $!") unless $sent; - if($sent != length($full_msg)) { + my $sent = 0; + my $data_len = length($full_msg); + while ($sent < $data_len) { + my $sent_bytes = $self->{socket}->syswrite($full_msg, + $data_len - $sent > MemcachedTest::MAX_READ_WRITE_SIZE ? + MemcachedTest::MAX_READ_WRITE_SIZE : ($data_len - $sent), + $sent); + last if ($sent_bytes <= 0); + $sent += $sent_bytes; + } + die("Send failed: $!") unless $data_len; + if($sent != $data_len) { die("only sent $sent of " . length($full_msg) . " bytes"); } } @@ -612,7 +628,7 @@ sub _handle_single_response { my $hdr = ""; while(::MIN_RECV_BYTES - length($hdr) > 0) { - $self->{socket}->recv(my $response, ::MIN_RECV_BYTES - length($hdr)); + $self->{socket}->sysread(my $response, ::MIN_RECV_BYTES - length($hdr)); $hdr .= $response; } Test::More::is(length($hdr), ::MIN_RECV_BYTES, "Expected read length"); @@ -628,7 +644,7 @@ sub _handle_single_response { # fetch the value my $rv=""; while($remaining - length($rv) > 0) { - $self->{socket}->recv(my $buf, $remaining - length($rv)); + $self->{socket}->sysread(my $buf, $remaining - length($rv)); $rv .= $buf; } if(length($rv) != $remaining) { diff --git a/t/cacert.pem b/t/cacert.pem new file mode 100644 index 0000000..522bd27 --- /dev/null +++ b/t/cacert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIJAOFc3ZmVKolRMA0GCSqGSIb3DQEBBQUAMIGLMSgwJgYD +VQQDDB9UZXN0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQswCQYDVQQIDAJD +QTELMAkGA1UEBhMCVVMxHDAaBgkqhkiG9w0BCQEWDXJvb3RAdGVzdC5jb20xDTAL +BgNVBAoMBFRlc3QxGDAWBgNVBAsMD1Rlc3QgRGVwYXJ0bWVudDAeFw0xOTAxMDcx +ODIzMjlaFw0yNDAxMDYxODIzMjlaMIGLMSgwJgYDVQQDDB9UZXN0IFJvb3QgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxHDAa +BgkqhkiG9w0BCQEWDXJvb3RAdGVzdC5jb20xDTALBgNVBAoMBFRlc3QxGDAWBgNV +BAsMD1Rlc3QgRGVwYXJ0bWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAJQcDfenVed0uJCykaWowL2qGUs9e5gyjGo9URoNhI5LDYSSq3ebxZGfbi1T +BcC7oL5OI/B0lCShPR9sJjKFkQ60vs43ltmkTLNSGoKLnxXMlBjdpCxweDDAMiF3 +p/vCG2hUa7auOkMWMYIkM81rcQsRB0qj0ilt3zcTsS860oKGzNrtPeAcz3KxbYWI +nJEhQVy3S4U59b7mm3cGz3/3m2NUjn+b8sA7J8F9K5mnFkCUCRva6zte6qmL2ruH +sGRav9ICLGxDqiJoic6Y2ReffgU77RDJO+sTuJme+VeTDE77vBIHvCVCSG+e0RSs +L+6nQYDtjHH5bLgoSXq9D3hgxEsCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq +hkiG9w0BAQUFAAOCAQEARWcYJvkleq+qfOPPI1eQAuBf5OZwz8mthsBvMfsQMCLk ++wSxdlJvJyvPoFgZBv8YbTde2b40lQe94gTsGDUXGEkOsERrjt/jqHxO9X8n7a+z +M/okeSSYnam0Zcl1M9sa5L7BVXbGh/sE9j/bXrAhz64np5P773dZTLTPYjBf2Grp +NheCsGDtJbegJqn7pp5MfAKcyzLxnZAE0cilSVKZB7R3urISJVdwiRtkprJL7IwQ +oIu+XhUgdZbx7TQQnjTkq3COSIIof5+5oqFnhzTqfSgi/06dWWvCwl17Mz+vCMZ9 +1MA8L4cR+iNdJYlCQPbk30laJx1akfqnpv7qTXq7nQ== +-----END CERTIFICATE----- diff --git a/t/cakey.pem b/t/cakey.pem new file mode 100644 index 0000000..3396f25 --- /dev/null +++ b/t/cakey.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIigxGWoxgfJACAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECHgfMUpgAX2tBIIEyFcJT6kFw1TH +kmwmbtB+MPW3+zUxoKZuP+L7UCaMHQPHcQ4/AThVNPPhXa++/lgL0P1q33SBhqsm +HK5nRfzEe75bQIFoZ1FFg3YGaAB4KUPm5vJ4XhmyzCEiUvp75mgiw38fkL5ZCPqW +eitNKgyAYEl9zIrF1cRyN/s6O6mPR8NOPbVL2ZtCGGvy/LN+mhlolvuMFySEEI+s +nzu5682LU7QQOzLFB/q3Vqrt2tafzoIHYtj8YYVsPMO6bWkoKx1BWyTCuesFOLTN +agnXx3AKtmD8Q0C3vvdmpqNnWw1iP1Vc4r/BZwmD2MFXUh8cExBGRaPIfUr41BoR +p1bHqtcAsbipuU7qQ6wjnLyuqAvFQxy1LCBGNyBrzMMD25+lXh9BoeS9H5L+WW0N +pcAPA5FoD1RQc27ZXVf0kRGEy8Vj/UsE3Pf74Z8u16bC+6ojAUvvvc49ERm0t85O +T5rP9ql3sITtg4EvNdNhHtYdJGVkZQ7H8T9G1OXEf4dE/vqYNnqhtFm+5CyWb8Vk +Rly2XFbBs4I4UnVIi0Nt0ybIqqwAvvKAU5kSOIEy6Q9mvUYyvBZrhY5Va2KEwaTU +ig2yjWxWFoOArE1UVu2kJaslaOKqAr9OPqW510+6G9s+lREm7EYqUd6Ut1cwcXUv +/s1fdx/As6U6qApH9+TC0XqNm5yXNCuADVtK2PmOoanczpEXZTZGijylGFDROQQj +bofjoB0hiN80Xc+II0zClGwXwZz43Xy4uVIMbvMBi3yp03ct1RMwORPCGkiH/1uV +iazsfV4DAD8KdGmgUL57WfnMPZJCEfqpM4YrM7rKu3Md8v8hKyFGUAdeNsCFTwwY +g2E6NXWbtqGrUFC/r/70/axfijWRoyPaLcBoourc5HcZ+K/TmmY+uOxKBcJsfS/t +HiRZ5l48sva+lZVWN6KNG5N93pa3TqgCCfp56VPOo3o3kj4XAJ3aMK6RsK3QrGi7 +TTXlv/hKFYW3GUJ0IGNfinnARbdMoD6ww8nQLe3Id3HKzqh7xfQb4xJZpQhpSXVS +KJmf5H80GHQnJq54Xwi7daYmxpTS+yNHuxKq+ryBqO7WeotNkOCbG6Flc/GBO6a3 +7rbSOTmqpyJPTRPQEf1ogHNgCG9txPIbZRAi9PPJVn/gV/dKttUpj5OGI9fjDaSK +ILEwLuokdRwTAGeFRIkucKnvA0pzXQkZRMG4D4kYzxskutUQVvKFAsqvEkb2c6qL +j8MjKYfYZqxG44o68aOk8H42vR6lkemclj6byvLfnqbZPUka3MUnrG8oPI+vNLlg +N57QpU2Kw5joBf1oCSROTXEv3BT/JYE3qQ2T6q/NGgG0s8aXbROh/7HaZJrENmoD +pDJZp+bSGn6On6vmDu98F3fyubKgg611tA5pyDdWE4MSvJBGKHc2/HmqgxbLtK1c +gn2BBefAi+Qqzc+XSeJxh2nlAx7ohvgEcodO3Vqb9eSoPviMHyO9bap8QIFJqTNW +QK6rMqtou0QTEcXp5cIlVRW59zZHKEPpNpJ08fNtxB5n/Ngo+vo86LLVUysfbwkY +p7GK4kraBGhU3rEXzuFBXn1Cr7015VrAC8mLafKqar7OLhLduHDRPxGidXJc6oxE +2PpJudZFhS6P+0M5AkMq2Q== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/t/client_crt.pem b/t/client_crt.pem new file mode 100644 index 0000000..f9031ee --- /dev/null +++ b/t/client_crt.pem @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=Test Root Certificate Authority, ST=CA, C=US/emailAddress=root@test.com, O=Test, OU=Test Department + Validity + Not Before: Jan 7 19:26:14 2019 GMT + Not After : Jan 6 19:26:14 2024 GMT + Subject: CN=client.test.com, ST=CA, C=US/emailAddress=root@client.test.com, O=Test Client, OU=Subunit of Test Organization + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:a6:a4:24:19:14:9e:96:0a:3e:b8:14:7b:e9:04: + ca:a0:ef:61:1a:e6:63:84:51:34:10:58:9e:f2:6f: + 9d:27:64:e5:a9:32:02:e2:fb:f0:c5:47:d0:b2:8f: + f4:19:71:2a:de:f8:de:ae:cb:0b:41:cf:cc:76:63: + 9b:4a:9b:12:50:5f:b9:b4:fc:e3:fd:05:85:7f:a7: + 1c:ad:ec:d1:40:70:fa:4c:51:88:a3:d4:e5:49:b2: + 72:7c:2e:4d:c5:00:ae:40:96:15:84:34:5f:99:75: + 7b:6a:00:d3:ec:a0:7d:82:d3:71:a3:79:cc:d4:4c: + 3b:50:49:d0:9b:27:e4:0b:cb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Alternative Name: + DNS:client.test.com, DNS:alt.client.test.com + Signature Algorithm: sha1WithRSAEncryption + 4f:11:ff:ed:05:e2:80:75:bd:e0:b3:f3:21:34:65:50:67:ff: + 3c:45:88:58:58:77:9a:6e:f6:1e:74:f9:cb:02:e1:31:e0:52: + d9:f9:63:e5:fb:01:d2:83:df:20:c1:77:a7:15:da:18:3a:e0: + ea:e0:66:ab:41:21:9e:36:9c:36:28:1c:cb:20:43:94:94:e8: + 9b:0d:3d:2a:ac:20:48:5b:b8:c0:45:0d:5c:30:91:be:ba:67: + b9:f6:bd:64:08:ab:af:35:a1:db:dd:54:e8:32:c9:3a:95:34: + 26:8f:a1:1b:a1:a2:32:47:a0:e0:a4:11:06:dc:d2:67:87:1a: + 51:50:bc:09:26:e3:1c:e7:83:a5:69:48:92:6c:87:94:46:f6: + b2:45:55:6f:5e:f2:6b:c8:9d:65:61:31:83:09:71:60:71:d5: + 9c:44:65:27:f6:3f:fd:fb:40:30:47:02:b1:6f:5a:ff:7a:c5: + 83:e0:80:52:53:a7:2c:24:71:51:81:df:3f:2f:1d:42:df:bc: + 86:b4:0c:18:64:8d:33:a7:c0:e8:f2:9e:f5:0b:92:c4:4d:f7: + 4b:2f:13:8d:81:25:f3:47:f5:72:71:c2:62:3d:36:09:3c:ec: + d1:15:6d:15:77:28:c6:de:f9:73:5d:5b:a0:a4:0f:f2:50:a0: + 00:20:87:fa +-----BEGIN CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBizEoMCYGA1UEAwwfVGVz +dCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkGA1UECAwCQ0ExCzAJBgNV +BAYTAlVTMRwwGgYJKoZIhvcNAQkBFg1yb290QHRlc3QuY29tMQ0wCwYDVQQKDARU +ZXN0MRgwFgYDVQQLDA9UZXN0IERlcGFydG1lbnQwHhcNMTkwMTA3MTkyNjE0WhcN +MjQwMTA2MTkyNjE0WjCBljEYMBYGA1UEAwwPY2xpZW50LnRlc3QuY29tMQswCQYD +VQQIDAJDQTELMAkGA1UEBhMCVVMxIzAhBgkqhkiG9w0BCQEWFHJvb3RAY2xpZW50 +LnRlc3QuY29tMRQwEgYDVQQKDAtUZXN0IENsaWVudDElMCMGA1UECwwcU3VidW5p +dCBvZiBUZXN0IE9yZ2FuaXphdGlvbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC +gYEApqQkGRSelgo+uBR76QTKoO9hGuZjhFE0EFie8m+dJ2TlqTIC4vvwxUfQso/0 +GXEq3vjerssLQc/MdmObSpsSUF+5tPzj/QWFf6ccrezRQHD6TFGIo9TlSbJyfC5N +xQCuQJYVhDRfmXV7agDT7KB9gtNxo3nM1Ew7UEnQmyfkC8sCAwEAAaNLMEkwCQYD +VR0TBAIwADALBgNVHQ8EBAMCBeAwLwYDVR0RBCgwJoIPY2xpZW50LnRlc3QuY29t +ghNhbHQuY2xpZW50LnRlc3QuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQBPEf/tBeKA +db3gs/MhNGVQZ/88RYhYWHeabvYedPnLAuEx4FLZ+WPl+wHSg98gwXenFdoYOuDq +4GarQSGeNpw2KBzLIEOUlOibDT0qrCBIW7jARQ1cMJG+ume59r1kCKuvNaHb3VTo +Msk6lTQmj6EboaIyR6DgpBEG3NJnhxpRULwJJuMc54OlaUiSbIeURvayRVVvXvJr +yJ1lYTGDCXFgcdWcRGUn9j/9+0AwRwKxb1r/esWD4IBSU6csJHFRgd8/Lx1C37yG +tAwYZI0zp8Do8p71C5LETfdLLxONgSXzR/VyccJiPTYJPOzRFW0VdyjG3vlzXVug +pA/yUKAAIIf6 +-----END CERTIFICATE----- diff --git a/t/client_key.pem b/t/client_key.pem new file mode 100644 index 0000000..22d1e37 --- /dev/null +++ b/t/client_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCmpCQZFJ6WCj64FHvpBMqg72Ea5mOEUTQQWJ7yb50nZOWpMgLi ++/DFR9Cyj/QZcSre+N6uywtBz8x2Y5tKmxJQX7m0/OP9BYV/pxyt7NFAcPpMUYij +1OVJsnJ8Lk3FAK5AlhWENF+ZdXtqANPsoH2C03GjeczUTDtQSdCbJ+QLywIDAQAB +AoGAXFVMrxzutiIdGHA5LCb8g2m/+2C2uYUo/PmtsJVJlZ9hZXuRf+WrRhSBvb7n +uQUshPmOoXld1mxmVR7h19fOsBbgKYqwDTlLZEnvdMVzaGiyeHiwDAvJgkkrK7pV +kod5JIjFd+UMho6+Qn3K7tzfttLze5xuBPNrMH3q2b8LgBECQQDbJVyF+gLk4gmd +BBInYl0BHPjYmGW9xfHfn0fhkKhQCZ9eNzH5Wbk1D8yqdlfmJ5nI8FkLQunzwzgv +P51m+USJAkEAwqpaJoVOaaRfmsgEXOsZop32DBCBHwOqOyqH9qMez8qfBPDHrUbA +TMtJN/TqLhi4VEPeaHbioUdUybA+1MggswJALWEgNrId1U2lVflY1QT+Y1OfiCKO +tux9eKQgG2p8IA7ODJF7bLoSqxU5eXcGHqfGpaB3n+hcT9j2Enqm2oL1mQJAIp53 +D9ivPDxeQEGH/RpWYcQjyLt6qxBUytbifSs/RIbtRsynRhqKAl44tDnbF72PsnSr +bfqOjU4JNyEf22mH3wJBAK1yx2ilG//KYHtcfFYtll0Rkkife+2It6bTMVdkeVCH +o5iDnW/+VsJCawhS9jHLZAjors+A9iyjygl1O6zLZTE= +-----END RSA PRIVATE KEY----- diff --git a/t/idle-timeout.t b/t/idle-timeout.t index 66558ac..bc908e9 100644 --- a/t/idle-timeout.t +++ b/t/idle-timeout.t @@ -30,7 +30,13 @@ is($stats->{idle_kicks}, "0", "check stats 2"); sleep(5); mem_stats($sock); # Network activity, so socket code will see dead socket sleep(1); -is($sock->connected(), undef, "check disconnected"); +# we run SSL tests over TCP; hence IO::Socket::SSL returns +# '' upon disconnecting with the server. +if (enabled_tls_testing()) { + is($sock->connected(),'', "check disconnected"); +} else { + is($sock->connected(),undef, "check disconnected"); +} $sock = $server->sock; $stats = mem_stats($sock); 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}"); } diff --git a/t/misbehave.t b/t/misbehave.t index 13cb7f3..1312a27 100755 --- a/t/misbehave.t +++ b/t/misbehave.t @@ -7,7 +7,7 @@ use Socket qw(MSG_PEEK MSG_DONTWAIT); use lib "$Bin/lib"; use MemcachedTest; -if (supports_drop_priv()) { +if (!enabled_tls_testing() && supports_drop_priv()) { plan tests => 1; } else { plan skip_all => 'Privilege drop not supported'; diff --git a/t/multiversioning.t b/t/multiversioning.t index df9eab4..c65c2df 100755 --- a/t/multiversioning.t +++ b/t/multiversioning.t @@ -24,7 +24,17 @@ mem_get_is($sock, "big", $bigval, "big value got correctly"); print $sock "get big\r\n"; my $buf; -is(read($sock, $buf, $size / 2), $size / 2, "read half the answer back"); +my $read = 0; +my $to_read = $size / 2; +while ($read < $to_read) { + my $read_bytes = $sock->sysread($buf, + ($to_read - $read > MemcachedTest::MAX_READ_WRITE_SIZE ? + MemcachedTest::MAX_READ_WRITE_SIZE : $to_read - $read), + $read); + last if ($read_bytes <= 0); + $read += $read_bytes; +} +is($read, $size / 2, "read half the answer back"); like($buf, qr/VALUE big/, "buf has big value header in it"); like($buf, qr/abcdef/, "buf has some data in it"); unlike($buf, qr/abcde\]/, "buf doesn't yet close"); diff --git a/t/noreply.t b/t/noreply.t index 54a3f13..6aa3dc2 100644 --- a/t/noreply.t +++ b/t/noreply.t @@ -44,4 +44,3 @@ mem_get_is($sock, "noreply:foo", "7"); print $sock "delete noreply:foo noreply\r\n"; mem_get_is($sock, "noreply:foo"); - diff --git a/t/server.pem b/t/server.pem new file mode 100644 index 0000000..d4bc393 --- /dev/null +++ b/t/server.pem @@ -0,0 +1,79 @@ +subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Server Cert +issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA +-----BEGIN CERTIFICATE----- +MIID0DCCArigAwIBAgIIcsOElVeHzfYwDQYJKoZIhvcNAQELBQAwcDELMAkGA1UE +BhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBURVNU +SU5HIFBVUlBPU0VTIE9OTFkxJTAjBgNVBAMMHE9wZW5TU0wgVGVzdCBJbnRlcm1l +ZGlhdGUgQ0EwIBcNMTgwNjE0MTI0NjI4WhgPMjExODA2MTQxMjQ2MjhaMGQxCzAJ +BgNVBAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1Ig +VEVTVElORyBQVVJQT1NFUyBPTkxZMRkwFwYDVQQDDBBUZXN0IFNlcnZlciBDZXJ0 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0jIZ8IZ4dIzBc+ZfdmG5 +n8G3JzRX99QvIqv52s4hFVfdzoa+AciKJpo9zkegWPmfsAVNa4uVceg/ZQt6qJsu +G/pxbQSZVnyjDQGtt7rgaDEbyUP0XJCnzyRdWSUjFS8yNZn4NkmZU01GlHtXdzWy +dEa5PaiTIwW0HI+bjjOEhwJ1hFuFqzlKHVKHA6DBzNcl6ly0E/q2kyslbR+0hq7p +NMqKvvuAxqgc//W8KvLDlKAt9D3t5zgh2+BrMPemrzjEaM97yHTogJo7+SKVDdUw +YQ7Br3xfyki9u2bUYib1BMSvLezxNP0qf/iU91z4xyLmMvOXE6W0D1WHwya1CfE7 +vwIDAQABo3gwdjAdBgNVHQ4EFgQU3ulCbvgfxej6rHnddMpBidwnLIIwHwYDVR0j +BBgwFoAUCgNEpWg658NdblSLsvg43EA1WwUwCQYDVR0TBAIwADATBgNVHSUEDDAK +BggrBgEFBQcDATAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQAD +ggEBAENMzaqJtmWED++W4KXFVwNBkQ87errBXe4jVeYKpjNb0JGMm60MS5ty54fb +r27SsR2EEk3EK2rcd85RR7TEKZCn9SvPykVtVf0tru7nOptQJgSbRvxIzyyq1UcE +K+BXDgN/I0f1X6qbk4Stb6uJF7yyAUabacjwKqgVifOOeKF9WJhVA8qJKoVq7HLN +k+uvm0geO1I4LKeULXVnQy8kwB6twcxN8iPyO45ZxbYIVeEKaYtbj/XPoq6KsLIb +5fj+mK1r/LkWk352ksNhf73r3alF8TBcSLqnbMoy1/ZvzlI4ksp9IGWtIU+CzP/f +VUjh00NOwDLd5jJbPoWW0oNp9m4= +-----END CERTIFICATE----- +subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA +issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Root CA +-----BEGIN CERTIFICATE----- +MIIEPzCCAqegAwIBAgIILsaQqJAjK4IwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UE +BhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBURVNU +SU5HIFBVUlBPU0VTIE9OTFkxHTAbBgNVBAMMFE9wZW5TU0wgVGVzdCBSb290IENB +MCAXDTE4MDYxNDEyNDYyOFoYDzIxMTgwNjE0MTI0NjI4WjBwMQswCQYDVQQGEwJV +SzEWMBQGA1UECgwNT3BlblNTTCBHcm91cDEiMCAGA1UECwwZRk9SIFRFU1RJTkcg +UFVSUE9TRVMgT05MWTElMCMGA1UEAwwcT3BlblNTTCBUZXN0IEludGVybWVkaWF0 +ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANIpVng2wNFJp2kF +oJ6Yji25wy1YufnS8NxA82fk5OHdhGWj1CWqnQNotEqEQzcOUszQYrNxd8tEvoWk +Ik4JMBVoEcgBGedchftptTNulFWodWpi1yFaqA/Nz2BsVgcCJW4C+UWDT7VeHtGU +7tYKKr35lxp6io/a4jUDQXvO2nJA9YlrxOktunMqtoZSYqUz35ZXsdkn58o8Fbqm +dEpw6AqAr9aBgY5DSaGxbaX2lwNt9NvB+f9ucOqEnPP8AfTlPYc/ENwJ6u/H8RGw +d1im71mu2lHjcws3aHkbluH860U3vlKWx6Ff1qdQcH98e2HwElqxCK00xya8leu4 +u64nljkCAwEAAaNjMGEwHQYDVR0OBBYEFAoDRKVoOufDXW5Ui7L4ONxANVsFMB8G +A1UdIwQYMBaAFDZjTeLsQUG6KL9xuLhzXVdB4pkKMA8GA1UdEwEB/wQFMAMBAf8w +DgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBgQDZQJLA90ewVaS3E3du +gSjPkQ1xsHm8H1am+7zr5oZ81J+R8XYIZgMR+9ShVo38OradiYNqDLso+4iuVdxh +hzoSoQELoDXCficzWKnlAtWvwDDoczyK+/p94g3VKx14n2+GvQzoZ4kwQQgaFH1w +YI6w0oH9zwoklCxvihj8D069QrYyuTT8JGZ2m0FHqVJg6teuQKFahSgwYR2CUoIb +6PrpSUQeCVCH8TPkzlRT6UgtM3ERt7+TlQ+zZ80dSf4YTAsDv9Z/CJXiF/5wZr6/ +lWuFjWmX2HkpEW6Wiv5KF8QP6Ft7Z+RYua7RMtELCYvqYbWDBs7fXWGBkZ5xhB09 +jCxz+F7zOeRbyzacfFq9DhxCWCRbIrdgGGE/Of2ujJtmK/2p4M6E5IsKNAI2SJBW +iJXvIgQgR22ehPqy6er2Gog5LkWUwqB0kHZJJpbp1IW01IGTpD6YAJyVCEAlyMbo +Kto9+wQFLT3Auv/W5h6OwxkNdfAyZBYy0ZSFk4EE8OdWWY4= +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA0jIZ8IZ4dIzBc+ZfdmG5n8G3JzRX99QvIqv52s4hFVfdzoa+ +AciKJpo9zkegWPmfsAVNa4uVceg/ZQt6qJsuG/pxbQSZVnyjDQGtt7rgaDEbyUP0 +XJCnzyRdWSUjFS8yNZn4NkmZU01GlHtXdzWydEa5PaiTIwW0HI+bjjOEhwJ1hFuF +qzlKHVKHA6DBzNcl6ly0E/q2kyslbR+0hq7pNMqKvvuAxqgc//W8KvLDlKAt9D3t +5zgh2+BrMPemrzjEaM97yHTogJo7+SKVDdUwYQ7Br3xfyki9u2bUYib1BMSvLezx +NP0qf/iU91z4xyLmMvOXE6W0D1WHwya1CfE7vwIDAQABAoIBAQC2HAo1RYvfDoQc +sh9LJWf5bZANO2Brqz4bP/x9AdHP+AyH/l1oliJ7R2785TmbXMppam6lGo4j3h/u +n39pzOip/NWAqldfgySRBD9Jy3LZUpLMUT/JYtrAsLTfozk+BWHu5rMR9boNXgok +Yqho8/DkpNGhBghUc4CUricLkL7laD3ziAHpx8yALL3tnLGOpgT9hNrA8Dm3yfUS +JEfiG12ILXvq1IP+vUNuaLpTLJZuqUmLpK8v+CBYgKxfd+TDnEjul4PqhhIIFK3A +xEZYQR2D/AXUwng9hP9uCbVm5lOY6vRbi9Fpbt+KRv+m25s1AnuhJFBOsL30h/Tb +iCKWm/nhAoGBAO0bFqMvZHjaT2KiwOwG/Ze9NsjynFPVltiuCqNj8HE5wM6imC5J +SdB+jMkgN6ERXALWrtr8Uf2pqzfeMsi6pekOOVTWLe/8c4bAZRxaCZn/BlZRysZI +vB9Gb7m7Oymw5iDSqrYywgOiUu+oIiCrmPOealhmn7zmHzHaETvdL9zDAoGBAOLy +DVT1csoexnuHVIWqnp7FK7lv6eOGZSdXpfJ3XYjmKJLK2hpVZe+J/mFOL1wsKSt4 +0k/V0dnkHR7V4Pa4ECiCthkWMWrBVIHe7+ZnZ0ocKQSC+EEecavOiZ57S/qnUlT6 +NtQP4cSy4DHzzFZdTZnn+2oymapPZpb2mvSN/GVVAoGADrIlHwwq8Aqn7Pclefuc +8DC8GoxfABs29EslQadKGdp4htYxFH1aY9/UHgsvJ36J82sW/1+wPUas5BOTljlr +WxyUlRuJUVyWVH3MRouWGMNjwynipZOQhWe6OQrPye+688Ha7twKhmsjNNN4+glo +u4DQGpaRxAWHXXGkq88zzj0CgYEAsICEceD7R8srnwMfb13FQ8IhQXWSuAvcO/7k +53CCZGhsgc4WVoi4YNY360G9f7gwxMiQ+NpY/Vd2dnbtIbUBjCAss9IY2OhHa0IR +3mXpZTAFjqa1oR+mVHKrgYBvFSBw3fpEDiXT9wEPcIomD709D0fmty9nZ5edOCfP +WAfdlokCgYEAqXuMuAg3NMMgEv+eBfsf43v3hRwBqPYanE26wcO3GoT/S8BpB6wy +vBoPZOlO5ZfsD2jaTec60GLay+MofxC7qNXIjzHOw50ry4bqHqqoQbn2cONE1k+0 +ov7H2keTcG9FEGgL7dRUq3pRUo/W12WmRuDN17IEgkzAeisJnoiPtaQ= +-----END RSA PRIVATE KEY----- diff --git a/t/server_crt.pem b/t/server_crt.pem new file mode 100644 index 0000000..6b7a315 --- /dev/null +++ b/t/server_crt.pem @@ -0,0 +1,67 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=Test Root Certificate Authority, ST=CA, C=US/emailAddress=root@test.com, O=Test, OU=Test Department + Validity + Not Before: Jan 7 18:25:01 2019 GMT + Not After : Jan 6 18:25:01 2024 GMT + Subject: CN=test.com, ST=CA, C=US/emailAddress=root@test.com, O=Test, OU=Subunit of Test Organization + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:ca:76:35:79:91:e8:a2:ee:ef:f4:35:7e:29:85: + 75:90:65:5a:60:f8:a0:d9:ef:68:d1:61:79:69:d7: + e2:7b:f1:67:71:65:50:31:4e:9a:f8:6f:27:e9:05: + 0b:0e:76:95:24:9b:c2:bf:90:e5:6b:45:fd:e3:54: + ac:d5:62:90:4e:37:de:8f:ae:96:f6:b3:57:eb:ad: + b8:44:13:5d:a7:34:76:c1:26:49:91:67:3e:5e:52: + 68:c1:1c:7f:91:c7:9e:01:e2:be:a7:a8:eb:3f:44: + 6d:c7:c5:82:4b:97:d9:3f:c0:51:99:1b:20:df:12: + a3:e6:bb:66:45:6d:b4:e1:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Alternative Name: + DNS:test.com, DNS:alt.test.com + Signature Algorithm: sha1WithRSAEncryption + 61:c1:18:b4:04:79:05:0e:b9:79:2f:0e:3f:aa:f1:36:e3:90: + b9:c6:99:25:53:4a:06:64:52:92:29:c5:09:41:a6:16:74:1b: + 3c:4e:81:32:c2:d8:54:e0:1e:08:45:cf:f1:d0:ad:ea:11:1a: + b5:cf:7c:98:8a:dd:c1:01:e4:d0:f5:8e:60:fa:7f:e7:74:2d: + 91:43:81:bd:95:92:41:66:84:8b:8c:70:d7:2f:d4:2f:37:82: + 8f:9a:ef:c0:7d:c5:56:56:92:7a:00:b6:30:65:37:4c:6c:7a: + ba:cc:e2:dc:73:e9:f5:2c:3c:3e:31:67:ee:3d:b7:78:96:89: + ba:be:4f:85:a2:a8:83:3e:53:20:f0:bf:29:50:dc:23:38:58: + d8:33:f5:7b:4a:12:df:2b:34:4c:1c:f1:76:6b:86:95:74:43: + 29:f7:68:f0:ca:04:08:89:ac:97:7d:05:14:a0:ca:81:56:5c: + dd:c3:56:a3:53:01:0a:01:5c:55:b4:39:10:1b:be:47:19:58: + a1:f2:e6:0c:08:95:b0:35:4e:6c:81:6d:b9:cf:0e:5c:70:ff: + f3:b4:a7:95:69:1a:58:b7:ac:cc:2c:79:47:7e:20:17:cc:36: + be:2c:10:11:31:28:63:dd:6f:8d:8d:e9:11:ea:ca:fc:10:0a: + e0:ae:53:db +-----BEGIN CERTIFICATE----- +MIIDQjCCAiqgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBizEoMCYGA1UEAwwfVGVz +dCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkGA1UECAwCQ0ExCzAJBgNV +BAYTAlVTMRwwGgYJKoZIhvcNAQkBFg1yb290QHRlc3QuY29tMQ0wCwYDVQQKDARU +ZXN0MRgwFgYDVQQLDA9UZXN0IERlcGFydG1lbnQwHhcNMTkwMTA3MTgyNTAxWhcN +MjQwMTA2MTgyNTAxWjCBgTERMA8GA1UEAwwIdGVzdC5jb20xCzAJBgNVBAgMAkNB +MQswCQYDVQQGEwJVUzEcMBoGCSqGSIb3DQEJARYNcm9vdEB0ZXN0LmNvbTENMAsG +A1UECgwEVGVzdDElMCMGA1UECwwcU3VidW5pdCBvZiBUZXN0IE9yZ2FuaXphdGlv +bjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAynY1eZHoou7v9DV+KYV1kGVa +YPig2e9o0WF5adfie/FncWVQMU6a+G8n6QULDnaVJJvCv5Dla0X941Ss1WKQTjfe +j66W9rNX6624RBNdpzR2wSZJkWc+XlJowRx/kceeAeK+p6jrP0Rtx8WCS5fZP8BR +mRsg3xKj5rtmRW204QcCAwEAAaM9MDswCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw +IQYDVR0RBBowGIIIdGVzdC5jb22CDGFsdC50ZXN0LmNvbTANBgkqhkiG9w0BAQUF +AAOCAQEAYcEYtAR5BQ65eS8OP6rxNuOQucaZJVNKBmRSkinFCUGmFnQbPE6BMsLY +VOAeCEXP8dCt6hEatc98mIrdwQHk0PWOYPp/53QtkUOBvZWSQWaEi4xw1y/ULzeC +j5rvwH3FVlaSegC2MGU3TGx6uszi3HPp9Sw8PjFn7j23eJaJur5PhaKogz5TIPC/ +KVDcIzhY2DP1e0oS3ys0TBzxdmuGlXRDKfdo8MoECImsl30FFKDKgVZc3cNWo1MB +CgFcVbQ5EBu+RxlYofLmDAiVsDVObIFtuc8OXHD/87SnlWkaWLeszCx5R34gF8w2 +viwQETEoY91vjY3pEerK/BAK4K5T2w== +-----END CERTIFICATE----- diff --git a/t/server_key.pem b/t/server_key.pem new file mode 100644 index 0000000..9e02ce4 --- /dev/null +++ b/t/server_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDKdjV5keii7u/0NX4phXWQZVpg+KDZ72jRYXlp1+J78WdxZVAx +Tpr4byfpBQsOdpUkm8K/kOVrRf3jVKzVYpBON96Prpb2s1frrbhEE12nNHbBJkmR +Zz5eUmjBHH+Rx54B4r6nqOs/RG3HxYJLl9k/wFGZGyDfEqPmu2ZFbbThBwIDAQAB +AoGBAItN/ItSVrRNHTN13wHovzSEWERiriJl9UQkAmtOTJqlRlyiriPPBxgrO1W8 +z5e7BfGzbrNqmkBOX1uctnL4J3tA7xFO6OnquDCLXhLc49mw+zxkcDP5ta1ROeiV +kIm8rSsvh8ks7StA17m5910rNfn5/IRHK6dC+G4FK7qLfCiRAkEA5Szy22sFeE4D +OM/wmCHpoOc0qA5k0FeyvnfGFKcAsVZ2+b/MPI2/KbB0uY/PWj43H6h9fEqMGVf6 +J7Ukas1N2QJBAOIozZjzfs3PQvKHMzOG3mQt+qSjsDKiEq/cPMIRPXYX5pS0+2Gz +mtUaikI+Nk5hekXqA2i+4uis9UhCzm+W+d8CQQCEo/ZPrmp1DdnpiNh8hKw+l3Kv +jd0lhIyMlrALhfjtqtijhjHEHlo0289DEwv09CtdZFx0koTxqiy7zKiuM/NJAkBZ +S2sB/QIQGMmCIMeijJm6TD0uTEMBeuSN8xM6PLxbqEwuYtbuWI/FnFkClrWydOJm +QGNgNB47aC7gfSAtBxtZAkBiCJcoVmXkm3rS7scUgCHrNhKH0G0nJbqjgfj57I31 +rCw34N6L+fyUozJQCBYdECyI1xG2eajqrMmnVZ046cjF +-----END RSA PRIVATE KEY----- diff --git a/t/ssl_cert_refresh.t b/t/ssl_cert_refresh.t new file mode 100644 index 0000000..6fdb37a --- /dev/null +++ b/t/ssl_cert_refresh.t @@ -0,0 +1,76 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use File::Copy; +use Test::More; +use FindBin qw($Bin); +use lib "$Bin/lib"; +use MemcachedTest; + +if (!enabled_tls_testing()) { + plan skip_all => 'SSL testing is not enabled'; + exit 0; +} + +my $cert = "t/". MemcachedTest::SRV_CRT; +my $key = "t/". MemcachedTest::SRV_KEY; +my $cert_back = "t/cert_back"; +my $key_back = "t/pkey_back"; +my $new_cert_key = "t/server.pem"; +my $default_crt_ou = "OU=Subunit of Test Organization"; + +my $server = new_memcached(); +my $stats = mem_stats($server->sock); +my $pid = $stats->{pid}; +my $sock = $server->sock; + +# This connection should return the default server certificate +# memcached was started with. +my $cert_details =$sock->dump_peer_certificate(); +$cert_details =~ m/(OU=([^\/\n]*))/; +is($1, $default_crt_ou, 'Got the default cert'); + +# Swap a new certificate with a key +copy($cert, $cert_back) or die "Cert backup failed: $!"; +copy($key, $key_back) or die "Key backup failed: $!"; +copy($new_cert_key, $cert) or die "New Cert copy failed: $!"; +copy($new_cert_key, $key) or die "New key copy failed: $!"; + +# Ask server to refresh certificates +print $sock "refresh_certs\r\n"; +is(scalar <$sock>, "OK\r\n", "refreshed certificates"); + +# New connections should use the new certificate +$cert_details = $server->new_sock->dump_peer_certificate(); +$cert_details =~ m/(OU=([^\/]*))/; +is($1, 'OU=FOR TESTING PURPOSES ONLY','Got the new cert'); +# Old connection should use the previous certificate +$cert_details =$sock->dump_peer_certificate(); +$cert_details =~ m/(OU=([^\/\n]*))/; +is($1, $default_crt_ou, 'Old connection still has the old cert'); + +# Just sleep a while to test the time_since_server_cert_refresh as it's counted +# in seconds. +sleep 2; +$stats = mem_stats($sock); + +# Restore and ensure previous certificate is back for new connections. +move($cert_back, $cert) or die "Cert restore failed: $!"; +move($key_back, $key) or die "Key restore failed: $!"; +print $sock "refresh_certs\r\n"; +is(scalar <$sock>, "OK\r\n", "refreshed certificates"); + + +$cert_details = $server->new_sock->dump_peer_certificate(); +$cert_details =~ m/(OU=([^\/\n]*))/; +is($1, $default_crt_ou, 'Got the old cert back'); + +my $stats_after = mem_stats($sock); + +# We should see last refresh time is reset; hence the new +# time_since_server_cert_refresh should be less. +cmp_ok($stats_after->{time_since_server_cert_refresh}, '<', + $stats->{time_since_server_cert_refresh}, 'Certs refreshed'); + +done_testing(); diff --git a/t/ssl_ports.t b/t/ssl_ports.t new file mode 100644 index 0000000..d717f63 --- /dev/null +++ b/t/ssl_ports.t @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use FindBin qw($Bin); +use lib "$Bin/lib"; +use MemcachedTest; + + +if (!enabled_tls_testing()) { + plan skip_all => 'SSL testing is not enabled'; + exit 0; +} + +my $tcp_port = free_port(); +my $ssl_port = free_port(); + +my $server = new_memcached("-l notls:127.0.0.1:$tcp_port,127.0.0.1:$ssl_port", $ssl_port); +my $sock = $server->sock; + +# Make sure we can talk over SSL +print $sock "set foo:123 0 0 16\r\nfoo set over SSL\r\n"; +is(scalar <$sock>, "STORED\r\n", "stored foo"); + + +#.. and TCP +my $tcp_sock = IO::Socket::INET->new(PeerAddr => "127.0.0.1:$tcp_port"); +mem_get_is($tcp_sock, "foo:123", "foo set over SSL"); + +done_testing() diff --git a/t/ssl_settings.t b/t/ssl_settings.t new file mode 100644 index 0000000..57f9668 --- /dev/null +++ b/t/ssl_settings.t @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use FindBin qw($Bin); +use lib "$Bin/lib"; +use MemcachedTest; +use Cwd; + +if (!enabled_tls_testing()) { + plan skip_all => 'SSL testing is not enabled'; + exit 0; +} + +my $server = new_memcached(); +my $settings = mem_stats($server->sock, ' settings'); + +my $cert = getcwd ."/t/". MemcachedTest::SRV_CRT; +my $key = getcwd ."/t/". MemcachedTest::SRV_KEY; + +is($settings->{'ssl_enabled'}, 'yes'); +is($settings->{'ssl_chain_cert'}, $cert); +is($settings->{'ssl_key'}, $key); +is($settings->{'ssl_verify_mode'}, 0); +is($settings->{'ssl_keyformat'}, 1); +is($settings->{'ssl_ciphers'}, 'NULL'); +is($settings->{'ssl_ca_cert'}, 'NULL'); +is($settings->{'ssl_wbuf_size'}, 16384); + +$server->DESTROY(); +$server = new_memcached("-o ssl_wbuf_size=64"); +$settings = mem_stats($server->sock, ' settings'); +is($settings->{'ssl_wbuf_size'},65536); + +done_testing(); diff --git a/t/ssl_verify_modes.t b/t/ssl_verify_modes.t new file mode 100644 index 0000000..4d6445c --- /dev/null +++ b/t/ssl_verify_modes.t @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use FindBin qw($Bin); +use lib "$Bin/lib"; +use MemcachedTest; +use Cwd; + +if (!enabled_tls_testing()) { + plan skip_all => 'SSL testing is not enabled'; + exit 0; +} + +my $ca_crt = getcwd() . "/t/" . MemcachedTest::CA_CRT; +my $server = new_memcached("-o ssl_verify_mode=2 -o ssl_ca_cert=$ca_crt"); +# just using stats to make sure everything is working fine. +my $stats = mem_stats($server->sock); +is($stats->{accepting_conns}, 1, "client cert is verified"); + +done_testing(); @@ -24,7 +24,12 @@ my $sock = $server->sock; my $stats = mem_stats($sock); # Test number of keys -is(scalar(keys(%$stats)), 70, "expected count of stats values"); +if (MemcachedTest::enabled_tls_testing()) { + # when TLS is enabled, stats contains time_since_server_cert_refresh + is(scalar(keys(%$stats)), 71, "expected count of stats values"); +} else { + is(scalar(keys(%$stats)), 70, "expected count of stats values"); +} # Test initial state foreach my $key (qw(curr_items total_items bytes cmd_get cmd_set get_hits evictions get_misses get_expired @@ -130,7 +135,13 @@ is('z', $v, 'got the expected value'); my $settings = mem_stats($sock, ' settings'); is(1024, $settings->{'maxconns'}); -isnt('NULL', $settings->{'domain_socket'}); +# we run SSL tests over TCP; hence the domain_socket +# is expected to be NULL. +if (enabled_tls_testing()) { + is('NULL', $settings->{'domain_socket'}); +} else { + isnt('NULL', $settings->{'domain_socket'}); +} is('on', $settings->{'evictions'}); is('yes', $settings->{'cas_enabled'}); is('no', $settings->{'auth_enabled_sasl'}); |