示例#1
0
static void test_ostream_file_random(void)
{
	struct ostream *output;
	string_t *path = t_str_new(128);
	char buf[MAX_BUFSIZE*4], buf2[MAX_BUFSIZE*4], randbuf[MAX_BUFSIZE];
	unsigned int i, offset, size;
	ssize_t ret;
	int fd;

	memset(buf, 0, sizeof(buf));
	fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
	if (fd == -1)
		i_fatal("safe_mkstemp(%s) failed: %m", str_c(path));
	if (unlink(str_c(path)) < 0)
		i_fatal("unlink(%s) failed: %m", str_c(path));
	output = o_stream_create_fd(fd, MAX_BUFSIZE, FALSE);
	o_stream_cork(output);

	size = (rand() % MAX_BUFSIZE) + 1;
	random_fill_weak(randbuf, size);
	memcpy(buf, randbuf, size);
	test_assert(o_stream_send(output, buf, size) > 0);

	for (i = 0; i < 10; i++) {
		offset = rand() % (MAX_BUFSIZE*3);
		size = (rand() % MAX_BUFSIZE) + 1;
		random_fill_weak(randbuf, size);
		memcpy(buf + offset, randbuf, size);
		test_assert(o_stream_pwrite(output, randbuf, size, offset) == 0);
		if (rand() % 10 == 0)
			test_assert(o_stream_flush(output) > 0);
	}

	test_assert(o_stream_flush(output) > 0);
	o_stream_uncork(output);
	ret = pread(fd, buf2, sizeof(buf2), 0);
	if (ret < 0)
		i_fatal("pread() failed: %m");
	else {
		i_assert(ret > 0);
		test_assert(memcmp(buf, buf2, ret) == 0);
	}
	o_stream_unref(&output);
	i_close_fd(&fd);
}
示例#2
0
static const char *unique_fname(void)
{
	unsigned char randbuf[8];

	random_fill_weak(randbuf, sizeof(randbuf));
	return t_strdup_printf("%s.%s.%s", my_hostname, my_pid,
			       binary_to_hex(randbuf, sizeof(randbuf)));

}
示例#3
0
safe_mkstemp_full(string_t *prefix, mode_t mode, uid_t uid, gid_t gid,
		  const char *gid_origin)
{
	size_t prefix_len;
	struct stat st;
	unsigned char randbuf[8];
	mode_t old_umask;
	int fd;

	prefix_len = str_len(prefix);
	for (;;) {
		do {
			random_fill_weak(randbuf, sizeof(randbuf));
			str_truncate(prefix, prefix_len);
			str_append(prefix,
				   binary_to_hex(randbuf, sizeof(randbuf)));
		} while (lstat(str_c(prefix), &st) == 0);

		if (errno != ENOENT) {
			i_error("stat(%s) failed: %m", str_c(prefix));
			str_truncate(prefix, prefix_len);
			return -1;
		}

		old_umask = umask(0666 ^ mode);
		fd = open(str_c(prefix), O_RDWR | O_EXCL | O_CREAT, 0666);
		umask(old_umask);
		if (fd != -1)
			break;

		if (errno != EEXIST) {
			if (errno != ENOENT && errno != EACCES)
				i_error("open(%s) failed: %m", str_c(prefix));
			str_truncate(prefix, prefix_len);
			return -1;
		}
	}
	if (uid == (uid_t)-1 && gid == (gid_t)-1)
		return fd;

	if (fchown(fd, uid, gid) < 0) {
		if (errno == EPERM) {
			i_error("%s", eperm_error_get_chgrp("fchown",
					str_c(prefix), gid, gid_origin));
		} else {
			i_error("fchown(%s, %ld, %ld) failed: %m",
				str_c(prefix),
				uid == (uid_t)-1 ? -1L : (long)uid,
				gid == (gid_t)-1 ? -1L : (long)gid);
		}
		i_close_fd(&fd);
		(void)unlink(str_c(prefix));
		return -1;
	}
	return fd;
}
示例#4
0
static
void test_write_read_v2(void)
{
	test_begin("test_write_read_v2");
	unsigned char payload[IO_BLOCK_SIZE*10];
	const unsigned char *ptr;
	size_t pos = 0, siz;
	random_fill_weak(payload, IO_BLOCK_SIZE*10);

	buffer_t *buf = buffer_create_dynamic(default_pool, sizeof(payload));
	struct ostream *os = o_stream_create_buffer(buf);
	struct ostream *os_2 = o_stream_create_encrypt(os, "aes-256-gcm-sha256", test_v1_kp.pub, IO_STREAM_ENC_INTEGRITY_AEAD);
	o_stream_nsend(os_2, payload, sizeof(payload));
	test_assert(o_stream_nfinish(os_2) == 0);
	if (os_2->stream_errno != 0)
		i_debug("error: %s", o_stream_get_error(os_2));

	o_stream_unref(&os);
	o_stream_unref(&os_2);

	struct istream *is = test_istream_create_data(buf->data, buf->used);
	/* test regression where read fails due to incorrect behaviour
	   when buffer is full before going to decrypt code */
	i_stream_set_max_buffer_size(is, 8192);
	i_stream_read(is);
	struct istream *is_2 = i_stream_create_decrypt(is, test_v1_kp.priv);

	size_t offset = 0;
	test_istream_set_size(is, 0);
	test_istream_set_allow_eof(is, FALSE);
	while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) {
		if (offset == buf->used)
			test_istream_set_allow_eof(is, TRUE);
		else
			test_istream_set_size(is, ++offset);

		test_assert_idx(pos + siz <= sizeof(payload), pos);
		if (pos + siz > sizeof(payload)) break;
		test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos);
		i_stream_skip(is_2, siz); pos += siz;
	}

	test_assert(is_2->stream_errno == 0);
	if (is_2->stream_errno != 0)
		i_debug("error: %s", i_stream_get_error(is_2));

	i_stream_unref(&is);
	i_stream_unref(&is_2);
	buffer_free(&buf);

	test_end();
}
示例#5
0
static
void test_write_read_v1_short(void)
{
	test_begin("test_write_read_v1_short");
	unsigned char payload[1];
	const unsigned char *ptr;
	size_t pos = 0, siz;
	random_fill_weak(payload, 1);

	buffer_t *buf = buffer_create_dynamic(default_pool, 64);
	struct ostream *os = o_stream_create_buffer(buf);
	struct ostream *os_2 = o_stream_create_encrypt(os, "<unused>", test_v2_kp.pub, IO_STREAM_ENC_VERSION_1);
	o_stream_nsend(os_2, payload, sizeof(payload));

	if (os_2->stream_errno != 0)
		i_debug("error: %s", o_stream_get_error(os_2));

	test_assert(os_2->stream_errno == 0);
	test_assert(o_stream_nfinish(os_2) == 0);
	test_assert(os_2->stream_errno == 0);

	o_stream_unref(&os);
	o_stream_unref(&os_2);

	struct istream *is = test_istream_create_data(buf->data, buf->used);
	struct istream *is_2 = i_stream_create_decrypt(is, test_v2_kp.priv);

	size_t offset = 0;
	test_istream_set_allow_eof(is, FALSE);
	test_istream_set_size(is, 0);
	while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) {
		if (offset == buf->used)
			test_istream_set_allow_eof(is, TRUE);
		else
			test_istream_set_size(is, ++offset);

		test_assert_idx(pos + siz <= sizeof(payload), pos);
		if (pos + siz > sizeof(payload)) break;
		test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos);
		i_stream_skip(is_2, siz); pos += siz;
	}

	test_assert(is_2->stream_errno == 0);

	i_stream_unref(&is);
	i_stream_unref(&is_2);
	buffer_free(&buf);

	test_end();
}
示例#6
0
static int
hardlink_replace(const char *src, const char *dest, ino_t src_inode)
{
	const char *p, *destdir, *tmppath;
	unsigned char randbuf[8];
	struct stat st;

	p = strrchr(dest, '/');
	i_assert(p != NULL);
	destdir = t_strdup_until(dest, p);

	random_fill_weak(randbuf, sizeof(randbuf));
	tmppath = t_strdup_printf("%s/temp.%s.%s.%s",
				  destdir, my_hostname, my_pid,
				  binary_to_hex(randbuf, sizeof(randbuf)));
	if (link(src, tmppath) < 0) {
		if (errno == EMLINK)
			return 0;
		i_error("link(%s, %s) failed: %m", src, tmppath);
		return -1;
	}
	if (stat(tmppath, &st) < 0) {
		i_error("stat(%s) failed: %m", tmppath);
		return -1;
	}
	if (st.st_ino != src_inode) {
		if (unlink(tmppath) < 0)
			i_error("unlink(%s) failed: %m", tmppath);
		return 0;
	}
	if (rename(tmppath, dest) < 0) {
		i_error("rename(%s, %s) failed: %m", src, tmppath);
		if (unlink(tmppath) < 0)
			i_error("unlink(%s) failed: %m", tmppath);
		return -1;
	}
	return 1;
}
示例#7
0
static void mbox_save_x_delivery_id(struct mbox_save_context *ctx)
{
	unsigned char md5_result[MD5_RESULTLEN];
	buffer_t *buf;
	string_t *str;
	void *randbuf;

	buf = buffer_create_dynamic(pool_datastack_create(), 256);
	buffer_append(buf, &ioloop_time, sizeof(ioloop_time));
	buffer_append(buf, &ioloop_timeval.tv_usec,
		      sizeof(ioloop_timeval.tv_usec));

	randbuf = buffer_append_space_unsafe(buf, MBOX_DELIVERY_ID_RAND_BYTES);
	random_fill_weak(randbuf, MBOX_DELIVERY_ID_RAND_BYTES);

	md5_get_digest(buf->data, buf->used, md5_result);

	str = t_str_new(128);
	str_append(str, "X-Delivery-ID: ");
	base64_encode(md5_result, sizeof(md5_result), str);
	str_append_c(str, '\n');

	ctx->x_delivery_id_header = i_strdup(str_c(str));
}
示例#8
0
static void test_compression_handler(const struct compression_handler *handler)
{
	const char *path = "test-compression.tmp";
	struct istream *file_input, *input;
	struct ostream *file_output, *output;
	unsigned char buf[IO_BLOCK_SIZE];
	const unsigned char *data;
	size_t size;
	struct sha1_ctxt sha1;
	unsigned char output_sha1[SHA1_RESULTLEN], input_sha1[SHA1_RESULTLEN];
	unsigned int i;
	int fd;
	ssize_t ret;

	test_begin(t_strdup_printf("compression handler %s", handler->name));

	/* write compressed data */
	fd = open(path, O_TRUNC | O_CREAT | O_RDWR, 0600);
	if (fd == -1)
		i_fatal("creat(%s) failed: %m", path);
	file_output = o_stream_create_fd_file(fd, 0, FALSE);
	output = handler->create_ostream(file_output, 1);
	sha1_init(&sha1);

	/* 1) write lots of easily compressible data */
	memset(buf, 0, sizeof(buf));
	for (i = 0; i < 1024*1024*4 / sizeof(buf); i++) {
		sha1_loop(&sha1, buf, sizeof(buf));
		test_assert(o_stream_send(output, buf, sizeof(buf)) == sizeof(buf));
	}

	/* 2) write uncompressible data */
	for (i = 0; i < 1024*128 / sizeof(buf); i++) {
		random_fill_weak(buf, sizeof(buf));
		sha1_loop(&sha1, buf, sizeof(buf));
		test_assert(o_stream_send(output, buf, sizeof(buf)) == sizeof(buf));
	}

	/* 3) write semi-compressible data */
	for (i = 0; i < sizeof(buf); i++) {
		if (rand () % 3 == 0)
			buf[i] = rand() % 4;
		else
			buf[i] = i;
	}
	for (i = 0; i < 1024*128 / sizeof(buf); i++) {
		sha1_loop(&sha1, buf, sizeof(buf));
		test_assert(o_stream_send(output, buf, sizeof(buf)) == sizeof(buf));
	}

	o_stream_destroy(&output);
	o_stream_destroy(&file_output);
	sha1_result(&sha1, output_sha1);

	/* read and uncompress the data */
	sha1_init(&sha1);
	file_input = i_stream_create_fd(fd, IO_BLOCK_SIZE, FALSE);
	input = handler->create_istream(file_input, FALSE);
	while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
		sha1_loop(&sha1, data, size);
		i_stream_skip(input, size);
	}
	test_assert(ret == -1);
	i_stream_destroy(&input);
	i_stream_destroy(&file_input);
	sha1_result(&sha1, input_sha1);

	test_assert(memcmp(input_sha1, output_sha1, sizeof(input_sha1)) == 0);
	if (unlink(path) < 0)
		i_error("unlink(%s) failed: %m", path);

	test_end();
}