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

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
« no previous file with comments | « net/tools/testserver/minica.py ('k') | net/url_request/url_request_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 started on %s:%d...' %
2000 (host, ocsp_server.server_port))
2001
2002 ocsp_der = None
2003 ocsp_revoked = False
2004 ocsp_invalid = False
2005
2006 if options.ocsp == 'ok':
2007 pass
2008 elif options.ocsp == 'revoked':
2009 ocsp_revoked = True
2010 elif options.ocsp == 'invalid':
2011 ocsp_invalid = True
2012 else:
2013 print 'unknown OCSP status: ' + options.ocsp_status
2014 return
2015
2016 (pem_cert_and_key, ocsp_der) = \
2017 minica.GenerateCertKeyAndOCSP(
2018 subject = "127.0.0.1",
2019 ocsp_url = ("http://%s:%d/ocsp" %
2020 (host, ocsp_server.server_port)),
2021 ocsp_revoked = ocsp_revoked)
2022
2023 if ocsp_invalid:
2024 ocsp_der = '3'
2025
2026 ocsp_server.ocsp_response = ocsp_der
2027
1966 for ca_cert in options.ssl_client_ca: 2028 for ca_cert in options.ssl_client_ca:
1967 if not os.path.isfile(ca_cert): 2029 if not os.path.isfile(ca_cert):
1968 print 'specified trusted client CA file not found: ' + ca_cert + \ 2030 print 'specified trusted client CA file not found: ' + ca_cert + \
1969 ' exiting...' 2031 ' exiting...'
1970 return 2032 return
1971 server = HTTPSServer((host, port), TestPageHandler, options.cert, 2033 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key,
1972 options.ssl_client_auth, options.ssl_client_ca, 2034 options.ssl_client_auth, options.ssl_client_ca,
1973 options.ssl_bulk_cipher, options.record_resume) 2035 options.ssl_bulk_cipher, options.record_resume)
1974 print 'HTTPS server started on %s:%d...' % (host, server.server_port) 2036 print 'HTTPS server started on %s:%d...' % (host, server.server_port)
1975 else: 2037 else:
1976 server = HTTPServer((host, port), TestPageHandler) 2038 server = HTTPServer((host, port), TestPageHandler)
1977 print 'HTTP server started on %s:%d...' % (host, server.server_port) 2039 print 'HTTP server started on %s:%d...' % (host, server.server_port)
1978 2040
1979 server.data_dir = MakeDataDir() 2041 server.data_dir = MakeDataDir()
1980 server.file_root_url = options.file_root_url 2042 server.file_root_url = options.file_root_url
1981 server_data['port'] = server.server_port 2043 server_data['port'] = server.server_port
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2041 else: 2103 else:
2042 fd = options.startup_pipe 2104 fd = options.startup_pipe
2043 startup_pipe = os.fdopen(fd, "w") 2105 startup_pipe = os.fdopen(fd, "w")
2044 # First write the data length as an unsigned 4-byte value. This 2106 # 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 2107 # is _not_ using network byte ordering since the other end of the
2046 # pipe is on the same machine. 2108 # pipe is on the same machine.
2047 startup_pipe.write(struct.pack('=L', server_data_len)) 2109 startup_pipe.write(struct.pack('=L', server_data_len))
2048 startup_pipe.write(server_data_json) 2110 startup_pipe.write(server_data_json)
2049 startup_pipe.close() 2111 startup_pipe.close()
2050 2112
2113 if ocsp_server is not None:
2114 ocsp_server.serve_forever_on_thread()
2115
2051 try: 2116 try:
2052 server.serve_forever() 2117 server.serve_forever()
2053 except KeyboardInterrupt: 2118 except KeyboardInterrupt:
2054 print 'shutting down server' 2119 print 'shutting down server'
2120 if ocsp_server is not None:
2121 ocsp_server.stop_serving()
2055 server.stop = True 2122 server.stop = True
2056 2123
2057 if __name__ == '__main__': 2124 if __name__ == '__main__':
2058 option_parser = optparse.OptionParser() 2125 option_parser = optparse.OptionParser()
2059 option_parser.add_option("-f", '--ftp', action='store_const', 2126 option_parser.add_option("-f", '--ftp', action='store_const',
2060 const=SERVER_FTP, default=SERVER_HTTP, 2127 const=SERVER_FTP, default=SERVER_HTTP,
2061 dest='server_type', 2128 dest='server_type',
2062 help='start up an FTP server.') 2129 help='start up an FTP server.')
2063 option_parser.add_option('', '--sync', action='store_const', 2130 option_parser.add_option('', '--sync', action='store_const',
2064 const=SERVER_SYNC, default=SERVER_HTTP, 2131 const=SERVER_SYNC, default=SERVER_HTTP,
(...skipping 10 matching lines...) Expand all
2075 option_parser.add_option('', '--log-to-console', action='store_const', 2142 option_parser.add_option('', '--log-to-console', action='store_const',
2076 const=True, default=False, 2143 const=True, default=False,
2077 dest='log_to_console', 2144 dest='log_to_console',
2078 help='Enables or disables sys.stdout logging to ' 2145 help='Enables or disables sys.stdout logging to '
2079 'the console.') 2146 'the console.')
2080 option_parser.add_option('', '--port', default='0', type='int', 2147 option_parser.add_option('', '--port', default='0', type='int',
2081 help='Port used by the server. If unspecified, the ' 2148 help='Port used by the server. If unspecified, the '
2082 'server will listen on an ephemeral port.') 2149 'server will listen on an ephemeral port.')
2083 option_parser.add_option('', '--data-dir', dest='data_dir', 2150 option_parser.add_option('', '--data-dir', dest='data_dir',
2084 help='Directory from which to read the files.') 2151 help='Directory from which to read the files.')
2085 option_parser.add_option('', '--https', dest='cert', 2152 option_parser.add_option('', '--https', action='store_true', dest='https',
2086 help='Specify that https should be used, specify ' 2153 help='Specify that https should be used.')
2087 'the path to the cert containing the private key ' 2154 option_parser.add_option('', '--cert-and-key-file', dest='cert_and_key_file',
2088 'the server should use.') 2155 help='specify the path to the file containing the '
2156 'certificate and private key for the server in PEM '
2157 'format')
2158 option_parser.add_option('', '--ocsp', dest='ocsp', default='ok',
2159 help='The type of OCSP response generated for the '
2160 'automatically generated certificate. One of '
2161 '[ok,revoked,invalid]')
2089 option_parser.add_option('', '--https-record-resume', dest='record_resume', 2162 option_parser.add_option('', '--https-record-resume', dest='record_resume',
2090 const=True, default=False, action='store_const', 2163 const=True, default=False, action='store_const',
2091 help='Record resumption cache events rather than' 2164 help='Record resumption cache events rather than'
2092 ' resuming as normal. Allows the use of the' 2165 ' resuming as normal. Allows the use of the'
2093 ' /ssl-session-cache request') 2166 ' /ssl-session-cache request')
2094 option_parser.add_option('', '--ssl-client-auth', action='store_true', 2167 option_parser.add_option('', '--ssl-client-auth', action='store_true',
2095 help='Require SSL client auth on every connection.') 2168 help='Require SSL client auth on every connection.')
2096 option_parser.add_option('', '--ssl-client-ca', action='append', default=[], 2169 option_parser.add_option('', '--ssl-client-ca', action='append', default=[],
2097 help='Specify that the client certificate request ' 2170 help='Specify that the client certificate request '
2098 'should include the CA named in the subject of ' 2171 'should include the CA named in the subject of '
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2131 dest='host', 2204 dest='host',
2132 help='Hostname or IP upon which the server will ' 2205 help='Hostname or IP upon which the server will '
2133 'listen. Client connections will also only be ' 2206 'listen. Client connections will also only be '
2134 'allowed from this address.') 2207 'allowed from this address.')
2135 option_parser.add_option('', '--auth-token', dest='auth_token', 2208 option_parser.add_option('', '--auth-token', dest='auth_token',
2136 help='Specify the auth token which should be used' 2209 help='Specify the auth token which should be used'
2137 'in the authorization header for GData.') 2210 'in the authorization header for GData.')
2138 options, args = option_parser.parse_args() 2211 options, args = option_parser.parse_args()
2139 2212
2140 sys.exit(main(options, args)) 2213 sys.exit(main(options, args))
OLDNEW
« no previous file with comments | « net/tools/testserver/minica.py ('k') | net/url_request/url_request_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698