Merge lp:~david-goetz/swift/invalid_url_backport into lp:swift/1.1

Proposed by David Goetz
Status: Merged
Approved by: Chuck Thier
Approved revision: 109
Merged at revision: 109
Proposed branch: lp:~david-goetz/swift/invalid_url_backport
Merge into: lp:swift/1.1
Diff against target: 251 lines (+76/-17)
11 files modified
swift/account/server.py (+6/-1)
swift/auth/server.py (+5/-2)
swift/common/middleware/auth.py (+12/-6)
swift/common/middleware/ratelimit.py (+5/-1)
swift/common/utils.py (+2/-0)
swift/obj/server.py (+6/-2)
swift/proxy/server.py (+2/-0)
swift/stats/access_processor.py (+7/-4)
test/functional/tests.py (+9/-0)
test/unit/auth/test_server.py (+2/-1)
test/unit/common/middleware/test_ratelimit.py (+20/-0)
To merge this branch: bzr merge lp:~david-goetz/swift/invalid_url_backport
Reviewer Review Type Date Requested Status
Chuck Thier Approve
Review via email: mp+39889@code.launchpad.net

Description of the change

back porting bug fix into 1.1

To post a comment you must log in.
Revision history for this message
Chuck Thier (cthier) wrote :

Looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'swift/account/server.py'
2--- swift/account/server.py 2010-09-22 19:34:52 +0000
3+++ swift/account/server.py 2010-11-02 19:52:43 +0000
4@@ -77,7 +77,12 @@
5
6 def PUT(self, req):
7 """Handle HTTP PUT request."""
8- drive, part, account, container = split_path(unquote(req.path), 3, 4)
9+ try:
10+ drive, part, account, container = split_path(unquote(req.path),
11+ 3, 4)
12+ except ValueError, err:
13+ return HTTPBadRequest(body=str(err), content_type='text/plain',
14+ request=req)
15 if self.mount_check and not check_mount(self.root, drive):
16 return Response(status='507 %s is not mounted' % drive)
17 broker = self._get_account_broker(drive, part, account)
18
19=== modified file 'swift/auth/server.py'
20--- swift/auth/server.py 2010-10-19 22:35:18 +0000
21+++ swift/auth/server.py 2010-11-02 19:52:43 +0000
22@@ -516,8 +516,11 @@
23
24 :param request: A webob.Request instance.
25 """
26- pathsegs = \
27- split_path(request.path, minsegs=1, maxsegs=3, rest_with_last=True)
28+ try:
29+ pathsegs = split_path(request.path, minsegs=1, maxsegs=3,
30+ rest_with_last=True)
31+ except ValueError:
32+ return HTTPBadRequest()
33 if pathsegs[0] == 'v1' and pathsegs[2] == 'auth':
34 account = pathsegs[1]
35 user = request.headers.get('x-storage-user')
36
37=== modified file 'swift/common/middleware/auth.py'
38--- swift/common/middleware/auth.py 2010-09-17 18:26:30 +0000
39+++ swift/common/middleware/auth.py 2010-11-02 19:52:43 +0000
40@@ -16,7 +16,7 @@
41 from time import time
42
43 from eventlet.timeout import Timeout
44-from webob.exc import HTTPForbidden, HTTPUnauthorized
45+from webob.exc import HTTPForbidden, HTTPUnauthorized, HTTPNotFound
46
47 from swift.common.bufferedhttp import http_connect_raw as http_connect
48 from swift.common.middleware.acl import clean_acl, parse_acl, referrer_allowed
49@@ -82,8 +82,11 @@
50 # With a non-empty reseller_prefix, I would like to be called
51 # back for anonymous access to accounts I know I'm the
52 # definitive auth for.
53- version, rest = split_path(env.get('PATH_INFO', ''),
54- 1, 2, True)
55+ try:
56+ version, rest = split_path(env.get('PATH_INFO', ''),
57+ 1, 2, True)
58+ except ValueError:
59+ return HTTPNotFound()(env, start_response)
60 if rest and rest.startswith(self.reseller_prefix):
61 # Handle anonymous access to accounts I'm the definitive
62 # auth for.
63@@ -103,10 +106,10 @@
64 def get_groups(self, token, memcache_client=None):
65 """
66 Get groups for the given token.
67-
68+
69 If memcache_client is set, token credentials will be cached
70 appropriately.
71-
72+
73 With a cache miss, or no memcache_client, the configurated external
74 authentication server will be queried for the group information.
75
76@@ -146,7 +149,10 @@
77 Returns None if the request is authorized to continue or a standard
78 WSGI response callable if not.
79 """
80- version, account, container, obj = split_path(req.path, 1, 4, True)
81+ try:
82+ version, account, container, obj = split_path(req.path, 1, 4, True)
83+ except ValueError:
84+ return HTTPNotFound(request=req)
85 if not account or not account.startswith(self.reseller_prefix):
86 return self.denied_response(req)
87 user_groups = (req.remote_user or '').split(',')
88
89=== modified file 'swift/common/middleware/ratelimit.py'
90--- swift/common/middleware/ratelimit.py 2010-10-20 17:31:50 +0000
91+++ swift/common/middleware/ratelimit.py 2010-11-02 19:52:43 +0000
92@@ -14,6 +14,7 @@
93 import time
94 import eventlet
95 from webob import Request, Response
96+from webob.exc import HTTPNotFound
97
98 from swift.common.utils import split_path, cache_from_env, get_logger
99 from swift.proxy.server import get_container_memcache_key
100@@ -197,7 +198,10 @@
101 req = Request(env)
102 if self.memcache_client is None:
103 self.memcache_client = cache_from_env(env)
104- version, account, container, obj = split_path(req.path, 1, 4, True)
105+ try:
106+ version, account, container, obj = split_path(req.path, 1, 4, True)
107+ except ValueError:
108+ return HTTPNotFound()(env, start_response)
109 ratelimit_resp = self.handle_ratelimit(req, account, container, obj)
110 if ratelimit_resp is None:
111 return self.app(env, start_response)
112
113=== modified file 'swift/common/utils.py'
114--- swift/common/utils.py 2010-10-21 18:32:10 +0000
115+++ swift/common/utils.py 2010-11-02 19:52:43 +0000
116@@ -208,6 +208,7 @@
117 trailing data, raises ValueError.
118 :returns: list of segments with a length of maxsegs (non-existant
119 segments will return as None)
120+ :raises: ValueError if given an invalid path
121 """
122 if not maxsegs:
123 maxsegs = minsegs
124@@ -622,6 +623,7 @@
125 os.fsync(fd)
126 renamer(tmppath, dest)
127
128+
129 def audit_location_generator(devices, datadir, mount_check=True, logger=None):
130 '''
131 Given a devices path and a data directory, yield (path, device,
132
133=== modified file 'swift/obj/server.py'
134--- swift/obj/server.py 2010-10-19 01:05:54 +0000
135+++ swift/obj/server.py 2010-11-02 19:52:43 +0000
136@@ -534,8 +534,12 @@
137 Handle REPLICATE requests for the Swift Object Server. This is used
138 by the object replicator to get hashes for directories.
139 """
140- device, partition, suffix = split_path(
141- unquote(request.path), 2, 3, True)
142+ try:
143+ device, partition, suffix = split_path(
144+ unquote(request.path), 2, 3, True)
145+ except ValueError, e:
146+ return HTTPBadRequest(body=str(e), request=request,
147+ content_type='text/plain')
148 if self.mount_check and not check_mount(self.devices, device):
149 return Response(status='507 %s is not mounted' % device)
150 path = os.path.join(self.devices, device, DATADIR, partition)
151
152=== modified file 'swift/proxy/server.py'
153--- swift/proxy/server.py 2010-10-15 15:07:19 +0000
154+++ swift/proxy/server.py 2010-11-02 19:52:43 +0000
155@@ -1257,6 +1257,8 @@
156
157 :param path: path from request
158 :returns: tuple of (controller class, path dictionary)
159+
160+ :raises: ValueError (thrown by split_path) id given invalid path
161 """
162 version, account, container, obj = split_path(path, 1, 4, True)
163 d = dict(version=version,
164
165=== modified file 'swift/stats/access_processor.py'
166--- swift/stats/access_processor.py 2010-10-08 01:56:31 +0000
167+++ swift/stats/access_processor.py 2010-11-02 19:52:43 +0000
168@@ -66,10 +66,13 @@
169 self.logger.debug('Bad server name: found "%s" expected "%s"' \
170 % (server, self.server_name))
171 return {}
172- (version,
173- account,
174- container_name,
175- object_name) = split_path(request, 2, 4, True)
176+ try:
177+ (version, account, container_name, object_name) = \
178+ split_path(request, 2, 4, True)
179+ except ValueError, e:
180+ self.logger.debug(
181+ 'Invalid path: %s from data: %s' % (e, repr(raw_log)))
182+ return {}
183 if container_name is not None:
184 container_name = container_name.split('?', 1)[0]
185 if object_name is not None:
186
187=== modified file 'test/functional/tests.py'
188--- test/functional/tests.py 2010-09-10 20:40:43 +0000
189+++ test/functional/tests.py 2010-11-02 19:52:43 +0000
190@@ -170,6 +170,15 @@
191 self.assert_status(412)
192 self.assert_body('Bad URL')
193
194+ def testInvalidPath(self):
195+ was_url = self.env.account.conn.storage_url
196+ self.env.account.conn.storage_url = "/%s" % was_url
197+ self.env.account.conn.make_request('GET')
198+ try:
199+ self.assert_status(404)
200+ finally:
201+ self.env.account.conn.storage_url = was_url
202+
203 def testPUT(self):
204 self.env.account.conn.make_request('PUT')
205 self.assert_status([403, 405])
206
207=== modified file 'test/unit/auth/test_server.py'
208--- test/unit/auth/test_server.py 2010-09-16 21:44:44 +0000
209+++ test/unit/auth/test_server.py 2010-11-02 19:52:43 +0000
210@@ -241,8 +241,9 @@
211 len(set(repr(a) for a in cfaccounts) - set(failed)), 2)
212
213 def test_auth_bad_path(self):
214- self.assertRaises(ValueError, self.controller.handle_auth,
215+ res = self.controller.handle_auth(
216 Request.blank('', environ={'REQUEST_METHOD': 'GET'}))
217+ self.assertEquals(res.status_int, 400)
218 res = self.controller.handle_auth(Request.blank('/bad',
219 environ={'REQUEST_METHOD': 'GET'}))
220 self.assertEquals(res.status_int, 400)
221
222=== modified file 'test/unit/common/middleware/test_ratelimit.py'
223--- test/unit/common/middleware/test_ratelimit.py 2010-10-20 18:05:38 +0000
224+++ test/unit/common/middleware/test_ratelimit.py 2010-11-02 19:52:43 +0000
225@@ -368,6 +368,26 @@
226 time_took = time.time() - begin
227 self.assert_(round(time_took, 1) == .4)
228
229+ def test_call_invalid_path(self):
230+ env = {'REQUEST_METHOD': 'GET',
231+ 'SCRIPT_NAME': '',
232+ 'PATH_INFO': '//v1/AUTH_1234567890',
233+ 'SERVER_NAME': '127.0.0.1',
234+ 'SERVER_PORT': '80',
235+ 'swift.cache': FakeMemcache(),
236+ 'SERVER_PROTOCOL': 'HTTP/1.0'}
237+
238+ app = lambda *args, **kwargs: None
239+ rate_mid = ratelimit.RateLimitMiddleware(app, {},
240+ logger=FakeLogger())
241+
242+ class a_callable(object):
243+
244+ def __call__(self, *args, **kwargs):
245+ pass
246+ resp = rate_mid.__call__(env, a_callable())
247+ self.assert_('404 Not Found' in resp[0])
248+
249
250 if __name__ == '__main__':
251 unittest.main()

Subscribers

People subscribed via source and target branches