Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: net/tools/testserver/testserver.py

Issue 9663017: net: add OCSP tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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
11 explicit port if necessary. 11 explicit port if necessary.
12 It can use https if you specify the flag --https=CERT where CERT is the path 12 It can use https if you specify the flag --https=CERT where CERT is the path
13 to a pem file containing the certificate and private key that should be used. 13 to a pem file containing the certificate and private key that should be used.
14 """ 14 """
15 15
16 import asyncore 16 import asyncore
17 import base64 17 import base64
18 import BaseHTTPServer 18 import BaseHTTPServer
19 import cgi 19 import cgi
20 import errno 20 import errno
21 import httplib 21 import httplib
22 import minica
22 import optparse 23 import optparse
23 import os 24 import os
24 import random 25 import random
25 import re 26 import re
26 import select 27 import select
28 import socket
27 import SocketServer 29 import SocketServer
28 import socket 30 import struct
29 import sys 31 import sys
30 import struct 32 import threading
31 import time 33 import time
32 import urllib 34 import urllib
33 import urlparse 35 import urlparse
34 import warnings 36 import warnings
35 import zlib 37 import zlib
36 38
37 # Ignore deprecation warnings, they make our output more cluttered. 39 # Ignore deprecation warnings, they make our output more cluttered.
38 warnings.filterwarnings("ignore", category=DeprecationWarning) 40 warnings.filterwarnings("ignore", category=DeprecationWarning)
39 41
40 import echo_message 42 import echo_message
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 100
99 def serve_forever(self): 101 def serve_forever(self):
100 self.stop = False 102 self.stop = False
101 self.nonce_time = None 103 self.nonce_time = None
102 while not self.stop: 104 while not self.stop:
103 self.handle_request() 105 self.handle_request()
104 self.socket.close() 106 self.socket.close()
105 107
106 108
107 class HTTPServer(ClientRestrictingServerMixIn, StoppableHTTPServer): 109 class HTTPServer(ClientRestrictingServerMixIn, StoppableHTTPServer):
108 """This is a specialization of StoppableHTTPerver that adds client 110 """This is a specialization of StoppableHTTPServer that adds client
109 verification.""" 111 verification."""
110 112
111 pass 113 pass
112 114
115 class OCSPServer(ClientRestrictingServerMixIn, BaseHTTPServer.HTTPServer):
116 """This is a specialization of HTTPServer that serves an
117 OCSP response"""
118
119 def serve_forever_on_thread(self):
120 self.thread = threading.Thread(target = self.serve_forever,
121 name = "OCSPServerThread")
122 self.thread.start()
123
124 def stop_serving(self):
125 self.shutdown()
126 self.thread.join()
113 127
114 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, 128 class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
115 ClientRestrictingServerMixIn, 129 ClientRestrictingServerMixIn,
116 StoppableHTTPServer): 130 StoppableHTTPServer):
117 """This is a specialization of StoppableHTTPerver that add https support and 131 """This is a specialization of StoppableHTTPServer that add https support and
118 client verification.""" 132 client verification."""
119 133
120 def __init__(self, server_address, request_hander_class, cert_path, 134 def __init__(self, server_address, request_hander_class, pem_cert_and_key,
121 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, 135 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers,
122 record_resume_info): 136 record_resume_info):
123 s = open(cert_path).read() 137 self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key)
124 self.cert_chain = tlslite.api.X509CertChain().parseChain(s) 138 self.private_key = tlslite.api.parsePEMKey(pem_cert_and_key, private=True)
125 s = open(cert_path).read()
126 self.private_key = tlslite.api.parsePEMKey(s, private=True)
127 self.ssl_client_auth = ssl_client_auth 139 self.ssl_client_auth = ssl_client_auth
128 self.ssl_client_cas = [] 140 self.ssl_client_cas = []
129 for ca_file in ssl_client_cas: 141 for ca_file in ssl_client_cas:
130 s = open(ca_file).read() 142 s = open(ca_file).read()
131 x509 = tlslite.api.X509() 143 x509 = tlslite.api.X509()
132 x509.parse(s) 144 x509.parse(s)
133 self.ssl_client_cas.append(x509.subject) 145 self.ssl_client_cas.append(x509.subject)
134 self.ssl_handshake_settings = tlslite.api.HandshakeSettings() 146 self.ssl_handshake_settings = tlslite.api.HandshakeSettings()
135 if ssl_bulk_ciphers is not None: 147 if ssl_bulk_ciphers is not None:
136 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers 148 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers
(...skipping 1732 matching lines...) Expand 10 before | Expand all | Expand 10 after
1869 # Create the default path to our data dir, relative to the exe dir. 1881 # Create the default path to our data dir, relative to the exe dir.
1870 my_data_dir = os.path.dirname(sys.argv[0]) 1882 my_data_dir = os.path.dirname(sys.argv[0])
1871 my_data_dir = os.path.join(my_data_dir, "..", "..", "..", "..", 1883 my_data_dir = os.path.join(my_data_dir, "..", "..", "..", "..",
1872 "test", "data") 1884 "test", "data")
1873 1885
1874 #TODO(ibrar): Must use Find* funtion defined in google\tools 1886 #TODO(ibrar): Must use Find* funtion defined in google\tools
1875 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data") 1887 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data")
1876 1888
1877 return my_data_dir 1889 return my_data_dir
1878 1890
1891 class OCSPHandler(BasePageHandler):
1892 def __init__(self, request, client_address, socket_server):
1893 handlers = [self.OCSPResponse]
1894 self.ocsp_response = socket_server.ocsp_response
1895 BasePageHandler.__init__(self, request, client_address, socket_server,
1896 [], handlers, [], handlers, [])
1897
1898 def OCSPResponse(self):
1899 self.send_response(200)
1900 self.send_header('Content-Type', 'application/ocsp-response')
1901 self.send_header('Content-Length', str(len(self.ocsp_response)))
1902 self.end_headers()
1903
1904 self.wfile.write(self.ocsp_response)
1879 1905
1880 class TCPEchoHandler(SocketServer.BaseRequestHandler): 1906 class TCPEchoHandler(SocketServer.BaseRequestHandler):
1881 """The RequestHandler class for TCP echo server. 1907 """The RequestHandler class for TCP echo server.
1882 1908
1883 It is instantiated once per connection to the server, and overrides the 1909 It is instantiated once per connection to the server, and overrides the
1884 handle() method to implement communication to the client. 1910 handle() method to implement communication to the client.
1885 """ 1911 """
1886 1912
1887 def handle(self): 1913 def handle(self):
1888 """Handles the request from the client and constructs a response.""" 1914 """Handles the request from the client and constructs a response."""
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1949 sys.stdout = FileMultiplexer(sys.stdout, logfile) 1975 sys.stdout = FileMultiplexer(sys.stdout, logfile)
1950 else: 1976 else:
1951 sys.stdout = logfile 1977 sys.stdout = logfile
1952 1978
1953 port = options.port 1979 port = options.port
1954 host = options.host 1980 host = options.host
1955 1981
1956 server_data = {} 1982 server_data = {}
1957 server_data['host'] = host 1983 server_data['host'] = host
1958 1984
1985 ocsp_server = None
1986
1959 if options.server_type == SERVER_HTTP: 1987 if options.server_type == SERVER_HTTP:
1960 if options.cert: 1988 if options.https:
1961 # let's make sure the cert file exists. 1989 pem_cert_and_key = None
1962 if not os.path.isfile(options.cert): 1990 if options.cert_and_key_file:
1963 print 'specified server cert file not found: ' + options.cert + \ 1991 if not os.path.isfile(options.cert_and_key_file):
1964 ' exiting...' 1992 print ('specified server cert file not found: ' +
1965 return 1993 options.cert_and_key_file + ' exiting...')
1994 return
1995 pem_cert_and_key = file(options.cert_and_key_file, 'r').read()
1996 else:
1997 # generate a new certificate and run an OCSP server for it.
1998 ocsp_server = OCSPServer((host, 0), OCSPHandler)
1999 print 'OCSP server on port ' + str(ocsp_server.server_port)
Ryan Sleevi 2012/03/13 23:06:39 nit: print 'OCSP server started on %s:%d' % (host
agl 2012/03/13 23:44:03 Done.
2000
2001 ocsp_der = None
2002 ocsp_revoked = False
2003 ocsp_invalid = False
2004
2005 if options.ocsp == 'ok':
2006 pass
2007 elif options.ocsp == 'revoked':
2008 ocsp_revoked = True
2009 elif options.ocsp == 'invalid':
2010 ocsp_invalid = True
2011 else:
2012 print 'unknown OCSP status: ' + options.ocsp_status
2013 return
2014
2015 (pem_cert_and_key, ocsp_der) = \
2016 minica.GenerateCertKeyAndOCSP(
2017 subject = "127.0.0.1",
2018 ocsp_url = "http://127.0.0.1:%d/ocsp" % ocsp_server.server_port,
Ryan Sleevi 2012/03/13 23:06:39 bug? 127.0.0.1 -> host We've avoided hardcoding i
agl 2012/03/13 23:44:03 Done.
2019 ocsp_revoked = ocsp_revoked)
2020
2021 if ocsp_invalid:
2022 ocsp_der = '3'
2023
2024 ocsp_server.ocsp_response = ocsp_der
2025
1966 for ca_cert in options.ssl_client_ca: 2026 for ca_cert in options.ssl_client_ca:
1967 if not os.path.isfile(ca_cert): 2027 if not os.path.isfile(ca_cert):
1968 print 'specified trusted client CA file not found: ' + ca_cert + \ 2028 print 'specified trusted client CA file not found: ' + ca_cert + \
1969 ' exiting...' 2029 ' exiting...'
1970 return 2030 return
1971 server = HTTPSServer((host, port), TestPageHandler, options.cert, 2031 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key,
1972 options.ssl_client_auth, options.ssl_client_ca, 2032 options.ssl_client_auth, options.ssl_client_ca,
1973 options.ssl_bulk_cipher, options.record_resume) 2033 options.ssl_bulk_cipher, options.record_resume)
1974 print 'HTTPS server started on %s:%d...' % (host, server.server_port) 2034 print 'HTTPS server started on %s:%d...' % (host, server.server_port)
1975 else: 2035 else:
1976 server = HTTPServer((host, port), TestPageHandler) 2036 server = HTTPServer((host, port), TestPageHandler)
1977 print 'HTTP server started on %s:%d...' % (host, server.server_port) 2037 print 'HTTP server started on %s:%d...' % (host, server.server_port)
1978 2038
1979 server.data_dir = MakeDataDir() 2039 server.data_dir = MakeDataDir()
1980 server.file_root_url = options.file_root_url 2040 server.file_root_url = options.file_root_url
1981 server_data['port'] = server.server_port 2041 server_data['port'] = server.server_port
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2041 else: 2101 else:
2042 fd = options.startup_pipe 2102 fd = options.startup_pipe
2043 startup_pipe = os.fdopen(fd, "w") 2103 startup_pipe = os.fdopen(fd, "w")
2044 # First write the data length as an unsigned 4-byte value. This 2104 # First write the data length as an unsigned 4-byte value. This
2045 # is _not_ using network byte ordering since the other end of the 2105 # is _not_ using network byte ordering since the other end of the
2046 # pipe is on the same machine. 2106 # pipe is on the same machine.
2047 startup_pipe.write(struct.pack('=L', server_data_len)) 2107 startup_pipe.write(struct.pack('=L', server_data_len))
2048 startup_pipe.write(server_data_json) 2108 startup_pipe.write(server_data_json)
2049 startup_pipe.close() 2109 startup_pipe.close()
2050 2110
2111 if ocsp_server is not None:
2112 ocsp_server.serve_forever_on_thread()
2113
2051 try: 2114 try:
2052 server.serve_forever() 2115 server.serve_forever()
2053 except KeyboardInterrupt: 2116 except KeyboardInterrupt:
2054 print 'shutting down server' 2117 print 'shutting down server'
2118 if ocsp_server is not None:
2119 ocsp_server.stop_serving()
2055 server.stop = True 2120 server.stop = True
2056 2121
2057 if __name__ == '__main__': 2122 if __name__ == '__main__':
2058 option_parser = optparse.OptionParser() 2123 option_parser = optparse.OptionParser()
2059 option_parser.add_option("-f", '--ftp', action='store_const', 2124 option_parser.add_option("-f", '--ftp', action='store_const',
2060 const=SERVER_FTP, default=SERVER_HTTP, 2125 const=SERVER_FTP, default=SERVER_HTTP,
2061 dest='server_type', 2126 dest='server_type',
2062 help='start up an FTP server.') 2127 help='start up an FTP server.')
2063 option_parser.add_option('', '--sync', action='store_const', 2128 option_parser.add_option('', '--sync', action='store_const',
2064 const=SERVER_SYNC, default=SERVER_HTTP, 2129 const=SERVER_SYNC, default=SERVER_HTTP,
(...skipping 10 matching lines...) Expand all
2075 option_parser.add_option('', '--log-to-console', action='store_const', 2140 option_parser.add_option('', '--log-to-console', action='store_const',
2076 const=True, default=False, 2141 const=True, default=False,
2077 dest='log_to_console', 2142 dest='log_to_console',
2078 help='Enables or disables sys.stdout logging to ' 2143 help='Enables or disables sys.stdout logging to '
2079 'the console.') 2144 'the console.')
2080 option_parser.add_option('', '--port', default='0', type='int', 2145 option_parser.add_option('', '--port', default='0', type='int',
2081 help='Port used by the server. If unspecified, the ' 2146 help='Port used by the server. If unspecified, the '
2082 'server will listen on an ephemeral port.') 2147 'server will listen on an ephemeral port.')
2083 option_parser.add_option('', '--data-dir', dest='data_dir', 2148 option_parser.add_option('', '--data-dir', dest='data_dir',
2084 help='Directory from which to read the files.') 2149 help='Directory from which to read the files.')
2085 option_parser.add_option('', '--https', dest='cert', 2150 option_parser.add_option('', '--https', action='store_true', dest='https',
2086 help='Specify that https should be used, specify ' 2151 help='Specify that https should be used.')
2087 'the path to the cert containing the private key ' 2152 option_parser.add_option('', '--cert-and-key-file', dest='cert_and_key_file',
2088 'the server should use.') 2153 help='specify the path to the file containing the '
2154 'certificate and private key for the server in PEM '
2155 'format')
2156 option_parser.add_option('', '--ocsp', dest='ocsp', default='ok',
2157 help='The type of OCSP response generated for the '
2158 'automatically generated certificate. One of of '
Ryan Sleevi 2012/03/13 23:06:39 nit: 'of of' -> 'of'
agl 2012/03/13 23:44:03 Done.
2159 '[ok,revoked,invalid]')
2089 option_parser.add_option('', '--https-record-resume', dest='record_resume', 2160 option_parser.add_option('', '--https-record-resume', dest='record_resume',
2090 const=True, default=False, action='store_const', 2161 const=True, default=False, action='store_const',
2091 help='Record resumption cache events rather than' 2162 help='Record resumption cache events rather than'
2092 ' resuming as normal. Allows the use of the' 2163 ' resuming as normal. Allows the use of the'
2093 ' /ssl-session-cache request') 2164 ' /ssl-session-cache request')
2094 option_parser.add_option('', '--ssl-client-auth', action='store_true', 2165 option_parser.add_option('', '--ssl-client-auth', action='store_true',
2095 help='Require SSL client auth on every connection.') 2166 help='Require SSL client auth on every connection.')
2096 option_parser.add_option('', '--ssl-client-ca', action='append', default=[], 2167 option_parser.add_option('', '--ssl-client-ca', action='append', default=[],
2097 help='Specify that the client certificate request ' 2168 help='Specify that the client certificate request '
2098 'should include the CA named in the subject of ' 2169 'should include the CA named in the subject of '
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2131 dest='host', 2202 dest='host',
2132 help='Hostname or IP upon which the server will ' 2203 help='Hostname or IP upon which the server will '
2133 'listen. Client connections will also only be ' 2204 'listen. Client connections will also only be '
2134 'allowed from this address.') 2205 'allowed from this address.')
2135 option_parser.add_option('', '--auth-token', dest='auth_token', 2206 option_parser.add_option('', '--auth-token', dest='auth_token',
2136 help='Specify the auth token which should be used' 2207 help='Specify the auth token which should be used'
2137 'in the authorization header for GData.') 2208 'in the authorization header for GData.')
2138 options, args = option_parser.parse_args() 2209 options, args = option_parser.parse_args()
2139 2210
2140 sys.exit(main(options, args)) 2211 sys.exit(main(options, args))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698