This is an automated email from the ASF dual-hosted git repository.
bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new a28ef5e Fix and add tests for requiring TLS certs from user agent.
a28ef5e is described below
commit a28ef5e72316049ae5b56889ef84b5bb96313a20
Author: Susan Hinrichs <[email protected]>
AuthorDate: Mon Nov 19 20:51:09 2018 +0000
Fix and add tests for requiring TLS certs from user agent.
---
iocore/net/SSLUtils.cc | 2 +-
tests/gold_tests/tls/ssl/server.key | 43 +++++---
tests/gold_tests/tls/ssl/server.pem | 49 ++++----
tests/gold_tests/tls/tls_client_verify.test.py | 141 ++++++++++++++++++++++++
tests/gold_tests/tls/tls_client_verify2.test.py | 129 ++++++++++++++++++++++
5 files changed, 318 insertions(+), 46 deletions(-)
diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
index bceae8b..c5a2915 100644
--- a/iocore/net/SSLUtils.cc
+++ b/iocore/net/SSLUtils.cc
@@ -403,7 +403,7 @@ ssl_verify_client_callback(int preverify_ok, X509_STORE_CTX
*ctx)
SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
netvc->callHooks(TS_EVENT_SSL_VERIFY_CLIENT);
- return SSL_TLSEXT_ERR_OK;
+ return preverify_ok;
}
// Use the certificate callback for openssl 1.0.2 and greater
diff --git a/tests/gold_tests/tls/ssl/server.key
b/tests/gold_tests/tls/ssl/server.key
index 4c7a661..9cdfc36 100644
--- a/tests/gold_tests/tls/ssl/server.key
+++ b/tests/gold_tests/tls/ssl/server.key
@@ -1,15 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDWMHOiUF+ORmZjAxI8MWE9dblb7gQSJ36WCXlPFiFx6ynF+S1E
-kXAYpIip5X0pzDUaIbLukxJUAAnOtMEO0PCgxJQUrEtRWh8wiJdbdQJF0Zs/9R+u
-SUgb61f+mdTQvhqefBGx+xrpfAcgtcWiZuSA9Q3fvpDj5WOWSPWXBUuxywIDAQAB
-AoGBAJPxRX2gjFAGWmQbU/YVmXfNH6navh8X/nx9sLeqrpE0AFeJI/ZPiqDKzMal
-B43eSfNxwVi+ZxN0L1ICUbL9KKZvHs/QBxWLA1fGVAXrz7sRplEVvakPpTfHoEnv
-sKaMWVKaK/S5WGbDhElb6zb/Lwo19DsIAPjGYqFvzFJBmobJAkEA9iSeTGkR9X26
-GywZoYrIMlRh34htOIRx1UUq88rFzdrCF21kQ4lhBIkX5OZMMy652i2gyak4OZTe
-YewIv8jw9QJBAN7EQNHG8jPwXfVp91/fqxVQEfumuP2i6uiWWYQgZCmla2+0xcLZ
-pMQ6sQEe10hhTrVnzHgAUVp50Ntn2jwBX78CQF09veGAI9d1Cxzj9cmmAvRd1r2Q
-tp8kPOLnUsALXib+6WtqewLCdcf8DtsdClyRJMIraq85tRzK8fryKNZNzkkCQEgA
-yS7FDj5JgCU15hZgFk1iPx3HCt44jZM2HaL+UUHAzRQjKxTLAl3G1rWVAWLMyQML
-lORoveLvotl4HOruSsMCQQCAx9dV9JUSFoyc1CWILp/FgUH/se4cjQCThGO0DoQQ
-vGTYmntY7j9WRJ9esQrjdD6Clw8zM/45GIBNwnXzqo7Z
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCZkEXSlZ+ZFKFg
+CPpcDG39e73BuK6E5uE38q2PHh4DV0xcsJnIUx51viqLPwYughxfP0crHyBdXoHV
+dW/3WX4gpiGrdiM/dvCouheo0DPaqUUJ2nZKVYh2M57oyeiuJidlKb7BGkfw3HWP
+9TV7dVyGWok/cowjopqaLHJWxg/kh2KqvUBD0CHt9Kd1XvgXVmHwE7vCv0j5owv2
+MaExTsFb16uWmVLhl1gNHI2RqCX2yLaebH1DvtbLrit1XErjtaSYeJE9clVRaqT6
+vsvLOhyB5tA9WfZqfBYr/MHDeXQfrbIf+4Cp3aTpq5grc5InIMMH0eOk6/f/4tW+
+nq1lfszZAgMBAAECggEAYvYAqRbXRRVwca0Xel5gO2yU+tSDUw5esWlow8RK3yhR
+A6KjV9+Iz6P/UsEIwMwEcLUcrgNfHgybau5Fe4dmqq+lHxQA3xNNP869FIMoB4/x
+98mbVYgNau8VRztnAWOBG8ZtMZA4MFZCRMVm8+rL96E8tXCiMwzEyPo/rP/ymfhN
+3GRunX+GhfIA79AYNbd7HMVL+cvWWUGUF5Bc5i1wXcLy4I7b9NYtv920BeCLzSFK
+BypFB7ku/vKgTcBxe4yxThxPeXPwm4WFzGYKk/Afl1j8tVXCE2U4Y3yykfC0Qk6S
+ECZbCKLO2Rxi9fclIDZBHWuKejZhdjHfjeNvZ2vLoQKBgQDJzLmkVLvWAxgl1yvF
+U7gwqj/TzYqtVowbjEvTNEnPU1j/hIVI343SVV/EvJmif/iRUop6sRYfLsUjpMsH
+CmPysNKL3UtgSYOxLs+0xLhG4OOQRpPSf/uvl9YyWY9G3AqiC7ScthkQjEhZa4c1
+eycYy0jr42kX0OL9MuIH9q0ENQKBgQDCzvGKMs8r5E/Qd3YB9VYB60dx+6G83AHZ
+YqIelykObhCdxL9n4K+p4VKKLvgTcCOLYYIkBSWRJWR+ue3s3ey9+XWd2/q4Xvfh
+TCjAuO2ibMV+y5ClNlW0fQ/doIVWSDbjO2tZW1jh7YWZ4CtuVrsEisv1sk3KltMB
+MguhpTUylQKBgG6TfrncMFzxrx61C+gBmvEXqQffHfkjbnx94OKnSTaQ3jiNHhez
+X9v8KhD8o1bWtpay2uyl8pA9qYqBdzqxZ9kJKSW4qd/mCIJjOy87iBpWint5IPD8
+biZmldlbF9ZlJnJq5ZnlclCN/er5r8oPZHoCkj+nieOh8294nUBt25ptAoGAMnPA
+EIeaKgbmONpHgLhWPwb9KOL/f1cHT5KA5CVH58nPmdyTqcaCGCAX7Vu+ueIIApgN
+SWDf2thxT3S9zuOm5YiO0oRfSZKm5f2AbHE4ciFzgKQd4PvSdH0TN9XT0oW/WVhR
+NAI5YcHPIQvyk4/4vXNo4Uf9Z6NqIFwisQmFXoUCgYBK/ZI/HsFsvnR5MV0tFdGM
+AdNe6bsQRSZkowoaPxuWbklE4Hn6QvwEmQg3ST2O+vCQV1f1yI6YiWYoptOYscJc
+MSs/HxhhaaO5ZsiuPUO6WEPzpNb2CxuIGDDtl83VtUQyjxCmOb6pqqjwzFmZ2bsw
+JNMaBCzokrJTxknvauCuSQ==
+-----END PRIVATE KEY-----
diff --git a/tests/gold_tests/tls/ssl/server.pem
b/tests/gold_tests/tls/ssl/server.pem
index 58b9b97..2b56cc8 100644
--- a/tests/gold_tests/tls/ssl/server.pem
+++ b/tests/gold_tests/tls/ssl/server.pem
@@ -1,32 +1,21 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDWMHOiUF+ORmZjAxI8MWE9dblb7gQSJ36WCXlPFiFx6ynF+S1E
-kXAYpIip5X0pzDUaIbLukxJUAAnOtMEO0PCgxJQUrEtRWh8wiJdbdQJF0Zs/9R+u
-SUgb61f+mdTQvhqefBGx+xrpfAcgtcWiZuSA9Q3fvpDj5WOWSPWXBUuxywIDAQAB
-AoGBAJPxRX2gjFAGWmQbU/YVmXfNH6navh8X/nx9sLeqrpE0AFeJI/ZPiqDKzMal
-B43eSfNxwVi+ZxN0L1ICUbL9KKZvHs/QBxWLA1fGVAXrz7sRplEVvakPpTfHoEnv
-sKaMWVKaK/S5WGbDhElb6zb/Lwo19DsIAPjGYqFvzFJBmobJAkEA9iSeTGkR9X26
-GywZoYrIMlRh34htOIRx1UUq88rFzdrCF21kQ4lhBIkX5OZMMy652i2gyak4OZTe
-YewIv8jw9QJBAN7EQNHG8jPwXfVp91/fqxVQEfumuP2i6uiWWYQgZCmla2+0xcLZ
-pMQ6sQEe10hhTrVnzHgAUVp50Ntn2jwBX78CQF09veGAI9d1Cxzj9cmmAvRd1r2Q
-tp8kPOLnUsALXib+6WtqewLCdcf8DtsdClyRJMIraq85tRzK8fryKNZNzkkCQEgA
-yS7FDj5JgCU15hZgFk1iPx3HCt44jZM2HaL+UUHAzRQjKxTLAl3G1rWVAWLMyQML
-lORoveLvotl4HOruSsMCQQCAx9dV9JUSFoyc1CWILp/FgUH/se4cjQCThGO0DoQQ
-vGTYmntY7j9WRJ9esQrjdD6Clw8zM/45GIBNwnXzqo7Z
------END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-MIICszCCAhwCCQD4jSkztmlO1TANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC
-VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh
-aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u
-ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j
-b20wHhcNMTcwODI4MDM0NDQ1WhcNMjcwODI2MDM0NDQ1WjCBnTELMAkGA1UEBhMC
-VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh
-aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u
-ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j
-b20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYwc6JQX45GZmMDEjwxYT11
-uVvuBBInfpYJeU8WIXHrKcX5LUSRcBikiKnlfSnMNRohsu6TElQACc60wQ7Q8KDE
-lBSsS1FaHzCIl1t1AkXRmz/1H65JSBvrV/6Z1NC+Gp58EbH7Gul8ByC1xaJm5ID1
-Dd++kOPlY5ZI9ZcFS7HLAgMBAAEwDQYJKoZIhvcNAQELBQADgYEATX7975NdhIbJ
-glda+sXI9a86GgOpiuKO+vKubRJQZA+UlPf2vHEONjC2+7Y1aZvZYaKYL74vxGky
-zkgp6ANSPl45lqD632x0e1Z7vzW5TkqK1JB2/xH2WgDcQZmP0FuQHzVNs4GjghDr
-HCp1+sQDhfPB4aLmLFeyN0TkhdH1N3M=
+MIIDZDCCAkygAwIBAgIJANod1+h9CtCaMA0GCSqGSIb3DQEBCwUAMEcxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIDAJJTDEPMA0GA1UECgwGQXBhY2hlMRowGAYDVQQDDBFy
+YW5kb20uc2VydmVyLmNvbTAeFw0xODExMTkxNzEwMTlaFw0yODExMTYxNzEwMTla
+MEcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJJTDEPMA0GA1UECgwGQXBhY2hlMRow
+GAYDVQQDDBFyYW5kb20uc2VydmVyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAJmQRdKVn5kUoWAI+lwMbf17vcG4roTm4TfyrY8eHgNXTFywmchT
+HnW+Kos/Bi6CHF8/RysfIF1egdV1b/dZfiCmIat2Iz928Ki6F6jQM9qpRQnadkpV
+iHYznujJ6K4mJ2UpvsEaR/DcdY/1NXt1XIZaiT9yjCOimposclbGD+SHYqq9QEPQ
+Ie30p3Ve+BdWYfATu8K/SPmjC/YxoTFOwVvXq5aZUuGXWA0cjZGoJfbItp5sfUO+
+1suuK3VcSuO1pJh4kT1yVVFqpPq+y8s6HIHm0D1Z9mp8Fiv8wcN5dB+tsh/7gKnd
+pOmrmCtzkicgwwfR46Tr9//i1b6erWV+zNkCAwEAAaNTMFEwHQYDVR0OBBYEFI2y
+qm0+UAChDAnLrAINeFOuyUlhMB8GA1UdIwQYMBaAFI2yqm0+UAChDAnLrAINeFOu
+yUlhMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA3ZNFbqxcOX
+szS5A4EXCepyBJBFejEYy0CsvwQX/ai/pMrw5jqVeF0GAOTpBCVLddyY+ZV1arD2
+Pqi7Qwot9OxEZOzbCBiuMJGotruKgnWFQDHzJ9HA7KDQs270uNESAOG/xW9os9zN
+MXApzqfBSR5EIQU5L3RtaiPzoKdQenGQUOj86s0Kon7snDSUzaA2VcfstMWgGvXP
+JHtaVusULm0gry32cEap5G5UK+gII6DfLWgFwFGhHHmTz3mKjyGiJQ+09XBtu4lb
+ENE+HGRBBA49dUKSr3kwErO4HyHnS0YrsTDnbYURCsGUDma12oijX2sCos6Q4zn8
+3svaouRrucw=
-----END CERTIFICATE-----
diff --git a/tests/gold_tests/tls/tls_client_verify.test.py
b/tests/gold_tests/tls/tls_client_verify.test.py
new file mode 100644
index 0000000..d629853
--- /dev/null
+++ b/tests/gold_tests/tls/tls_client_verify.test.py
@@ -0,0 +1,141 @@
+'''
+Test requiring certificate from user agent
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import re
+
+Test.Summary = '''
+Test various options for requiring certificate from client for mutual
authentication TLS
+'''
+
+Test.SkipUnless(Condition.HasProgram("grep", "grep needs to be installed on
system for this test to work"))
+
+ts = Test.MakeATSProcess("ts", select_ports=False)
+cafile = "{0}/signer.pem".format(Test.RunDirectory)
+cafile2 = "{0}/signer2.pem".format(Test.RunDirectory)
+server = Test.MakeOriginServer("server")
+
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionlog.json", request_header, response_header)
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: bar.com\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionlog.json", request_header, response_header)
+
+ts.addSSLfile("ssl/server.pem")
+ts.addSSLfile("ssl/server.key")
+ts.addSSLfile("ssl/signer.pem")
+
+ts.Variables.ssl_port = 4443
+ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'ssl',
+ 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
+ 'proxy.config.ssl.server.private_key.path':
'{0}'.format(ts.Variables.SSLDir),
+ 'proxy.config.http.server_ports': '{0}:ssl'.format(ts.Variables.ssl_port),
+ 'proxy.config.ssl.client.verify.server': 0,
+ 'proxy.config.ssl.server.cipher_suite':
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2',
+ 'proxy.config.url_remap.pristine_host_hdr' : 1,
+ 'proxy.config.ssl.client.certification_level': 2,
+ 'proxy.config.ssl.CA.cert.filename':
'{0}/signer.pem'.format(ts.Variables.SSLDir),
+ 'proxy.config.ssl.TLSv1_3': 0
+})
+
+ts.Disk.ssl_multicert_config.AddLine(
+ 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
+)
+
+# Just map everything through to origin. This test is concentratign on the
user-agent side
+ts.Disk.remap_config.AddLine(
+ 'map / http://127.0.0.1:{0}/'.format(server.Variables.Port)
+)
+
+# Scenario 1: Default no client cert required. cert required for bar.com
+ts.Disk.ssl_server_name_yaml.AddLines([
+ '- fqdn: bar.com',
+ ' verify_client: NONE',
+])
+
+# to foo.com w/o client cert. Should fail
+tr = Test.AddTestRun("Connect to foo.com without cert")
+tr.Processes.Default.StartBefore(Test.Processes.ts,
ready=When.PortOpen(ts.Variables.ssl_port))
+tr.Processes.Default.StartBefore(server)
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve
'foo.com:{0}:127.0.0.1' https://foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 35
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert", "TLS
handshake should fail")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to foo.com with bad cert")
+tr.Setup.Copy("ssl/server.pem")
+tr.Setup.Copy("ssl/server.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key
server.key --resolve 'foo.com:{0}:127.0.0.1'
https://foo.com:{0}/case1".format(ts.Variables.ssl_port)
+# Should fail with badly signed certs
+tr.Processes.Default.ReturnCode = 35
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert unknown
ca", "TLS handshake should fail")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to foo.com with cert")
+tr.Setup.Copy("ssl/signed-foo.pem")
+tr.Setup.Copy("ssl/signed-foo.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert signed-foo.pem
--key signed-foo.key --resolve 'foo.com:{0}:127.0.0.1'
https://foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com without cert")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve
'bar.com:{0}:127.0.0.1' https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("alert", "TLS
handshake should succeed")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com with cert")
+tr.Setup.Copy("ssl/signed-bar.pem")
+tr.Setup.Copy("ssl/signed-bar.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert signed-bar.pem
--key signed-bar.key --resolve 'bar.com:{0}:127.0.0.1'
https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com with bad cert")
+tr.Setup.Copy("ssl/server.pem")
+tr.Setup.Copy("ssl/server.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key
server.key --resolve 'bar.com:{0}:127.0.0.1'
https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+# Should fail with badly signed certs
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check
response")
+tr.TimeOut = 5
+
diff --git a/tests/gold_tests/tls/tls_client_verify2.test.py
b/tests/gold_tests/tls/tls_client_verify2.test.py
new file mode 100644
index 0000000..8848dc2
--- /dev/null
+++ b/tests/gold_tests/tls/tls_client_verify2.test.py
@@ -0,0 +1,129 @@
+'''
+Test requiring certificate from user agent
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import re
+
+Test.Summary = '''
+Test various options for requiring certificate from client for mutual
authentication TLS
+'''
+
+Test.SkipUnless(Condition.HasProgram("grep", "grep needs to be installed on
system for this test to work"))
+
+ts = Test.MakeATSProcess("ts", select_ports=False)
+cafile = "{0}/signer.pem".format(Test.RunDirectory)
+cafile2 = "{0}/signer2.pem".format(Test.RunDirectory)
+server = Test.MakeOriginServer("server")
+
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionlog.json", request_header, response_header)
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: bar.com\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n",
"timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionlog.json", request_header, response_header)
+
+ts.addSSLfile("ssl/server.pem")
+ts.addSSLfile("ssl/server.key")
+ts.addSSLfile("ssl/signer.pem")
+
+ts.Variables.ssl_port = 4443
+ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'ssl',
+ 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
+ 'proxy.config.ssl.server.private_key.path':
'{0}'.format(ts.Variables.SSLDir),
+ 'proxy.config.http.server_ports': '{0}:ssl'.format(ts.Variables.ssl_port),
+ 'proxy.config.ssl.client.verify.server': 0,
+ 'proxy.config.ssl.server.cipher_suite':
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2',
+ 'proxy.config.url_remap.pristine_host_hdr' : 1,
+ 'proxy.config.ssl.client.certification_level': 0,
+ 'proxy.config.ssl.CA.cert.path': '',
+ 'proxy.config.ssl.CA.cert.filename':
'{0}/signer.pem'.format(ts.Variables.SSLDir)
+})
+
+ts.Disk.ssl_multicert_config.AddLine(
+ 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
+)
+
+# Just map everything through to origin. This test is concentratign on the
user-agent side
+ts.Disk.remap_config.AddLine(
+ 'map / http://127.0.0.1:{0}/'.format(server.Variables.Port)
+)
+
+# Scenario 1: Default no client cert required. cert required for bar.com
+ts.Disk.ssl_server_name_yaml.AddLines([
+ '- fqdn: bar.com',
+ ' verify_client: STRICT',
+])
+
+# to foo.com w/o client cert. Should succeed
+tr = Test.AddTestRun("Connect to foo.com without cert")
+tr.Processes.Default.StartBefore(Test.Processes.ts,
ready=When.PortOpen(ts.Variables.ssl_port))
+tr.Processes.Default.StartBefore(server)
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve
'foo.com:{0}:127.0.0.1' https://foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to foo.com with cert")
+tr.Setup.Copy("ssl/signed-foo.pem")
+tr.Setup.Copy("ssl/signed-foo.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert signed-foo.pem
--key signed-foo.key --resolve 'foo.com:{0}:127.0.0.1'
https://foo.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com without cert")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --resolve
'bar.com:{0}:127.0.0.1' https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 35
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert", "TLS
handshake should fail")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com with cert")
+tr.Setup.Copy("ssl/signed-bar.pem")
+tr.Setup.Copy("ssl/signed-bar.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert signed-bar.pem
--key signed-bar.key --resolve 'bar.com:{0}:127.0.0.1'
https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression("error", "Check
response")
+tr.TimeOut = 5
+
+tr = Test.AddTestRun("Connect to bar.com with bad cert")
+tr.Setup.Copy("ssl/server.pem")
+tr.Setup.Copy("ssl/server.key")
+tr.StillRunningAfter = ts
+tr.StillRunningAfter = server
+tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert server.pem --key
server.key --resolve 'bar.com:{0}:127.0.0.1'
https://bar.com:{0}/case1".format(ts.Variables.ssl_port)
+# Should fail with badly signed certs
+tr.Processes.Default.ReturnCode = 35
+tr.Processes.Default.TimeOut = 5
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("alert unknown
ca", "TLS handshake should fail")
+tr.TimeOut = 5
+