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
=== modified file 'swift/account/server.py'
--- swift/account/server.py 2010-09-22 19:34:52 +0000
+++ swift/account/server.py 2010-11-02 19:52:43 +0000
@@ -77,7 +77,12 @@
7777
78 def PUT(self, req):78 def PUT(self, req):
79 """Handle HTTP PUT request."""79 """Handle HTTP PUT request."""
80 drive, part, account, container = split_path(unquote(req.path), 3, 4)80 try:
81 drive, part, account, container = split_path(unquote(req.path),
82 3, 4)
83 except ValueError, err:
84 return HTTPBadRequest(body=str(err), content_type='text/plain',
85 request=req)
81 if self.mount_check and not check_mount(self.root, drive):86 if self.mount_check and not check_mount(self.root, drive):
82 return Response(status='507 %s is not mounted' % drive)87 return Response(status='507 %s is not mounted' % drive)
83 broker = self._get_account_broker(drive, part, account)88 broker = self._get_account_broker(drive, part, account)
8489
=== modified file 'swift/auth/server.py'
--- swift/auth/server.py 2010-10-19 22:35:18 +0000
+++ swift/auth/server.py 2010-11-02 19:52:43 +0000
@@ -516,8 +516,11 @@
516516
517 :param request: A webob.Request instance.517 :param request: A webob.Request instance.
518 """518 """
519 pathsegs = \519 try:
520 split_path(request.path, minsegs=1, maxsegs=3, rest_with_last=True)520 pathsegs = split_path(request.path, minsegs=1, maxsegs=3,
521 rest_with_last=True)
522 except ValueError:
523 return HTTPBadRequest()
521 if pathsegs[0] == 'v1' and pathsegs[2] == 'auth':524 if pathsegs[0] == 'v1' and pathsegs[2] == 'auth':
522 account = pathsegs[1]525 account = pathsegs[1]
523 user = request.headers.get('x-storage-user')526 user = request.headers.get('x-storage-user')
524527
=== modified file 'swift/common/middleware/auth.py'
--- swift/common/middleware/auth.py 2010-09-17 18:26:30 +0000
+++ swift/common/middleware/auth.py 2010-11-02 19:52:43 +0000
@@ -16,7 +16,7 @@
16from time import time16from time import time
1717
18from eventlet.timeout import Timeout18from eventlet.timeout import Timeout
19from webob.exc import HTTPForbidden, HTTPUnauthorized19from webob.exc import HTTPForbidden, HTTPUnauthorized, HTTPNotFound
2020
21from swift.common.bufferedhttp import http_connect_raw as http_connect21from swift.common.bufferedhttp import http_connect_raw as http_connect
22from swift.common.middleware.acl import clean_acl, parse_acl, referrer_allowed22from swift.common.middleware.acl import clean_acl, parse_acl, referrer_allowed
@@ -82,8 +82,11 @@
82 # With a non-empty reseller_prefix, I would like to be called82 # With a non-empty reseller_prefix, I would like to be called
83 # back for anonymous access to accounts I know I'm the83 # back for anonymous access to accounts I know I'm the
84 # definitive auth for.84 # definitive auth for.
85 version, rest = split_path(env.get('PATH_INFO', ''),85 try:
86 1, 2, True)86 version, rest = split_path(env.get('PATH_INFO', ''),
87 1, 2, True)
88 except ValueError:
89 return HTTPNotFound()(env, start_response)
87 if rest and rest.startswith(self.reseller_prefix):90 if rest and rest.startswith(self.reseller_prefix):
88 # Handle anonymous access to accounts I'm the definitive91 # Handle anonymous access to accounts I'm the definitive
89 # auth for.92 # auth for.
@@ -103,10 +106,10 @@
103 def get_groups(self, token, memcache_client=None):106 def get_groups(self, token, memcache_client=None):
104 """107 """
105 Get groups for the given token.108 Get groups for the given token.
106 109
107 If memcache_client is set, token credentials will be cached110 If memcache_client is set, token credentials will be cached
108 appropriately.111 appropriately.
109 112
110 With a cache miss, or no memcache_client, the configurated external113 With a cache miss, or no memcache_client, the configurated external
111 authentication server will be queried for the group information.114 authentication server will be queried for the group information.
112115
@@ -146,7 +149,10 @@
146 Returns None if the request is authorized to continue or a standard149 Returns None if the request is authorized to continue or a standard
147 WSGI response callable if not.150 WSGI response callable if not.
148 """151 """
149 version, account, container, obj = split_path(req.path, 1, 4, True)152 try:
153 version, account, container, obj = split_path(req.path, 1, 4, True)
154 except ValueError:
155 return HTTPNotFound(request=req)
150 if not account or not account.startswith(self.reseller_prefix):156 if not account or not account.startswith(self.reseller_prefix):
151 return self.denied_response(req)157 return self.denied_response(req)
152 user_groups = (req.remote_user or '').split(',')158 user_groups = (req.remote_user or '').split(',')
153159
=== modified file 'swift/common/middleware/ratelimit.py'
--- swift/common/middleware/ratelimit.py 2010-10-20 17:31:50 +0000
+++ swift/common/middleware/ratelimit.py 2010-11-02 19:52:43 +0000
@@ -14,6 +14,7 @@
14import time14import time
15import eventlet15import eventlet
16from webob import Request, Response16from webob import Request, Response
17from webob.exc import HTTPNotFound
1718
18from swift.common.utils import split_path, cache_from_env, get_logger19from swift.common.utils import split_path, cache_from_env, get_logger
19from swift.proxy.server import get_container_memcache_key20from swift.proxy.server import get_container_memcache_key
@@ -197,7 +198,10 @@
197 req = Request(env)198 req = Request(env)
198 if self.memcache_client is None:199 if self.memcache_client is None:
199 self.memcache_client = cache_from_env(env)200 self.memcache_client = cache_from_env(env)
200 version, account, container, obj = split_path(req.path, 1, 4, True)201 try:
202 version, account, container, obj = split_path(req.path, 1, 4, True)
203 except ValueError:
204 return HTTPNotFound()(env, start_response)
201 ratelimit_resp = self.handle_ratelimit(req, account, container, obj)205 ratelimit_resp = self.handle_ratelimit(req, account, container, obj)
202 if ratelimit_resp is None:206 if ratelimit_resp is None:
203 return self.app(env, start_response)207 return self.app(env, start_response)
204208
=== modified file 'swift/common/utils.py'
--- swift/common/utils.py 2010-10-21 18:32:10 +0000
+++ swift/common/utils.py 2010-11-02 19:52:43 +0000
@@ -208,6 +208,7 @@
208 trailing data, raises ValueError.208 trailing data, raises ValueError.
209 :returns: list of segments with a length of maxsegs (non-existant209 :returns: list of segments with a length of maxsegs (non-existant
210 segments will return as None)210 segments will return as None)
211 :raises: ValueError if given an invalid path
211 """212 """
212 if not maxsegs:213 if not maxsegs:
213 maxsegs = minsegs214 maxsegs = minsegs
@@ -622,6 +623,7 @@
622 os.fsync(fd)623 os.fsync(fd)
623 renamer(tmppath, dest)624 renamer(tmppath, dest)
624625
626
625def audit_location_generator(devices, datadir, mount_check=True, logger=None):627def audit_location_generator(devices, datadir, mount_check=True, logger=None):
626 '''628 '''
627 Given a devices path and a data directory, yield (path, device,629 Given a devices path and a data directory, yield (path, device,
628630
=== modified file 'swift/obj/server.py'
--- swift/obj/server.py 2010-10-19 01:05:54 +0000
+++ swift/obj/server.py 2010-11-02 19:52:43 +0000
@@ -534,8 +534,12 @@
534 Handle REPLICATE requests for the Swift Object Server. This is used534 Handle REPLICATE requests for the Swift Object Server. This is used
535 by the object replicator to get hashes for directories.535 by the object replicator to get hashes for directories.
536 """536 """
537 device, partition, suffix = split_path(537 try:
538 unquote(request.path), 2, 3, True)538 device, partition, suffix = split_path(
539 unquote(request.path), 2, 3, True)
540 except ValueError, e:
541 return HTTPBadRequest(body=str(e), request=request,
542 content_type='text/plain')
539 if self.mount_check and not check_mount(self.devices, device):543 if self.mount_check and not check_mount(self.devices, device):
540 return Response(status='507 %s is not mounted' % device)544 return Response(status='507 %s is not mounted' % device)
541 path = os.path.join(self.devices, device, DATADIR, partition)545 path = os.path.join(self.devices, device, DATADIR, partition)
542546
=== modified file 'swift/proxy/server.py'
--- swift/proxy/server.py 2010-10-15 15:07:19 +0000
+++ swift/proxy/server.py 2010-11-02 19:52:43 +0000
@@ -1257,6 +1257,8 @@
12571257
1258 :param path: path from request1258 :param path: path from request
1259 :returns: tuple of (controller class, path dictionary)1259 :returns: tuple of (controller class, path dictionary)
1260
1261 :raises: ValueError (thrown by split_path) id given invalid path
1260 """1262 """
1261 version, account, container, obj = split_path(path, 1, 4, True)1263 version, account, container, obj = split_path(path, 1, 4, True)
1262 d = dict(version=version,1264 d = dict(version=version,
12631265
=== modified file 'swift/stats/access_processor.py'
--- swift/stats/access_processor.py 2010-10-08 01:56:31 +0000
+++ swift/stats/access_processor.py 2010-11-02 19:52:43 +0000
@@ -66,10 +66,13 @@
66 self.logger.debug('Bad server name: found "%s" expected "%s"' \66 self.logger.debug('Bad server name: found "%s" expected "%s"' \
67 % (server, self.server_name))67 % (server, self.server_name))
68 return {}68 return {}
69 (version,69 try:
70 account,70 (version, account, container_name, object_name) = \
71 container_name,71 split_path(request, 2, 4, True)
72 object_name) = split_path(request, 2, 4, True)72 except ValueError, e:
73 self.logger.debug(
74 'Invalid path: %s from data: %s' % (e, repr(raw_log)))
75 return {}
73 if container_name is not None:76 if container_name is not None:
74 container_name = container_name.split('?', 1)[0]77 container_name = container_name.split('?', 1)[0]
75 if object_name is not None:78 if object_name is not None:
7679
=== modified file 'test/functional/tests.py'
--- test/functional/tests.py 2010-09-10 20:40:43 +0000
+++ test/functional/tests.py 2010-11-02 19:52:43 +0000
@@ -170,6 +170,15 @@
170 self.assert_status(412)170 self.assert_status(412)
171 self.assert_body('Bad URL')171 self.assert_body('Bad URL')
172172
173 def testInvalidPath(self):
174 was_url = self.env.account.conn.storage_url
175 self.env.account.conn.storage_url = "/%s" % was_url
176 self.env.account.conn.make_request('GET')
177 try:
178 self.assert_status(404)
179 finally:
180 self.env.account.conn.storage_url = was_url
181
173 def testPUT(self):182 def testPUT(self):
174 self.env.account.conn.make_request('PUT')183 self.env.account.conn.make_request('PUT')
175 self.assert_status([403, 405])184 self.assert_status([403, 405])
176185
=== modified file 'test/unit/auth/test_server.py'
--- test/unit/auth/test_server.py 2010-09-16 21:44:44 +0000
+++ test/unit/auth/test_server.py 2010-11-02 19:52:43 +0000
@@ -241,8 +241,9 @@
241 len(set(repr(a) for a in cfaccounts) - set(failed)), 2)241 len(set(repr(a) for a in cfaccounts) - set(failed)), 2)
242242
243 def test_auth_bad_path(self):243 def test_auth_bad_path(self):
244 self.assertRaises(ValueError, self.controller.handle_auth,244 res = self.controller.handle_auth(
245 Request.blank('', environ={'REQUEST_METHOD': 'GET'}))245 Request.blank('', environ={'REQUEST_METHOD': 'GET'}))
246 self.assertEquals(res.status_int, 400)
246 res = self.controller.handle_auth(Request.blank('/bad',247 res = self.controller.handle_auth(Request.blank('/bad',
247 environ={'REQUEST_METHOD': 'GET'}))248 environ={'REQUEST_METHOD': 'GET'}))
248 self.assertEquals(res.status_int, 400)249 self.assertEquals(res.status_int, 400)
249250
=== modified file 'test/unit/common/middleware/test_ratelimit.py'
--- test/unit/common/middleware/test_ratelimit.py 2010-10-20 18:05:38 +0000
+++ test/unit/common/middleware/test_ratelimit.py 2010-11-02 19:52:43 +0000
@@ -368,6 +368,26 @@
368 time_took = time.time() - begin368 time_took = time.time() - begin
369 self.assert_(round(time_took, 1) == .4)369 self.assert_(round(time_took, 1) == .4)
370370
371 def test_call_invalid_path(self):
372 env = {'REQUEST_METHOD': 'GET',
373 'SCRIPT_NAME': '',
374 'PATH_INFO': '//v1/AUTH_1234567890',
375 'SERVER_NAME': '127.0.0.1',
376 'SERVER_PORT': '80',
377 'swift.cache': FakeMemcache(),
378 'SERVER_PROTOCOL': 'HTTP/1.0'}
379
380 app = lambda *args, **kwargs: None
381 rate_mid = ratelimit.RateLimitMiddleware(app, {},
382 logger=FakeLogger())
383
384 class a_callable(object):
385
386 def __call__(self, *args, **kwargs):
387 pass
388 resp = rate_mid.__call__(env, a_callable())
389 self.assert_('404 Not Found' in resp[0])
390
371391
372if __name__ == '__main__':392if __name__ == '__main__':
373 unittest.main()393 unittest.main()

Subscribers

People subscribed via source and target branches