def test_restore_restricted_user_group(): if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(prefix='bup-tmetadata-') try: path = tmpdir + '/foo' os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) WVPASSEQ(m.apply_to_path(path), None) orig_uid = m.uid m.uid = 0; m.apply_to_path(path, restore_numeric_ids=True) WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('lchown: ')) clear_errors() m.uid = orig_uid m.gid = 0; m.apply_to_path(path, restore_numeric_ids=True) WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('lchown: ') or os.stat(path).st_gid == m.gid) clear_errors() finally: subprocess.call(['rm', '-rf', tmpdir])
def test_apply_to_path_restricted_access(tmpdir): if is_superuser() or detect_fakeroot(): return if sys.platform.startswith('cygwin'): return # chmod 000 isn't effective. try: parent = tmpdir + b'/foo' path = parent + b'/bar' os.mkdir(parent) os.mkdir(path) clear_errors() if metadata.xattr: try: metadata.xattr.set(path, b'user.buptest', b'bup') except: print("failed to set test xattr") # ignore any failures here - maybe FS cannot do it pass m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(parent, 0o000) m.apply_to_path(path) print(b'saved_errors:', helpers.saved_errors, file=sys.stderr) expected_errors = ['utime: '] if m.linux_attr and _linux_attr_supported(tmpdir): expected_errors.append('Linux chattr: ') if metadata.xattr and m.linux_xattr: expected_errors.append("xattr.set ") WVPASS(len(helpers.saved_errors) == len(expected_errors)) for i in range(len(expected_errors)): assert str(helpers.saved_errors[i]).startswith(expected_errors[i]) finally: clear_errors()
def test_apply_to_path_restricted_access(): if is_superuser() or detect_fakeroot(): return if sys.platform.startswith('cygwin'): return # chmod 000 isn't effective. with no_lingering_errors(), test_tempdir('bup-tmetadata-') as tmpdir: parent = tmpdir + '/foo' path = parent + '/bar' os.mkdir(parent) os.mkdir(path) clear_errors() m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(parent, 000) m.apply_to_path(path) print >> sys.stderr, 'saved_errors:', helpers.saved_errors expected_errors = ['utime: '] if m.linux_attr and _linux_attr_supported(tmpdir): expected_errors.append('Linux chattr: ') if metadata.xattr and m.linux_xattr: expected_errors.append("xattr.set '") WVPASS(len(helpers.saved_errors) == len(expected_errors)) for i in xrange(len(expected_errors)): WVPASS(str(helpers.saved_errors[i]).startswith(expected_errors[i])) clear_errors()
def test_handling_of_incorrect_existing_linux_xattrs(): if not is_superuser() or detect_fakeroot(): WVMSG('skipping test -- not superuser') return setup_testfs() for f in glob.glob('testfs/*'): ex('rm', '-rf', f) path = 'testfs/foo' open(path, 'w').close() xattr.set(path, 'foo', 'bar', namespace=xattr.NS_USER) m = metadata.from_path(path, archive_path=path, save_symlinks=True) xattr.set(path, 'baz', 'bax', namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(xattr.list(path), ['user.foo']) WVPASSEQ(xattr.get(path, 'user.foo'), 'bar') xattr.set(path, 'foo', 'baz', namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(xattr.list(path), ['user.foo']) WVPASSEQ(xattr.get(path, 'user.foo'), 'bar') xattr.remove(path, 'foo', namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(xattr.list(path), ['user.foo']) WVPASSEQ(xattr.get(path, 'user.foo'), 'bar') os.chdir(start_dir) cleanup_testfs()
def test_apply_to_path_restricted_access(): initial_failures = wvfailure_count() if is_superuser() or detect_fakeroot(): return if sys.platform.startswith('cygwin'): return # chmod 000 isn't effective. tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tmetadata-') parent = tmpdir + '/foo' path = parent + '/bar' os.mkdir(parent) os.mkdir(path) clear_errors() m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(parent, 000) m.apply_to_path(path) print >> sys.stderr, helpers.saved_errors expected_errors = ['utime: '] if m.linux_attr and _linux_attr_supported(tmpdir): expected_errors.append('Linux chattr: ') if metadata.xattr and m.linux_xattr: expected_errors.append("xattr.set '") WVPASS(len(helpers.saved_errors) == len(expected_errors)) for i in xrange(len(expected_errors)): WVPASS(str(helpers.saved_errors[i]).startswith(expected_errors[i])) clear_errors() if wvfailure_count() == initial_failures: subprocess.call(['chmod', '-R', 'u+rwX', tmpdir]) subprocess.call(['rm', '-rf', tmpdir])
def test_handling_of_incorrect_existing_linux_xattrs(): if not is_superuser() or detect_fakeroot(): WVMSG("skipping test -- not superuser") return setup_testfs() for f in glob.glob("testfs/*"): ex("rm", "-rf", f) path = "testfs/foo" open(path, "w").close() xattr.set(path, "foo", "bar", namespace=xattr.NS_USER) m = metadata.from_path(path, archive_path=path, save_symlinks=True) xattr.set(path, "baz", "bax", namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(xattr.list(path), ["user.foo"]) WVPASSEQ(xattr.get(path, "user.foo"), "bar") xattr.set(path, "foo", "baz", namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(xattr.list(path), ["user.foo"]) WVPASSEQ(xattr.get(path, "user.foo"), "bar") xattr.remove(path, "foo", namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(xattr.list(path), ["user.foo"]) WVPASSEQ(xattr.get(path, "user.foo"), "bar") os.chdir(start_dir) cleanup_testfs()
def test_apply_to_path_restricted_access(): if is_superuser() or detect_fakeroot(): return if sys.platform.startswith("cygwin"): return # chmod 000 isn't effective. tmpdir = tempfile.mkdtemp(prefix="bup-tmetadata-") try: parent = tmpdir + "/foo" path = parent + "/bar" os.mkdir(parent) os.mkdir(path) clear_errors() m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(parent, 000) m.apply_to_path(path) print >>sys.stderr, helpers.saved_errors expected_errors = ["utime: "] if m.linux_attr and _linux_attr_supported(tmpdir): expected_errors.append("Linux chattr: ") if metadata.xattr and m.linux_xattr: expected_errors.append("xattr.set: ") WVPASS(len(helpers.saved_errors) == len(expected_errors)) for i in xrange(len(expected_errors)): WVPASS(str(helpers.saved_errors[i]).startswith(expected_errors[i])) clear_errors() finally: subprocess.call(["chmod", "-R", "u+rwX", tmpdir]) subprocess.call(["rm", "-rf", tmpdir])
def test_apply_to_path_restricted_access(): initial_failures = wvfailure_count() if is_superuser() or detect_fakeroot(): return if sys.platform.startswith('cygwin'): return # chmod 000 isn't effective. tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tmetadata-') parent = tmpdir + '/foo' path = parent + '/bar' os.mkdir(parent) os.mkdir(path) clear_errors() m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(parent, 000) m.apply_to_path(path) print >> sys.stderr, helpers.saved_errors expected_errors = ['utime: '] if m.linux_attr and _linux_attr_supported(tmpdir): expected_errors.append('Linux chattr: ') if metadata.xattr and m.linux_xattr: expected_errors.append('xattr.set: ') WVPASS(len(helpers.saved_errors) == len(expected_errors)) for i in xrange(len(expected_errors)): WVPASS(str(helpers.saved_errors[i]).startswith(expected_errors[i])) clear_errors() if wvfailure_count() == initial_failures: subprocess.call(['chmod', '-R', 'u+rwX', tmpdir]) subprocess.call(['rm', '-rf', tmpdir])
def test_handling_of_incorrect_existing_linux_xattrs(): if not is_superuser() or detect_fakeroot(): pytest.skip('skipping test -- not superuser') return if not setup_testfs(): pytest.skip('unable to load loop module; skipping dependent tests') return for f in glob.glob(b'testfs/*'): ex(b'rm', b'-rf', f) path = b'testfs/foo' open(path, 'w').close() xattr.set(path, b'foo', b'bar', namespace=xattr.NS_USER) m = metadata.from_path(path, archive_path=path, save_symlinks=True) xattr.set(path, b'baz', b'bax', namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(remove_selinux(xattr.list(path)), [b'user.foo']) WVPASSEQ(xattr.get(path, b'user.foo'), b'bar') xattr.set(path, b'foo', b'baz', namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(remove_selinux(xattr.list(path)), [b'user.foo']) WVPASSEQ(xattr.get(path, b'user.foo'), b'bar') xattr.remove(path, b'foo', namespace=xattr.NS_USER) m.apply_to_path(path, restore_numeric_ids=False) WVPASSEQ(remove_selinux(xattr.list(path)), [b'user.foo']) WVPASSEQ(xattr.get(path, b'user.foo'), b'bar') cleanup_testfs()
def test_from_path_error(tmpdir): if is_superuser() or detect_fakeroot(): return path = tmpdir + b'/foo' os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(path, 0o000) metadata.from_path(path, archive_path=path, save_symlinks=True) if metadata.get_linux_file_attr: print('saved_errors:', helpers.saved_errors, file=sys.stderr) WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('read Linux attr')) clear_errors()
def test_from_path_error(): if is_superuser() or detect_fakeroot(): return with no_lingering_errors(), test_tempdir('bup-tmetadata-') as tmpdir: path = tmpdir + '/foo' os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(path, 000) metadata.from_path(path, archive_path=path, save_symlinks=True) if metadata.get_linux_file_attr: print >> sys.stderr, 'saved_errors:', helpers.saved_errors WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('read Linux attr')) clear_errors()
def test_apply_to_path_restricted_access(): if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(prefix='bup-tmetadata-') try: path = tmpdir + '/foo' os.mkdir(path) clear_errors() m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(tmpdir, 000) m.apply_to_path(path) errmsg = _first_err() WVPASS(errmsg.startswith('utime: ')) clear_errors() finally: subprocess.call(['rm', '-rf', tmpdir])
def test_from_path_error(): if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(prefix='bup-tmetadata-') try: path = tmpdir + '/foo' os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(path, 000) metadata.from_path(path, archive_path=path, save_symlinks=True) if metadata.get_linux_file_attr: errmsg = _first_err() WVPASS(errmsg.startswith('read Linux attr')) clear_errors() finally: subprocess.call(['rm', '-rf', tmpdir])
def test_apply_to_path_restricted_access(): if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(prefix='bup-tmetadata-') try: path = tmpdir + '/foo' os.mkdir(path) clear_errors() m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(tmpdir, 000) m.apply_to_path(path) WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('utime: ')) clear_errors() finally: subprocess.call(['rm', '-rf', tmpdir])
def test_from_path_error(): if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(prefix='bup-tmetadata-') try: path = tmpdir + '/foo' os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(path, 000) metadata.from_path(path, archive_path=path, save_symlinks=True) if metadata.get_linux_file_attr: WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('read Linux attr')) clear_errors() finally: subprocess.call(['rm', '-rf', tmpdir])
def test_from_path_error(): if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(prefix="bup-tmetadata-") try: path = tmpdir + "/foo" os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(path, 000) metadata.from_path(path, archive_path=path, save_symlinks=True) if metadata.get_linux_file_attr: WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith("read Linux attr")) clear_errors() finally: subprocess.call(["chmod", "-R", "u+rwX", tmpdir]) subprocess.call(["rm", "-rf", tmpdir])
def test_from_path_error(): initial_failures = wvfailure_count() if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tmetadata-') path = tmpdir + '/foo' os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(path, 000) metadata.from_path(path, archive_path=path, save_symlinks=True) if metadata.get_linux_file_attr: WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('read Linux attr')) clear_errors() if wvfailure_count() == initial_failures: subprocess.call(['chmod', '-R', 'u+rwX', tmpdir]) subprocess.call(['rm', '-rf', tmpdir])
def test_from_path_error(): initial_failures = wvfailure_count() if is_superuser() or detect_fakeroot(): return tmpdir = tempfile.mkdtemp(dir=bup_tmp, prefix='bup-tmetadata-') path = tmpdir + '/foo' os.mkdir(path) m = metadata.from_path(path, archive_path=path, save_symlinks=True) WVPASSEQ(m.path, path) os.chmod(path, 000) metadata.from_path(path, archive_path=path, save_symlinks=True) if metadata.get_linux_file_attr: print >> sys.stderr, 'saved_errors:', helpers.saved_errors WVPASS(len(helpers.saved_errors) == 1) errmsg = _first_err() WVPASS(errmsg.startswith('read Linux attr')) clear_errors() if wvfailure_count() == initial_failures: subprocess.call(['chmod', '-R', 'u+rwX', tmpdir]) subprocess.call(['rm', '-rf', tmpdir])
else: raise else: try: utime(path, (self.atime, self.mtime)) except OSError, e: if e.errno == errno.EACCES: raise ApplyError("utime: %s" % e) else: raise # Implement tar/rsync-like semantics; see bup-restore(1). # FIXME: should we consider caching user/group name <-> id # mappings, getgroups(), etc.? uid = gid = -1 # By default, do nothing. if is_superuser(): uid = self.uid gid = self.gid if not restore_numeric_ids: if self.uid != 0 and self.user: entry = pwd_from_name(self.user) if entry: uid = entry.pw_uid if self.gid != 0 and self.group: entry = grp_from_name(self.group) if entry: gid = entry.gr_gid else: # not superuser - only consider changing the group/gid user_gids = os.getgroups() if self.gid in user_gids: gid = self.gid
def _apply_common_rec(self, path, restore_numeric_ids=False): if not self.mode: raise ApplyError('no metadata - cannot apply to ' + path_msg(path)) # FIXME: S_ISDOOR, S_IFMPB, S_IFCMP, S_IFNWK, ... see stat(2). # EACCES errors at this stage are fatal for the current path. if lutime and stat.S_ISLNK(self.mode): try: lutime(path, (self.atime, self.mtime)) except OSError as e: if e.errno == errno.EACCES: raise ApplyError('lutime: %s' % e) else: raise else: try: utime(path, (self.atime, self.mtime)) except OSError as e: if e.errno == errno.EACCES: raise ApplyError('utime: %s' % e) else: raise uid = gid = -1 # By default, do nothing. if is_superuser(): if self.uid is not None: uid = self.uid if self.gid is not None: gid = self.gid if not restore_numeric_ids: if self.uid != 0 and self.user: entry = pwd_from_name(self.user) if entry: uid = entry.pw_uid if self.gid != 0 and self.group: entry = grp_from_name(self.group) if entry: gid = entry.gr_gid else: # not superuser - only consider changing the group/gid user_gids = os.getgroups() if self.gid in user_gids: gid = self.gid if not restore_numeric_ids and self.gid != 0: # The grp might not exist on the local system. grps = filter(None, [grp_from_gid(x) for x in user_gids]) if self.group in [x.gr_name for x in grps]: g = grp_from_name(self.group) if g: gid = g.gr_gid if uid != -1 or gid != -1: try: os.lchown(path, uid, gid) except OSError as e: if e.errno == errno.EPERM: add_error('lchown: %s' % e) elif sys.platform.startswith('cygwin') \ and e.errno == errno.EINVAL: add_error('lchown: unknown uid/gid (%d/%d) for %s' % (uid, gid, path_msg(path))) else: raise if _have_lchmod: try: os.lchmod(path, stat.S_IMODE(self.mode)) except OSError as e: # - "Function not implemented" # - "Operation not supported" might be generated by glibc if e.errno in (errno.ENOSYS, errno.EOPNOTSUPP): pass else: raise elif not stat.S_ISLNK(self.mode): os.chmod(path, stat.S_IMODE(self.mode))
if e.errno == errno.EACCES: raise ApplyError('utime: %s' % e) else: raise # Don't try to restore owner unless we're root, and even # if asked, don't try to restore the owner or group if # it doesn't exist in the system db. uid = self.uid gid = self.gid if not restore_numeric_ids: if not self.owner: uid = -1 add_error('ignoring missing owner for "%s"\n' % path) else: if not is_superuser(): uid = -1 # Not root; assume we can't change owner. else: try: uid = pwd.getpwnam(self.owner)[2] except KeyError: uid = -1 fmt = 'ignoring unknown owner %s for "%s"\n' add_error(fmt % (self.owner, path)) if not self.group: gid = -1 add_error('ignoring missing group for "%s"\n' % path) else: try: gid = grp.getgrnam(self.group)[2] except KeyError:
if e.errno == errno.EACCES: raise ApplyError("utime: %s" % e) else: raise # Don't try to restore owner unless we're root, and even # if asked, don't try to restore the owner or group if # it doesn't exist in the system db. uid = self.uid gid = self.gid if not restore_numeric_ids: if not self.owner: uid = -1 add_error('ignoring missing owner for "%s"\n' % path) else: if not is_superuser(): uid = -1 # Not root; assume we can't change owner. else: try: uid = pwd.getpwnam(self.owner)[2] except KeyError: uid = -1 fmt = 'ignoring unknown owner %s for "%s"\n' add_error(fmt % (self.owner, path)) if not self.group: gid = -1 add_error('ignoring missing group for "%s"\n' % path) else: try: gid = grp.getgrnam(self.group)[2] except KeyError:
else: raise else: try: utime(path, (self.atime, self.mtime)) except OSError, e: if e.errno == errno.EACCES: raise ApplyError('utime: %s' % e) else: raise # Implement tar/rsync-like semantics; see bup-restore(1). # FIXME: should we consider caching user/group name <-> id # mappings, getgroups(), etc.? uid = gid = -1 # By default, do nothing. if is_superuser(): uid = self.uid gid = self.gid if not restore_numeric_ids: if self.uid != 0 and self.user: entry = pwd_from_name(self.user) if entry: uid = entry.pw_uid if self.gid != 0 and self.group: entry = grp_from_name(self.group) if entry: gid = entry.gr_gid else: # not superuser - only consider changing the group/gid user_gids = os.getgroups() if self.gid in user_gids: gid = self.gid
def _apply_common_rec(self, path, restore_numeric_ids=False): if not self.mode: raise ApplyError('no metadata - cannot apply to ' + path) # FIXME: S_ISDOOR, S_IFMPB, S_IFCMP, S_IFNWK, ... see stat(2). # EACCES errors at this stage are fatal for the current path. if lutime and stat.S_ISLNK(self.mode): try: lutime(path, (self.atime, self.mtime)) except OSError as e: if e.errno == errno.EACCES: raise ApplyError('lutime: %s' % e) else: raise else: try: utime(path, (self.atime, self.mtime)) except OSError as e: if e.errno == errno.EACCES: raise ApplyError('utime: %s' % e) else: raise uid = gid = -1 # By default, do nothing. if is_superuser(): uid = self.uid gid = self.gid if not restore_numeric_ids: if self.uid != 0 and self.user: entry = pwd_from_name(self.user) if entry: uid = entry.pw_uid if self.gid != 0 and self.group: entry = grp_from_name(self.group) if entry: gid = entry.gr_gid else: # not superuser - only consider changing the group/gid user_gids = os.getgroups() if self.gid in user_gids: gid = self.gid if not restore_numeric_ids and self.gid != 0: # The grp might not exist on the local system. grps = filter(None, [grp_from_gid(x) for x in user_gids]) if self.group in [x.gr_name for x in grps]: g = grp_from_name(self.group) if g: gid = g.gr_gid if uid != -1 or gid != -1: try: os.lchown(path, uid, gid) except OSError as e: if e.errno == errno.EPERM: add_error('lchown: %s' % e) elif sys.platform.startswith('cygwin') \ and e.errno == errno.EINVAL: add_error('lchown: unknown uid/gid (%d/%d) for %s' % (uid, gid, path)) else: raise if _have_lchmod: try: os.lchmod(path, stat.S_IMODE(self.mode)) except errno.ENOSYS: # Function not implemented pass elif not stat.S_ISLNK(self.mode): os.chmod(path, stat.S_IMODE(self.mode))