OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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()) |
OLD | NEW |