OLD | NEW |
1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """This is a simple HTTP server used for testing Chrome. | 6 """This is a simple HTTP server used for testing Chrome. |
7 | 7 |
8 It supports several test URLs, as specified by the handlers in TestPageHandler. | 8 It supports several test URLs, as specified by the handlers in TestPageHandler. |
9 By default, it listens on an ephemeral port and sends the port number back to | 9 By default, it listens on an ephemeral port and sends the port number back to |
10 the originating process over a pipe. The originating process can specify an | 10 the originating process over a pipe. The originating process can specify an |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 self.stop = False | 66 self.stop = False |
67 self.nonce_time = None | 67 self.nonce_time = None |
68 while not self.stop: | 68 while not self.stop: |
69 self.handle_request() | 69 self.handle_request() |
70 self.socket.close() | 70 self.socket.close() |
71 | 71 |
72 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer): | 72 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer): |
73 """This is a specialization of StoppableHTTPerver that add https support.""" | 73 """This is a specialization of StoppableHTTPerver that add https support.""" |
74 | 74 |
75 def __init__(self, server_address, request_hander_class, cert_path, | 75 def __init__(self, server_address, request_hander_class, cert_path, |
76 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers): | 76 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, |
| 77 use_tls_srp, only_tls_srp): |
77 s = open(cert_path).read() | 78 s = open(cert_path).read() |
78 x509 = tlslite.api.X509() | 79 x509 = tlslite.api.X509() |
79 x509.parse(s) | 80 x509.parse(s) |
80 self.cert_chain = tlslite.api.X509CertChain([x509]) | 81 self.cert_chain = tlslite.api.X509CertChain([x509]) |
81 s = open(cert_path).read() | 82 s = open(cert_path).read() |
82 self.private_key = tlslite.api.parsePEMKey(s, private=True) | 83 self.private_key = tlslite.api.parsePEMKey(s, private=True) |
83 self.ssl_client_auth = ssl_client_auth | 84 self.ssl_client_auth = ssl_client_auth |
84 self.ssl_client_cas = [] | 85 self.ssl_client_cas = [] |
85 for ca_file in ssl_client_cas: | 86 for ca_file in ssl_client_cas: |
86 s = open(ca_file).read() | 87 s = open(ca_file).read() |
87 x509 = tlslite.api.X509() | 88 x509 = tlslite.api.X509() |
88 x509.parse(s) | 89 x509.parse(s) |
89 self.ssl_client_cas.append(x509.subject) | 90 self.ssl_client_cas.append(x509.subject) |
90 self.ssl_handshake_settings = tlslite.api.HandshakeSettings() | 91 self.ssl_handshake_settings = tlslite.api.HandshakeSettings() |
91 if ssl_bulk_ciphers is not None: | 92 if ssl_bulk_ciphers is not None: |
92 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers | 93 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers |
| 94 self.only_tls_srp = only_tls_srp |
| 95 self.srp_verifier_db = None |
| 96 if use_tls_srp: |
| 97 # Make dummy SRP verifier database |
| 98 self.srp_verifier_db = tlslite.api.VerifierDB() |
| 99 self.srp_verifier_db.create() |
| 100 entry = tlslite.api.VerifierDB.makeVerifier('user', 'secret', 1536) |
| 101 self.srp_verifier_db['user'] = entry |
93 | 102 |
94 self.session_cache = tlslite.api.SessionCache() | 103 self.session_cache = tlslite.api.SessionCache() |
95 StoppableHTTPServer.__init__(self, server_address, request_hander_class) | 104 StoppableHTTPServer.__init__(self, server_address, request_hander_class) |
96 | 105 |
97 def handshake(self, tlsConnection): | 106 def handshake(self, tlsConnection): |
98 """Creates the SSL connection.""" | 107 """Creates the SSL connection.""" |
99 try: | 108 try: |
100 tlsConnection.handshakeServer(certChain=self.cert_chain, | 109 if not self.only_tls_srp: |
101 privateKey=self.private_key, | 110 tlsConnection.handshakeServer(certChain=self.cert_chain, |
102 sessionCache=self.session_cache, | 111 privateKey=self.private_key, |
103 reqCert=self.ssl_client_auth, | 112 sessionCache=self.session_cache, |
104 settings=self.ssl_handshake_settings, | 113 reqCert=self.ssl_client_auth, |
105 reqCAs=self.ssl_client_cas) | 114 settings=self.ssl_handshake_settings, |
| 115 reqCAs=self.ssl_client_cas, |
| 116 verifierDB=self.srp_verifier_db) |
| 117 else: |
| 118 tlsConnection.handshakeServer(verifierDB=self.srp_verifier_db) |
106 tlsConnection.ignoreAbruptClose = True | 119 tlsConnection.ignoreAbruptClose = True |
| 120 self.tlsConnection = tlsConnection |
107 return True | 121 return True |
108 except tlslite.api.TLSAbruptCloseError: | 122 except tlslite.api.TLSAbruptCloseError: |
109 # Ignore abrupt close. | 123 # Ignore abrupt close. |
110 return True | 124 return True |
111 except tlslite.api.TLSError, error: | 125 except tlslite.api.TLSError, error: |
112 print "Handshake failure:", str(error) | 126 print "Handshake failure:", str(error) |
113 return False | 127 return False |
114 | 128 |
115 | 129 |
116 class SyncHTTPServer(StoppableHTTPServer): | 130 class SyncHTTPServer(StoppableHTTPServer): |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 asyncore.dispatcher.handle_write_event) | 218 asyncore.dispatcher.handle_write_event) |
205 | 219 |
206 for fd in exceptional_fds: | 220 for fd in exceptional_fds: |
207 HandleXmppSocket(fd, self._xmpp_socket_map, | 221 HandleXmppSocket(fd, self._xmpp_socket_map, |
208 asyncore.dispatcher.handle_expt_event) | 222 asyncore.dispatcher.handle_expt_event) |
209 | 223 |
210 | 224 |
211 class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler): | 225 class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
212 | 226 |
213 def __init__(self, request, client_address, socket_server, | 227 def __init__(self, request, client_address, socket_server, |
214 connect_handlers, get_handlers, post_handlers, put_handlers): | 228 connect_handlers, get_handlers, get_with_socket_handlers, |
| 229 post_handlers, put_handlers): |
215 self._connect_handlers = connect_handlers | 230 self._connect_handlers = connect_handlers |
216 self._get_handlers = get_handlers | 231 self._get_handlers = get_handlers |
| 232 self._get_with_socket_handlers = get_with_socket_handlers |
217 self._post_handlers = post_handlers | 233 self._post_handlers = post_handlers |
218 self._put_handlers = put_handlers | 234 self._put_handlers = put_handlers |
| 235 self._socket_server = socket_server |
219 BaseHTTPServer.BaseHTTPRequestHandler.__init__( | 236 BaseHTTPServer.BaseHTTPRequestHandler.__init__( |
220 self, request, client_address, socket_server) | 237 self, request, client_address, socket_server) |
221 | 238 |
222 def log_request(self, *args, **kwargs): | 239 def log_request(self, *args, **kwargs): |
223 # Disable request logging to declutter test log output. | 240 # Disable request logging to declutter test log output. |
224 pass | 241 pass |
225 | 242 |
226 def _ShouldHandleRequest(self, handler_name): | 243 def _ShouldHandleRequest(self, handler_name): |
227 """Determines if the path can be handled by the handler. | 244 """Determines if the path can be handled by the handler. |
228 | 245 |
229 We consider a handler valid if the path begins with the | 246 We consider a handler valid if the path begins with the |
230 handler name. It can optionally be followed by "?*", "/*". | 247 handler name. It can optionally be followed by "?*", "/*". |
231 """ | 248 """ |
232 | 249 |
233 pattern = re.compile('%s($|\?|/).*' % handler_name) | 250 pattern = re.compile('%s($|\?|/).*' % handler_name) |
234 return pattern.match(self.path) | 251 return pattern.match(self.path) |
235 | 252 |
236 def do_CONNECT(self): | 253 def do_CONNECT(self): |
237 for handler in self._connect_handlers: | 254 for handler in self._connect_handlers: |
238 if handler(): | 255 if handler(): |
239 return | 256 return |
240 | 257 |
241 def do_GET(self): | 258 def do_GET(self): |
| 259 for handler in self._get_with_socket_handlers: |
| 260 if handler(self._socket_server): |
| 261 return |
242 for handler in self._get_handlers: | 262 for handler in self._get_handlers: |
243 if handler(): | 263 if handler(): |
244 return | 264 return |
245 | 265 |
246 def do_POST(self): | 266 def do_POST(self): |
247 for handler in self._post_handlers: | 267 for handler in self._post_handlers: |
248 if handler(): | 268 if handler(): |
249 return | 269 return |
250 | 270 |
251 def do_PUT(self): | 271 def do_PUT(self): |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 self.RealBZ2FileWithCommonHeaderHandler, | 305 self.RealBZ2FileWithCommonHeaderHandler, |
286 self.SetCookieHandler, | 306 self.SetCookieHandler, |
287 self.AuthBasicHandler, | 307 self.AuthBasicHandler, |
288 self.AuthDigestHandler, | 308 self.AuthDigestHandler, |
289 self.SlowServerHandler, | 309 self.SlowServerHandler, |
290 self.ContentTypeHandler, | 310 self.ContentTypeHandler, |
291 self.ServerRedirectHandler, | 311 self.ServerRedirectHandler, |
292 self.ClientRedirectHandler, | 312 self.ClientRedirectHandler, |
293 self.MultipartHandler, | 313 self.MultipartHandler, |
294 self.DefaultResponseHandler] | 314 self.DefaultResponseHandler] |
| 315 get_with_socket_handlers = [ |
| 316 self.TLSLoginInfoHandler] |
295 post_handlers = [ | 317 post_handlers = [ |
296 self.EchoTitleHandler, | 318 self.EchoTitleHandler, |
297 self.EchoAllHandler, | 319 self.EchoAllHandler, |
298 self.EchoHandler, | 320 self.EchoHandler, |
299 self.DeviceManagementHandler] + get_handlers | 321 self.DeviceManagementHandler] + get_handlers |
300 put_handlers = [ | 322 put_handlers = [ |
301 self.EchoTitleHandler, | 323 self.EchoTitleHandler, |
302 self.EchoAllHandler, | 324 self.EchoAllHandler, |
303 self.EchoHandler] + get_handlers | 325 self.EchoHandler] + get_handlers |
304 | 326 |
305 self._mime_types = { | 327 self._mime_types = { |
306 'crx' : 'application/x-chrome-extension', | 328 'crx' : 'application/x-chrome-extension', |
307 'exe' : 'application/octet-stream', | 329 'exe' : 'application/octet-stream', |
308 'gif': 'image/gif', | 330 'gif': 'image/gif', |
309 'jpeg' : 'image/jpeg', | 331 'jpeg' : 'image/jpeg', |
310 'jpg' : 'image/jpeg', | 332 'jpg' : 'image/jpeg', |
311 'pdf' : 'application/pdf', | 333 'pdf' : 'application/pdf', |
312 'xml' : 'text/xml' | 334 'xml' : 'text/xml' |
313 } | 335 } |
314 self._default_mime_type = 'text/html' | 336 self._default_mime_type = 'text/html' |
315 | 337 |
316 BasePageHandler.__init__(self, request, client_address, socket_server, | 338 BasePageHandler.__init__(self, request, client_address, socket_server, |
317 connect_handlers, get_handlers, post_handlers, | 339 connect_handlers, get_handlers, |
| 340 get_with_socket_handlers, post_handlers, |
318 put_handlers) | 341 put_handlers) |
319 | 342 |
320 def GetMIMETypeFromName(self, file_name): | 343 def GetMIMETypeFromName(self, file_name): |
321 """Returns the mime type for the specified file_name. So far it only looks | 344 """Returns the mime type for the specified file_name. So far it only looks |
322 at the file extension.""" | 345 at the file extension.""" |
323 | 346 |
324 (shortname, extension) = os.path.splitext(file_name.split("?")[0]) | 347 (shortname, extension) = os.path.splitext(file_name.split("?")[0]) |
325 if len(extension) == 0: | 348 if len(extension) == 0: |
326 # no extension. | 349 # no extension. |
327 return self._default_mime_type | 350 return self._default_mime_type |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 while True: | 629 while True: |
607 line = self.rfile.readline() | 630 line = self.rfile.readline() |
608 length = int(line, 16) | 631 length = int(line, 16) |
609 if length == 0: | 632 if length == 0: |
610 self.rfile.readline() | 633 self.rfile.readline() |
611 break | 634 break |
612 body += self.rfile.read(length) | 635 body += self.rfile.read(length) |
613 self.rfile.read(2) | 636 self.rfile.read(2) |
614 return body | 637 return body |
615 | 638 |
| 639 def TLSLoginInfoHandler(self, socket_server): |
| 640 """This handler echoes back the username used to log in via TLS.""" |
| 641 |
| 642 if not self._ShouldHandleRequest("/tlslogininfo"): |
| 643 return False |
| 644 |
| 645 self.send_response(200) |
| 646 self.send_header('Content-type', 'text/html') |
| 647 self.end_headers() |
| 648 |
| 649 srp_user = socket_server.tlsConnection.session.srpUsername |
| 650 if srp_user: |
| 651 self.wfile.write('username: ' + srp_user) |
| 652 else: |
| 653 self.wfile.write('not using TLS-SRP') |
| 654 return True |
| 655 |
616 def EchoHandler(self): | 656 def EchoHandler(self): |
617 """This handler just echoes back the payload of the request, for testing | 657 """This handler just echoes back the payload of the request, for testing |
618 form submission.""" | 658 form submission.""" |
619 | 659 |
620 if not self._ShouldHandleRequest("/echo"): | 660 if not self._ShouldHandleRequest("/echo"): |
621 return False | 661 return False |
622 | 662 |
623 self.send_response(200) | 663 self.send_response(200) |
624 self.send_header('Content-type', 'text/html') | 664 self.send_header('Content-type', 'text/html') |
625 self.end_headers() | 665 self.end_headers() |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1406 print 'specified server cert file not found: ' + options.cert + \ | 1446 print 'specified server cert file not found: ' + options.cert + \ |
1407 ' exiting...' | 1447 ' exiting...' |
1408 return | 1448 return |
1409 for ca_cert in options.ssl_client_ca: | 1449 for ca_cert in options.ssl_client_ca: |
1410 if not os.path.isfile(ca_cert): | 1450 if not os.path.isfile(ca_cert): |
1411 print 'specified trusted client CA file not found: ' + ca_cert + \ | 1451 print 'specified trusted client CA file not found: ' + ca_cert + \ |
1412 ' exiting...' | 1452 ' exiting...' |
1413 return | 1453 return |
1414 server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert, | 1454 server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert, |
1415 options.ssl_client_auth, options.ssl_client_ca, | 1455 options.ssl_client_auth, options.ssl_client_ca, |
1416 options.ssl_bulk_cipher) | 1456 options.ssl_bulk_cipher, options.use_tls_srp, |
| 1457 options.only_tls_srp) |
1417 print 'HTTPS server started on port %d...' % server.server_port | 1458 print 'HTTPS server started on port %d...' % server.server_port |
1418 else: | 1459 else: |
1419 server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) | 1460 server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) |
1420 print 'HTTP server started on port %d...' % server.server_port | 1461 print 'HTTP server started on port %d...' % server.server_port |
1421 | 1462 |
1422 server.data_dir = MakeDataDir() | 1463 server.data_dir = MakeDataDir() |
1423 server.file_root_url = options.file_root_url | 1464 server.file_root_url = options.file_root_url |
1424 server_data['port'] = server.server_port | 1465 server_data['port'] = server.server_port |
1425 server._device_management_handler = None | 1466 server._device_management_handler = None |
1426 server.policy_cert_chain = options.policy_cert_chain | 1467 server.policy_cert_chain = options.policy_cert_chain |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1515 'specified file. This option may appear multiple ' | 1556 'specified file. This option may appear multiple ' |
1516 'times, indicating multiple CA names should be ' | 1557 'times, indicating multiple CA names should be ' |
1517 'sent in the request.') | 1558 'sent in the request.') |
1518 option_parser.add_option('', '--ssl-bulk-cipher', action='append', | 1559 option_parser.add_option('', '--ssl-bulk-cipher', action='append', |
1519 help='Specify the bulk encryption algorithm(s)' | 1560 help='Specify the bulk encryption algorithm(s)' |
1520 'that will be accepted by the SSL server. Valid ' | 1561 'that will be accepted by the SSL server. Valid ' |
1521 'values are "aes256", "aes128", "3des", "rc4". If ' | 1562 'values are "aes256", "aes128", "3des", "rc4". If ' |
1522 'omitted, all algorithms will be used. This ' | 1563 'omitted, all algorithms will be used. This ' |
1523 'option may appear multiple times, indicating ' | 1564 'option may appear multiple times, indicating ' |
1524 'multiple algorithms should be enabled.'); | 1565 'multiple algorithms should be enabled.'); |
| 1566 option_parser.add_option('', '--use-tls-srp', action='store_true', |
| 1567 help='Allow TLS authentication using TLS-SRP' |
| 1568 ' (user jsmith, password asdf)') |
| 1569 option_parser.add_option('', '--only-tls-srp', action='store_true', |
| 1570 help='Only allow connections using TLS-SRP') |
1525 option_parser.add_option('', '--file-root-url', default='/files/', | 1571 option_parser.add_option('', '--file-root-url', default='/files/', |
1526 help='Specify a root URL for files served.') | 1572 help='Specify a root URL for files served.') |
1527 option_parser.add_option('', '--startup-pipe', type='int', | 1573 option_parser.add_option('', '--startup-pipe', type='int', |
1528 dest='startup_pipe', | 1574 dest='startup_pipe', |
1529 help='File handle of pipe to parent process') | 1575 help='File handle of pipe to parent process') |
1530 option_parser.add_option('', '--policy-cert-chain', action='append', | 1576 option_parser.add_option('', '--policy-cert-chain', action='append', |
1531 help='Specify a path to a certificate file to sign ' | 1577 help='Specify a path to a certificate file to sign ' |
1532 'policy responses. This option may be used ' | 1578 'policy responses. This option may be used ' |
1533 'multiple times to define a certificate chain. ' | 1579 'multiple times to define a certificate chain. ' |
1534 'The first element will be used for signing, ' | 1580 'The first element will be used for signing, ' |
1535 'the last element should be the root ' | 1581 'the last element should be the root ' |
1536 'certificate.') | 1582 'certificate.') |
1537 options, args = option_parser.parse_args() | 1583 options, args = option_parser.parse_args() |
1538 | 1584 |
1539 sys.exit(main(options, args)) | 1585 sys.exit(main(options, args)) |
OLD | NEW |