##// END OF EJS Templates
tests: fix toctou race in tinyproxy.py (issue3795)...
Mads Kiilerich -
r18519:ca430fb6 stable
parent child Browse files
Show More
@@ -1,147 +1,150 b''
1 1 #!/usr/bin/env python
2 2
3 3 __doc__ = """Tiny HTTP Proxy.
4 4
5 5 This module implements GET, HEAD, POST, PUT and DELETE methods
6 6 on BaseHTTPServer, and behaves as an HTTP proxy. The CONNECT
7 7 method is also implemented experimentally, but has not been
8 8 tested yet.
9 9
10 10 Any help will be greatly appreciated. SUZUKI Hisao
11 11 """
12 12
13 13 __version__ = "0.2.1"
14 14
15 15 import BaseHTTPServer, select, socket, SocketServer, urlparse, os
16 16
17 17 class ProxyHandler (BaseHTTPServer.BaseHTTPRequestHandler):
18 18 __base = BaseHTTPServer.BaseHTTPRequestHandler
19 19 __base_handle = __base.handle
20 20
21 21 server_version = "TinyHTTPProxy/" + __version__
22 22 rbufsize = 0 # self.rfile Be unbuffered
23 23
24 24 def handle(self):
25 25 (ip, port) = self.client_address
26 26 allowed = getattr(self, 'allowed_clients', None)
27 27 if allowed is not None and ip not in allowed:
28 28 self.raw_requestline = self.rfile.readline()
29 29 if self.parse_request():
30 30 self.send_error(403)
31 31 else:
32 32 self.__base_handle()
33 33
34 34 def log_request(self, code='-', size='-'):
35 35 xheaders = [h for h in self.headers.items() if h[0].startswith('x-')]
36 36 self.log_message('"%s" %s %s%s',
37 37 self.requestline, str(code), str(size),
38 38 ''.join([' %s:%s' % h for h in sorted(xheaders)]))
39 39
40 40 def _connect_to(self, netloc, soc):
41 41 i = netloc.find(':')
42 42 if i >= 0:
43 43 host_port = netloc[:i], int(netloc[i + 1:])
44 44 else:
45 45 host_port = netloc, 80
46 46 print "\t" "connect to %s:%d" % host_port
47 47 try: soc.connect(host_port)
48 48 except socket.error, arg:
49 49 try: msg = arg[1]
50 50 except (IndexError, TypeError): msg = arg
51 51 self.send_error(404, msg)
52 52 return 0
53 53 return 1
54 54
55 55 def do_CONNECT(self):
56 56 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
57 57 try:
58 58 if self._connect_to(self.path, soc):
59 59 self.log_request(200)
60 60 self.wfile.write(self.protocol_version +
61 61 " 200 Connection established\r\n")
62 62 self.wfile.write("Proxy-agent: %s\r\n" % self.version_string())
63 63 self.wfile.write("\r\n")
64 64 self._read_write(soc, 300)
65 65 finally:
66 66 print "\t" "bye"
67 67 soc.close()
68 68 self.connection.close()
69 69
70 70 def do_GET(self):
71 71 (scm, netloc, path, params, query, fragment) = urlparse.urlparse(
72 72 self.path, 'http')
73 73 if scm != 'http' or fragment or not netloc:
74 74 self.send_error(400, "bad url %s" % self.path)
75 75 return
76 76 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
77 77 try:
78 78 if self._connect_to(netloc, soc):
79 79 self.log_request()
80 80 soc.send("%s %s %s\r\n" % (
81 81 self.command,
82 82 urlparse.urlunparse(('', '', path, params, query, '')),
83 83 self.request_version))
84 84 self.headers['Connection'] = 'close'
85 85 del self.headers['Proxy-Connection']
86 86 for key_val in self.headers.items():
87 87 soc.send("%s: %s\r\n" % key_val)
88 88 soc.send("\r\n")
89 89 self._read_write(soc)
90 90 finally:
91 91 print "\t" "bye"
92 92 soc.close()
93 93 self.connection.close()
94 94
95 95 def _read_write(self, soc, max_idling=20):
96 96 iw = [self.connection, soc]
97 97 ow = []
98 98 count = 0
99 99 while True:
100 100 count += 1
101 101 (ins, _, exs) = select.select(iw, ow, iw, 3)
102 102 if exs:
103 103 break
104 104 if ins:
105 105 for i in ins:
106 106 if i is soc:
107 107 out = self.connection
108 108 else:
109 109 out = soc
110 try:
110 111 data = i.recv(8192)
112 except socket.error:
113 break
111 114 if data:
112 115 out.send(data)
113 116 count = 0
114 117 else:
115 118 print "\t" "idle", count
116 119 if count == max_idling:
117 120 break
118 121
119 122 do_HEAD = do_GET
120 123 do_POST = do_GET
121 124 do_PUT = do_GET
122 125 do_DELETE = do_GET
123 126
124 127 class ThreadingHTTPServer (SocketServer.ThreadingMixIn,
125 128 BaseHTTPServer.HTTPServer):
126 129 def __init__(self, *args, **kwargs):
127 130 BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs)
128 131 a = open("proxy.pid", "w")
129 132 a.write(str(os.getpid()) + "\n")
130 133 a.close()
131 134
132 135 if __name__ == '__main__':
133 136 from sys import argv
134 137 if argv[1:] and argv[1] in ('-h', '--help'):
135 138 print argv[0], "[port [allowed_client_name ...]]"
136 139 else:
137 140 if argv[2:]:
138 141 allowed = []
139 142 for name in argv[2:]:
140 143 client = socket.gethostbyname(name)
141 144 allowed.append(client)
142 145 print "Accept: %s (%s)" % (client, name)
143 146 ProxyHandler.allowed_clients = allowed
144 147 del argv[2:]
145 148 else:
146 149 print "Any clients will be served..."
147 150 BaseHTTPServer.test(ProxyHandler, ThreadingHTTPServer)
General Comments 0
You need to be logged in to leave comments. Login now