int do_unpack(void) { struct file_header untrusted_hdr; #ifdef HAVE_SYNCFS int cwd_fd; int saved_errno; #endif total_bytes = total_files = 0; /* initialize checksum */ crc32_sum = 0; while (read_all_with_crc(0, &untrusted_hdr, sizeof untrusted_hdr)) { /* check for end of transfer marker */ if (untrusted_hdr.namelen == 0) { errno = 0; break; } total_files++; if (files_limit && total_files > files_limit) do_exit(EDQUOT, untrusted_namebuf); process_one_file(&untrusted_hdr); } #ifdef HAVE_SYNCFS saved_errno = errno; cwd_fd = open(".", O_RDONLY); if (cwd_fd >= 0 && syncfs(cwd_fd) == 0 && close(cwd_fd) == 0) errno = saved_errno; #endif send_status_and_crc(errno, untrusted_namebuf); return errno; }
void process_one_file_link(struct file_header *untrusted_hdr, const char *untrusted_name) { char untrusted_content[MAX_PATH_LENGTH]; unsigned int filelen; if (untrusted_hdr->filelen > MAX_PATH_LENGTH - 1) do_exit(ENAMETOOLONG, untrusted_name); filelen = untrusted_hdr->filelen; /* sanitized above */ total_bytes += filelen; if (bytes_limit && total_bytes > bytes_limit) do_exit(EDQUOT, untrusted_name); if (!read_all_with_crc(0, untrusted_content, filelen)) do_exit(LEGAL_EOF, untrusted_name); // hopefully remote has produced error message untrusted_content[filelen] = 0; if (symlink(untrusted_content, untrusted_name)) /* safe because of chroot */ do_exit(errno, untrusted_name); }
void process_one_file(struct file_header *untrusted_hdr) { unsigned int namelen; if (untrusted_hdr->namelen > MAX_PATH_LENGTH - 1) do_exit(ENAMETOOLONG, NULL); /* filename too long so not received at all */ namelen = untrusted_hdr->namelen; /* sanitized above */ if (!read_all_with_crc(0, untrusted_namebuf, namelen)) do_exit(LEGAL_EOF, NULL); // hopefully remote has produced error message untrusted_namebuf[namelen] = 0; if (S_ISREG(untrusted_hdr->mode)) process_one_file_reg(untrusted_hdr, untrusted_namebuf); else if (S_ISLNK(untrusted_hdr->mode)) process_one_file_link(untrusted_hdr, untrusted_namebuf); else if (S_ISDIR(untrusted_hdr->mode)) process_one_file_dir(untrusted_hdr, untrusted_namebuf); else do_exit(EINVAL, untrusted_namebuf); if (verbose && !S_ISDIR(untrusted_hdr->mode)) fprintf(stderr, "%s\n", untrusted_namebuf); }
int do_unpack(void) { struct file_header untrusted_hdr; total_bytes = total_files = 0; /* initialize checksum */ crc32_sum = 0; while (read_all_with_crc(0, &untrusted_hdr, sizeof untrusted_hdr)) { /* check for end of transfer marker */ if (untrusted_hdr.namelen == 0) { errno = 0; break; } total_files++; if (files_limit && total_files > files_limit) do_exit(EDQUOT, untrusted_namebuf); process_one_file(&untrusted_hdr); } send_status_and_crc(errno, untrusted_namebuf); return errno; }