Beispiel #1
0
void process_one_file_dir(struct file_header *untrusted_hdr,
			  const char *untrusted_name)
{
// fix perms only when the directory is sent for the second time
// it allows to transfer r.x directory contents, as we create it rwx initially
	struct stat buf;
	if (!mkdir(untrusted_name, 0700))	/* safe because of chroot */
		return;
	if (errno != EEXIST)
		do_exit(errno, untrusted_name);
	if (stat(untrusted_name,&buf) < 0)
		do_exit(errno, untrusted_name);
	total_bytes += buf.st_size;
	/* size accumulated after the fact, so don't check limit here */
	fix_times_and_perms(untrusted_hdr, untrusted_name);
}
Beispiel #2
0
void process_one_file_reg(struct file_header *untrusted_hdr,
			  const char *untrusted_name)
{
	int ret;
	int fdout = -1;

	/* make the file inaccessible until fully written */
	if (use_tmpfile) {
		fdout = open(".", O_WRONLY | O_TMPFILE, 0700);
		if (fdout < 0) {
		   if (errno==ENOENT)
			   /* if it fails, do not attempt further use - most likely kernel too old */
			   use_tmpfile = 0;
		   else
			   do_exit(errno, untrusted_name);
		}
	}
	if (fdout < 0)
		fdout = open(untrusted_name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0000);	/* safe because of chroot */
	if (fdout < 0)
		do_exit(errno, untrusted_name);
	/* sizes are signed elsewhere */
	if (untrusted_hdr->filelen > LLONG_MAX || (bytes_limit && untrusted_hdr->filelen > bytes_limit))
		do_exit(EDQUOT, untrusted_name);
	if (bytes_limit && total_bytes > bytes_limit - untrusted_hdr->filelen)
		do_exit(EDQUOT, untrusted_name);
	total_bytes += untrusted_hdr->filelen;
	ret = copy_file(fdout, 0, untrusted_hdr->filelen, &crc32_sum);
	if (ret != COPY_FILE_OK) {
		if (ret == COPY_FILE_READ_EOF
		    || ret == COPY_FILE_READ_ERROR)
			do_exit(LEGAL_EOF, untrusted_name);	// hopefully remote will produce error message
		else
			do_exit(errno, untrusted_name);
	}
	fdatasync(fdout);
	if (use_tmpfile) {
		char fd_str[7];
		snprintf(fd_str, sizeof(fd_str), "%d", fdout);
		if (linkat(procdir_fd, fd_str, AT_FDCWD, untrusted_name, AT_SYMLINK_FOLLOW) < 0)
			do_exit(errno, untrusted_name);
	}
	close(fdout);
	fix_times_and_perms(untrusted_hdr, untrusted_name);
}