OLD | NEW |
---|---|
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 minica |
23 import optparse | |
24 import os | 23 import os |
25 import random | 24 import random |
26 import re | 25 import re |
27 import select | 26 import select |
28 import socket | 27 import socket |
29 import SocketServer | 28 import SocketServer |
30 import struct | |
31 import sys | 29 import sys |
32 import threading | 30 import threading |
33 import time | 31 import time |
34 import urllib | 32 import urllib |
35 import urlparse | 33 import urlparse |
36 import warnings | |
37 import zlib | 34 import zlib |
38 | 35 |
39 # Ignore deprecation warnings, they make our output more cluttered. | |
40 warnings.filterwarnings("ignore", category=DeprecationWarning) | |
41 | |
42 import echo_message | 36 import echo_message |
43 import pyftpdlib.ftpserver | 37 import pyftpdlib.ftpserver |
38 import testserver_base | |
44 import tlslite | 39 import tlslite |
45 import tlslite.api | 40 import tlslite.api |
46 | 41 |
47 try: | 42 try: |
48 import hashlib | 43 import hashlib |
49 _new_md5 = hashlib.md5 | 44 _new_md5 = hashlib.md5 |
50 except ImportError: | 45 except ImportError: |
51 import md5 | 46 import md5 |
52 _new_md5 = md5.new | 47 _new_md5 = md5.new |
53 | 48 |
54 try: | |
55 import json | |
56 except ImportError: | |
57 import simplejson as json | |
58 | |
59 if sys.platform == 'win32': | |
60 import msvcrt | |
61 | |
62 SERVER_HTTP = 0 | 49 SERVER_HTTP = 0 |
63 SERVER_FTP = 1 | 50 SERVER_FTP = 1 |
64 SERVER_SYNC = 2 | 51 SERVER_SYNC = 2 |
65 SERVER_TCP_ECHO = 3 | 52 SERVER_TCP_ECHO = 3 |
66 SERVER_UDP_ECHO = 4 | 53 SERVER_UDP_ECHO = 4 |
67 | 54 |
68 # Using debug() seems to cause hangs on XP: see http://crbug.com/64515 . | 55 # Using debug() seems to cause hangs on XP: see http://crbug.com/64515 . |
69 debug_output = sys.stderr | 56 debug_output = sys.stderr |
70 def debug(str): | 57 def debug(str): |
71 debug_output.write(str + "\n") | 58 debug_output.write(str + "\n") |
(...skipping 1862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1934 return False | 1921 return False |
1935 result, raw_reply = self.server._sync_handler.HandleCreateSyncedBookmarks() | 1922 result, raw_reply = self.server._sync_handler.HandleCreateSyncedBookmarks() |
1936 self.send_response(result) | 1923 self.send_response(result) |
1937 self.send_header('Content-Type', 'text/html') | 1924 self.send_header('Content-Type', 'text/html') |
1938 self.send_header('Content-Length', len(raw_reply)) | 1925 self.send_header('Content-Length', len(raw_reply)) |
1939 self.end_headers() | 1926 self.end_headers() |
1940 self.wfile.write(raw_reply) | 1927 self.wfile.write(raw_reply) |
1941 return True; | 1928 return True; |
1942 | 1929 |
1943 | 1930 |
1944 def MakeDataDir(): | |
1945 if options.data_dir: | |
1946 if not os.path.isdir(options.data_dir): | |
1947 print 'specified data dir not found: ' + options.data_dir + ' exiting...' | |
1948 return None | |
1949 my_data_dir = options.data_dir | |
1950 else: | |
1951 # Create the default path to our data dir, relative to the exe dir. | |
1952 my_data_dir = os.path.dirname(sys.argv[0]) | |
1953 my_data_dir = os.path.join(my_data_dir, "..", "..", "..", "..", | |
1954 "test", "data") | |
1955 | |
1956 #TODO(ibrar): Must use Find* funtion defined in google\tools | |
1957 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data") | |
1958 | |
1959 return my_data_dir | |
1960 | |
1961 class OCSPHandler(BasePageHandler): | 1931 class OCSPHandler(BasePageHandler): |
1962 def __init__(self, request, client_address, socket_server): | 1932 def __init__(self, request, client_address, socket_server): |
1963 handlers = [self.OCSPResponse] | 1933 handlers = [self.OCSPResponse] |
1964 self.ocsp_response = socket_server.ocsp_response | 1934 self.ocsp_response = socket_server.ocsp_response |
1965 BasePageHandler.__init__(self, request, client_address, socket_server, | 1935 BasePageHandler.__init__(self, request, client_address, socket_server, |
1966 [], handlers, [], handlers, []) | 1936 [], handlers, [], handlers, []) |
1967 | 1937 |
1968 def OCSPResponse(self): | 1938 def OCSPResponse(self): |
1969 self.send_response(200) | 1939 self.send_response(200) |
1970 self.send_header('Content-Type', 'application/ocsp-response') | 1940 self.send_header('Content-Type', 'application/ocsp-response') |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2012 # "echo response" message if "echo request" message is valid. | 1982 # "echo response" message if "echo request" message is valid. |
2013 try: | 1983 try: |
2014 return_data = echo_message.GetEchoResponseData(data) | 1984 return_data = echo_message.GetEchoResponseData(data) |
2015 if not return_data: | 1985 if not return_data: |
2016 return | 1986 return |
2017 except ValueError: | 1987 except ValueError: |
2018 return | 1988 return |
2019 socket.sendto(return_data, self.client_address) | 1989 socket.sendto(return_data, self.client_address) |
2020 | 1990 |
2021 | 1991 |
2022 class FileMultiplexer: | 1992 class ServerRunner(testserver_base.TestServerRunner): |
2023 def __init__(self, fd1, fd2) : | 1993 def __make_data_dir(self): |
2024 self.__fd1 = fd1 | 1994 if self.options.data_dir: |
2025 self.__fd2 = fd2 | 1995 if not os.path.isdir(self.options.data_dir): |
2026 | 1996 print ('specified data dir not found: ' + self.options.data_dir + |
2027 def __del__(self) : | 1997 ' exiting...') |
2028 if self.__fd1 != sys.stdout and self.__fd1 != sys.stderr: | 1998 return None |
2029 self.__fd1.close() | 1999 my_data_dir = self.options.data_dir |
2030 if self.__fd2 != sys.stdout and self.__fd2 != sys.stderr: | 2000 else: |
2031 self.__fd2.close() | 2001 # Create the default path to our data dir, relative to the exe dir. |
2032 | 2002 my_data_dir = os.path.dirname(sys.argv[0]) |
M-A Ruel
2012/08/31 22:04:05
it's not a good idea in general to do this. If an
mattm
2012/09/01 01:44:54
Done.
| |
2033 def write(self, text) : | 2003 my_data_dir = os.path.join(my_data_dir, "..", "..", "..", "..", |
2034 self.__fd1.write(text) | 2004 "test", "data") |
2035 self.__fd2.write(text) | 2005 |
2036 | 2006 #TODO(ibrar): Must use Find* funtion defined in google\tools |
2037 def flush(self) : | 2007 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data") |
2038 self.__fd1.flush() | 2008 |
2039 self.__fd2.flush() | 2009 return my_data_dir |
2040 | 2010 |
2041 def main(options, args): | 2011 def create_server(self, server_data): |
M-A Ruel
2012/08/31 22:04:05
This function is really long and doesn't have a do
mattm
2012/09/01 01:44:54
Fixed the issue with returning weird things.
For
| |
2042 logfile = open('testserver.log', 'w') | 2012 port = self.options.port |
2043 sys.stderr = FileMultiplexer(sys.stderr, logfile) | 2013 host = self.options.host |
2044 if options.log_to_console: | 2014 |
2045 sys.stdout = FileMultiplexer(sys.stdout, logfile) | 2015 self.__ocsp_server = None |
M-A Ruel
2012/08/31 22:04:05
If you want to make this code pylint-clean, which
mattm
2012/09/01 01:44:54
Done.
| |
2046 else: | 2016 |
2047 sys.stdout = logfile | 2017 if self.options.server_type == SERVER_HTTP: |
2048 | 2018 if self.options.https: |
2049 port = options.port | 2019 pem_cert_and_key = None |
2050 host = options.host | 2020 if self.options.cert_and_key_file: |
2051 | 2021 if not os.path.isfile(self.options.cert_and_key_file): |
2052 server_data = {} | 2022 print ('specified server cert file not found: ' + |
2053 server_data['host'] = host | 2023 self.options.cert_and_key_file + ' exiting...') |
2054 | 2024 return |
2055 ocsp_server = None | 2025 pem_cert_and_key = file(self.options.cert_and_key_file, 'r').read() |
2056 | 2026 else: |
2057 if options.server_type == SERVER_HTTP: | 2027 # generate a new certificate and run an OCSP server for it. |
2058 if options.https: | 2028 self.__ocsp_server = OCSPServer((host, 0), OCSPHandler) |
2059 pem_cert_and_key = None | 2029 print ('OCSP server started on %s:%d...' % |
2060 if options.cert_and_key_file: | 2030 (host, self.__ocsp_server.server_port)) |
2061 if not os.path.isfile(options.cert_and_key_file): | 2031 |
2062 print ('specified server cert file not found: ' + | 2032 ocsp_der = None |
2063 options.cert_and_key_file + ' exiting...') | 2033 ocsp_state = None |
2064 return | 2034 |
2065 pem_cert_and_key = file(options.cert_and_key_file, 'r').read() | 2035 if self.options.ocsp == 'ok': |
2036 ocsp_state = minica.OCSP_STATE_GOOD | |
2037 elif self.options.ocsp == 'revoked': | |
2038 ocsp_state = minica.OCSP_STATE_REVOKED | |
2039 elif self.options.ocsp == 'invalid': | |
2040 ocsp_state = minica.OCSP_STATE_INVALID | |
2041 elif self.options.ocsp == 'unauthorized': | |
2042 ocsp_state = minica.OCSP_STATE_UNAUTHORIZED | |
2043 elif self.options.ocsp == 'unknown': | |
2044 ocsp_state = minica.OCSP_STATE_UNKNOWN | |
2045 else: | |
2046 print 'unknown OCSP status: ' + self.options.ocsp_status | |
2047 return | |
2048 | |
2049 (pem_cert_and_key, ocsp_der) = \ | |
M-A Ruel
2012/08/31 22:04:05
style nit:
(pem_cert_and_key, ocsp_der) = minica.G
mattm
2012/09/01 01:44:54
Done.
| |
2050 minica.GenerateCertKeyAndOCSP( | |
2051 subject = "127.0.0.1", | |
2052 ocsp_url = ("http://%s:%d/ocsp" % | |
2053 (host, self.__ocsp_server.server_port)), | |
2054 ocsp_state = ocsp_state) | |
2055 | |
2056 self.__ocsp_server.ocsp_response = ocsp_der | |
2057 | |
2058 for ca_cert in self.options.ssl_client_ca: | |
2059 if not os.path.isfile(ca_cert): | |
2060 print 'specified trusted client CA file not found: ' + ca_cert + \ | |
2061 ' exiting...' | |
2062 return | |
2063 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key, | |
2064 self.options.ssl_client_auth, | |
2065 self.options.ssl_client_ca, | |
2066 self.options.ssl_bulk_cipher, | |
2067 self.options.record_resume, | |
2068 self.options.tls_intolerant) | |
2069 print 'HTTPS server started on %s:%d...' % (host, server.server_port) | |
2066 else: | 2070 else: |
2067 # generate a new certificate and run an OCSP server for it. | 2071 server = HTTPServer((host, port), TestPageHandler) |
2068 ocsp_server = OCSPServer((host, 0), OCSPHandler) | 2072 print 'HTTP server started on %s:%d...' % (host, server.server_port) |
2069 print ('OCSP server started on %s:%d...' % | 2073 |
2070 (host, ocsp_server.server_port)) | 2074 server.data_dir = self.__make_data_dir() |
2071 | 2075 server.file_root_url = self.options.file_root_url |
2072 ocsp_der = None | 2076 server_data['port'] = server.server_port |
2073 ocsp_state = None | 2077 server._device_management_handler = None |
2074 | 2078 server.policy_keys = self.options.policy_keys |
2075 if options.ocsp == 'ok': | 2079 server.policy_user = self.options.policy_user |
2076 ocsp_state = minica.OCSP_STATE_GOOD | 2080 server.gdata_auth_token = self.options.auth_token |
2077 elif options.ocsp == 'revoked': | 2081 elif self.options.server_type == SERVER_SYNC: |
2078 ocsp_state = minica.OCSP_STATE_REVOKED | 2082 xmpp_port = self.options.xmpp_port |
2079 elif options.ocsp == 'invalid': | 2083 server = SyncHTTPServer((host, port), xmpp_port, SyncPageHandler) |
2080 ocsp_state = minica.OCSP_STATE_INVALID | 2084 print 'Sync HTTP server started on port %d...' % server.server_port |
2081 elif options.ocsp == 'unauthorized': | 2085 print 'Sync XMPP server started on port %d...' % server.xmpp_port |
2082 ocsp_state = minica.OCSP_STATE_UNAUTHORIZED | 2086 server_data['port'] = server.server_port |
2083 elif options.ocsp == 'unknown': | 2087 server_data['xmpp_port'] = server.xmpp_port |
2084 ocsp_state = minica.OCSP_STATE_UNKNOWN | 2088 elif self.options.server_type == SERVER_TCP_ECHO: |
2085 else: | 2089 # Used for generating the key (randomly) that encodes the "echo request" |
2086 print 'unknown OCSP status: ' + options.ocsp_status | 2090 # message. |
2087 return | 2091 random.seed() |
2088 | 2092 server = TCPEchoServer((host, port), TCPEchoHandler) |
2089 (pem_cert_and_key, ocsp_der) = \ | 2093 print 'Echo TCP server started on port %d...' % server.server_port |
2090 minica.GenerateCertKeyAndOCSP( | 2094 server_data['port'] = server.server_port |
2091 subject = "127.0.0.1", | 2095 elif self.options.server_type == SERVER_UDP_ECHO: |
2092 ocsp_url = ("http://%s:%d/ocsp" % | 2096 # Used for generating the key (randomly) that encodes the "echo request" |
2093 (host, ocsp_server.server_port)), | 2097 # message. |
2094 ocsp_state = ocsp_state) | 2098 random.seed() |
2095 | 2099 server = UDPEchoServer((host, port), UDPEchoHandler) |
2096 ocsp_server.ocsp_response = ocsp_der | 2100 print 'Echo UDP server started on port %d...' % server.server_port |
2097 | 2101 server_data['port'] = server.server_port |
2098 for ca_cert in options.ssl_client_ca: | 2102 elif self.options.server_type == SERVER_FTP: |
2099 if not os.path.isfile(ca_cert): | 2103 my_data_dir = self.__make_data_dir() |
2100 print 'specified trusted client CA file not found: ' + ca_cert + \ | 2104 |
2101 ' exiting...' | 2105 # Instantiate a dummy authorizer for managing 'virtual' users |
2102 return | 2106 authorizer = pyftpdlib.ftpserver.DummyAuthorizer() |
2103 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key, | 2107 |
2104 options.ssl_client_auth, options.ssl_client_ca, | 2108 # Define a new user having full r/w permissions and a read-only |
2105 options.ssl_bulk_cipher, options.record_resume, | 2109 # anonymous user |
2106 options.tls_intolerant) | 2110 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') |
2107 print 'HTTPS server started on %s:%d...' % (host, server.server_port) | 2111 |
2112 authorizer.add_anonymous(my_data_dir) | |
2113 | |
2114 # Instantiate FTP handler class | |
2115 ftp_handler = pyftpdlib.ftpserver.FTPHandler | |
2116 ftp_handler.authorizer = authorizer | |
2117 | |
2118 # Define a customized banner (string returned when client connects) | |
2119 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." % | |
2120 pyftpdlib.ftpserver.__ver__) | |
2121 | |
2122 # Instantiate FTP server class and listen to address:port | |
2123 server = pyftpdlib.ftpserver.FTPServer((host, port), ftp_handler) | |
2124 server_data['port'] = server.socket.getsockname()[1] | |
2125 print 'FTP server started on port %d...' % server_data['port'] | |
2108 else: | 2126 else: |
2109 server = HTTPServer((host, port), TestPageHandler) | 2127 print 'unknown server type', self.options.server_type |
2110 print 'HTTP server started on %s:%d...' % (host, server.server_port) | 2128 return 1 |
2111 | 2129 |
2112 server.data_dir = MakeDataDir() | 2130 return server |
2113 server.file_root_url = options.file_root_url | 2131 |
2114 server_data['port'] = server.server_port | 2132 def run_server(self): |
2115 server._device_management_handler = None | 2133 if self.__ocsp_server is not None: |
M-A Ruel
2012/08/31 22:04:05
if self.__ocsp_server:
mattm
2012/09/01 01:44:54
Done.
| |
2116 server.policy_keys = options.policy_keys | 2134 self.__ocsp_server.serve_forever_on_thread() |
2117 server.policy_user = options.policy_user | 2135 |
2118 server.gdata_auth_token = options.auth_token | 2136 testserver_base.TestServerRunner.run_server(self) |
2119 elif options.server_type == SERVER_SYNC: | 2137 |
2120 xmpp_port = options.xmpp_port | 2138 if self.__ocsp_server is not None: |
M-A Ruel
2012/08/31 22:04:05
same
mattm
2012/09/01 01:44:54
Done.
| |
2121 server = SyncHTTPServer((host, port), xmpp_port, SyncPageHandler) | 2139 self.__ocsp_server.stop_serving() |
2122 print 'Sync HTTP server started on port %d...' % server.server_port | 2140 |
2123 print 'Sync XMPP server started on port %d...' % server.xmpp_port | 2141 def add_options(self): |
2124 server_data['port'] = server.server_port | 2142 testserver_base.TestServerRunner.add_options(self) |
2125 server_data['xmpp_port'] = server.xmpp_port | 2143 self.option_parser.add_option("-f", '--ftp', action='store_const', |
2126 elif options.server_type == SERVER_TCP_ECHO: | 2144 const=SERVER_FTP, default=SERVER_HTTP, |
2127 # Used for generating the key (randomly) that encodes the "echo request" | 2145 dest='server_type', |
2128 # message. | 2146 help='start up an FTP server.') |
2129 random.seed() | 2147 self.option_parser.add_option('', '--sync', action='store_const', |
2130 server = TCPEchoServer((host, port), TCPEchoHandler) | 2148 const=SERVER_SYNC, default=SERVER_HTTP, |
2131 print 'Echo TCP server started on port %d...' % server.server_port | 2149 dest='server_type', |
2132 server_data['port'] = server.server_port | 2150 help='start up a sync server.') |
2133 elif options.server_type == SERVER_UDP_ECHO: | 2151 self.option_parser.add_option('', '--tcp-echo', action='store_const', |
2134 # Used for generating the key (randomly) that encodes the "echo request" | 2152 const=SERVER_TCP_ECHO, default=SERVER_HTTP, |
2135 # message. | 2153 dest='server_type', |
2136 random.seed() | 2154 help='start up a tcp echo server.') |
2137 server = UDPEchoServer((host, port), UDPEchoHandler) | 2155 self.option_parser.add_option('', '--udp-echo', action='store_const', |
2138 print 'Echo UDP server started on port %d...' % server.server_port | 2156 const=SERVER_UDP_ECHO, default=SERVER_HTTP, |
2139 server_data['port'] = server.server_port | 2157 dest='server_type', |
2140 # means FTP Server | 2158 help='start up a udp echo server.') |
2141 else: | 2159 self.option_parser.add_option('', '--xmpp-port', default='0', type='int', |
2142 my_data_dir = MakeDataDir() | 2160 help='Port used by the XMPP server. If ' |
2143 | 2161 'unspecified, the XMPP server will listen on ' |
2144 # Instantiate a dummy authorizer for managing 'virtual' users | 2162 'an ephemeral port.') |
2145 authorizer = pyftpdlib.ftpserver.DummyAuthorizer() | 2163 self.option_parser.add_option('', '--data-dir', dest='data_dir', |
2146 | 2164 help='Directory from which to read the ' |
2147 # Define a new user having full r/w permissions and a read-only | 2165 'files.') |
2148 # anonymous user | 2166 self.option_parser.add_option('', '--https', action='store_true', |
2149 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') | 2167 dest='https', help='Specify that https ' |
2150 | 2168 'should be used.') |
2151 authorizer.add_anonymous(my_data_dir) | 2169 self.option_parser.add_option('', '--cert-and-key-file', |
2152 | 2170 dest='cert_and_key_file', help='specify the ' |
2153 # Instantiate FTP handler class | 2171 'path to the file containing the certificate ' |
2154 ftp_handler = pyftpdlib.ftpserver.FTPHandler | 2172 'and private key for the server in PEM ' |
2155 ftp_handler.authorizer = authorizer | 2173 'format') |
2156 | 2174 self.option_parser.add_option('', '--ocsp', dest='ocsp', default='ok', |
2157 # Define a customized banner (string returned when client connects) | 2175 help='The type of OCSP response generated ' |
2158 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." % | 2176 'for the automatically generated ' |
2159 pyftpdlib.ftpserver.__ver__) | 2177 'certificate. One of [ok,revoked,invalid]') |
2160 | 2178 self.option_parser.add_option('', '--tls-intolerant', dest='tls_intolerant', |
2161 # Instantiate FTP server class and listen to address:port | 2179 default='0', type='int', |
2162 server = pyftpdlib.ftpserver.FTPServer((host, port), ftp_handler) | 2180 help='If nonzero, certain TLS connections ' |
2163 server_data['port'] = server.socket.getsockname()[1] | 2181 'will be aborted in order to test version ' |
2164 print 'FTP server started on port %d...' % server_data['port'] | 2182 'fallback. 1 means all TLS versions will be ' |
2165 | 2183 'aborted. 2 means TLS 1.1 or higher will be ' |
2166 # Notify the parent that we've started. (BaseServer subclasses | 2184 'aborted. 3 means TLS 1.2 or higher will be ' |
2167 # bind their sockets on construction.) | 2185 'aborted.') |
2168 if options.startup_pipe is not None: | 2186 self.option_parser.add_option('', '--https-record-resume', |
2169 server_data_json = json.dumps(server_data) | 2187 dest='record_resume', const=True, |
2170 server_data_len = len(server_data_json) | 2188 default=False, action='store_const', |
2171 print 'sending server_data: %s (%d bytes)' % ( | 2189 help='Record resumption cache events rather ' |
2172 server_data_json, server_data_len) | 2190 'than resuming as normal. Allows the use of ' |
2173 if sys.platform == 'win32': | 2191 'the /ssl-session-cache request') |
2174 fd = msvcrt.open_osfhandle(options.startup_pipe, 0) | 2192 self.option_parser.add_option('', '--ssl-client-auth', action='store_true', |
2175 else: | 2193 help='Require SSL client auth on every ' |
2176 fd = options.startup_pipe | 2194 'connection.') |
2177 startup_pipe = os.fdopen(fd, "w") | 2195 self.option_parser.add_option('', '--ssl-client-ca', action='append', |
2178 # First write the data length as an unsigned 4-byte value. This | 2196 default=[], help='Specify that the client ' |
2179 # is _not_ using network byte ordering since the other end of the | 2197 'certificate request should include the CA ' |
2180 # pipe is on the same machine. | 2198 'named in the subject of the DER-encoded ' |
2181 startup_pipe.write(struct.pack('=L', server_data_len)) | 2199 'certificate contained in the specified ' |
2182 startup_pipe.write(server_data_json) | 2200 'file. This option may appear multiple ' |
2183 startup_pipe.close() | 2201 'times, indicating multiple CA names should ' |
2184 | 2202 'be sent in the request.') |
2185 if ocsp_server is not None: | 2203 self.option_parser.add_option('', '--ssl-bulk-cipher', action='append', |
2186 ocsp_server.serve_forever_on_thread() | 2204 help='Specify the bulk encryption ' |
2187 | 2205 'algorithm(s) that will be accepted by the ' |
2188 try: | 2206 'SSL server. Valid values are "aes256", ' |
2189 server.serve_forever() | 2207 '"aes128", "3des", "rc4". If omitted, all ' |
2190 except KeyboardInterrupt: | 2208 'algorithms will be used. This option may ' |
2191 print 'shutting down server' | 2209 'appear multiple times, indicating ' |
2192 if ocsp_server is not None: | 2210 'multiple algorithms should be enabled.'); |
2193 ocsp_server.stop_serving() | 2211 self.option_parser.add_option('', '--file-root-url', default='/files/', |
2194 server.stop = True | 2212 help='Specify a root URL for files served.') |
2213 self.option_parser.add_option('', '--policy-key', action='append', | |
2214 dest='policy_keys', | |
2215 help='Specify a path to a PEM-encoded ' | |
2216 'private key to use for policy signing. May ' | |
2217 'be specified multiple times in order to ' | |
2218 'load multipe keys into the server. If the ' | |
2219 'server has multiple keys, it will rotate ' | |
2220 'through them in at each request a ' | |
2221 'round-robin fashion. The server will ' | |
2222 'generate a random key if none is specified ' | |
2223 'on the command line.') | |
2224 self.option_parser.add_option('', '--policy-user', | |
2225 default='user@example.com', | |
2226 dest='policy_user', | |
2227 help='Specify the user name the server ' | |
2228 'should report back to the client as the ' | |
2229 'user owning the token used for making the ' | |
2230 'policy request.') | |
2231 self.option_parser.add_option('', '--auth-token', dest='auth_token', | |
2232 help='Specify the auth token which should be ' | |
2233 'used in the authorization header for GData.') | |
2195 | 2234 |
2196 if __name__ == '__main__': | 2235 if __name__ == '__main__': |
2197 option_parser = optparse.OptionParser() | 2236 sys.exit(ServerRunner().main()) |
2198 option_parser.add_option("-f", '--ftp', action='store_const', | |
2199 const=SERVER_FTP, default=SERVER_HTTP, | |
2200 dest='server_type', | |
2201 help='start up an FTP server.') | |
2202 option_parser.add_option('', '--sync', action='store_const', | |
2203 const=SERVER_SYNC, default=SERVER_HTTP, | |
2204 dest='server_type', | |
2205 help='start up a sync server.') | |
2206 option_parser.add_option('', '--tcp-echo', action='store_const', | |
2207 const=SERVER_TCP_ECHO, default=SERVER_HTTP, | |
2208 dest='server_type', | |
2209 help='start up a tcp echo server.') | |
2210 option_parser.add_option('', '--udp-echo', action='store_const', | |
2211 const=SERVER_UDP_ECHO, default=SERVER_HTTP, | |
2212 dest='server_type', | |
2213 help='start up a udp echo server.') | |
2214 option_parser.add_option('', '--log-to-console', action='store_const', | |
2215 const=True, default=False, | |
2216 dest='log_to_console', | |
2217 help='Enables or disables sys.stdout logging to ' | |
2218 'the console.') | |
2219 option_parser.add_option('', '--port', default='0', type='int', | |
2220 help='Port used by the server. If unspecified, the ' | |
2221 'server will listen on an ephemeral port.') | |
2222 option_parser.add_option('', '--xmpp-port', default='0', type='int', | |
2223 help='Port used by the XMPP server. If unspecified, ' | |
2224 'the XMPP server will listen on an ephemeral port.') | |
2225 option_parser.add_option('', '--data-dir', dest='data_dir', | |
2226 help='Directory from which to read the files.') | |
2227 option_parser.add_option('', '--https', action='store_true', dest='https', | |
2228 help='Specify that https should be used.') | |
2229 option_parser.add_option('', '--cert-and-key-file', dest='cert_and_key_file', | |
2230 help='specify the path to the file containing the ' | |
2231 'certificate and private key for the server in PEM ' | |
2232 'format') | |
2233 option_parser.add_option('', '--ocsp', dest='ocsp', default='ok', | |
2234 help='The type of OCSP response generated for the ' | |
2235 'automatically generated certificate. One of ' | |
2236 '[ok,revoked,invalid]') | |
2237 option_parser.add_option('', '--tls-intolerant', dest='tls_intolerant', | |
2238 default='0', type='int', | |
2239 help='If nonzero, certain TLS connections will be' | |
2240 ' aborted in order to test version fallback. 1' | |
2241 ' means all TLS versions will be aborted. 2 means' | |
2242 ' TLS 1.1 or higher will be aborted. 3 means TLS' | |
2243 ' 1.2 or higher will be aborted.') | |
2244 option_parser.add_option('', '--https-record-resume', dest='record_resume', | |
2245 const=True, default=False, action='store_const', | |
2246 help='Record resumption cache events rather than' | |
2247 ' resuming as normal. Allows the use of the' | |
2248 ' /ssl-session-cache request') | |
2249 option_parser.add_option('', '--ssl-client-auth', action='store_true', | |
2250 help='Require SSL client auth on every connection.') | |
2251 option_parser.add_option('', '--ssl-client-ca', action='append', default=[], | |
2252 help='Specify that the client certificate request ' | |
2253 'should include the CA named in the subject of ' | |
2254 'the DER-encoded certificate contained in the ' | |
2255 'specified file. This option may appear multiple ' | |
2256 'times, indicating multiple CA names should be ' | |
2257 'sent in the request.') | |
2258 option_parser.add_option('', '--ssl-bulk-cipher', action='append', | |
2259 help='Specify the bulk encryption algorithm(s)' | |
2260 'that will be accepted by the SSL server. Valid ' | |
2261 'values are "aes256", "aes128", "3des", "rc4". If ' | |
2262 'omitted, all algorithms will be used. This ' | |
2263 'option may appear multiple times, indicating ' | |
2264 'multiple algorithms should be enabled.'); | |
2265 option_parser.add_option('', '--file-root-url', default='/files/', | |
2266 help='Specify a root URL for files served.') | |
2267 option_parser.add_option('', '--startup-pipe', type='int', | |
2268 dest='startup_pipe', | |
2269 help='File handle of pipe to parent process') | |
2270 option_parser.add_option('', '--policy-key', action='append', | |
2271 dest='policy_keys', | |
2272 help='Specify a path to a PEM-encoded private key ' | |
2273 'to use for policy signing. May be specified ' | |
2274 'multiple times in order to load multipe keys into ' | |
2275 'the server. If ther server has multiple keys, it ' | |
2276 'will rotate through them in at each request a ' | |
2277 'round-robin fashion. The server will generate a ' | |
2278 'random key if none is specified on the command ' | |
2279 'line.') | |
2280 option_parser.add_option('', '--policy-user', default='user@example.com', | |
2281 dest='policy_user', | |
2282 help='Specify the user name the server should ' | |
2283 'report back to the client as the user owning the ' | |
2284 'token used for making the policy request.') | |
2285 option_parser.add_option('', '--host', default='127.0.0.1', | |
2286 dest='host', | |
2287 help='Hostname or IP upon which the server will ' | |
2288 'listen. Client connections will also only be ' | |
2289 'allowed from this address.') | |
2290 option_parser.add_option('', '--auth-token', dest='auth_token', | |
2291 help='Specify the auth token which should be used' | |
2292 'in the authorization header for GData.') | |
2293 options, args = option_parser.parse_args() | |
2294 | |
2295 sys.exit(main(options, args)) | |
OLD | NEW |