test_write_disk_secure744.c revision 306941
1139823Simp/*-
211819Sjulian * Copyright (c) 2003-2007,2016 Tim Kientzle
311819Sjulian * All rights reserved.
411819Sjulian *
511819Sjulian * Redistribution and use in source and binary forms, with or without
611819Sjulian * modification, are permitted provided that the following conditions
711819Sjulian * are met:
811819Sjulian * 1. Redistributions of source code must retain the above copyright
911819Sjulian *    notice, this list of conditions and the following disclaimer.
1011819Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1111819Sjulian *    notice, this list of conditions and the following disclaimer in the
1211819Sjulian *    documentation and/or other materials provided with the distribution.
13165899Srwatson *
14165899Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15165899Srwatson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16165899Srwatson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17165899Srwatson * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18165899Srwatson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19165899Srwatson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20165899Srwatson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21165899Srwatson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22165899Srwatson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23165899Srwatson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24165899Srwatson */
25165899Srwatson#include "test.h"
26165899Srwatson__FBSDID("$FreeBSD: releng/10.3/contrib/libarchive/libarchive/test/test_write_disk_secure744.c 306941 2016-10-10 07:18:54Z delphij $");
27165899Srwatson
28165899Srwatson#define UMASK 022
29165899Srwatson
30165899Srwatson/*
31165899Srwatson * Github Issue #744 describes a bug in the sandboxing code that
32165899Srwatson * causes very long pathnames to not get checked for symlinks.
33165899Srwatson */
34165899Srwatson
35165899SrwatsonDEFINE_TEST(test_write_disk_secure744)
36165899Srwatson{
37165899Srwatson#if defined(_WIN32) && !defined(__CYGWIN__)
38165899Srwatson	skipping("archive_write_disk security checks not supported on Windows");
3911819Sjulian#else
4011819Sjulian	struct archive *a;
4111819Sjulian	struct archive_entry *ae;
4211819Sjulian	size_t buff_size = 8192;
4311819Sjulian	char *buff = malloc(buff_size);
4411819Sjulian	char *p = buff;
4511819Sjulian	int n = 0;
4611819Sjulian	int t;
4711819Sjulian
4811819Sjulian	assert(buff != NULL);
4911819Sjulian
5011819Sjulian	/* Start with a known umask. */
5111819Sjulian	assertUmask(UMASK);
5211819Sjulian
5311819Sjulian	/* Create an archive_write_disk object. */
5411819Sjulian	assert((a = archive_write_disk_new()) != NULL);
5511819Sjulian	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
5611819Sjulian
5711819Sjulian	while (p + 500 < buff + buff_size) {
5811819Sjulian		memset(p, 'x', 100);
5912057Sjulian		p += 100;
6011819Sjulian		p[0] = '\0';
6111819Sjulian
62116189Sobrien		buff[0] = ((n / 1000) % 10) + '0';
63116189Sobrien		buff[1] = ((n / 100) % 10)+ '0';
64116189Sobrien		buff[2] = ((n / 10) % 10)+ '0';
6511819Sjulian		buff[3] = ((n / 1) % 10)+ '0';
6611819Sjulian		buff[4] = '_';
6750519Sjhay		++n;
6811819Sjulian
6950519Sjhay		/* Create a symlink pointing to the testworkdir */
7025652Sjhay		assert((ae = archive_entry_new()) != NULL);
7111991Sjulian		archive_entry_copy_pathname(ae, buff);
7211819Sjulian		archive_entry_set_mode(ae, S_IFREG | 0777);
7350519Sjhay		archive_entry_copy_symlink(ae, testworkdir);
7411819Sjulian		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
7511819Sjulian		archive_entry_free(ae);
76169463Srwatson
77169463Srwatson		*p++ = '/';
7850519Sjhay		sprintf(p, "target%d", n);
79132779Skan
8050519Sjhay		/* Try to create a file through the symlink, should fail. */
8150519Sjhay		assert((ae = archive_entry_new()) != NULL);
8250519Sjhay		archive_entry_copy_pathname(ae, buff);
8311819Sjulian		archive_entry_set_mode(ae, S_IFDIR | 0777);
8450519Sjhay
8550519Sjhay		t = archive_write_header(a, ae);
8650519Sjhay		archive_entry_free(ae);
8711819Sjulian		failure("Attempt to create target%d via %d-character symlink should have failed", n, (int)strlen(buff));
8850519Sjhay		if(!assertEqualInt(ARCHIVE_FAILED, t)) {
8950519Sjhay			break;
9050519Sjhay		}
91132779Skan	}
9250519Sjhay	archive_free(a);
9350519Sjhay	free(buff);
9450519Sjhay#endif
9550519Sjhay}
9650519Sjhay/*-
9750519Sjhay * Copyright (c) 2003-2007,2016 Tim Kientzle
9850519Sjhay * All rights reserved.
9950519Sjhay *
10050519Sjhay * Redistribution and use in source and binary forms, with or without
10150519Sjhay * modification, are permitted provided that the following conditions
10250519Sjhay * are met:
10350519Sjhay * 1. Redistributions of source code must retain the above copyright
10450519Sjhay *    notice, this list of conditions and the following disclaimer.
10511819Sjulian * 2. Redistributions in binary form must reproduce the above copyright
10650519Sjhay *    notice, this list of conditions and the following disclaimer in the
10750519Sjhay *    documentation and/or other materials provided with the distribution.
10850519Sjhay *
10950519Sjhay * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
11050519Sjhay * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
11150519Sjhay * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
112132779Skan * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
11350519Sjhay * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
11450519Sjhay * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11550519Sjhay * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11650519Sjhay * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
11750519Sjhay * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
11811819Sjulian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11950519Sjhay */
12050519Sjhay#include "test.h"
12150519Sjhay__FBSDID("$FreeBSD: releng/10.3/contrib/libarchive/libarchive/test/test_write_disk_secure744.c 306941 2016-10-10 07:18:54Z delphij $");
122132779Skan
12350519Sjhay#define UMASK 022
124132779Skan
12550519Sjhay/*
126132779Skan * Github Issue #744 describes a bug in the sandboxing code that
12750519Sjhay * causes very long pathnames to not get checked for symlinks.
12850519Sjhay */
129139584Srwatson
13011819SjulianDEFINE_TEST(test_write_disk_secure744)
13150519Sjhay{
13250519Sjhay#if defined(_WIN32) && !defined(__CYGWIN__)
13350519Sjhay	skipping("archive_write_disk security checks not supported on Windows");
13450519Sjhay#else
13550519Sjhay	struct archive *a;
13650519Sjhay	struct archive_entry *ae;
13750519Sjhay	size_t buff_size = 8192;
13850519Sjhay	char *buff = malloc(buff_size);
13911819Sjulian	char *p = buff;
14011819Sjulian	int n = 0;
141	int t;
142
143	assert(buff != NULL);
144
145	/* Start with a known umask. */
146	assertUmask(UMASK);
147
148	/* Create an archive_write_disk object. */
149	assert((a = archive_write_disk_new()) != NULL);
150	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
151
152	while (p + 500 < buff + buff_size) {
153		memset(p, 'x', 100);
154		p += 100;
155		p[0] = '\0';
156
157		buff[0] = ((n / 1000) % 10) + '0';
158		buff[1] = ((n / 100) % 10)+ '0';
159		buff[2] = ((n / 10) % 10)+ '0';
160		buff[3] = ((n / 1) % 10)+ '0';
161		buff[4] = '_';
162		++n;
163
164		/* Create a symlink pointing to the testworkdir */
165		assert((ae = archive_entry_new()) != NULL);
166		archive_entry_copy_pathname(ae, buff);
167		archive_entry_set_mode(ae, S_IFREG | 0777);
168		archive_entry_copy_symlink(ae, testworkdir);
169		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
170		archive_entry_free(ae);
171
172		*p++ = '/';
173		sprintf(p, "target%d", n);
174
175		/* Try to create a file through the symlink, should fail. */
176		assert((ae = archive_entry_new()) != NULL);
177		archive_entry_copy_pathname(ae, buff);
178		archive_entry_set_mode(ae, S_IFDIR | 0777);
179
180		t = archive_write_header(a, ae);
181		archive_entry_free(ae);
182		failure("Attempt to create target%d via %d-character symlink should have failed", n, (int)strlen(buff));
183		if(!assertEqualInt(ARCHIVE_FAILED, t)) {
184			break;
185		}
186	}
187	archive_free(a);
188	free(buff);
189#endif
190}
191