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 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 def __init__(self): | 75 def __init__(self): |
76 self.log = [] | 76 self.log = [] |
77 | 77 |
78 def __getitem__(self, sessionID): | 78 def __getitem__(self, sessionID): |
79 self.log.append(('lookup', sessionID)) | 79 self.log.append(('lookup', sessionID)) |
80 raise KeyError() | 80 raise KeyError() |
81 | 81 |
82 def __setitem__(self, sessionID, session): | 82 def __setitem__(self, sessionID, session): |
83 self.log.append(('insert', sessionID)) | 83 self.log.append(('insert', sessionID)) |
84 | 84 |
85 | |
86 class ClientRestrictingServerMixIn: | |
87 """Implements verify_request to limit connections to our configured IP | |
88 address.""" | |
89 | |
90 def verify_request(self, request, client_address): | |
91 return client_address[0] == self.server_address[0] | |
92 | |
93 | |
85 class StoppableHTTPServer(BaseHTTPServer.HTTPServer): | 94 class StoppableHTTPServer(BaseHTTPServer.HTTPServer): |
86 """This is a specialization of of BaseHTTPServer to allow it | 95 """This is a specialization of BaseHTTPServer to allow it |
87 to be exited cleanly (by setting its "stop" member to True).""" | 96 to be exited cleanly (by setting its "stop" member to True).""" |
88 | 97 |
89 def serve_forever(self): | 98 def serve_forever(self): |
90 self.stop = False | 99 self.stop = False |
91 self.nonce_time = None | 100 self.nonce_time = None |
92 while not self.stop: | 101 while not self.stop: |
93 self.handle_request() | 102 self.handle_request() |
94 self.socket.close() | 103 self.socket.close() |
95 | 104 |
96 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, StoppableHTTPServer): | 105 |
97 """This is a specialization of StoppableHTTPerver that add https support.""" | 106 class HTTPServer(ClientRestrictingServerMixIn, StoppableHTTPServer): |
107 """This is a specialization of StoppableHTTPerver that add client | |
Paweł Hajdan Jr.
2012/02/15 17:11:01
nit: "that adds", note the "s".
| |
108 verification.""" | |
109 | |
110 pass | |
111 | |
112 | |
113 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, | |
114 ClientRestrictingServerMixIn, | |
115 StoppableHTTPServer): | |
116 """This is a specialization of StoppableHTTPerver that add https support and | |
117 client verification.""" | |
98 | 118 |
99 def __init__(self, server_address, request_hander_class, cert_path, | 119 def __init__(self, server_address, request_hander_class, cert_path, |
100 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, | 120 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, |
101 record_resume_info): | 121 record_resume_info): |
102 s = open(cert_path).read() | 122 s = open(cert_path).read() |
103 x509 = tlslite.api.X509() | 123 x509 = tlslite.api.X509() |
104 x509.parse(s) | 124 x509.parse(s) |
105 self.cert_chain = tlslite.api.X509CertChain([x509]) | 125 self.cert_chain = tlslite.api.X509CertChain([x509]) |
106 s = open(cert_path).read() | 126 s = open(cert_path).read() |
107 self.private_key = tlslite.api.parsePEMKey(s, private=True) | 127 self.private_key = tlslite.api.parsePEMKey(s, private=True) |
(...skipping 28 matching lines...) Expand all Loading... | |
136 tlsConnection.ignoreAbruptClose = True | 156 tlsConnection.ignoreAbruptClose = True |
137 return True | 157 return True |
138 except tlslite.api.TLSAbruptCloseError: | 158 except tlslite.api.TLSAbruptCloseError: |
139 # Ignore abrupt close. | 159 # Ignore abrupt close. |
140 return True | 160 return True |
141 except tlslite.api.TLSError, error: | 161 except tlslite.api.TLSError, error: |
142 print "Handshake failure:", str(error) | 162 print "Handshake failure:", str(error) |
143 return False | 163 return False |
144 | 164 |
145 | 165 |
146 class SyncHTTPServer(StoppableHTTPServer): | 166 class SyncHTTPServer(ClientRestrictingServerMixIn, StoppableHTTPServer): |
147 """An HTTP server that handles sync commands.""" | 167 """An HTTP server that handles sync commands.""" |
148 | 168 |
149 def __init__(self, server_address, request_handler_class): | 169 def __init__(self, server_address, request_handler_class): |
150 # We import here to avoid pulling in chromiumsync's dependencies | 170 # We import here to avoid pulling in chromiumsync's dependencies |
151 # unless strictly necessary. | 171 # unless strictly necessary. |
152 import chromiumsync | 172 import chromiumsync |
153 import xmppserver | 173 import xmppserver |
154 StoppableHTTPServer.__init__(self, server_address, request_handler_class) | 174 StoppableHTTPServer.__init__(self, server_address, request_handler_class) |
155 self._sync_handler = chromiumsync.TestServer() | 175 self._sync_handler = chromiumsync.TestServer() |
156 self._xmpp_socket_map = {} | 176 self._xmpp_socket_map = {} |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 | 261 |
242 for fd in write_fds: | 262 for fd in write_fds: |
243 HandleXmppSocket(fd, self._xmpp_socket_map, | 263 HandleXmppSocket(fd, self._xmpp_socket_map, |
244 asyncore.dispatcher.handle_write_event) | 264 asyncore.dispatcher.handle_write_event) |
245 | 265 |
246 for fd in exceptional_fds: | 266 for fd in exceptional_fds: |
247 HandleXmppSocket(fd, self._xmpp_socket_map, | 267 HandleXmppSocket(fd, self._xmpp_socket_map, |
248 asyncore.dispatcher.handle_expt_event) | 268 asyncore.dispatcher.handle_expt_event) |
249 | 269 |
250 | 270 |
251 class TCPEchoServer(SocketServer.TCPServer): | 271 class FTPServer(ClientRestrictingServerMixIn, pyftpdlib.ftpserver.FTPServer): |
272 """This is a specialization of FTPServer that add client | |
Paweł Hajdan Jr.
2012/02/15 17:11:01
nit: "that adds"
| |
273 verification.""" | |
274 | |
275 pass | |
276 | |
277 | |
278 class TCPEchoServer(ClientRestrictingServerMixIn, SocketServer.TCPServer): | |
252 """A TCP echo server that echoes back what it has received.""" | 279 """A TCP echo server that echoes back what it has received.""" |
253 | 280 |
254 def server_bind(self): | 281 def server_bind(self): |
255 """Override server_bind to store the server name.""" | 282 """Override server_bind to store the server name.""" |
256 SocketServer.TCPServer.server_bind(self) | 283 SocketServer.TCPServer.server_bind(self) |
257 host, port = self.socket.getsockname()[:2] | 284 host, port = self.socket.getsockname()[:2] |
258 self.server_name = socket.getfqdn(host) | 285 self.server_name = socket.getfqdn(host) |
259 self.server_port = port | 286 self.server_port = port |
260 | 287 |
261 def serve_forever(self): | 288 def serve_forever(self): |
262 self.stop = False | 289 self.stop = False |
263 self.nonce_time = None | 290 self.nonce_time = None |
264 while not self.stop: | 291 while not self.stop: |
265 self.handle_request() | 292 self.handle_request() |
266 self.socket.close() | 293 self.socket.close() |
267 | 294 |
268 | 295 |
269 class UDPEchoServer(SocketServer.UDPServer): | 296 class UDPEchoServer(ClientRestrictingServerMixIn, SocketServer.UDPServer): |
270 """A UDP echo server that echoes back what it has received.""" | 297 """A UDP echo server that echoes back what it has received.""" |
271 | 298 |
272 def server_bind(self): | 299 def server_bind(self): |
273 """Override server_bind to store the server name.""" | 300 """Override server_bind to store the server name.""" |
274 SocketServer.UDPServer.server_bind(self) | 301 SocketServer.UDPServer.server_bind(self) |
275 host, port = self.socket.getsockname()[:2] | 302 host, port = self.socket.getsockname()[:2] |
276 self.server_name = socket.getfqdn(host) | 303 self.server_name = socket.getfqdn(host) |
277 self.server_port = port | 304 self.server_port = port |
278 | 305 |
279 def serve_forever(self): | 306 def serve_forever(self): |
(...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1581 test_name = "/chromiumsync/command" | 1608 test_name = "/chromiumsync/command" |
1582 if not self._ShouldHandleRequest(test_name): | 1609 if not self._ShouldHandleRequest(test_name): |
1583 return False | 1610 return False |
1584 | 1611 |
1585 length = int(self.headers.getheader('content-length')) | 1612 length = int(self.headers.getheader('content-length')) |
1586 raw_request = self.rfile.read(length) | 1613 raw_request = self.rfile.read(length) |
1587 http_response = 200 | 1614 http_response = 200 |
1588 raw_reply = None | 1615 raw_reply = None |
1589 if not self.server.GetAuthenticated(): | 1616 if not self.server.GetAuthenticated(): |
1590 http_response = 401 | 1617 http_response = 401 |
1591 challenge = 'GoogleLogin realm="http://127.0.0.1", service="chromiumsync"' | 1618 challenge = 'GoogleLogin realm="http://%s", service="chromiumsync"' % ( |
1619 self.server.server_address[0]) | |
1592 else: | 1620 else: |
1593 http_response, raw_reply = self.server.HandleCommand( | 1621 http_response, raw_reply = self.server.HandleCommand( |
1594 self.path, raw_request) | 1622 self.path, raw_request) |
1595 | 1623 |
1596 ### Now send the response to the client. ### | 1624 ### Now send the response to the client. ### |
1597 self.send_response(http_response) | 1625 self.send_response(http_response) |
1598 if http_response == 401: | 1626 if http_response == 401: |
1599 self.send_header('www-Authenticate', challenge) | 1627 self.send_header('www-Authenticate', challenge) |
1600 self.end_headers() | 1628 self.end_headers() |
1601 self.wfile.write(raw_reply) | 1629 self.wfile.write(raw_reply) |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1828 | 1856 |
1829 def main(options, args): | 1857 def main(options, args): |
1830 logfile = open('testserver.log', 'w') | 1858 logfile = open('testserver.log', 'w') |
1831 sys.stderr = FileMultiplexer(sys.stderr, logfile) | 1859 sys.stderr = FileMultiplexer(sys.stderr, logfile) |
1832 if options.log_to_console: | 1860 if options.log_to_console: |
1833 sys.stdout = FileMultiplexer(sys.stdout, logfile) | 1861 sys.stdout = FileMultiplexer(sys.stdout, logfile) |
1834 else: | 1862 else: |
1835 sys.stdout = logfile | 1863 sys.stdout = logfile |
1836 | 1864 |
1837 port = options.port | 1865 port = options.port |
1866 host = options.host | |
1838 | 1867 |
1839 server_data = {} | 1868 server_data = {} |
1869 server_data['host'] = host | |
1840 | 1870 |
1841 if options.server_type == SERVER_HTTP: | 1871 if options.server_type == SERVER_HTTP: |
1842 if options.cert: | 1872 if options.cert: |
1843 # let's make sure the cert file exists. | 1873 # let's make sure the cert file exists. |
1844 if not os.path.isfile(options.cert): | 1874 if not os.path.isfile(options.cert): |
1845 print 'specified server cert file not found: ' + options.cert + \ | 1875 print 'specified server cert file not found: ' + options.cert + \ |
1846 ' exiting...' | 1876 ' exiting...' |
1847 return | 1877 return |
1848 for ca_cert in options.ssl_client_ca: | 1878 for ca_cert in options.ssl_client_ca: |
1849 if not os.path.isfile(ca_cert): | 1879 if not os.path.isfile(ca_cert): |
1850 print 'specified trusted client CA file not found: ' + ca_cert + \ | 1880 print 'specified trusted client CA file not found: ' + ca_cert + \ |
1851 ' exiting...' | 1881 ' exiting...' |
1852 return | 1882 return |
1853 server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert, | 1883 server = HTTPSServer((host, port), TestPageHandler, options.cert, |
1854 options.ssl_client_auth, options.ssl_client_ca, | 1884 options.ssl_client_auth, options.ssl_client_ca, |
1855 options.ssl_bulk_cipher, options.record_resume) | 1885 options.ssl_bulk_cipher, options.record_resume) |
1856 print 'HTTPS server started on port %d...' % server.server_port | 1886 print 'HTTPS server started on %s:%d...' % (host, server.server_port) |
1857 else: | 1887 else: |
1858 server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) | 1888 server = HTTPServer((host, port), TestPageHandler) |
1859 print 'HTTP server started on port %d...' % server.server_port | 1889 print 'HTTP server started on %s:%d...' % (host, server.server_port) |
1860 | 1890 |
1861 server.data_dir = MakeDataDir() | 1891 server.data_dir = MakeDataDir() |
1862 server.file_root_url = options.file_root_url | 1892 server.file_root_url = options.file_root_url |
1863 server_data['port'] = server.server_port | 1893 server_data['port'] = server.server_port |
1864 server._device_management_handler = None | 1894 server._device_management_handler = None |
1865 server.policy_keys = options.policy_keys | 1895 server.policy_keys = options.policy_keys |
1866 server.policy_user = options.policy_user | 1896 server.policy_user = options.policy_user |
1867 elif options.server_type == SERVER_SYNC: | 1897 elif options.server_type == SERVER_SYNC: |
1868 server = SyncHTTPServer(('127.0.0.1', port), SyncPageHandler) | 1898 server = SyncHTTPServer((host, port), SyncPageHandler) |
1869 print 'Sync HTTP server started on port %d...' % server.server_port | 1899 print 'Sync HTTP server started on port %d...' % server.server_port |
1870 print 'Sync XMPP server started on port %d...' % server.xmpp_port | 1900 print 'Sync XMPP server started on port %d...' % server.xmpp_port |
1871 server_data['port'] = server.server_port | 1901 server_data['port'] = server.server_port |
1872 server_data['xmpp_port'] = server.xmpp_port | 1902 server_data['xmpp_port'] = server.xmpp_port |
1873 elif options.server_type == SERVER_TCP_ECHO: | 1903 elif options.server_type == SERVER_TCP_ECHO: |
1874 # Used for generating the key (randomly) that encodes the "echo request" | 1904 # Used for generating the key (randomly) that encodes the "echo request" |
1875 # message. | 1905 # message. |
1876 random.seed() | 1906 random.seed() |
1877 server = TCPEchoServer(('127.0.0.1', port), TCPEchoHandler) | 1907 server = TCPEchoServer((host, port), TCPEchoHandler) |
1878 print 'Echo TCP server started on port %d...' % server.server_port | 1908 print 'Echo TCP server started on port %d...' % server.server_port |
1879 server_data['port'] = server.server_port | 1909 server_data['port'] = server.server_port |
1880 elif options.server_type == SERVER_UDP_ECHO: | 1910 elif options.server_type == SERVER_UDP_ECHO: |
1881 # Used for generating the key (randomly) that encodes the "echo request" | 1911 # Used for generating the key (randomly) that encodes the "echo request" |
1882 # message. | 1912 # message. |
1883 random.seed() | 1913 random.seed() |
1884 server = UDPEchoServer(('127.0.0.1', port), UDPEchoHandler) | 1914 server = UDPEchoServer((host, port), UDPEchoHandler) |
1885 print 'Echo UDP server started on port %d...' % server.server_port | 1915 print 'Echo UDP server started on port %d...' % server.server_port |
1886 server_data['port'] = server.server_port | 1916 server_data['port'] = server.server_port |
1887 # means FTP Server | 1917 # means FTP Server |
1888 else: | 1918 else: |
1889 my_data_dir = MakeDataDir() | 1919 my_data_dir = MakeDataDir() |
1890 | 1920 |
1891 # Instantiate a dummy authorizer for managing 'virtual' users | 1921 # Instantiate a dummy authorizer for managing 'virtual' users |
1892 authorizer = pyftpdlib.ftpserver.DummyAuthorizer() | 1922 authorizer = pyftpdlib.ftpserver.DummyAuthorizer() |
1893 | 1923 |
1894 # Define a new user having full r/w permissions and a read-only | 1924 # Define a new user having full r/w permissions and a read-only |
1895 # anonymous user | 1925 # anonymous user |
1896 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') | 1926 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') |
1897 | 1927 |
1898 authorizer.add_anonymous(my_data_dir) | 1928 authorizer.add_anonymous(my_data_dir) |
1899 | 1929 |
1900 # Instantiate FTP handler class | 1930 # Instantiate FTP handler class |
1901 ftp_handler = pyftpdlib.ftpserver.FTPHandler | 1931 ftp_handler = pyftpdlib.ftpserver.FTPHandler |
1902 ftp_handler.authorizer = authorizer | 1932 ftp_handler.authorizer = authorizer |
1903 | 1933 |
1904 # Define a customized banner (string returned when client connects) | 1934 # Define a customized banner (string returned when client connects) |
1905 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." % | 1935 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." % |
1906 pyftpdlib.ftpserver.__ver__) | 1936 pyftpdlib.ftpserver.__ver__) |
1907 | 1937 |
1908 # Instantiate FTP server class and listen to 127.0.0.1:port | 1938 # Instantiate FTP server class and listen to address:port |
1909 address = ('127.0.0.1', port) | 1939 server = pyftpdlib.ftpserver.FTPServer((host, port), ftp_handler) |
1910 server = pyftpdlib.ftpserver.FTPServer(address, ftp_handler) | |
1911 server_data['port'] = server.socket.getsockname()[1] | 1940 server_data['port'] = server.socket.getsockname()[1] |
1912 print 'FTP server started on port %d...' % server_data['port'] | 1941 print 'FTP server started on port %d...' % server_data['port'] |
1913 | 1942 |
1914 # Notify the parent that we've started. (BaseServer subclasses | 1943 # Notify the parent that we've started. (BaseServer subclasses |
1915 # bind their sockets on construction.) | 1944 # bind their sockets on construction.) |
1916 if options.startup_pipe is not None: | 1945 if options.startup_pipe is not None: |
1917 server_data_json = json.dumps(server_data) | 1946 server_data_json = json.dumps(server_data) |
1918 server_data_len = len(server_data_json) | 1947 server_data_len = len(server_data_json) |
1919 print 'sending server_data: %s (%d bytes)' % ( | 1948 print 'sending server_data: %s (%d bytes)' % ( |
1920 server_data_json, server_data_len) | 1949 server_data_json, server_data_len) |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2002 'the server. If ther server has multiple keys, it ' | 2031 'the server. If ther server has multiple keys, it ' |
2003 'will rotate through them in at each request a ' | 2032 'will rotate through them in at each request a ' |
2004 'round-robin fashion. The server will generate a ' | 2033 'round-robin fashion. The server will generate a ' |
2005 'random key if none is specified on the command ' | 2034 'random key if none is specified on the command ' |
2006 'line.') | 2035 'line.') |
2007 option_parser.add_option('', '--policy-user', default='user@example.com', | 2036 option_parser.add_option('', '--policy-user', default='user@example.com', |
2008 dest='policy_user', | 2037 dest='policy_user', |
2009 help='Specify the user name the server should ' | 2038 help='Specify the user name the server should ' |
2010 'report back to the client as the user owning the ' | 2039 'report back to the client as the user owning the ' |
2011 'token used for making the policy request.') | 2040 'token used for making the policy request.') |
2041 option_parser.add_option('', '--host', default='127.0.0.1', | |
2042 dest='host', | |
2043 help='Hostname or IP upon which the server will ' | |
2044 'listen. Client connections will also only be ' | |
2045 'allowed from this address.') | |
2012 options, args = option_parser.parse_args() | 2046 options, args = option_parser.parse_args() |
2013 | 2047 |
2014 sys.exit(main(options, args)) | 2048 sys.exit(main(options, args)) |
OLD | NEW |