1'''
2'''
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#      http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing, software
14#  distributed under the License is distributed on an "AS IS" BASIS,
15#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16#  See the License for the specific language governing permissions and
17#  limitations under the License.
18
19Test.Summary = '''
20Test tls server certificate verification options. Exercise conf_remap
21'''
22
23# Define default ATS
24ts = Test.MakeATSProcess("ts", select_ports=True)
25server_foo = Test.MakeOriginServer("server_foo",
26                                   ssl=True,
27                                   options={"--key": "{0}/signed-foo.key".format(Test.RunDirectory),
28                                            "--cert": "{0}/signed-foo.pem".format(Test.RunDirectory)})
29server_bar = Test.MakeOriginServer("server_bar",
30                                   ssl=True,
31                                   options={"--key": "{0}/signed-bar.key".format(Test.RunDirectory),
32                                            "--cert": "{0}/signed-bar.pem".format(Test.RunDirectory)})
33server = Test.MakeOriginServer("server", ssl=True)
34
35dns = Test.MakeDNServer("dns")
36
37request_foo_header = {"headers": "GET / HTTP/1.1\r\nHost: foo.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
38request_bad_foo_header = {"headers": "GET / HTTP/1.1\r\nHost: bad_foo.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
39request_bar_header = {"headers": "GET / HTTP/1.1\r\nHost: bar.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
40request_bad_bar_header = {"headers": "GET / HTTP/1.1\r\nHost: bad_bar.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
41response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
42server_foo.addResponse("sessionlog.json", request_foo_header, response_header)
43server_foo.addResponse("sessionlog.json", request_bad_foo_header, response_header)
44server_bar.addResponse("sessionlog.json", request_bar_header, response_header)
45server_bar.addResponse("sessionlog.json", request_bad_bar_header, response_header)
46
47# add ssl materials like key, certificates for the server
48ts.addSSLfile("ssl/signed-foo.pem")
49ts.addSSLfile("ssl/signed-foo.key")
50ts.addSSLfile("ssl/signed-bar.pem")
51ts.addSSLfile("ssl/signed-bar.key")
52ts.addSSLfile("ssl/server.pem")
53ts.addSSLfile("ssl/server.key")
54ts.addSSLfile("ssl/signer.pem")
55ts.addSSLfile("ssl/signer.key")
56
57ts.Disk.remap_config.AddLine(
58    'map http://foo.com/basictobar https://bar.com:{0}'.format(server_bar.Variables.SSL_Port))
59ts.Disk.remap_config.AddLine(
60    'map http://foo.com/basic https://foo.com:{0}'.format(server_foo.Variables.SSL_Port))
61ts.Disk.remap_config.AddLine(
62    'map http://foo.com/override https://foo.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED'.format(
63        server_foo.Variables.SSL_Port))
64ts.Disk.remap_config.AddLine(
65    'map http://bar.com/basic https://bar.com:{0}'.format(server_foo.Variables.SSL_Port))
66ts.Disk.remap_config.AddLine(
67    'map http://bar.com/overridedisabled https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=DISABLED'.format(
68        server_foo.Variables.SSL_Port))
69ts.Disk.remap_config.AddLine(
70    'map http://bad_bar.com/overridedisabled https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=DISABLED'.format(
71        server_foo.Variables.SSL_Port))
72ts.Disk.remap_config.AddLine(
73    'map http://bar.com/overridesignature https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=SIGNATURE @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED'.format(
74        server_foo.Variables.SSL_Port))
75ts.Disk.remap_config.AddLine(
76    'map http://bar.com/overridenone https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NONE @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED"'.format(
77        server_foo.Variables.SSL_Port))
78ts.Disk.remap_config.AddLine(
79    'map http://bar.com/overrideenforced https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED'.format(
80        server_foo.Variables.SSL_Port))
81ts.Disk.remap_config.AddLine(
82    'map /basic https://random.com:{0}'.format(server.Variables.SSL_Port))
83ts.Disk.remap_config.AddLine(
84    'map /overrideenforce https://127.0.0.1:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED'.format(
85        server.Variables.SSL_Port))
86ts.Disk.remap_config.AddLine(
87    'map /overridename  https://127.0.0.1:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NAME'.format(
88        server.Variables.SSL_Port))
89ts.Disk.remap_config.AddLine(
90    'map /snipolicyfooremap  https://foo.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NAME @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED @plugin=conf_remap.so @pparam=proxy.config.ssl.client.sni_policy=remap'.format(
91        server_bar.Variables.SSL_Port))
92ts.Disk.remap_config.AddLine(
93    'map /snipolicyfoohost  https://foo.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NAME @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED @plugin=conf_remap.so @pparam=proxy.config.ssl.client.sni_policy=host'.format(
94        server_bar.Variables.SSL_Port))
95ts.Disk.remap_config.AddLine(
96    'map /snipolicybarremap  https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NAME @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED @plugin=conf_remap.so @pparam=proxy.config.ssl.client.sni_policy=remap'.format(
97        server_bar.Variables.SSL_Port))
98ts.Disk.remap_config.AddLine(
99    'map /snipolicybarhost  https://bar.com:{0} @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.properties=NAME @plugin=conf_remap.so @pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED @plugin=conf_remap.so @pparam=proxy.config.ssl.client.sni_policy=host'.format(
100        server_bar.Variables.SSL_Port))
101
102ts.Disk.ssl_multicert_config.AddLine(
103    'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
104)
105
106# Case 1, global config policy=permissive properties=signature
107#         override for foo.com policy=enforced properties=all
108ts.Disk.records_config.update({
109    'proxy.config.diags.debug.enabled': 1,
110    'proxy.config.diags.debug.tags': 'ssl',
111    'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
112    'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir),
113    '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',
114    # set global policy
115    'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE',
116    'proxy.config.ssl.client.verify.server.properties': 'ALL',
117    'proxy.config.ssl.client.CA.cert.path': '{0}'.format(ts.Variables.SSLDir),
118    'proxy.config.ssl.client.CA.cert.filename': 'signer.pem',
119    'proxy.config.url_remap.pristine_host_hdr': 1,
120    'proxy.config.dns.nameservers': '127.0.0.1:{0}'.format(dns.Variables.Port),
121    'proxy.config.dns.resolv_conf': 'NULL',
122    'proxy.config.exec_thread.autoconfig.scale': 1.0,
123    'proxy.config.ssl.client.sni_policy': 'remap',
124})
125
126dns.addRecords(records={"foo.com.": ["127.0.0.1"]})
127dns.addRecords(records={"bar.com.": ["127.0.0.1"]})
128dns.addRecords(records={"random.com.": ["127.0.0.1"]})
129
130# Should succeed without message
131tr = Test.AddTestRun("default-permissive-success")
132tr.Setup.Copy("ssl/signed-foo.key")
133tr.Setup.Copy("ssl/signed-foo.pem")
134tr.Setup.Copy("ssl/signed-bar.key")
135tr.Setup.Copy("ssl/signed-bar.pem")
136tr.Processes.Default.Command = 'curl -v -k -H \"host: foo.com\"  http://127.0.0.1:{0}/basic'.format(ts.Variables.port)
137tr.ReturnCode = 0
138tr.Processes.Default.StartBefore(dns)
139tr.Processes.Default.StartBefore(server_foo)
140tr.Processes.Default.StartBefore(server_bar)
141tr.Processes.Default.StartBefore(server)
142tr.Processes.Default.StartBefore(Test.Processes.ts)
143tr.StillRunningAfter = server
144tr.StillRunningAfter = ts
145# Should succeed.  No message
146tr.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
147tr.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
148
149tr2 = Test.AddTestRun("default-permissive-fail")
150tr2.Processes.Default.Command = "curl -v -k -H \"host: bar.com\"  http://127.0.0.1:{0}/basic".format(ts.Variables.port)
151tr2.ReturnCode = 0
152tr2.StillRunningAfter = server
153tr2.StillRunningAfter = ts
154# Should succeed, but will be message in log about name mismatch
155tr2.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
156tr2.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
157
158tr2 = Test.AddTestRun("default-permissive-fail2")
159tr2.Processes.Default.Command = "curl -v -k -H \"host: random.com\"  http://127.0.0.1:{0}/basic".format(ts.Variables.port)
160tr2.ReturnCode = 0
161tr2.StillRunningAfter = server
162tr2.StillRunningAfter = ts
163# Should succeed, but will be message in log about signature
164tr2.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
165tr2.Processes.Default.Streams.All += Testers.ContainsExpression("404 Not Found", "Curl attempt should have succeeded")
166
167tr3 = Test.AddTestRun("default-foo-to-bar")
168tr3.Processes.Default.Command = "curl -k -v -H \"host: foo.com\"  http://127.0.0.1:{0}/basictobar".format(ts.Variables.port)
169tr3.ReturnCode = 0
170tr3.StillRunningAfter = server
171tr3.StillRunningAfter = ts
172# Should succeed.  No error messages
173tr3.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
174tr3.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
175
176tr3 = Test.AddTestRun("override-foo")
177tr3.Processes.Default.Command = "curl -k -v -H \"host: foo.com\"  http://127.0.0.1:{0}/override".format(ts.Variables.port)
178tr3.ReturnCode = 0
179tr3.StillRunningAfter = server
180tr3.StillRunningAfter = ts
181# Should succeed.  No error messages
182tr3.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
183tr3.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
184
185tr4 = Test.AddTestRun("override-bar-disabled")
186tr4.Processes.Default.Command = "curl -k -v -H \"host: bad_bar.com\"  http://127.0.0.1:{0}/overridedisabled".format(
187    ts.Variables.port)
188tr4.ReturnCode = 0
189tr4.StillRunningAfter = server
190tr4.StillRunningAfter = ts
191# Succeed. No error messages
192tr4.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
193tr4.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
194
195tr5 = Test.AddTestRun("override-bar-signature-enforced")
196tr5.Processes.Default.Command = "curl -k -v -H \"host: bar.com\"  http://127.0.0.1:{0}/overridesignature".format(ts.Variables.port)
197tr5.ReturnCode = 0
198tr5.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
199tr5.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
200tr5.StillRunningAfter = server
201tr5.StillRunningAfter = ts
202
203tr5a = Test.AddTestRun("override-bar-none-permissive")
204tr5a.Processes.Default.Command = "curl -k -v -H \"host: bar.com\"  http://127.0.0.1:{0}/overridenone".format(ts.Variables.port)
205tr5a.ReturnCode = 0
206tr5a.Processes.Default.Streams.All = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")
207tr5a.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
208tr5a.StillRunningAfter = server
209tr5a.StillRunningAfter = ts
210
211tr6 = Test.AddTestRun("override-bar-enforced")
212tr6.Processes.Default.Command = "curl -v -k -H \"host: bar.com\"  http://127.0.0.1:{0}/overrideenforced".format(ts.Variables.port)
213tr6.ReturnCode = 0
214# Should fail
215tr6.Processes.Default.Streams.All = Testers.ContainsExpression("Could Not Connect", "Curl attempt should have failed")
216tr6.StillRunningAfter = server
217tr6.StillRunningAfter = ts
218
219# Should succeed
220tr = Test.AddTestRun("foo-to-bar-sni-policy-remap")
221tr.Processes.Default.Command = "curl -v -k -H \"host: foo.com\"  http://127.0.0.1:{0}/snipolicybarremap".format(ts.Variables.port)
222tr.ReturnCode = 0
223tr.StillRunningAfter = server
224tr.StillRunningAfter = ts
225tr.Processes.Default.Streams.All = Testers.ExcludesExpression("Could not connect", "Curl attempt should succeed")
226tr.Processes.Default.Streams.All += Testers.ContainsExpression("200 OK", "Curl attempt should have succeeded")
227
228# Should fail
229tr = Test.AddTestRun("foo-to-bar-sni-policy-host")
230tr.Processes.Default.Command = "curl -v -k -H \"host: foo.com\"  http://127.0.0.1:{0}/snipolicybarhost".format(ts.Variables.port)
231tr.ReturnCode = 0
232tr.StillRunningAfter = server
233tr.StillRunningAfter = ts
234tr.Processes.Default.Streams.All = Testers.ContainsExpression("Could not connect", "Curl attempt should fail")
235
236# Should fail
237tr = Test.AddTestRun("bar-to-foo-sni-policy-remap")
238tr.Processes.Default.Command = "curl -v -k -H \"host: bar.com\"  http://127.0.0.1:{0}/snipolicyfooremap".format(ts.Variables.port)
239tr.ReturnCode = 0
240tr.StillRunningAfter = server
241tr.StillRunningAfter = ts
242tr.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could not connect", "Curl attempt should fail")
243
244# Should succeed
245tr = Test.AddTestRun("bar-to-foo-sni-policy-host")
246tr.Processes.Default.Command = "curl -v -k -H \"host: bar.com\"  http://127.0.0.1:{0}/snipolicyfoohost".format(ts.Variables.port)
247tr.ReturnCode = 0
248tr.StillRunningAfter = server
249tr.StillRunningAfter = ts
250tr.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could not connect", "Curl attempt should succeed")
251
252# Over riding the built in ERROR check since we expect some cases to fail
253
254# checks on random.com should fail with message only
255ts.Disk.diags_log.Content = Testers.ContainsExpression(
256    r"WARNING: Core server certificate verification failed for \(random.com\). Action=Continue Error=self signed certificate server=random.com\(127.0.0.1\) depth=0",
257    "Warning for self signed certificate")
258# permissive failure for bar.com
259ts.Disk.diags_log.Content += Testers.ContainsExpression(
260    r"WARNING: SNI \(bar.com\) not in certificate. Action=Continue server=bar.com\(127.0.0.1\)",
261    "Warning on missing name for bar.com")
262# name check failure for random.com
263ts.Disk.diags_log.Content += Testers.ContainsExpression(
264    r"WARNING: SNI \(random.com\) not in certificate. Action=Continue server=random.com\(127.0.0.1\)",
265    "Warning on missing name for randome.com")
266# name check failure for bar.com
267ts.Disk.diags_log.Content += Testers.ContainsExpression(
268    r"WARNING: SNI \(bar.com\) not in certificate. Action=Terminate server=bar.com\(127.0.0.1\)",
269    "Failure on missing name for bar.com")
270# See if the explicitly set default sni_policy of remap works.
271ts.Disk.diags_log.Content += Testers.ExcludesExpression(
272    "WARNING: SNI \(foo.com\) not in certificate. Action=Continue", "Warning on missing name for foo.com")
273