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

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

Issue 10073033: Run safebrowsing_service_test through the net testserver code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 3 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/run_testserver.cc ('k') | net/tools/testserver/testserver_base.py » ('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 hashlib
21 import httplib 22 import httplib
22 import minica 23 import minica
23 import optparse
24 import os 24 import os
25 import random 25 import random
26 import re 26 import re
27 import select 27 import select
28 import socket 28 import socket
29 import SocketServer 29 import SocketServer
30 import struct
31 import sys 30 import sys
32 import threading 31 import threading
33 import time 32 import time
34 import urllib 33 import urllib
35 import urlparse 34 import urlparse
36 import warnings
37 import zlib 35 import zlib
38 36
39 # Ignore deprecation warnings, they make our output more cluttered.
40 warnings.filterwarnings("ignore", category=DeprecationWarning)
41
42 import echo_message 37 import echo_message
43 import pyftpdlib.ftpserver 38 import pyftpdlib.ftpserver
39 import testserver_base
44 import tlslite 40 import tlslite
45 import tlslite.api 41 import tlslite.api
46 42
47 try:
48 import hashlib
49 _new_md5 = hashlib.md5
50 except ImportError:
51 import md5
52 _new_md5 = md5.new
53 43
54 try: 44 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
55 import json
56 except ImportError:
57 import simplejson as json
58
59 if sys.platform == 'win32':
60 import msvcrt
61 45
62 SERVER_HTTP = 0 46 SERVER_HTTP = 0
63 SERVER_FTP = 1 47 SERVER_FTP = 1
64 SERVER_SYNC = 2 48 SERVER_SYNC = 2
65 SERVER_TCP_ECHO = 3 49 SERVER_TCP_ECHO = 3
66 SERVER_UDP_ECHO = 4 50 SERVER_UDP_ECHO = 4
67 51
52
68 # Using debug() seems to cause hangs on XP: see http://crbug.com/64515 . 53 # Using debug() seems to cause hangs on XP: see http://crbug.com/64515 .
69 debug_output = sys.stderr 54 debug_output = sys.stderr
70 def debug(str): 55 def debug(str):
71 debug_output.write(str + "\n") 56 debug_output.write(str + "\n")
72 debug_output.flush() 57 debug_output.flush()
73 58
59
74 class RecordingSSLSessionCache(object): 60 class RecordingSSLSessionCache(object):
75 """RecordingSSLSessionCache acts as a TLS session cache and maintains a log of 61 """RecordingSSLSessionCache acts as a TLS session cache and maintains a log of
76 lookups and inserts in order to test session cache behaviours.""" 62 lookups and inserts in order to test session cache behaviours."""
77 63
78 def __init__(self): 64 def __init__(self):
79 self.log = [] 65 self.log = []
80 66
81 def __getitem__(self, sessionID): 67 def __getitem__(self, sessionID):
82 self.log.append(('lookup', sessionID)) 68 self.log.append(('lookup', sessionID))
83 raise KeyError() 69 raise KeyError()
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 104
119 def serve_forever_on_thread(self): 105 def serve_forever_on_thread(self):
120 self.thread = threading.Thread(target = self.serve_forever, 106 self.thread = threading.Thread(target = self.serve_forever,
121 name = "OCSPServerThread") 107 name = "OCSPServerThread")
122 self.thread.start() 108 self.thread.start()
123 109
124 def stop_serving(self): 110 def stop_serving(self):
125 self.shutdown() 111 self.shutdown()
126 self.thread.join() 112 self.thread.join()
127 113
114
128 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, 115 class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
129 ClientRestrictingServerMixIn, 116 ClientRestrictingServerMixIn,
130 StoppableHTTPServer): 117 StoppableHTTPServer):
131 """This is a specialization of StoppableHTTPServer that add https support and 118 """This is a specialization of StoppableHTTPServer that add https support and
132 client verification.""" 119 client verification."""
133 120
134 def __init__(self, server_address, request_hander_class, pem_cert_and_key, 121 def __init__(self, server_address, request_hander_class, pem_cert_and_key,
135 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, 122 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers,
136 record_resume_info, tls_intolerant): 123 record_resume_info, tls_intolerant):
137 self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key) 124 self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key)
(...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 This is a fake implementation. A real implementation would only use a given 1297 This is a fake implementation. A real implementation would only use a given
1311 nonce a single time (hence the name n-once). However, for the purposes of 1298 nonce a single time (hence the name n-once). However, for the purposes of
1312 unittesting, we don't care about the security of the nonce. 1299 unittesting, we don't care about the security of the nonce.
1313 1300
1314 Args: 1301 Args:
1315 force_reset: Iff set, the nonce will be changed. Useful for testing the 1302 force_reset: Iff set, the nonce will be changed. Useful for testing the
1316 "stale" response. 1303 "stale" response.
1317 """ 1304 """
1318 if force_reset or not self.server.nonce_time: 1305 if force_reset or not self.server.nonce_time:
1319 self.server.nonce_time = time.time() 1306 self.server.nonce_time = time.time()
1320 return _new_md5('privatekey%s%d' % 1307 return hashlib.md5('privatekey%s%d' %
1321 (self.path, self.server.nonce_time)).hexdigest() 1308 (self.path, self.server.nonce_time)).hexdigest()
1322 1309
1323 def AuthDigestHandler(self): 1310 def AuthDigestHandler(self):
1324 """This handler tests 'Digest' authentication. 1311 """This handler tests 'Digest' authentication.
1325 1312
1326 It just sends a page with title 'user/pass' if you succeed. 1313 It just sends a page with title 'user/pass' if you succeed.
1327 1314
1328 A stale response is sent iff "stale" is present in the request path. 1315 A stale response is sent iff "stale" is present in the request path.
1329 """ 1316 """
1330 if not self._ShouldHandleRequest("/auth-digest"): 1317 if not self._ShouldHandleRequest("/auth-digest"):
1331 return False 1318 return False
1332 1319
1333 stale = 'stale' in self.path 1320 stale = 'stale' in self.path
1334 nonce = self.GetNonce(force_reset=stale) 1321 nonce = self.GetNonce(force_reset=stale)
1335 opaque = _new_md5('opaque').hexdigest() 1322 opaque = hashlib.md5('opaque').hexdigest()
1336 password = 'secret' 1323 password = 'secret'
1337 realm = 'testrealm' 1324 realm = 'testrealm'
1338 1325
1339 auth = self.headers.getheader('authorization') 1326 auth = self.headers.getheader('authorization')
1340 pairs = {} 1327 pairs = {}
1341 try: 1328 try:
1342 if not auth: 1329 if not auth:
1343 raise Exception('no auth') 1330 raise Exception('no auth')
1344 if not auth.startswith('Digest'): 1331 if not auth.startswith('Digest'):
1345 raise Exception('not digest') 1332 raise Exception('not digest')
1346 # Pull out all the name="value" pairs as a dictionary. 1333 # Pull out all the name="value" pairs as a dictionary.
1347 pairs = dict(re.findall(r'(\b[^ ,=]+)="?([^",]+)"?', auth)) 1334 pairs = dict(re.findall(r'(\b[^ ,=]+)="?([^",]+)"?', auth))
1348 1335
1349 # Make sure it's all valid. 1336 # Make sure it's all valid.
1350 if pairs['nonce'] != nonce: 1337 if pairs['nonce'] != nonce:
1351 raise Exception('wrong nonce') 1338 raise Exception('wrong nonce')
1352 if pairs['opaque'] != opaque: 1339 if pairs['opaque'] != opaque:
1353 raise Exception('wrong opaque') 1340 raise Exception('wrong opaque')
1354 1341
1355 # Check the 'response' value and make sure it matches our magic hash. 1342 # Check the 'response' value and make sure it matches our magic hash.
1356 # See http://www.ietf.org/rfc/rfc2617.txt 1343 # See http://www.ietf.org/rfc/rfc2617.txt
1357 hash_a1 = _new_md5( 1344 hash_a1 = hashlib.md5(
1358 ':'.join([pairs['username'], realm, password])).hexdigest() 1345 ':'.join([pairs['username'], realm, password])).hexdigest()
1359 hash_a2 = _new_md5(':'.join([self.command, pairs['uri']])).hexdigest() 1346 hash_a2 = hashlib.md5(':'.join([self.command, pairs['uri']])).hexdigest()
1360 if 'qop' in pairs and 'nc' in pairs and 'cnonce' in pairs: 1347 if 'qop' in pairs and 'nc' in pairs and 'cnonce' in pairs:
1361 response = _new_md5(':'.join([hash_a1, nonce, pairs['nc'], 1348 response = hashlib.md5(':'.join([hash_a1, nonce, pairs['nc'],
1362 pairs['cnonce'], pairs['qop'], hash_a2])).hexdigest() 1349 pairs['cnonce'], pairs['qop'], hash_a2])).hexdigest()
1363 else: 1350 else:
1364 response = _new_md5(':'.join([hash_a1, nonce, hash_a2])).hexdigest() 1351 response = hashlib.md5(':'.join([hash_a1, nonce, hash_a2])).hexdigest()
1365 1352
1366 if pairs['response'] != response: 1353 if pairs['response'] != response:
1367 raise Exception('wrong password') 1354 raise Exception('wrong password')
1368 except Exception, e: 1355 except Exception, e:
1369 # Authentication failed. 1356 # Authentication failed.
1370 self.send_response(401) 1357 self.send_response(401)
1371 hdr = ('Digest ' 1358 hdr = ('Digest '
1372 'realm="%s", ' 1359 'realm="%s", '
1373 'domain="/", ' 1360 'domain="/", '
1374 'qop="auth", ' 1361 'qop="auth", '
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 """TestServerRunner for the net test servers."""
2024 self.__fd1 = fd1 1994
2025 self.__fd2 = fd2 1995 def __init__(self):
2026 1996 super(ServerRunner, self).__init__()
2027 def __del__(self) : 1997 self.__ocsp_server = None
2028 if self.__fd1 != sys.stdout and self.__fd1 != sys.stderr: 1998
2029 self.__fd1.close() 1999 def __make_data_dir(self):
2030 if self.__fd2 != sys.stdout and self.__fd2 != sys.stderr: 2000 if self.options.data_dir:
2031 self.__fd2.close() 2001 if not os.path.isdir(self.options.data_dir):
2032 2002 raise testserver_base.OptionError('specified data dir not found: ' +
2033 def write(self, text) : 2003 self.options.data_dir + ' exiting...')
2034 self.__fd1.write(text) 2004 my_data_dir = self.options.data_dir
2035 self.__fd2.write(text) 2005 else:
2036 2006 # Create the default path to our data dir, relative to the exe dir.
2037 def flush(self) : 2007 my_data_dir = os.path.join(BASE_DIR, "..", "..", "..", "..",
2038 self.__fd1.flush() 2008 "test", "data")
2039 self.__fd2.flush() 2009
2040 2010 #TODO(ibrar): Must use Find* funtion defined in google\tools
2041 def main(options, args): 2011 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data")
2042 logfile = open('testserver.log', 'w') 2012
2043 sys.stderr = FileMultiplexer(sys.stderr, logfile) 2013 return my_data_dir
2044 if options.log_to_console: 2014
2045 sys.stdout = FileMultiplexer(sys.stdout, logfile) 2015 def create_server(self, server_data):
2046 else: 2016 port = self.options.port
2047 sys.stdout = logfile 2017 host = self.options.host
2048 2018
2049 port = options.port 2019 if self.options.server_type == SERVER_HTTP:
2050 host = options.host 2020 if self.options.https:
2051 2021 pem_cert_and_key = None
2052 server_data = {} 2022 if self.options.cert_and_key_file:
2053 server_data['host'] = host 2023 if not os.path.isfile(self.options.cert_and_key_file):
2054 2024 raise testserver_base.OptionError(
2055 ocsp_server = None 2025 'specified server cert file not found: ' +
2056 2026 self.options.cert_and_key_file + ' exiting...')
2057 if options.server_type == SERVER_HTTP: 2027 pem_cert_and_key = file(self.options.cert_and_key_file, 'r').read()
2058 if options.https: 2028 else:
2059 pem_cert_and_key = None 2029 # generate a new certificate and run an OCSP server for it.
2060 if options.cert_and_key_file: 2030 self.__ocsp_server = OCSPServer((host, 0), OCSPHandler)
2061 if not os.path.isfile(options.cert_and_key_file): 2031 print ('OCSP server started on %s:%d...' %
2062 print ('specified server cert file not found: ' + 2032 (host, self.__ocsp_server.server_port))
2063 options.cert_and_key_file + ' exiting...') 2033
2064 return 2034 ocsp_der = None
2065 pem_cert_and_key = file(options.cert_and_key_file, 'r').read() 2035 ocsp_state = None
2036
2037 if self.options.ocsp == 'ok':
2038 ocsp_state = minica.OCSP_STATE_GOOD
2039 elif self.options.ocsp == 'revoked':
2040 ocsp_state = minica.OCSP_STATE_REVOKED
2041 elif self.options.ocsp == 'invalid':
2042 ocsp_state = minica.OCSP_STATE_INVALID
2043 elif self.options.ocsp == 'unauthorized':
2044 ocsp_state = minica.OCSP_STATE_UNAUTHORIZED
2045 elif self.options.ocsp == 'unknown':
2046 ocsp_state = minica.OCSP_STATE_UNKNOWN
2047 else:
2048 raise testserver_base.OptionError('unknown OCSP status: ' +
2049 self.options.ocsp_status)
2050
2051 (pem_cert_and_key, ocsp_der) = minica.GenerateCertKeyAndOCSP(
2052 subject = "127.0.0.1",
2053 ocsp_url = ("http://%s:%d/ocsp" %
2054 (host, self.__ocsp_server.server_port)),
2055 ocsp_state = ocsp_state)
2056
2057 self.__ocsp_server.ocsp_response = ocsp_der
2058
2059 for ca_cert in self.options.ssl_client_ca:
2060 if not os.path.isfile(ca_cert):
2061 raise testserver_base.OptionError(
2062 'specified trusted client CA file not found: ' + ca_cert +
2063 ' exiting...')
2064 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key,
2065 self.options.ssl_client_auth,
2066 self.options.ssl_client_ca,
2067 self.options.ssl_bulk_cipher,
2068 self.options.record_resume,
2069 self.options.tls_intolerant)
2070 print 'HTTPS server started on %s:%d...' % (host, server.server_port)
2066 else: 2071 else:
2067 # generate a new certificate and run an OCSP server for it. 2072 server = HTTPServer((host, port), TestPageHandler)
2068 ocsp_server = OCSPServer((host, 0), OCSPHandler) 2073 print 'HTTP server started on %s:%d...' % (host, server.server_port)
2069 print ('OCSP server started on %s:%d...' % 2074
2070 (host, ocsp_server.server_port)) 2075 server.data_dir = self.__make_data_dir()
2071 2076 server.file_root_url = self.options.file_root_url
2072 ocsp_der = None 2077 server_data['port'] = server.server_port
2073 ocsp_state = None 2078 server._device_management_handler = None
2074 2079 server.policy_keys = self.options.policy_keys
2075 if options.ocsp == 'ok': 2080 server.policy_user = self.options.policy_user
2076 ocsp_state = minica.OCSP_STATE_GOOD 2081 server.gdata_auth_token = self.options.auth_token
2077 elif options.ocsp == 'revoked': 2082 elif self.options.server_type == SERVER_SYNC:
2078 ocsp_state = minica.OCSP_STATE_REVOKED 2083 xmpp_port = self.options.xmpp_port
2079 elif options.ocsp == 'invalid': 2084 server = SyncHTTPServer((host, port), xmpp_port, SyncPageHandler)
2080 ocsp_state = minica.OCSP_STATE_INVALID 2085 print 'Sync HTTP server started on port %d...' % server.server_port
2081 elif options.ocsp == 'unauthorized': 2086 print 'Sync XMPP server started on port %d...' % server.xmpp_port
2082 ocsp_state = minica.OCSP_STATE_UNAUTHORIZED 2087 server_data['port'] = server.server_port
2083 elif options.ocsp == 'unknown': 2088 server_data['xmpp_port'] = server.xmpp_port
2084 ocsp_state = minica.OCSP_STATE_UNKNOWN 2089 elif self.options.server_type == SERVER_TCP_ECHO:
2085 else: 2090 # Used for generating the key (randomly) that encodes the "echo request"
2086 print 'unknown OCSP status: ' + options.ocsp_status 2091 # message.
2087 return 2092 random.seed()
2088 2093 server = TCPEchoServer((host, port), TCPEchoHandler)
2089 (pem_cert_and_key, ocsp_der) = \ 2094 print 'Echo TCP server started on port %d...' % server.server_port
2090 minica.GenerateCertKeyAndOCSP( 2095 server_data['port'] = server.server_port
2091 subject = "127.0.0.1", 2096 elif self.options.server_type == SERVER_UDP_ECHO:
2092 ocsp_url = ("http://%s:%d/ocsp" % 2097 # Used for generating the key (randomly) that encodes the "echo request"
2093 (host, ocsp_server.server_port)), 2098 # message.
2094 ocsp_state = ocsp_state) 2099 random.seed()
2095 2100 server = UDPEchoServer((host, port), UDPEchoHandler)
2096 ocsp_server.ocsp_response = ocsp_der 2101 print 'Echo UDP server started on port %d...' % server.server_port
2097 2102 server_data['port'] = server.server_port
2098 for ca_cert in options.ssl_client_ca: 2103 elif self.options.server_type == SERVER_FTP:
2099 if not os.path.isfile(ca_cert): 2104 my_data_dir = self.__make_data_dir()
2100 print 'specified trusted client CA file not found: ' + ca_cert + \ 2105
2101 ' exiting...' 2106 # Instantiate a dummy authorizer for managing 'virtual' users
2102 return 2107 authorizer = pyftpdlib.ftpserver.DummyAuthorizer()
2103 server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key, 2108
2104 options.ssl_client_auth, options.ssl_client_ca, 2109 # Define a new user having full r/w permissions and a read-only
2105 options.ssl_bulk_cipher, options.record_resume, 2110 # anonymous user
2106 options.tls_intolerant) 2111 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw')
2107 print 'HTTPS server started on %s:%d...' % (host, server.server_port) 2112
2113 authorizer.add_anonymous(my_data_dir)
2114
2115 # Instantiate FTP handler class
2116 ftp_handler = pyftpdlib.ftpserver.FTPHandler
2117 ftp_handler.authorizer = authorizer
2118
2119 # Define a customized banner (string returned when client connects)
2120 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." %
2121 pyftpdlib.ftpserver.__ver__)
2122
2123 # Instantiate FTP server class and listen to address:port
2124 server = pyftpdlib.ftpserver.FTPServer((host, port), ftp_handler)
2125 server_data['port'] = server.socket.getsockname()[1]
2126 print 'FTP server started on port %d...' % server_data['port']
2108 else: 2127 else:
2109 server = HTTPServer((host, port), TestPageHandler) 2128 raise testserver_base.OptionError('unknown server type' +
2110 print 'HTTP server started on %s:%d...' % (host, server.server_port) 2129 self.options.server_type)
2111 2130
2112 server.data_dir = MakeDataDir() 2131 return server
2113 server.file_root_url = options.file_root_url 2132
2114 server_data['port'] = server.server_port 2133 def run_server(self):
2115 server._device_management_handler = None 2134 if self.__ocsp_server:
2116 server.policy_keys = options.policy_keys 2135 self.__ocsp_server.serve_forever_on_thread()
2117 server.policy_user = options.policy_user 2136
2118 server.gdata_auth_token = options.auth_token 2137 testserver_base.TestServerRunner.run_server(self)
2119 elif options.server_type == SERVER_SYNC: 2138
2120 xmpp_port = options.xmpp_port 2139 if self.__ocsp_server:
2121 server = SyncHTTPServer((host, port), xmpp_port, SyncPageHandler) 2140 self.__ocsp_server.stop_serving()
2122 print 'Sync HTTP server started on port %d...' % server.server_port 2141
2123 print 'Sync XMPP server started on port %d...' % server.xmpp_port 2142 def add_options(self):
2124 server_data['port'] = server.server_port 2143 testserver_base.TestServerRunner.add_options(self)
2125 server_data['xmpp_port'] = server.xmpp_port 2144 self.option_parser.add_option('-f', '--ftp', action='store_const',
2126 elif options.server_type == SERVER_TCP_ECHO: 2145 const=SERVER_FTP, default=SERVER_HTTP,
2127 # Used for generating the key (randomly) that encodes the "echo request" 2146 dest='server_type',
2128 # message. 2147 help='start up an FTP server.')
2129 random.seed() 2148 self.option_parser.add_option('--sync', action='store_const',
2130 server = TCPEchoServer((host, port), TCPEchoHandler) 2149 const=SERVER_SYNC, default=SERVER_HTTP,
2131 print 'Echo TCP server started on port %d...' % server.server_port 2150 dest='server_type',
2132 server_data['port'] = server.server_port 2151 help='start up a sync server.')
2133 elif options.server_type == SERVER_UDP_ECHO: 2152 self.option_parser.add_option('--tcp-echo', action='store_const',
2134 # Used for generating the key (randomly) that encodes the "echo request" 2153 const=SERVER_TCP_ECHO, default=SERVER_HTTP,
2135 # message. 2154 dest='server_type',
2136 random.seed() 2155 help='start up a tcp echo server.')
2137 server = UDPEchoServer((host, port), UDPEchoHandler) 2156 self.option_parser.add_option('--udp-echo', action='store_const',
2138 print 'Echo UDP server started on port %d...' % server.server_port 2157 const=SERVER_UDP_ECHO, default=SERVER_HTTP,
2139 server_data['port'] = server.server_port 2158 dest='server_type',
2140 # means FTP Server 2159 help='start up a udp echo server.')
2141 else: 2160 self.option_parser.add_option('--xmpp-port', default='0', type='int',
2142 my_data_dir = MakeDataDir() 2161 help='Port used by the XMPP server. If '
2143 2162 'unspecified, the XMPP server will listen on '
2144 # Instantiate a dummy authorizer for managing 'virtual' users 2163 'an ephemeral port.')
2145 authorizer = pyftpdlib.ftpserver.DummyAuthorizer() 2164 self.option_parser.add_option('--data-dir', dest='data_dir',
2146 2165 help='Directory from which to read the '
2147 # Define a new user having full r/w permissions and a read-only 2166 'files.')
2148 # anonymous user 2167 self.option_parser.add_option('--https', action='store_true',
2149 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') 2168 dest='https', help='Specify that https '
2150 2169 'should be used.')
2151 authorizer.add_anonymous(my_data_dir) 2170 self.option_parser.add_option('--cert-and-key-file',
2152 2171 dest='cert_and_key_file', help='specify the '
2153 # Instantiate FTP handler class 2172 'path to the file containing the certificate '
2154 ftp_handler = pyftpdlib.ftpserver.FTPHandler 2173 'and private key for the server in PEM '
2155 ftp_handler.authorizer = authorizer 2174 'format')
2156 2175 self.option_parser.add_option('--ocsp', dest='ocsp', default='ok',
2157 # Define a customized banner (string returned when client connects) 2176 help='The type of OCSP response generated '
2158 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." % 2177 'for the automatically generated '
2159 pyftpdlib.ftpserver.__ver__) 2178 'certificate. One of [ok,revoked,invalid]')
2160 2179 self.option_parser.add_option('--tls-intolerant', dest='tls_intolerant',
2161 # Instantiate FTP server class and listen to address:port 2180 default='0', type='int',
2162 server = pyftpdlib.ftpserver.FTPServer((host, port), ftp_handler) 2181 help='If nonzero, certain TLS connections '
2163 server_data['port'] = server.socket.getsockname()[1] 2182 'will be aborted in order to test version '
2164 print 'FTP server started on port %d...' % server_data['port'] 2183 'fallback. 1 means all TLS versions will be '
2165 2184 'aborted. 2 means TLS 1.1 or higher will be '
2166 # Notify the parent that we've started. (BaseServer subclasses 2185 'aborted. 3 means TLS 1.2 or higher will be '
2167 # bind their sockets on construction.) 2186 'aborted.')
2168 if options.startup_pipe is not None: 2187 self.option_parser.add_option('--https-record-resume',
2169 server_data_json = json.dumps(server_data) 2188 dest='record_resume', const=True,
2170 server_data_len = len(server_data_json) 2189 default=False, action='store_const',
2171 print 'sending server_data: %s (%d bytes)' % ( 2190 help='Record resumption cache events rather '
2172 server_data_json, server_data_len) 2191 'than resuming as normal. Allows the use of '
2173 if sys.platform == 'win32': 2192 'the /ssl-session-cache request')
2174 fd = msvcrt.open_osfhandle(options.startup_pipe, 0) 2193 self.option_parser.add_option('--ssl-client-auth', action='store_true',
2175 else: 2194 help='Require SSL client auth on every '
2176 fd = options.startup_pipe 2195 'connection.')
2177 startup_pipe = os.fdopen(fd, "w") 2196 self.option_parser.add_option('--ssl-client-ca', action='append',
2178 # First write the data length as an unsigned 4-byte value. This 2197 default=[], help='Specify that the client '
2179 # is _not_ using network byte ordering since the other end of the 2198 'certificate request should include the CA '
2180 # pipe is on the same machine. 2199 'named in the subject of the DER-encoded '
2181 startup_pipe.write(struct.pack('=L', server_data_len)) 2200 'certificate contained in the specified '
2182 startup_pipe.write(server_data_json) 2201 'file. This option may appear multiple '
2183 startup_pipe.close() 2202 'times, indicating multiple CA names should '
2184 2203 'be sent in the request.')
2185 if ocsp_server is not None: 2204 self.option_parser.add_option('--ssl-bulk-cipher', action='append',
2186 ocsp_server.serve_forever_on_thread() 2205 help='Specify the bulk encryption '
2187 2206 'algorithm(s) that will be accepted by the '
2188 try: 2207 'SSL server. Valid values are "aes256", '
2189 server.serve_forever() 2208 '"aes128", "3des", "rc4". If omitted, all '
2190 except KeyboardInterrupt: 2209 'algorithms will be used. This option may '
2191 print 'shutting down server' 2210 'appear multiple times, indicating '
2192 if ocsp_server is not None: 2211 'multiple algorithms should be enabled.');
2193 ocsp_server.stop_serving() 2212 self.option_parser.add_option('--file-root-url', default='/files/',
2194 server.stop = True 2213 help='Specify a root URL for files served.')
2214 self.option_parser.add_option('--policy-key', action='append',
2215 dest='policy_keys',
2216 help='Specify a path to a PEM-encoded '
2217 'private key to use for policy signing. May '
2218 'be specified multiple times in order to '
2219 'load multipe keys into the server. If the '
2220 'server has multiple keys, it will rotate '
2221 'through them in at each request a '
2222 'round-robin fashion. The server will '
2223 'generate a random key if none is specified '
2224 'on the command line.')
2225 self.option_parser.add_option('--policy-user',
2226 default='user@example.com',
2227 dest='policy_user',
2228 help='Specify the user name the server '
2229 'should report back to the client as the '
2230 'user owning the token used for making the '
2231 'policy request.')
2232 self.option_parser.add_option('--auth-token', dest='auth_token',
2233 help='Specify the auth token which should be '
2234 'used in the authorization header for GData.')
2235
2195 2236
2196 if __name__ == '__main__': 2237 if __name__ == '__main__':
2197 option_parser = optparse.OptionParser() 2238 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))
OLDNEW
« no previous file with comments | « net/tools/testserver/run_testserver.cc ('k') | net/tools/testserver/testserver_base.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698