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

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

Issue 92443002: Extract Certificate Transparency SCTs from stapled OCSP responses (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@extract_scts
Patch Set: review comments Created 7 years 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
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2013 The Chromium Authors. All rights reserved. 2 # Copyright 2013 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/TCP/UDP/BASIC_AUTH_PROXY/WEBSOCKET server used for 6 """This is a simple HTTP/FTP/TCP/UDP/BASIC_AUTH_PROXY/WEBSOCKET server used for
7 testing Chrome. 7 testing Chrome.
8 8
9 It supports several test URLs, as specified by the handlers in TestPageHandler. 9 It supports several test URLs, as specified by the handlers in TestPageHandler.
10 By default, it listens on an ephemeral port and sends the port number back to 10 By default, it listens on an ephemeral port and sends the port number back to
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 121
122 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, 122 class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
123 testserver_base.ClientRestrictingServerMixIn, 123 testserver_base.ClientRestrictingServerMixIn,
124 testserver_base.BrokenPipeHandlerMixIn, 124 testserver_base.BrokenPipeHandlerMixIn,
125 testserver_base.StoppableHTTPServer): 125 testserver_base.StoppableHTTPServer):
126 """This is a specialization of StoppableHTTPServer that add https support and 126 """This is a specialization of StoppableHTTPServer that add https support and
127 client verification.""" 127 client verification."""
128 128
129 def __init__(self, server_address, request_hander_class, pem_cert_and_key, 129 def __init__(self, server_address, request_hander_class, pem_cert_and_key,
130 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, 130 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers,
131 record_resume_info, tls_intolerant, signed_cert_timestamps): 131 record_resume_info, tls_intolerant,
132 signed_cert_timestamps, ocsp_response):
132 self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key) 133 self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key)
133 # Force using only python implementation - otherwise behavior is different 134 # Force using only python implementation - otherwise behavior is different
134 # depending on whether m2crypto Python module is present (error is thrown 135 # depending on whether m2crypto Python module is present (error is thrown
135 # when it is). m2crypto uses a C (based on OpenSSL) implementation under 136 # when it is). m2crypto uses a C (based on OpenSSL) implementation under
136 # the hood. 137 # the hood.
137 self.private_key = tlslite.api.parsePEMKey(pem_cert_and_key, 138 self.private_key = tlslite.api.parsePEMKey(pem_cert_and_key,
138 private=True, 139 private=True,
139 implementations=['python']) 140 implementations=['python'])
140 self.ssl_client_auth = ssl_client_auth 141 self.ssl_client_auth = ssl_client_auth
141 self.ssl_client_cas = [] 142 self.ssl_client_cas = []
142 self.tls_intolerant = tls_intolerant 143 self.tls_intolerant = tls_intolerant
143 self.signed_cert_timestamps = signed_cert_timestamps 144 self.signed_cert_timestamps = signed_cert_timestamps
145 self.ocsp_response = ocsp_response
144 146
145 for ca_file in ssl_client_cas: 147 for ca_file in ssl_client_cas:
146 s = open(ca_file).read() 148 s = open(ca_file).read()
147 x509 = tlslite.api.X509() 149 x509 = tlslite.api.X509()
148 x509.parse(s) 150 x509.parse(s)
149 self.ssl_client_cas.append(x509.subject) 151 self.ssl_client_cas.append(x509.subject)
150 self.ssl_handshake_settings = tlslite.api.HandshakeSettings() 152 self.ssl_handshake_settings = tlslite.api.HandshakeSettings()
151 if ssl_bulk_ciphers is not None: 153 if ssl_bulk_ciphers is not None:
152 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers 154 self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers
153 155
(...skipping 13 matching lines...) Expand all
167 try: 169 try:
168 self.tlsConnection = tlsConnection 170 self.tlsConnection = tlsConnection
169 tlsConnection.handshakeServer(certChain=self.cert_chain, 171 tlsConnection.handshakeServer(certChain=self.cert_chain,
170 privateKey=self.private_key, 172 privateKey=self.private_key,
171 sessionCache=self.session_cache, 173 sessionCache=self.session_cache,
172 reqCert=self.ssl_client_auth, 174 reqCert=self.ssl_client_auth,
173 settings=self.ssl_handshake_settings, 175 settings=self.ssl_handshake_settings,
174 reqCAs=self.ssl_client_cas, 176 reqCAs=self.ssl_client_cas,
175 tlsIntolerant=self.tls_intolerant, 177 tlsIntolerant=self.tls_intolerant,
176 signedCertTimestamps= 178 signedCertTimestamps=
177 self.signed_cert_timestamps) 179 self.signed_cert_timestamps,
180 OCSPResponse = self.ocsp_response)
wtc 2013/12/03 21:04:25 Nit: should "OCSPResponse" start in lowercase "ocs
ekasper 2013/12/04 19:25:15 Done.
178 tlsConnection.ignoreAbruptClose = True 181 tlsConnection.ignoreAbruptClose = True
179 return True 182 return True
180 except tlslite.api.TLSAbruptCloseError: 183 except tlslite.api.TLSAbruptCloseError:
181 # Ignore abrupt close. 184 # Ignore abrupt close.
182 return True 185 return True
183 except tlslite.api.TLSError, error: 186 except tlslite.api.TLSError, error:
184 print "Handshake failure:", str(error) 187 print "Handshake failure:", str(error)
185 return False 188 return False
186 189
187 190
(...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after
1879 "test", "data") 1882 "test", "data")
1880 1883
1881 #TODO(ibrar): Must use Find* funtion defined in google\tools 1884 #TODO(ibrar): Must use Find* funtion defined in google\tools
1882 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data") 1885 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data")
1883 1886
1884 return my_data_dir 1887 return my_data_dir
1885 1888
1886 def create_server(self, server_data): 1889 def create_server(self, server_data):
1887 port = self.options.port 1890 port = self.options.port
1888 host = self.options.host 1891 host = self.options.host
1892 ocsp_der = None
1889 1893
1890 if self.options.server_type == SERVER_HTTP: 1894 if self.options.server_type == SERVER_HTTP:
1891 if self.options.https: 1895 if self.options.https:
1892 pem_cert_and_key = None 1896 pem_cert_and_key = None
1893 if self.options.cert_and_key_file: 1897 if self.options.cert_and_key_file:
1894 if not os.path.isfile(self.options.cert_and_key_file): 1898 if not os.path.isfile(self.options.cert_and_key_file):
1895 raise testserver_base.OptionError( 1899 raise testserver_base.OptionError(
1896 'specified server cert file not found: ' + 1900 'specified server cert file not found: ' +
1897 self.options.cert_and_key_file + ' exiting...') 1901 self.options.cert_and_key_file + ' exiting...')
1898 pem_cert_and_key = file(self.options.cert_and_key_file, 'r').read() 1902 pem_cert_and_key = file(self.options.cert_and_key_file, 'r').read()
1899 else: 1903 else:
1900 # generate a new certificate and run an OCSP server for it. 1904 # generate a new certificate and run an OCSP server for it.
1901 self.__ocsp_server = OCSPServer((host, 0), OCSPHandler) 1905 self.__ocsp_server = OCSPServer((host, 0), OCSPHandler)
1902 print ('OCSP server started on %s:%d...' % 1906 print ('OCSP server started on %s:%d...' %
1903 (host, self.__ocsp_server.server_port)) 1907 (host, self.__ocsp_server.server_port))
1904 1908
1905 ocsp_der = None
1906 ocsp_state = None 1909 ocsp_state = None
1907 1910
1908 if self.options.ocsp == 'ok': 1911 if self.options.ocsp == 'ok':
1909 ocsp_state = minica.OCSP_STATE_GOOD 1912 ocsp_state = minica.OCSP_STATE_GOOD
1910 elif self.options.ocsp == 'revoked': 1913 elif self.options.ocsp == 'revoked':
1911 ocsp_state = minica.OCSP_STATE_REVOKED 1914 ocsp_state = minica.OCSP_STATE_REVOKED
1912 elif self.options.ocsp == 'invalid': 1915 elif self.options.ocsp == 'invalid':
1913 ocsp_state = minica.OCSP_STATE_INVALID 1916 ocsp_state = minica.OCSP_STATE_INVALID
1914 elif self.options.ocsp == 'unauthorized': 1917 elif self.options.ocsp == 'unauthorized':
1915 ocsp_state = minica.OCSP_STATE_UNAUTHORIZED 1918 ocsp_state = minica.OCSP_STATE_UNAUTHORIZED
1916 elif self.options.ocsp == 'unknown': 1919 elif self.options.ocsp == 'unknown':
1917 ocsp_state = minica.OCSP_STATE_UNKNOWN 1920 ocsp_state = minica.OCSP_STATE_UNKNOWN
1918 else: 1921 else:
1919 raise testserver_base.OptionError('unknown OCSP status: ' + 1922 raise testserver_base.OptionError('unknown OCSP status: ' +
1920 self.options.ocsp_status) 1923 self.options.ocsp_status)
1921 1924
1922 (pem_cert_and_key, ocsp_der) = minica.GenerateCertKeyAndOCSP( 1925 (pem_cert_and_key, ocsp_der) = minica.GenerateCertKeyAndOCSP(
1923 subject = "127.0.0.1", 1926 subject = "127.0.0.1",
1924 ocsp_url = ("http://%s:%d/ocsp" % 1927 ocsp_url = ("http://%s:%d/ocsp" %
1925 (host, self.__ocsp_server.server_port)), 1928 (host, self.__ocsp_server.server_port)),
1926 ocsp_state = ocsp_state, 1929 ocsp_state = ocsp_state,
1927 serial = self.options.cert_serial) 1930 serial = self.options.cert_serial,
1931 # Signed Certificate Timestamps are only accepted in a stapled
1932 # response: when included in a non-stapled response, the client
1933 # will simply ignore the extension.
wtc 2013/12/03 21:04:25 Is this comment true? If I get an OCSP response fr
ekasper 2013/12/04 19:25:15 I've reverted the extension code here as the testi
1934 sct_extension = (
1935 self.options.signed_cert_timestamps_ocsp.decode("base64")))
1928 1936
1929 self.__ocsp_server.ocsp_response = ocsp_der 1937 self.__ocsp_server.ocsp_response = ocsp_der
1930 1938
1931 for ca_cert in self.options.ssl_client_ca: 1939 for ca_cert in self.options.ssl_client_ca:
1932 if not os.path.isfile(ca_cert): 1940 if not os.path.isfile(ca_cert):
1933 raise testserver_base.OptionError( 1941 raise testserver_base.OptionError(
1934 'specified trusted client CA file not found: ' + ca_cert + 1942 'specified trusted client CA file not found: ' + ca_cert +
1935 ' exiting...') 1943 ' exiting...')
1944
1936 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key, 1945 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key,
1937 self.options.ssl_client_auth, 1946 self.options.ssl_client_auth,
1938 self.options.ssl_client_ca, 1947 self.options.ssl_client_ca,
1939 self.options.ssl_bulk_cipher, 1948 self.options.ssl_bulk_cipher,
1940 self.options.record_resume, 1949 self.options.record_resume,
1941 self.options.tls_intolerant, 1950 self.options.tls_intolerant,
1942 self.options.signed_cert_timestamps.decode( 1951 self.options.signed_cert_timestamps_tls_ext.decode(
1943 "base64")) 1952 "base64"),
1953 ocsp_der)
wtc 2013/12/03 21:04:25 Should we use self.__ocsp_server.ocsp_response her
ekasper 2013/12/04 19:25:15 Changed.
1944 print 'HTTPS server started on %s:%d...' % (host, server.server_port) 1954 print 'HTTPS server started on %s:%d...' % (host, server.server_port)
1945 else: 1955 else:
1946 server = HTTPServer((host, port), TestPageHandler) 1956 server = HTTPServer((host, port), TestPageHandler)
1947 print 'HTTP server started on %s:%d...' % (host, server.server_port) 1957 print 'HTTP server started on %s:%d...' % (host, server.server_port)
1948 1958
1949 server.data_dir = self.__make_data_dir() 1959 server.data_dir = self.__make_data_dir()
1950 server.file_root_url = self.options.file_root_url 1960 server.file_root_url = self.options.file_root_url
1951 server_data['port'] = server.server_port 1961 server_data['port'] = server.server_port
1952 elif self.options.server_type == SERVER_WEBSOCKET: 1962 elif self.options.server_type == SERVER_WEBSOCKET:
1953 # Launch pywebsocket via WebSocketServer. 1963 # Launch pywebsocket via WebSocketServer.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2071 help='If non-zero then the generated ' 2081 help='If non-zero then the generated '
2072 'certificate will have this serial number') 2082 'certificate will have this serial number')
2073 self.option_parser.add_option('--tls-intolerant', dest='tls_intolerant', 2083 self.option_parser.add_option('--tls-intolerant', dest='tls_intolerant',
2074 default='0', type='int', 2084 default='0', type='int',
2075 help='If nonzero, certain TLS connections ' 2085 help='If nonzero, certain TLS connections '
2076 'will be aborted in order to test version ' 2086 'will be aborted in order to test version '
2077 'fallback. 1 means all TLS versions will be ' 2087 'fallback. 1 means all TLS versions will be '
2078 'aborted. 2 means TLS 1.1 or higher will be ' 2088 'aborted. 2 means TLS 1.1 or higher will be '
2079 'aborted. 3 means TLS 1.2 or higher will be ' 2089 'aborted. 3 means TLS 1.2 or higher will be '
2080 'aborted.') 2090 'aborted.')
2081 self.option_parser.add_option('--signed-cert-timestamps', 2091 self.option_parser.add_option('--signed-cert-timestamps-tls-ext',
2082 dest='signed_cert_timestamps', 2092 dest='signed_cert_timestamps_tls_ext',
2083 default='', 2093 default='',
2084 help='Base64 encoded SCT list. If set, ' 2094 help='Base64 encoded SCT list. If set, '
2085 'server will respond with a ' 2095 'server will respond with a '
2086 'signed_certificate_timestamp TLS extension ' 2096 'signed_certificate_timestamp TLS extension '
2087 'whenever the client supports it.') 2097 'whenever the client supports it.')
2098 self.option_parser.add_option('--signed-cert-timestamps-ocsp',
2099 dest='signed_cert_timestamps_ocsp',
2100 default='',
2101 help='Base64 encoded SCT list. If set, '
2102 'server will include the list in a stapled '
2103 'OCSP response whenever the client supports '
2104 'OCSP stapling.')
2088 self.option_parser.add_option('--https-record-resume', 2105 self.option_parser.add_option('--https-record-resume',
2089 dest='record_resume', const=True, 2106 dest='record_resume', const=True,
2090 default=False, action='store_const', 2107 default=False, action='store_const',
2091 help='Record resumption cache events rather ' 2108 help='Record resumption cache events rather '
2092 'than resuming as normal. Allows the use of ' 2109 'than resuming as normal. Allows the use of '
2093 'the /ssl-session-cache request') 2110 'the /ssl-session-cache request')
2094 self.option_parser.add_option('--ssl-client-auth', action='store_true', 2111 self.option_parser.add_option('--ssl-client-auth', action='store_true',
2095 help='Require SSL client auth on every ' 2112 help='Require SSL client auth on every '
2096 'connection.') 2113 'connection.')
2097 self.option_parser.add_option('--ssl-client-ca', action='append', 2114 self.option_parser.add_option('--ssl-client-ca', action='append',
(...skipping 11 matching lines...) Expand all
2109 '"aes128", "3des", "rc4". If omitted, all ' 2126 '"aes128", "3des", "rc4". If omitted, all '
2110 'algorithms will be used. This option may ' 2127 'algorithms will be used. This option may '
2111 'appear multiple times, indicating ' 2128 'appear multiple times, indicating '
2112 'multiple algorithms should be enabled.'); 2129 'multiple algorithms should be enabled.');
2113 self.option_parser.add_option('--file-root-url', default='/files/', 2130 self.option_parser.add_option('--file-root-url', default='/files/',
2114 help='Specify a root URL for files served.') 2131 help='Specify a root URL for files served.')
2115 2132
2116 2133
2117 if __name__ == '__main__': 2134 if __name__ == '__main__':
2118 sys.exit(ServerRunner().main()) 2135 sys.exit(ServerRunner().main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698