[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#799369: marked as done (jessie-pu: package swift/2.2.0-1)



Your message dated Sat, 23 Jan 2016 13:57:15 +0000
with message-id <1453557435.1835.52.camel@adam-barratt.org.uk>
and subject line 8.3 point release cleanup
has caused the Debian Bug report #799369,
regarding jessie-pu: package swift/2.2.0-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
799369: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=799369
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
Usertags: pu

Dear Stable release team,

I'd like to upload an update of Swift through s-p-u, in order to fix a
number of issues listed below:
- User creation was done in a non-OpenStack package standard way, namely
missing the --disabled-login option.
- On removal, the package was calling userdel, which I consider dangerous
(potential reuse of the UUID).
- On purge, /var/cache/swift wasn't removed.
- The swift-container-sync init script wasn't installed.

More importantly, there's 2 CVEs which needs to be fixed:
- CVE-2015-1856 & OSSA 2015-006: Unauthorized delete of versioned Swift
  object.
- CVE-2015-5223: Information leak via Swift tempurls.

The above CVEs were considered not critical enough by the security team
to deserve a DSA, though they still deserve fixing.

I have attached a debdiff with all of the above problems corrected. The
pre-built package is also available here:
http://sid.gplhost.com/jessie-proposed-updates/swift/

Please allow me to upload swift/2.2.0-1+deb8u1 to jessie-proposed-updates.

Cheers,

Thomas Goirand (zigo)
diff -Nru swift-2.2.0/debian/changelog swift-2.2.0/debian/changelog
--- swift-2.2.0/debian/changelog	2014-10-16 12:48:43.000000000 +0000
+++ swift-2.2.0/debian/changelog	2015-09-15 19:29:22.000000000 +0000
@@ -1,3 +1,20 @@
+swift (2.2.0-1+deb8u1) jessie-proposed-updates; urgency=medium
+
+  [ Thomas Goirand ]
+  * Fixed swift user creation (standardized on pkgos way).
+  * CVE-2015-1856 & OSSA 2015-006: Unauthorized delete of versioned Swift
+    object. Applied upstream patch: Prevent unauthorized delete in versioned
+    container (Closes: #783163).
+
+  [ Ondřej Nový ]
+  * Fixed service name of object-expirer.
+  * Added container-sync init script.
+  * CVE-2015-5223: Information leak via Swift tempurls.
+    Applied upstream patch: Disallow unsafe tempurl operations to point
+    to unauthorized data (Closes: #797032).
+
+ -- Thomas Goirand <zigo@debian.org>  Tue, 15 Sep 2015 21:28:14 +0200
+
 swift (2.2.0-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru swift-2.2.0/debian/patches/CVE-2015-1856_Prevent-unauthorized-delete-in-versioned-container.patch swift-2.2.0/debian/patches/CVE-2015-1856_Prevent-unauthorized-delete-in-versioned-container.patch
--- swift-2.2.0/debian/patches/CVE-2015-1856_Prevent-unauthorized-delete-in-versioned-container.patch	1970-01-01 00:00:00.000000000 +0000
+++ swift-2.2.0/debian/patches/CVE-2015-1856_Prevent-unauthorized-delete-in-versioned-container.patch	2015-09-15 19:29:22.000000000 +0000
@@ -0,0 +1,242 @@
+Description: CVE-2015-1856: Prevent unauthorized delete in versioned container
+ An authenticated user can delete the most recent version of any versioned
+ object who's name is known if the user has listing access to the
+ x-versions-location container. Only Swift setups with allow_version setting
+ are affected.
+ .
+ This patch closes this bug, tracked as CVE-2015-1856.
+Author: Alistair Coles <alistair.coles@hp.com>
+Date: Fri, 3 Apr 2015 16:05:36 +0000 (+0100)
+X-Git-Url: https://review.openstack.org/gitweb?p=openstack%2Fswift.git;a=commitdiff_plain;h=85afe9316570855c87ea731d0627f6f8f2b73264
+Co-Authored-By: Clay Gerrard <clay.gerrard@gmail.com>
+Co-Authored-By: Christian Schwede <info@cschwede.de>
+Co-Authored-By: Alistair Coles <alistair.coles@hp.com>
+Bug-Ubuntu: https://bugs.launchpad.net/swift/+bug/1430645
+Change-Id: I74448c12bc4d4cd07d4300f452cf3dd6f66ca70a
+Bug-Debian: https://bugs.debian.org/783163
+
+diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py
+index abd4cc2..36c1058 100644
+--- a/swift/proxy/controllers/obj.py
++++ b/swift/proxy/controllers/obj.py
+@@ -783,6 +783,10 @@ class ObjectController(Controller):
+         req.acl = container_info['write_acl']
+         req.environ['swift_sync_key'] = container_info['sync_key']
+         object_versions = container_info['versions']
++        if 'swift.authorize' in req.environ:
++            aresp = req.environ['swift.authorize'](req)
++            if aresp:
++                return aresp
+         if object_versions:
+             # this is a version manifest and needs to be handled differently
+             object_versions = unquote(object_versions)
+@@ -853,11 +857,11 @@ class ObjectController(Controller):
+                 # remove 'X-If-Delete-At', since it is not for the older copy
+                 if 'X-If-Delete-At' in req.headers:
+                     del req.headers['X-If-Delete-At']
++                if 'swift.authorize' in req.environ:
++                    aresp = req.environ['swift.authorize'](req)
++                    if aresp:
++                        return aresp
+                 break
+-        if 'swift.authorize' in req.environ:
+-            aresp = req.environ['swift.authorize'](req)
+-            if aresp:
+-                return aresp
+         if not containers:
+             return HTTPNotFound(request=req)
+         partition, nodes = obj_ring.get_nodes(
+diff --git a/test/functional/tests.py b/test/functional/tests.py
+index d6b0b70..e57f22b 100644
+--- a/test/functional/tests.py
++++ b/test/functional/tests.py
+@@ -2397,6 +2397,14 @@ class TestObjectVersioningEnv(object):
+         cls.account = Account(cls.conn, tf.config.get('account',
+                                                       tf.config['username']))
+ 
++        # Second connection for ACL tests
++        config2 = deepcopy(tf.config)
++        config2['account'] = tf.config['account2']
++        config2['username'] = tf.config['username2']
++        config2['password'] = tf.config['password2']
++        cls.conn2 = Connection(config2)
++        cls.conn2.authenticate()
++
+         # avoid getting a prefix that stops halfway through an encoded
+         # character
+         prefix = Utils.create_name().decode("utf-8")[:10].encode("utf-8")
+@@ -2450,6 +2458,14 @@ class TestCrossPolicyObjectVersioningEnv(object):
+         cls.account = Account(cls.conn, tf.config.get('account',
+                                                       tf.config['username']))
+ 
++        # Second connection for ACL tests
++        config2 = deepcopy(tf.config)
++        config2['account'] = tf.config['account2']
++        config2['username'] = tf.config['username2']
++        config2['password'] = tf.config['password2']
++        cls.conn2 = Connection(config2)
++        cls.conn2.authenticate()
++
+         # avoid getting a prefix that stops halfway through an encoded
+         # character
+         prefix = Utils.create_name().decode("utf-8")[:10].encode("utf-8")
+@@ -2484,6 +2500,15 @@ class TestObjectVersioning(Base):
+                 "Expected versioning_enabled to be True/False, got %r" %
+                 (self.env.versioning_enabled,))
+ 
++    def tearDown(self):
++        super(TestObjectVersioning, self).tearDown()
++        try:
++            # delete versions first!
++            self.env.versions_container.delete_files()
++            self.env.container.delete_files()
++        except ResponseError:
++            pass
++
+     def test_overwriting(self):
+         container = self.env.container
+         versions_container = self.env.versions_container
+@@ -2515,6 +2540,33 @@ class TestObjectVersioning(Base):
+         versioned_obj.delete()
+         self.assertRaises(ResponseError, versioned_obj.read)
+ 
++    def test_versioning_check_acl(self):
++        container = self.env.container
++        versions_container = self.env.versions_container
++        versions_container.create(hdrs={'X-Container-Read': '.r:*,.rlistings'})
++
++        obj_name = Utils.create_name()
++        versioned_obj = container.file(obj_name)
++        versioned_obj.write("aaaaa")
++        self.assertEqual("aaaaa", versioned_obj.read())
++
++        versioned_obj.write("bbbbb")
++        self.assertEqual("bbbbb", versioned_obj.read())
++
++        # Use token from second account and try to delete the object
++        org_token = self.env.account.conn.storage_token
++        self.env.account.conn.storage_token = self.env.conn2.storage_token
++        try:
++            self.assertRaises(ResponseError, versioned_obj.delete)
++        finally:
++            self.env.account.conn.storage_token = org_token
++
++        # Verify with token from first account
++        self.assertEqual("bbbbb", versioned_obj.read())
++
++        versioned_obj.delete()
++        self.assertEqual("aaaaa", versioned_obj.read())
++
+ 
+ class TestObjectVersioningUTF8(Base2, TestObjectVersioning):
+     set_up = False
+diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py
+index b3b18a7..85ca553 100644
+--- a/test/unit/proxy/test_server.py
++++ b/test/unit/proxy/test_server.py
+@@ -56,7 +56,7 @@ from swift.proxy.controllers.base import get_container_memcache_key, \
+     get_account_memcache_key, cors_validation
+ import swift.proxy.controllers
+ from swift.common.swob import Request, Response, HTTPUnauthorized, \
+-    HTTPException
++    HTTPException, HTTPForbidden
+ from swift.common import storage_policy
+ from swift.common.storage_policy import StoragePolicy, \
+     StoragePolicyCollection, POLICIES
+@@ -1566,6 +1566,7 @@ class TestObjectController(unittest.TestCase):
+     ])
+     def test_DELETE_on_expired_versioned_object(self):
+         methods = set()
++        authorize_call_count = [0]
+ 
+         def test_connect(ipaddr, port, device, partition, method, path,
+                          headers=None, query_string=None):
+@@ -1591,6 +1592,10 @@ class TestObjectController(unittest.TestCase):
+             for obj in object_list:
+                 yield obj
+ 
++        def fake_authorize(req):
++            authorize_call_count[0] += 1
++            return None  # allow the request
++
+         with save_globals():
+             controller = proxy_server.ObjectController(self.app,
+                                                        'a', 'c', 'o')
+@@ -1602,7 +1607,8 @@ class TestObjectController(unittest.TestCase):
+                              204, 204, 204,  # delete for the pre-previous
+                              give_connect=test_connect)
+             req = Request.blank('/v1/a/c/o',
+-                                environ={'REQUEST_METHOD': 'DELETE'})
++                                environ={'REQUEST_METHOD': 'DELETE',
++                                         'swift.authorize': fake_authorize})
+ 
+             self.app.memcache.store = {}
+             self.app.update_request(req)
+@@ -1612,6 +1618,67 @@ class TestObjectController(unittest.TestCase):
+                            ('PUT', '/a/c/o'),
+                            ('DELETE', '/a/foo/2')]
+             self.assertEquals(set(exp_methods), (methods))
++            self.assertEquals(authorize_call_count[0], 2)
++
++    @patch_policies([
++        StoragePolicy(0, 'zero', False, object_ring=FakeRing()),
++        StoragePolicy(1, 'one', True, object_ring=FakeRing())
++    ])
++    def test_denied_DELETE_of_versioned_object(self):
++        """
++        Verify that a request with read access to a versions container
++        is unable to cause any write operations on the versioned container.
++        """
++        methods = set()
++        authorize_call_count = [0]
++
++        def test_connect(ipaddr, port, device, partition, method, path,
++                         headers=None, query_string=None):
++            methods.add((method, path))
++
++        def fake_container_info(account, container, req):
++            return {'status': 200, 'sync_key': None,
++                    'meta': {}, 'cors': {'allow_origin': None,
++                                         'expose_headers': None,
++                                         'max_age': None},
++                    'sysmeta': {}, 'read_acl': None, 'object_count': None,
++                    'write_acl': None, 'versions': 'foo',
++                    'partition': 1, 'bytes': None, 'storage_policy': '1',
++                    'nodes': [{'zone': 0, 'ip': '10.0.0.0', 'region': 0,
++                               'id': 0, 'device': 'sda', 'port': 1000},
++                              {'zone': 1, 'ip': '10.0.0.1', 'region': 1,
++                               'id': 1, 'device': 'sdb', 'port': 1001},
++                              {'zone': 2, 'ip': '10.0.0.2', 'region': 0,
++                               'id': 2, 'device': 'sdc', 'port': 1002}]}
++
++        def fake_list_iter(container, prefix, env):
++            object_list = [{'name': '1'}, {'name': '2'}, {'name': '3'}]
++            for obj in object_list:
++                yield obj
++
++        def fake_authorize(req):
++            # deny write access
++            authorize_call_count[0] += 1
++            return HTTPForbidden(req)  # allow the request
++
++        with save_globals():
++            controller = proxy_server.ObjectController(self.app,
++                                                       'a', 'c', 'o')
++            controller.container_info = fake_container_info
++            # patching _listing_iter simulates request being authorized
++            # to list versions container
++            controller._listing_iter = fake_list_iter
++            set_http_connect(give_connect=test_connect)
++            req = Request.blank('/v1/a/c/o',
++                                environ={'REQUEST_METHOD': 'DELETE',
++                                         'swift.authorize': fake_authorize})
++
++            self.app.memcache.store = {}
++            self.app.update_request(req)
++            resp = controller.DELETE(req)
++            self.assertEqual(403, resp.status_int)
++            self.assertFalse(methods, methods)
++            self.assertEquals(authorize_call_count[0], 1)
+ 
+     def test_PUT_auto_content_type(self):
+         with save_globals():
diff -Nru swift-2.2.0/debian/patches/CVE-2015-5223_Disallow-unsafe-tempurl-operations-to-point-to-unauthorized-data.patch swift-2.2.0/debian/patches/CVE-2015-5223_Disallow-unsafe-tempurl-operations-to-point-to-unauthorized-data.patch
--- swift-2.2.0/debian/patches/CVE-2015-5223_Disallow-unsafe-tempurl-operations-to-point-to-unauthorized-data.patch	1970-01-01 00:00:00.000000000 +0000
+++ swift-2.2.0/debian/patches/CVE-2015-5223_Disallow-unsafe-tempurl-operations-to-point-to-unauthorized-data.patch	2015-09-15 19:29:22.000000000 +0000
@@ -0,0 +1,182 @@
+From 0694e1911d10a18075ff99462c96781372422b2c Mon Sep 17 00:00:00 2001
+From: Clay Gerrard <clay.gerrard@gmail.com>
+Date: Thu, 23 Jul 2015 22:36:21 -0700
+Origin: upstream, https://review.openstack.org/#/c/217253/
+Subject: [PATCH] Disallow unsafe tempurl operations to point to unauthorized
+ data
+
+Do not allow PUT tempurls to create pointers to other data. Specifically
+disallow the creation of DLO object manifests by returning an error if a
+non-safe tempurl request includes an X-Object-Manifest header regardless of
+the value of the header.
+
+This prevents discoverability attacks which can use any PUT tempurl to probe
+for private data by creating a DLO object manifest and then using the PUT
+tempurl to head the object which would 404 if the prefix does not match any
+object data or form a valid DLO HEAD response if it does.
+
+This also prevents a tricky and potentially unexpected consequence of PUT
+tempurls which would make it unsafe to allow a user to download objects
+created by tempurl (even if they just created them) because the result of
+reading the object created via tempurl may not be the data which was uploaded.
+
+[CVE-2015-5223]
+
+Co-Authored-By: Kota Tsuyuzaki <tsuyuzaki.kota@lab.ntt.co.jp>
+
+Closes-Bug: 1453948
+
+Change-Id: I91161dfb0f089c3990aca1b4255b520299ef73c8
+---
+ swift/common/middleware/tempurl.py          | 31 ++++++++++++++++++++++++-
+ test/functional/tests.py                    | 36 +++++++++++++++++++++++++++++
+ test/unit/common/middleware/test_tempurl.py | 19 +++++++++++++++
+ 3 files changed, 85 insertions(+), 1 deletion(-)
+
+diff --git a/swift/common/middleware/tempurl.py b/swift/common/middleware/tempurl.py
+index c2381b3..1f94e8d 100644
+--- a/swift/common/middleware/tempurl.py
++++ b/swift/common/middleware/tempurl.py
+@@ -119,11 +119,13 @@ from urllib import urlencode
+ from urlparse import parse_qs
+ 
+ from swift.proxy.controllers.base import get_account_info
+-from swift.common.swob import HeaderKeyDict, HTTPUnauthorized
++from swift.common.swob import HeaderKeyDict, HTTPUnauthorized, HTTPBadRequest
+ from swift.common.utils import split_path, get_valid_utf8_str, \
+     register_swift_info, get_hmac, streq_const_time, quote
+ 
+ 
++DISALLOWED_INCOMING_HEADERS = 'x-object-manifest'
++
+ #: Default headers to remove from incoming requests. Simply a whitespace
+ #: delimited list of header names and names can optionally end with '*' to
+ #: indicate a prefix match. DEFAULT_INCOMING_ALLOW_HEADERS is a list of
+@@ -227,6 +229,10 @@ class TempURL(object):
+         #: The methods allowed with Temp URLs.
+         self.methods = methods
+ 
++        self.disallowed_headers = set(
++            'HTTP_' + h.upper().replace('-', '_')
++            for h in DISALLOWED_INCOMING_HEADERS.split())
++
+         headers = DEFAULT_INCOMING_REMOVE_HEADERS
+         if 'incoming_remove_headers' in conf:
+             headers = conf['incoming_remove_headers']
+@@ -320,6 +326,13 @@ class TempURL(object):
+                             for hmac in hmac_vals)
+         if not is_valid_hmac:
+             return self._invalid(env, start_response)
++        # disallowed headers prevent accidently allowing upload of a pointer
++        # to data that the PUT tempurl would not otherwise allow access for.
++        # It should be safe to provide a GET tempurl for data that an
++        # untrusted client just uploaded with a PUT tempurl.
++        resp = self._clean_disallowed_headers(env, start_response)
++        if resp:
++            return resp
+         self._clean_incoming_headers(env)
+         env['swift.authorize'] = lambda req: None
+         env['swift.authorize_override'] = True
+@@ -456,6 +469,22 @@ class TempURL(object):
+             body = '401 Unauthorized: Temp URL invalid\n'
+         return HTTPUnauthorized(body=body)(env, start_response)
+ 
++    def _clean_disallowed_headers(self, env, start_response):
++        """
++        Validate the absense of disallowed headers for "unsafe" operations.
++
++        :returns: None for safe operations or swob.HTTPBadResponse if the
++                  request includes disallowed headers.
++        """
++        if env['REQUEST_METHOD'] in ('GET', 'HEAD', 'OPTIONS'):
++            return
++        for h in env:
++            if h in self.disallowed_headers:
++                return HTTPBadRequest(
++                    body='The header %r is not allowed in this tempurl' %
++                    h[len('HTTP_'):].title().replace('_', '-'))(
++                        env, start_response)
++
+     def _clean_incoming_headers(self, env):
+         """
+         Removes any headers from the WSGI environment as per the
+diff --git a/test/functional/tests.py b/test/functional/tests.py
+index e57f22b..654949f 100644
+--- a/test/functional/tests.py
++++ b/test/functional/tests.py
+@@ -2687,6 +2687,42 @@ class TestTempurl(Base):
+         self.assert_(new_obj.info(parms=put_parms,
+                                   cfg={'no_auth_token': True}))
+ 
++    def test_PUT_manifest_access(self):
++        new_obj = self.env.container.file(Utils.create_name())
++
++        # give out a signature which allows a PUT to new_obj
++        expires = int(time.time()) + 86400
++        sig = self.tempurl_sig(
++            'PUT', expires, self.env.conn.make_path(new_obj.path),
++            self.env.tempurl_key)
++        put_parms = {'temp_url_sig': sig,
++                     'temp_url_expires': str(expires)}
++
++        # try to create manifest pointing to some random container
++        try:
++            new_obj.write('', {
++                'x-object-manifest': '%s/foo' % 'some_random_container'
++            }, parms=put_parms, cfg={'no_auth_token': True})
++        except ResponseError as e:
++            self.assertEqual(e.status, 400)
++        else:
++            self.fail('request did not error')
++
++        # create some other container
++        other_container = self.env.account.container(Utils.create_name())
++        if not other_container.create():
++            raise ResponseError(self.conn.response)
++
++        # try to create manifest pointing to new container
++        try:
++            new_obj.write('', {
++                'x-object-manifest': '%s/foo' % other_container
++            }, parms=put_parms, cfg={'no_auth_token': True})
++        except ResponseError as e:
++            self.assertEqual(e.status, 400)
++        else:
++            self.fail('request did not error')
++
+     def test_HEAD(self):
+         expires = int(time.time()) + 86400
+         sig = self.tempurl_sig(
+diff --git a/test/unit/common/middleware/test_tempurl.py b/test/unit/common/middleware/test_tempurl.py
+index 0581077..ffb3b98 100644
+--- a/test/unit/common/middleware/test_tempurl.py
++++ b/test/unit/common/middleware/test_tempurl.py
+@@ -623,6 +623,25 @@ class TestTempURL(unittest.TestCase):
+         self.assertTrue('Temp URL invalid' in resp.body)
+         self.assertTrue('Www-Authenticate' in resp.headers)
+ 
++    def test_disallowed_header_object_manifest(self):
++        self.tempurl = tempurl.filter_factory({})(self.auth)
++        method = 'PUT'
++        expires = int(time() + 86400)
++        path = '/v1/a/c/o'
++        key = 'abc'
++        hmac_body = '%s\n%s\n%s' % (method, expires, path)
++        sig = hmac.new(key, hmac_body, sha1).hexdigest()
++        req = self._make_request(
++            path, method='PUT', keys=[key],
++            headers={'x-object-manifest': 'private/secret'},
++            environ={'QUERY_STRING': 'temp_url_sig=%s&temp_url_expires=%s' % (
++                sig, expires)})
++        resp = req.get_response(self.tempurl)
++        self.assertEquals(resp.status_int, 400)
++        self.assertTrue('header' in resp.body)
++        self.assertTrue('not allowed' in resp.body)
++        self.assertTrue('X-Object-Manifest' in resp.body)
++
+     def test_removed_incoming_header(self):
+         self.tempurl = tempurl.filter_factory({
+             'incoming_remove_headers': 'x-remove-this'})(self.auth)
+-- 
+2.3.2 (Apple Git-55)
+
diff -Nru swift-2.2.0/debian/patches/series swift-2.2.0/debian/patches/series
--- swift-2.2.0/debian/patches/series	1970-01-01 00:00:00.000000000 +0000
+++ swift-2.2.0/debian/patches/series	2015-09-15 19:29:22.000000000 +0000
@@ -0,0 +1,2 @@
+CVE-2015-1856_Prevent-unauthorized-delete-in-versioned-container.patch
+CVE-2015-5223_Disallow-unsafe-tempurl-operations-to-point-to-unauthorized-data.patch
diff -Nru swift-2.2.0/debian/python-swift.postinst swift-2.2.0/debian/python-swift.postinst
--- swift-2.2.0/debian/python-swift.postinst	2014-10-16 12:48:43.000000000 +0000
+++ swift-2.2.0/debian/python-swift.postinst	2015-09-15 19:29:22.000000000 +0000
@@ -2,14 +2,34 @@
 
 set -e
 
-#DEBHELPER#
+pkgos_adduser () {
+	local VAR_UG_PKG_NAME
+	VAR_UG_PKG_NAME=${1}
+
+	# Create user and groups if they don't exist
+	if ! getent group ${VAR_UG_PKG_NAME} > /dev/null 2>&1 ; then
+		addgroup --quiet --system ${VAR_UG_PKG_NAME}
+	fi
+	if ! getent passwd ${VAR_UG_PKG_NAME} > /dev/null 2>&1 ; then
+		adduser --system \
+			--home /var/lib/${VAR_UG_PKG_NAME} \
+			--no-create-home \
+			--quiet \
+			--disabled-password \
+			--shell /bin/bash \
+			--group ${VAR_UG_PKG_NAME}
+	fi
+	usermod -G adm ${VAR_UG_PKG_NAME}
+}
 
-if ! getent passwd swift > /dev/null ; then
-  adduser --system --quiet --disabled-login --disabled-password --no-create-home --group --shell /bin/false swift
-fi
 
-usermod -G adm swift
+if [ "$1" = "configure" ] || [ "$1" = "reconfigure" ] ; then
+	pkgos_adduser swift
 
-chown swift:swift /var/cache/swift
+	mkdir -p /var/cache/swift
+	chown swift:swift /var/cache/swift
+fi
+
+#DEBHELPER#
 
 exit 0
diff -Nru swift-2.2.0/debian/python-swift.postrm swift-2.2.0/debian/python-swift.postrm
--- swift-2.2.0/debian/python-swift.postrm	2014-10-16 12:48:43.000000000 +0000
+++ swift-2.2.0/debian/python-swift.postrm	2015-09-15 19:29:22.000000000 +0000
@@ -2,18 +2,9 @@
 
 set -e
 
-case "$1" in
-    purge)
-        # Remove swift user if possible                                                                                                    
-        userdel swift || true
-    ;;
-    remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
-    ;;
-    *)
-        echo "postrm called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
+if [ "${1}" = "purge" ] ; then
+	rm -rf /var/cache/swift
+fi
 
 #DEBHELPER#                                                                                                                                
 
diff -Nru swift-2.2.0/debian/rules swift-2.2.0/debian/rules
--- swift-2.2.0/debian/rules	2014-10-16 12:48:43.000000000 +0000
+++ swift-2.2.0/debian/rules	2015-09-15 19:29:22.000000000 +0000
@@ -56,6 +56,7 @@
 	dh_installinit --no-start -pswift-container --name=swift-container-replicator
 	dh_installinit --no-start -pswift-container --name=swift-container-auditor
 	dh_installinit --no-start -pswift-container --name=swift-container-updater
+	dh_installinit --no-start -pswift-container --name=swift-container-sync
 	dh_installinit --no-start -pswift-account --name=swift-account-replicator
 	dh_installinit --no-start -pswift-account --name=swift-account-auditor
 	dh_installinit --no-start -pswift-account --name=swift-account-reaper
diff -Nru swift-2.2.0/debian/swift-container.swift-container-sync.init swift-2.2.0/debian/swift-container.swift-container-sync.init
--- swift-2.2.0/debian/swift-container.swift-container-sync.init	1970-01-01 00:00:00.000000000 +0000
+++ swift-2.2.0/debian/swift-container.swift-container-sync.init	2015-09-15 19:29:22.000000000 +0000
@@ -0,0 +1,57 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          swift-container-sync
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Swift container sync server
+# Description:       Container sync server for Swift.
+### END INIT INFO
+
+set -e
+
+SERVICE_NAME="container-sync"
+PRINT_NAME="container sync"
+
+. /lib/lsb/init-functions
+
+if ! [ -x /usr/bin/swift-init ] ; then
+	exit 0
+fi
+
+case "$1" in
+start)
+	log_daemon_msg "Starting Swift ${PRINT_NAME}" "swift-init ${SERVICE_NAME}"
+	/usr/bin/swift-init ${SERVICE_NAME} start
+	log_end_msg $?
+	exit $?
+;;
+stop)
+	log_daemon_msg "Stopping Swift ${PRINT_NAME}" "swift-init ${SERVICE_NAME}"
+	/usr/bin/swift-init ${SERVICE_NAME} stop
+	log_end_msg $?
+	exit $?
+;;
+restart)
+	log_daemon_msg "Restarting Swift ${PRINT_NAME}" "swift-init ${SERVICE_NAME}"
+	/usr/bin/swift-init ${SERVICE_NAME} restart
+	log_end_msg $?
+	exit $?
+;;
+reload|force-reload)
+	log_daemon_msg "Gracefully restarting Swift ${PRINT_NAME}" "swift-init ${SERVICE_NAME}"
+	/usr/bin/swift-init ${SERVICE_NAME} reload
+	log_end_msg $?
+	exit $?
+;;
+status)
+	exec /usr/bin/swift-init ${SERVICE_NAME} status
+;;
+*)
+	echo "Usage: $0 {start|stop|restart|reload}"
+	exit 1
+;;
+esac
+
+exit 0
diff -Nru swift-2.2.0/debian/swift-container.swift-container-sync.upstart.in swift-2.2.0/debian/swift-container.swift-container-sync.upstart.in
--- swift-2.2.0/debian/swift-container.swift-container-sync.upstart.in	1970-01-01 00:00:00.000000000 +0000
+++ swift-2.2.0/debian/swift-container.swift-container-sync.upstart.in	2015-09-15 19:29:22.000000000 +0000
@@ -0,0 +1,20 @@
+# swift-container-auditor - SWIFT Container Sync
+#
+# The swift container sync.
+
+description     "SWIFT Container Sync"
+author          "Marc Cluet <marc.cluet@ubuntu.com>"
+
+start on runlevel [2345]
+stop on runlevel [016]
+
+pre-start script
+  if [ -f "/etc/swift/container-server.conf" ]; then
+    exec /usr/bin/swift-init container-sync start
+  else
+    exit 1
+  fi
+end script
+
+post-stop exec /usr/bin/swift-init container-sync stop
+
diff -Nru swift-2.2.0/debian/swift-object-expirer.init swift-2.2.0/debian/swift-object-expirer.init
--- swift-2.2.0/debian/swift-object-expirer.init	2014-10-16 12:48:43.000000000 +0000
+++ swift-2.2.0/debian/swift-object-expirer.init	2015-09-15 19:29:22.000000000 +0000
@@ -9,7 +9,7 @@
 # Description:       Object expirer daemon for swift.
 ### END INIT INFO
 
-SERVICE_NAME="object-server-expirer"
+SERVICE_NAME="object-expirer"
 PRINT_NAME="object expirer daemon"
 
 . /lib/lsb/init-functions

--- End Message ---
--- Begin Message ---
Version: 8.3

Hi,

The updates referred to in these bugs were included in today's 8.3
Jessie point release.

Regards,

Adam

--- End Message ---

Reply to: