summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rwxr-xr-xt/binary.t34
-rw-r--r--t/cacert.pem22
-rw-r--r--t/cakey.pem30
-rw-r--r--t/client_crt.pem68
-rw-r--r--t/client_key.pem15
-rw-r--r--t/idle-timeout.t8
-rw-r--r--t/lib/MemcachedTest.pm86
-rwxr-xr-xt/misbehave.t2
-rwxr-xr-xt/multiversioning.t12
-rw-r--r--t/noreply.t1
-rw-r--r--t/server.pem79
-rw-r--r--t/server_crt.pem67
-rw-r--r--t/server_key.pem15
-rw-r--r--t/ssl_cert_refresh.t76
-rw-r--r--t/ssl_ports.t31
-rw-r--r--t/ssl_settings.t36
-rw-r--r--t/ssl_verify_modes.t22
-rwxr-xr-xt/stats.t15
18 files changed, 598 insertions, 21 deletions
diff --git a/t/binary.t b/t/binary.t
index 90da1c6..1c6568a 100755
--- a/t/binary.t
+++ b/t/binary.t
@@ -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();
diff --git a/t/stats.t b/t/stats.t
index d62f015..aa421ae 100755
--- a/t/stats.t
+++ b/t/stats.t
@@ -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'});