Blame libarchive/test/test_write_disk_perms.c

Packit 08bd4c
/*-
Packit 08bd4c
 * Copyright (c) 2003-2007 Tim Kientzle
Packit 08bd4c
 * All rights reserved.
Packit 08bd4c
 *
Packit 08bd4c
 * Redistribution and use in source and binary forms, with or without
Packit 08bd4c
 * modification, are permitted provided that the following conditions
Packit 08bd4c
 * are met:
Packit 08bd4c
 * 1. Redistributions of source code must retain the above copyright
Packit 08bd4c
 *    notice, this list of conditions and the following disclaimer.
Packit 08bd4c
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 08bd4c
 *    notice, this list of conditions and the following disclaimer in the
Packit 08bd4c
 *    documentation and/or other materials provided with the distribution.
Packit 08bd4c
 *
Packit 08bd4c
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
Packit 08bd4c
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit 08bd4c
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit 08bd4c
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit 08bd4c
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit 08bd4c
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 08bd4c
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 08bd4c
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 08bd4c
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit 08bd4c
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 08bd4c
 */
Packit 08bd4c
#include "test.h"
Packit 08bd4c
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_perms.c 201247 2009-12-30 05:59:21Z kientzle $");
Packit 08bd4c
Packit 08bd4c
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 08bd4c
Packit 08bd4c
#define UMASK 022
Packit 08bd4c
Packit 08bd4c
static long _default_gid = -1;
Packit 08bd4c
static long _invalid_gid = -1;
Packit 08bd4c
static long _alt_gid = -1;
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * To fully test SGID restores, we need three distinct GIDs to work
Packit 08bd4c
 * with:
Packit 08bd4c
 *    * the GID that files are created with by default (for the
Packit 08bd4c
 *      current user in the current directory)
Packit 08bd4c
 *    * An "alt gid" that this user can create files with
Packit 08bd4c
 *    * An "invalid gid" that this user is not permitted to create
Packit 08bd4c
 *      files with.
Packit 08bd4c
 * The second fails if this user doesn't belong to at least two groups;
Packit 08bd4c
 * the third fails if the current user is root.
Packit 08bd4c
 */
Packit 08bd4c
static void
Packit 08bd4c
searchgid(void)
Packit 08bd4c
{
Packit 08bd4c
	static int   _searched = 0;
Packit 08bd4c
	uid_t uid = getuid();
Packit 08bd4c
	gid_t gid = 0;
Packit 08bd4c
	unsigned int n;
Packit 08bd4c
	struct stat st;
Packit 08bd4c
	int fd;
Packit 08bd4c
Packit 08bd4c
	/* If we've already looked this up, we're done. */
Packit 08bd4c
	if (_searched)
Packit 08bd4c
		return;
Packit 08bd4c
	_searched = 1;
Packit 08bd4c
Packit 08bd4c
	/* Create a file on disk in the current default dir. */
Packit 08bd4c
	fd = open("test_gid", O_CREAT | O_BINARY, 0664);
Packit 08bd4c
	failure("Couldn't create a file for gid testing.");
Packit 08bd4c
	assert(fd > 0);
Packit 08bd4c
Packit 08bd4c
	/* See what GID it ended up with.  This is our "valid" GID. */
Packit 08bd4c
	assert(fstat(fd, &st) == 0);
Packit 08bd4c
	_default_gid = st.st_gid;
Packit 08bd4c
Packit 08bd4c
	/* Find a GID for which fchown() fails.  This is our "invalid" GID. */
Packit 08bd4c
	_invalid_gid = -1;
Packit 08bd4c
	/* This loop stops when we wrap the gid or examine 10,000 gids. */
Packit 08bd4c
	for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) {
Packit 08bd4c
		if (fchown(fd, uid, gid) != 0) {
Packit 08bd4c
			_invalid_gid = gid;
Packit 08bd4c
			break;
Packit 08bd4c
		}
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * Find a GID for which fchown() succeeds, but which isn't the
Packit 08bd4c
	 * default.  This is the "alternate" gid.
Packit 08bd4c
	 */
Packit 08bd4c
	_alt_gid = -1;
Packit 08bd4c
	for (gid = 0, n = 0; gid == n && n < 10000 ; n++, gid++) {
Packit 08bd4c
		/* _alt_gid must be different than _default_gid */
Packit 08bd4c
		if (gid == (gid_t)_default_gid)
Packit 08bd4c
			continue;
Packit 08bd4c
		if (fchown(fd, uid, gid) == 0) {
Packit 08bd4c
			_alt_gid = gid;
Packit 08bd4c
			break;
Packit 08bd4c
		}
Packit 08bd4c
	}
Packit 08bd4c
	close(fd);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static int
Packit 08bd4c
altgid(void)
Packit 08bd4c
{
Packit 08bd4c
	searchgid();
Packit 08bd4c
	return (_alt_gid);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static int
Packit 08bd4c
invalidgid(void)
Packit 08bd4c
{
Packit 08bd4c
	searchgid();
Packit 08bd4c
	return (_invalid_gid);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static int
Packit 08bd4c
defaultgid(void)
Packit 08bd4c
{
Packit 08bd4c
	searchgid();
Packit 08bd4c
	return (_default_gid);
Packit 08bd4c
}
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Exercise permission and ownership restores.
Packit 08bd4c
 * In particular, try to exercise a bunch of border cases related
Packit 08bd4c
 * to files/dirs that already exist, SUID/SGID bits, etc.
Packit 08bd4c
 */
Packit 08bd4c
Packit 08bd4c
DEFINE_TEST(test_write_disk_perms)
Packit 08bd4c
{
Packit 08bd4c
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit 08bd4c
	skipping("archive_write_disk interface");
Packit 08bd4c
#else
Packit 08bd4c
	struct archive *a;
Packit 08bd4c
	struct archive_entry *ae;
Packit 08bd4c
	struct stat st;
Packit 08bd4c
Packit 08bd4c
	assertUmask(UMASK);
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * Set ownership of the current directory to the group of this
Packit 08bd4c
	 * process.  Otherwise, the SGID tests below fail if the
Packit 08bd4c
	 * /tmp directory is owned by a group to which we don't belong
Packit 08bd4c
	 * and we're on a system where group ownership is inherited.
Packit 08bd4c
	 * (Because we're not allowed to SGID files with defaultgid().)
Packit 08bd4c
	 */
Packit 08bd4c
	assertEqualInt(0, chown(".", getuid(), getgid()));
Packit 08bd4c
Packit 08bd4c
	/* Create an archive_write_disk object. */
Packit 08bd4c
	assert((a = archive_write_disk_new()) != NULL);
Packit 08bd4c
Packit 08bd4c
	/* Write a regular file to it. */
Packit 08bd4c
	assert((ae = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_0755");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | 0777);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
	archive_entry_free(ae);
Packit 08bd4c
Packit 08bd4c
	/* Write a regular file, then write over it. */
Packit 08bd4c
	/* For files, the perms should get updated. */
Packit 08bd4c
	assert((ae = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_overwrite_0144");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | 0777);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	archive_entry_free(ae);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
	/* Check that file was created with different perms. */
Packit 08bd4c
	assertEqualInt(0, stat("file_overwrite_0144", &st);;
Packit 08bd4c
	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assert((st.st_mode & 07777) != 0144);
Packit 08bd4c
	/* Overwrite, this should change the perms. */
Packit 08bd4c
	assert((ae = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_overwrite_0144");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | 0144);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	archive_entry_free(ae);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
	/* Write a regular dir. */
Packit 08bd4c
	assert((ae = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "dir_0514");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFDIR | 0514);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	archive_entry_free(ae);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
	/* Overwrite an existing dir. */
Packit 08bd4c
	/* For dir, the first perms should get left. */
Packit 08bd4c
	assertMakeDir("dir_overwrite_0744", 0744);
Packit 08bd4c
	/* Check original perms. */
Packit 08bd4c
	assertEqualInt(0, stat("dir_overwrite_0744", &st);;
Packit 08bd4c
	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 0777, 0744);
Packit 08bd4c
	/* Overwrite shouldn't edit perms. */
Packit 08bd4c
	assert((ae = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "dir_overwrite_0744");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFDIR | 0777);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	archive_entry_free(ae);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
	/* Make sure they're unchanged. */
Packit 08bd4c
	assertEqualInt(0, stat("dir_overwrite_0744", &st);;
Packit 08bd4c
	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 0777, 0744);
Packit 08bd4c
Packit 08bd4c
	/* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */
Packit 08bd4c
	assert((ae = archive_entry_new()) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_no_suid");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777);
Packit 08bd4c
	archive_write_disk_set_options(a, 0);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
	/* Write a regular file with ARCHIVE_EXTRACT_PERM. */
Packit 08bd4c
	assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_0777");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | 0777);
Packit 08bd4c
	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */
Packit 08bd4c
	assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_4742");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
Packit 08bd4c
	archive_entry_set_uid(ae, getuid());
Packit 08bd4c
	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit,
Packit 08bd4c
	 * but wrong uid.  POSIX says you shouldn't restore SUID bit
Packit 08bd4c
	 * unless the UID could be restored.
Packit 08bd4c
	 */
Packit 08bd4c
	assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_bad_suid");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
Packit 08bd4c
	archive_entry_set_uid(ae, getuid() + 1);
Packit 08bd4c
	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
Packit 08bd4c
	assertA(0 == archive_write_header(a, ae));
Packit 08bd4c
	/*
Packit 08bd4c
	 * Because we didn't ask for owner, the failure to
Packit 08bd4c
	 * restore SUID shouldn't return a failure.
Packit 08bd4c
	 * We check below to make sure SUID really wasn't set.
Packit 08bd4c
	 * See more detailed comments below.
Packit 08bd4c
	 */
Packit 08bd4c
	failure("Opportunistic SUID failure shouldn't return error.");
Packit 08bd4c
	assertEqualInt(0, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
        if (getuid() != 0) {
Packit 08bd4c
		assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
		archive_entry_copy_pathname(ae, "file_bad_suid2");
Packit 08bd4c
		archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
Packit 08bd4c
		archive_entry_set_uid(ae, getuid() + 1);
Packit 08bd4c
		archive_write_disk_set_options(a,
Packit 08bd4c
		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
Packit 08bd4c
		assertA(0 == archive_write_header(a, ae));
Packit 08bd4c
		/* Owner change should fail here. */
Packit 08bd4c
		failure("Non-opportunistic SUID failure should return error.");
Packit 08bd4c
		assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a));
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
Packit 08bd4c
	assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
	archive_entry_copy_pathname(ae, "file_perm_sgid");
Packit 08bd4c
	archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
Packit 08bd4c
	archive_entry_set_gid(ae, defaultgid());
Packit 08bd4c
	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
Packit 08bd4c
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
	failure("Setting SGID bit should succeed here.");
Packit 08bd4c
	assertEqualIntA(a, 0, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
	if (altgid() == -1) {
Packit 08bd4c
		/*
Packit 08bd4c
		 * Current user must belong to at least two groups or
Packit 08bd4c
		 * else we can't test setting the GID to another group.
Packit 08bd4c
		 */
Packit 08bd4c
		skipping("Current user can't test gid restore: must belong to more than one group.");
Packit 08bd4c
	} else {
Packit 08bd4c
		/*
Packit 08bd4c
		 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit
Packit 08bd4c
		 * but without ARCHIVE_EXTRACT_OWNER.
Packit 08bd4c
		 */
Packit 08bd4c
		/*
Packit 08bd4c
		 * This is a weird case: The user has asked for permissions to
Packit 08bd4c
		 * be restored but not asked for ownership to be restored.  As
Packit 08bd4c
		 * a result, the default file creation will create a file with
Packit 08bd4c
		 * the wrong group.  There are several possible behaviors for
Packit 08bd4c
		 * libarchive in this scenario:
Packit 08bd4c
		 *  = Set the SGID bit.  It is wrong and a security hole to
Packit 08bd4c
		 *    set SGID with the wrong group.  Even POSIX thinks so.
Packit 08bd4c
		 *  = Implicitly set the group.  I don't like this.
Packit 08bd4c
		 *  = drop the SGID bit and warn (the old libarchive behavior)
Packit 08bd4c
		 *  = drop the SGID bit and don't warn (the current libarchive
Packit 08bd4c
		 *    behavior).
Packit 08bd4c
		 * The current behavior sees SGID/SUID restore when you
Packit 08bd4c
		 * don't ask for owner restore as an "opportunistic"
Packit 08bd4c
		 * action.  That is, libarchive should do it if it can,
Packit 08bd4c
		 * but if it can't, it's not an error.
Packit 08bd4c
		 */
Packit 08bd4c
		assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
		archive_entry_copy_pathname(ae, "file_alt_sgid");
Packit 08bd4c
		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
Packit 08bd4c
		archive_entry_set_uid(ae, getuid());
Packit 08bd4c
		archive_entry_set_gid(ae, altgid());
Packit 08bd4c
		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
Packit 08bd4c
		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
		failure("Setting SGID bit should fail because of group mismatch but the failure should be silent because we didn't ask for the group to be set.");
Packit 08bd4c
		assertEqualIntA(a, 0, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
		/*
Packit 08bd4c
		 * As above, but add _EXTRACT_OWNER to verify that it
Packit 08bd4c
		 * does succeed.
Packit 08bd4c
		 */
Packit 08bd4c
		assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
		archive_entry_copy_pathname(ae, "file_alt_sgid_owner");
Packit 08bd4c
		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
Packit 08bd4c
		archive_entry_set_uid(ae, getuid());
Packit 08bd4c
		archive_entry_set_gid(ae, altgid());
Packit 08bd4c
		archive_write_disk_set_options(a,
Packit 08bd4c
		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
Packit 08bd4c
		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
Packit 08bd4c
		failure("Setting SGID bit should succeed here.");
Packit 08bd4c
		assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/*
Packit 08bd4c
	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit,
Packit 08bd4c
	 * but wrong GID.  POSIX says you shouldn't restore SGID bit
Packit 08bd4c
	 * unless the GID could be restored.
Packit 08bd4c
	 */
Packit 08bd4c
	if (invalidgid() == -1) {
Packit 08bd4c
		/* This test always fails for root. */
Packit 08bd4c
		printf("Running as root: Can't test SGID failures.\n");
Packit 08bd4c
	} else {
Packit 08bd4c
		assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
		archive_entry_copy_pathname(ae, "file_bad_sgid");
Packit 08bd4c
		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
Packit 08bd4c
		archive_entry_set_gid(ae, invalidgid());
Packit 08bd4c
		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
Packit 08bd4c
		assertA(0 == archive_write_header(a, ae));
Packit 08bd4c
		failure("This SGID restore should fail without an error.");
Packit 08bd4c
		assertEqualIntA(a, 0, archive_write_finish_entry(a));
Packit 08bd4c
Packit 08bd4c
		assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
		archive_entry_copy_pathname(ae, "file_bad_sgid2");
Packit 08bd4c
		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
Packit 08bd4c
		archive_entry_set_gid(ae, invalidgid());
Packit 08bd4c
		archive_write_disk_set_options(a,
Packit 08bd4c
		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
Packit 08bd4c
		assertA(0 == archive_write_header(a, ae));
Packit 08bd4c
		failure("This SGID restore should fail with an error.");
Packit 08bd4c
		assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a));
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* Set ownership should fail if we're not root. */
Packit 08bd4c
	if (getuid() == 0) {
Packit 08bd4c
		printf("Running as root: Can't test setuid failures.\n");
Packit 08bd4c
	} else {
Packit 08bd4c
		assert(archive_entry_clear(ae) != NULL);
Packit 08bd4c
		archive_entry_copy_pathname(ae, "file_bad_owner");
Packit 08bd4c
		archive_entry_set_mode(ae, S_IFREG | 0744);
Packit 08bd4c
		archive_entry_set_uid(ae, getuid() + 1);
Packit 08bd4c
		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER);
Packit 08bd4c
		assertA(0 == archive_write_header(a, ae));
Packit 08bd4c
		assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a));
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
Packit 08bd4c
	archive_entry_free(ae);
Packit 08bd4c
Packit 08bd4c
	/* Test the entries on disk. */
Packit 08bd4c
	assertEqualInt(0, stat("file_0755", &st);;
Packit 08bd4c
	failure("file_0755: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, 0755);
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, stat("file_overwrite_0144", &st);;
Packit 08bd4c
	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, 0144);
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, stat("dir_0514", &st);;
Packit 08bd4c
	failure("dir_0514: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, 0514);
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, stat("dir_overwrite_0744", &st);;
Packit 08bd4c
	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 0777, 0744);
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, stat("file_no_suid", &st);;
Packit 08bd4c
	failure("file_0755: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, 0755);
Packit 08bd4c
Packit 08bd4c
	assertEqualInt(0, stat("file_0777", &st);;
Packit 08bd4c
	failure("file_0777: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, 0777);
Packit 08bd4c
Packit 08bd4c
	/* SUID bit should get set here. */
Packit 08bd4c
	assertEqualInt(0, stat("file_4742", &st);;
Packit 08bd4c
	failure("file_4742: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, S_ISUID | 0742);
Packit 08bd4c
Packit 08bd4c
	/* SUID bit should NOT have been set here. */
Packit 08bd4c
	assertEqualInt(0, stat("file_bad_suid", &st);;
Packit 08bd4c
	failure("file_bad_suid: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, 0742);
Packit 08bd4c
Packit 08bd4c
	/* Some things don't fail if you're root, so suppress this. */
Packit 08bd4c
	if (getuid() != 0) {
Packit 08bd4c
		/* SUID bit should NOT have been set here. */
Packit 08bd4c
		assertEqualInt(0, stat("file_bad_suid2", &st);;
Packit 08bd4c
		failure("file_bad_suid2: st.st_mode=%o", st.st_mode);
Packit 08bd4c
		assertEqualInt(st.st_mode & 07777, 0742);
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	/* SGID should be set here. */
Packit 08bd4c
	assertEqualInt(0, stat("file_perm_sgid", &st);;
Packit 08bd4c
	failure("file_perm_sgid: st.st_mode=%o", st.st_mode);
Packit 08bd4c
	assertEqualInt(st.st_mode & 07777, S_ISGID | 0742);
Packit 08bd4c
Packit 08bd4c
	if (altgid() != -1) {
Packit 08bd4c
		/* SGID should not be set here. */
Packit 08bd4c
		assertEqualInt(0, stat("file_alt_sgid", &st);;
Packit 08bd4c
		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
Packit 08bd4c
		assertEqualInt(st.st_mode & 07777, 0742);
Packit 08bd4c
Packit 08bd4c
		/* SGID should be set here. */
Packit 08bd4c
		assertEqualInt(0, stat("file_alt_sgid_owner", &st);;
Packit 08bd4c
		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
Packit 08bd4c
		assertEqualInt(st.st_mode & 07777, S_ISGID | 0742);
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	if (invalidgid() != -1) {
Packit 08bd4c
		/* SGID should NOT be set here. */
Packit 08bd4c
		assertEqualInt(0, stat("file_bad_sgid", &st);;
Packit 08bd4c
		failure("file_bad_sgid: st.st_mode=%o", st.st_mode);
Packit 08bd4c
		assertEqualInt(st.st_mode & 07777, 0742);
Packit 08bd4c
		/* SGID should NOT be set here. */
Packit 08bd4c
		assertEqualInt(0, stat("file_bad_sgid2", &st);;
Packit 08bd4c
		failure("file_bad_sgid2: st.st_mode=%o", st.st_mode);
Packit 08bd4c
		assertEqualInt(st.st_mode & 07777, 0742);
Packit 08bd4c
	}
Packit 08bd4c
Packit 08bd4c
	if (getuid() != 0) {
Packit 08bd4c
		assertEqualInt(0, stat("file_bad_owner", &st);;
Packit 08bd4c
		failure("file_bad_owner: st.st_mode=%o", st.st_mode);
Packit 08bd4c
		assertEqualInt(st.st_mode & 07777, 0744);
Packit 08bd4c
		failure("file_bad_owner: st.st_uid=%d getuid()=%d",
Packit 08bd4c
		    st.st_uid, getuid());
Packit 08bd4c
		/* The entry had getuid()+1, but because we're
Packit 08bd4c
		 * not root, we should not have been able to set that. */
Packit 08bd4c
		assertEqualInt(st.st_uid, getuid());
Packit 08bd4c
	}
Packit 08bd4c
#endif
Packit 08bd4c
}