Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Cloud:OpenStack:Essex
openstack-swift
dir-traversals-checks.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File dir-traversals-checks.patch of Package openstack-swift
From 63b9f3bf602dd19712b2ba19046153f5f8495cc5 Mon Sep 17 00:00:00 2001 From: Vincent Untz <vuntz@suse.com> Date: Tue, 19 Jun 2012 12:11:06 +0200 Subject: [PATCH] Validate devices and partitions to avoid directory traversals swift.common.utils.validate_device_partition is a new function to check that a device and a partition are valid. This means that they don't contain '/' and are not '.' or '..'. We use this new function every time we get devices and partitions from a request. Fix bug 1005908 Change-Id: Ia545ba8f877e85b4b576d6d7d09d890877ea6d34 --- swift/account/server.py | 11 +++++++++-- swift/common/utils.py | 22 ++++++++++++++++++++++ swift/container/server.py | 11 +++++++++-- swift/obj/server.py | 9 ++++++++- test/unit/common/test_utils.py | 21 +++++++++++++++++++++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/swift/account/server.py b/swift/account/server.py index 800b3c0..5353907 100644 --- a/swift/account/server.py +++ b/swift/account/server.py @@ -31,7 +31,8 @@ import simplejson from swift.common.db import AccountBroker from swift.common.utils import get_logger, get_param, hash_path, \ - normalize_timestamp, split_path, storage_directory + normalize_timestamp, split_path, storage_directory, \ + validate_device_partition from swift.common.constraints import ACCOUNT_LISTING_LIMIT, \ check_mount, check_float, check_utf8 from swift.common.db_replicator import ReplicatorRpc @@ -63,6 +64,7 @@ class AccountController(object): """Handle HTTP DELETE request.""" try: drive, part, account = split_path(unquote(req.path), 3) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -83,6 +85,7 @@ class AccountController(object): try: drive, part, account, container = split_path(unquote(req.path), 3, 4) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -142,6 +145,7 @@ class AccountController(object): try: drive, part, account, container = split_path(unquote(req.path), 3, 4) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -173,6 +177,7 @@ class AccountController(object): """Handle HTTP GET request.""" try: drive, part, account = split_path(unquote(req.path), 3) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -266,10 +271,11 @@ class AccountController(object): """ try: post_args = split_path(unquote(req.path), 3) + drive, partition, hash = post_args + validate_device_partition(drive, partition) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) - drive, partition, hash = post_args if self.mount_check and not check_mount(self.root, drive): return Response(status='507 %s is not mounted' % drive) try: @@ -284,6 +290,7 @@ class AccountController(object): """Handle HTTP POST request.""" try: drive, part, account = split_path(unquote(req.path), 3) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) diff --git a/swift/common/utils.py b/swift/common/utils.py index 47edce8..1e10028 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -243,6 +243,28 @@ def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False): return segs +def validate_device_partition(device, partition): + """ + Validate that a device and a partition are valid and won't lead to + directory traversal when used. + + :param device: device to validate + :param partition: partition to validate + :raises: ValueError if given an invalid device or partition + """ + invalid_device = False + invalid_partition = False + if not device or '/' in device or device in ['.', '..']: + invalid_device = True + if not partition or '/' in partition or partition in ['.', '..']: + invalid_partition = True + + if invalid_device: + raise ValueError('Invalid device: %s' % quote(device or '')) + elif invalid_partition: + raise ValueError('Invalid partition: %s' % quote(partition or '')) + + class NullLogger(): """A no-op logger for eventlet wsgi.""" diff --git a/swift/container/server.py b/swift/container/server.py index 8a18cfd..6278edb 100644 --- a/swift/container/server.py +++ b/swift/container/server.py @@ -31,7 +31,8 @@ from webob.exc import HTTPAccepted, HTTPBadRequest, HTTPConflict, \ from swift.common.db import ContainerBroker from swift.common.utils import get_logger, get_param, hash_path, \ - normalize_timestamp, storage_directory, split_path, validate_sync_to + normalize_timestamp, storage_directory, split_path, validate_sync_to, \ + validate_device_partition from swift.common.constraints import CONTAINER_LISTING_LIMIT, \ check_mount, check_float, check_utf8 from swift.common.bufferedhttp import http_connect @@ -136,6 +137,7 @@ class ContainerController(object): try: drive, part, account, container, obj = split_path( unquote(req.path), 4, 5, True) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -176,6 +178,7 @@ class ContainerController(object): try: drive, part, account, container, obj = split_path( unquote(req.path), 4, 5, True) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -235,6 +238,7 @@ class ContainerController(object): try: drive, part, account, container, obj = split_path( unquote(req.path), 4, 5, True) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -263,6 +267,7 @@ class ContainerController(object): try: drive, part, account, container, obj = split_path( unquote(req.path), 4, 5, True) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) @@ -377,10 +382,11 @@ class ContainerController(object): """ try: post_args = split_path(unquote(req.path), 3) + drive, partition, hash = post_args + validate_device_partition(drive, partition) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) - drive, partition, hash = post_args if self.mount_check and not check_mount(self.root, drive): return Response(status='507 %s is not mounted' % drive) try: @@ -395,6 +401,7 @@ class ContainerController(object): """Handle HTTP POST request.""" try: drive, part, account, container = split_path(unquote(req.path), 4) + validate_device_partition(drive, part) except ValueError, err: return HTTPBadRequest(body=str(err), content_type='text/plain', request=req) diff --git a/swift/obj/server.py b/swift/obj/server.py index 9cca16b..612e14c 100644 --- a/swift/obj/server.py +++ b/swift/obj/server.py @@ -37,7 +37,8 @@ from eventlet import sleep, Timeout, tpool from swift.common.utils import mkdirs, normalize_timestamp, \ storage_directory, hash_path, renamer, fallocate, \ - split_path, drop_buffer_cache, get_logger, write_pickle + split_path, drop_buffer_cache, get_logger, write_pickle, \ + validate_device_partition from swift.common.bufferedhttp import http_connect from swift.common.constraints import check_object_creation, check_mount, \ check_float, check_utf8 @@ -480,6 +481,7 @@ class ObjectController(object): try: device, partition, account, container, obj = \ split_path(unquote(request.path), 5, 5, True) + validate_device_partition(device, partition) except ValueError, err: return HTTPBadRequest(body=str(err), request=request, content_type='text/plain') @@ -532,6 +534,7 @@ class ObjectController(object): try: device, partition, account, container, obj = \ split_path(unquote(request.path), 5, 5, True) + validate_device_partition(device, partition) except ValueError, err: return HTTPBadRequest(body=str(err), request=request, content_type='text/plain') @@ -621,6 +624,7 @@ class ObjectController(object): try: device, partition, account, container, obj = \ split_path(unquote(request.path), 5, 5, True) + validate_device_partition(device, partition) except ValueError, err: return HTTPBadRequest(body=str(err), request=request, content_type='text/plain') @@ -695,6 +699,7 @@ class ObjectController(object): try: device, partition, account, container, obj = \ split_path(unquote(request.path), 5, 5, True) + validate_device_partition(device, partition) except ValueError, err: resp = HTTPBadRequest(request=request) resp.content_type = 'text/plain' @@ -734,6 +739,7 @@ class ObjectController(object): try: device, partition, account, container, obj = \ split_path(unquote(request.path), 5, 5, True) + validate_device_partition(device, partition) except ValueError, e: return HTTPBadRequest(body=str(e), request=request, content_type='text/plain') @@ -781,6 +787,7 @@ class ObjectController(object): try: device, partition, suffix = split_path( unquote(request.path), 2, 3, True) + validate_device_partition(device, partition) except ValueError, e: return HTTPBadRequest(body=str(e), request=request, content_type='text/plain') diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index f7e33c4..e897414 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -189,6 +189,27 @@ class TestUtils(unittest.TestCase): except ValueError, err: self.assertEquals(str(err), 'Invalid path: o%0An%20e') + def test_validate_device_partition(self): + """ Test swift.common.utils.validate_device_partition """ + utils.validate_device_partition('foo', 'bar') + self.assertRaises(ValueError, utils.validate_device_partition, '', '') + self.assertRaises(ValueError, utils.validate_device_partition, '', 'foo') + self.assertRaises(ValueError, utils.validate_device_partition, 'foo', '') + self.assertRaises(ValueError, utils.validate_device_partition, 'foo/bar', 'foo') + self.assertRaises(ValueError, utils.validate_device_partition, 'foo', 'foo/bar') + self.assertRaises(ValueError, utils.validate_device_partition, '.', 'foo') + self.assertRaises(ValueError, utils.validate_device_partition, '..', 'foo') + self.assertRaises(ValueError, utils.validate_device_partition, 'foo', '.') + self.assertRaises(ValueError, utils.validate_device_partition, 'foo', '..') + try: + utils.validate_device_partition,('o\nn e', 'foo') + except ValueError, err: + self.assertEquals(str(err), 'Invalid device: o%0An%20e') + try: + utils.validate_device_partition,('foo', 'o\nn e') + except ValueError, err: + self.assertEquals(str(err), 'Invalid partition: o%0An%20e') + def test_NullLogger(self): """ Test swift.common.utils.NullLogger """ sio = StringIO() -- 1.7.7
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor