| 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 |