Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 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/FTP/SYNC/TCP/UDP/ server used for testing Chrome. | 6 """This is a simple HTTP/FTP/SYNC/TCP/UDP/ 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 SERVER_SYNC = 2 | 61 SERVER_SYNC = 2 |
| 62 SERVER_TCP_ECHO = 3 | 62 SERVER_TCP_ECHO = 3 |
| 63 SERVER_UDP_ECHO = 4 | 63 SERVER_UDP_ECHO = 4 |
| 64 | 64 |
| 65 # Using debug() seems to cause hangs on XP: see http://crbug.com/64515 . | 65 # Using debug() seems to cause hangs on XP: see http://crbug.com/64515 . |
| 66 debug_output = sys.stderr | 66 debug_output = sys.stderr |
| 67 def debug(str): | 67 def debug(str): |
| 68 debug_output.write(str + "\n") | 68 debug_output.write(str + "\n") |
| 69 debug_output.flush() | 69 debug_output.flush() |
| 70 | 70 |
| 71 class RecordingSessionCache(object): | |
|
wtc
2011/12/10 01:22:37
I suggest renaming
SessionCache => SSLSessionCa
agl
2011/12/12 22:18:20
Done.
| |
| 72 """RecordingSessionCache acts as a TLS session cache and maintains a log of | |
| 73 lookups and inserts in order to test session cache behaviours.""" | |
| 74 | |
| 75 def __init__(self): | |
| 76 self.log = [] | |
| 77 | |
| 78 def __getitem__(self, sessionID): | |
| 79 self.log.append(('lookup', sessionID)) | |
| 80 raise KeyError() | |
| 81 | |
| 82 def __setitem__(self, sessionID, session): | |
| 83 self.log.append(('insert', sessionID)) | |
| 84 | |
| 71 class StoppableHTTPServer(BaseHTTPServer.HTTPServer): | 85 class StoppableHTTPServer(BaseHTTPServer.HTTPServer): |
| 72 """This is a specialization of of BaseHTTPServer to allow it | 86 """This is a specialization of of BaseHTTPServer to allow it |
| 73 to be exited cleanly (by setting its "stop" member to True).""" | 87 to be exited cleanly (by setting its "stop" member to True).""" |
| 74 | 88 |
| 75 def serve_forever(self): | 89 def serve_forever(self): |
| 76 self.stop = False | 90 self.stop = False |
| 77 self.nonce_time = None | 91 self.nonce_time = None |
| 78 while not self.stop: | 92 while not self.stop: |
| 79 self.handle_request() | 93 self.handle_request() |
| 80 self.socket.close() | 94 self.socket.close() |
| 81 | 95 |
| 82 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer): | 96 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer): |
| 83 """This is a specialization of StoppableHTTPerver that add https support.""" | 97 """This is a specialization of StoppableHTTPerver that add https support.""" |
| 84 | 98 |
| 85 def __init__(self, server_address, request_hander_class, cert_path, | 99 def __init__(self, server_address, request_hander_class, cert_path, |
| 86 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers): | 100 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, |
| 101 record_resume_info): | |
| 87 s = open(cert_path).read() | 102 s = open(cert_path).read() |
| 88 x509 = tlslite.api.X509() | 103 x509 = tlslite.api.X509() |
| 89 x509.parse(s) | 104 x509.parse(s) |
| 90 self.cert_chain = tlslite.api.X509CertChain([x509]) | 105 self.cert_chain = tlslite.api.X509CertChain([x509]) |
| 91 s = open(cert_path).read() | 106 s = open(cert_path).read() |
| 92 self.private_key = tlslite.api.parsePEMKey(s, private=True) | 107 self.private_key = tlslite.api.parsePEMKey(s, private=True) |
| 93 self.ssl_client_auth = ssl_client_auth | 108 self.ssl_client_auth = ssl_client_auth |
| 94 self.ssl_client_cas = [] | 109 self.ssl_client_cas = [] |
| 95 for ca_file in ssl_client_cas: | 110 for ca_file in ssl_client_cas: |
| 96 s = open(ca_file).read() | 111 s = open(ca_file).read() |
| 97 x509 = tlslite.api.X509() | 112 x509 = tlslite.api.X509() |
| 98 x509.parse(s) | 113 x509.parse(s) |
| 99 self.ssl_client_cas.append(x509.subject) | 114 self.ssl_client_cas.append(x509.subject) |
| 100 self.ssl_handshake_settings = tlslite.api.HandshakeSettings() | 115 self.ssl_handshake_settings = tlslite.api.HandshakeSettings() |
| 101 if ssl_bulk_ciphers is not None: | 116 if ssl_bulk_ciphers is not None: |
| 102 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers | 117 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers |
| 103 | 118 |
| 104 self.session_cache = tlslite.api.SessionCache() | 119 if record_resume_info: |
| 120 # If record_resume_info is true then we'll replace the session cache with | |
| 121 # an object that records the lookups and inserts that it sees. | |
| 122 self.session_cache = RecordingSessionCache() | |
| 123 else: | |
| 124 self.session_cache = tlslite.api.SessionCache() | |
| 105 StoppableHTTPServer.__init__(self, server_address, request_hander_class) | 125 StoppableHTTPServer.__init__(self, server_address, request_hander_class) |
| 106 | 126 |
| 107 def handshake(self, tlsConnection): | 127 def handshake(self, tlsConnection): |
| 108 """Creates the SSL connection.""" | 128 """Creates the SSL connection.""" |
| 109 try: | 129 try: |
| 110 tlsConnection.handshakeServer(certChain=self.cert_chain, | 130 tlsConnection.handshakeServer(certChain=self.cert_chain, |
| 111 privateKey=self.private_key, | 131 privateKey=self.private_key, |
| 112 sessionCache=self.session_cache, | 132 sessionCache=self.session_cache, |
| 113 reqCert=self.ssl_client_auth, | 133 reqCert=self.ssl_client_auth, |
| 114 settings=self.ssl_handshake_settings, | 134 settings=self.ssl_handshake_settings, |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 self.AuthBasicHandler, | 370 self.AuthBasicHandler, |
| 351 self.AuthDigestHandler, | 371 self.AuthDigestHandler, |
| 352 self.SlowServerHandler, | 372 self.SlowServerHandler, |
| 353 self.ChunkedServerHandler, | 373 self.ChunkedServerHandler, |
| 354 self.ContentTypeHandler, | 374 self.ContentTypeHandler, |
| 355 self.NoContentHandler, | 375 self.NoContentHandler, |
| 356 self.ServerRedirectHandler, | 376 self.ServerRedirectHandler, |
| 357 self.ClientRedirectHandler, | 377 self.ClientRedirectHandler, |
| 358 self.MultipartHandler, | 378 self.MultipartHandler, |
| 359 self.MultipartSlowHandler, | 379 self.MultipartSlowHandler, |
| 380 self.GetSessionCacheHandler, | |
| 360 self.DefaultResponseHandler] | 381 self.DefaultResponseHandler] |
| 361 post_handlers = [ | 382 post_handlers = [ |
| 362 self.EchoTitleHandler, | 383 self.EchoTitleHandler, |
| 363 self.EchoHandler, | 384 self.EchoHandler, |
| 364 self.DeviceManagementHandler] + get_handlers | 385 self.DeviceManagementHandler] + get_handlers |
| 365 put_handlers = [ | 386 put_handlers = [ |
| 366 self.EchoTitleHandler, | 387 self.EchoTitleHandler, |
| 367 self.EchoHandler] + get_handlers | 388 self.EchoHandler] + get_handlers |
| 368 head_handlers = [ | 389 head_handlers = [ |
| 369 self.FileHandler, | 390 self.FileHandler, |
| (...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1373 time.sleep(0.25) | 1394 time.sleep(0.25) |
| 1374 if i == 2: | 1395 if i == 2: |
| 1375 self.wfile.write('<title>PASS</title>') | 1396 self.wfile.write('<title>PASS</title>') |
| 1376 else: | 1397 else: |
| 1377 self.wfile.write('<title>page ' + str(i) + '</title>') | 1398 self.wfile.write('<title>page ' + str(i) + '</title>') |
| 1378 self.wfile.write('page ' + str(i) + '<!-- ' + ('x' * 2048) + '-->') | 1399 self.wfile.write('page ' + str(i) + '<!-- ' + ('x' * 2048) + '-->') |
| 1379 | 1400 |
| 1380 self.wfile.write('--' + bound + '--') | 1401 self.wfile.write('--' + bound + '--') |
| 1381 return True | 1402 return True |
| 1382 | 1403 |
| 1404 def GetSessionCacheHandler(self): | |
| 1405 """Send a reply containing a log of the session cache operations.""" | |
| 1406 | |
| 1407 if not self._ShouldHandleRequest('/session-cache'): | |
|
wtc
2011/12/10 01:22:37
/session-cache => /ssl-session-cache
also on line
agl
2011/12/12 22:18:20
Done.
| |
| 1408 return False | |
| 1409 | |
| 1410 self.send_response(200) | |
| 1411 self.send_header('Content-Type', 'text/plain') | |
| 1412 self.end_headers() | |
| 1413 try: | |
| 1414 for (action, sessionID) in self.server.session_cache.log: | |
| 1415 self.wfile.write('%s\t%s\n' % (action, sessionID.encode('hex'))) | |
| 1416 except AttributeError, e: | |
| 1417 self.wfile.write('Pass --https-record-resume in order to use' + | |
| 1418 ' this request') | |
| 1419 return True | |
| 1420 | |
| 1383 def DefaultResponseHandler(self): | 1421 def DefaultResponseHandler(self): |
| 1384 """This is the catch-all response handler for requests that aren't handled | 1422 """This is the catch-all response handler for requests that aren't handled |
| 1385 by one of the special handlers above. | 1423 by one of the special handlers above. |
| 1386 Note that we specify the content-length as without it the https connection | 1424 Note that we specify the content-length as without it the https connection |
| 1387 is not closed properly (and the browser keeps expecting data).""" | 1425 is not closed properly (and the browser keeps expecting data).""" |
| 1388 | 1426 |
| 1389 contents = "Default response given for path: " + self.path | 1427 contents = "Default response given for path: " + self.path |
| 1390 self.send_response(200) | 1428 self.send_response(200) |
| 1391 self.send_header('Content-Type', 'text/html') | 1429 self.send_header('Content-Type', 'text/html') |
| 1392 self.send_header('Content-Length', len(contents)) | 1430 self.send_header('Content-Length', len(contents)) |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1798 print 'specified server cert file not found: ' + options.cert + \ | 1836 print 'specified server cert file not found: ' + options.cert + \ |
| 1799 ' exiting...' | 1837 ' exiting...' |
| 1800 return | 1838 return |
| 1801 for ca_cert in options.ssl_client_ca: | 1839 for ca_cert in options.ssl_client_ca: |
| 1802 if not os.path.isfile(ca_cert): | 1840 if not os.path.isfile(ca_cert): |
| 1803 print 'specified trusted client CA file not found: ' + ca_cert + \ | 1841 print 'specified trusted client CA file not found: ' + ca_cert + \ |
| 1804 ' exiting...' | 1842 ' exiting...' |
| 1805 return | 1843 return |
| 1806 server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert, | 1844 server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert, |
| 1807 options.ssl_client_auth, options.ssl_client_ca, | 1845 options.ssl_client_auth, options.ssl_client_ca, |
| 1808 options.ssl_bulk_cipher) | 1846 options.ssl_bulk_cipher, options.record_resume) |
| 1809 print 'HTTPS server started on port %d...' % server.server_port | 1847 print 'HTTPS server started on port %d...' % server.server_port |
| 1810 else: | 1848 else: |
| 1811 server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) | 1849 server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) |
| 1812 print 'HTTP server started on port %d...' % server.server_port | 1850 print 'HTTP server started on port %d...' % server.server_port |
| 1813 | 1851 |
| 1814 server.data_dir = MakeDataDir() | 1852 server.data_dir = MakeDataDir() |
| 1815 server.file_root_url = options.file_root_url | 1853 server.file_root_url = options.file_root_url |
| 1816 server_data['port'] = server.server_port | 1854 server_data['port'] = server.server_port |
| 1817 server._device_management_handler = None | 1855 server._device_management_handler = None |
| 1818 server.policy_keys = options.policy_keys | 1856 server.policy_keys = options.policy_keys |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1914 'the console.') | 1952 'the console.') |
| 1915 option_parser.add_option('', '--port', default='0', type='int', | 1953 option_parser.add_option('', '--port', default='0', type='int', |
| 1916 help='Port used by the server. If unspecified, the ' | 1954 help='Port used by the server. If unspecified, the ' |
| 1917 'server will listen on an ephemeral port.') | 1955 'server will listen on an ephemeral port.') |
| 1918 option_parser.add_option('', '--data-dir', dest='data_dir', | 1956 option_parser.add_option('', '--data-dir', dest='data_dir', |
| 1919 help='Directory from which to read the files.') | 1957 help='Directory from which to read the files.') |
| 1920 option_parser.add_option('', '--https', dest='cert', | 1958 option_parser.add_option('', '--https', dest='cert', |
| 1921 help='Specify that https should be used, specify ' | 1959 help='Specify that https should be used, specify ' |
| 1922 'the path to the cert containing the private key ' | 1960 'the path to the cert containing the private key ' |
| 1923 'the server should use.') | 1961 'the server should use.') |
| 1962 option_parser.add_option('', '--https-record-resume', dest='record_resume', | |
| 1963 const=True, default=False, action='store_const', | |
| 1964 help='Record resumption cache events rather than' | |
| 1965 ' resuming as normal. Allows the use of the' | |
| 1966 ' /session-cache request') | |
| 1924 option_parser.add_option('', '--ssl-client-auth', action='store_true', | 1967 option_parser.add_option('', '--ssl-client-auth', action='store_true', |
| 1925 help='Require SSL client auth on every connection.') | 1968 help='Require SSL client auth on every connection.') |
| 1926 option_parser.add_option('', '--ssl-client-ca', action='append', default=[], | 1969 option_parser.add_option('', '--ssl-client-ca', action='append', default=[], |
| 1927 help='Specify that the client certificate request ' | 1970 help='Specify that the client certificate request ' |
| 1928 'should include the CA named in the subject of ' | 1971 'should include the CA named in the subject of ' |
| 1929 'the DER-encoded certificate contained in the ' | 1972 'the DER-encoded certificate contained in the ' |
| 1930 'specified file. This option may appear multiple ' | 1973 'specified file. This option may appear multiple ' |
| 1931 'times, indicating multiple CA names should be ' | 1974 'times, indicating multiple CA names should be ' |
| 1932 'sent in the request.') | 1975 'sent in the request.') |
| 1933 option_parser.add_option('', '--ssl-bulk-cipher', action='append', | 1976 option_parser.add_option('', '--ssl-bulk-cipher', action='append', |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1953 'random key if none is specified on the command ' | 1996 'random key if none is specified on the command ' |
| 1954 'line.') | 1997 'line.') |
| 1955 option_parser.add_option('', '--policy-user', default='user@example.com', | 1998 option_parser.add_option('', '--policy-user', default='user@example.com', |
| 1956 dest='policy_user', | 1999 dest='policy_user', |
| 1957 help='Specify the user name the server should ' | 2000 help='Specify the user name the server should ' |
| 1958 'report back to the client as the user owning the ' | 2001 'report back to the client as the user owning the ' |
| 1959 'token used for making the policy request.') | 2002 'token used for making the policy request.') |
| 1960 options, args = option_parser.parse_args() | 2003 options, args = option_parser.parse_args() |
| 1961 | 2004 |
| 1962 sys.exit(main(options, args)) | 2005 sys.exit(main(options, args)) |
| OLD | NEW |