1228753Smm/*- 2228753Smm * Copyright (c) 2008 Anselm Strauss 3228753Smm * Copyright (c) 2009 Joerg Sonnenberger 4302001Smm * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA 5228753Smm * All rights reserved. 6228753Smm * 7228753Smm * Redistribution and use in source and binary forms, with or without 8228753Smm * modification, are permitted provided that the following conditions 9228753Smm * are met: 10228753Smm * 1. Redistributions of source code must retain the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer. 12228753Smm * 2. Redistributions in binary form must reproduce the above copyright 13228753Smm * notice, this list of conditions and the following disclaimer in the 14228753Smm * documentation and/or other materials provided with the distribution. 15228753Smm * 16228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26228753Smm */ 27228753Smm 28228753Smm/* 29228753Smm * Development supported by Google Summer of Code 2008. 30228753Smm */ 31228753Smm 32228753Smm#include "archive_platform.h" 33228763Smm__FBSDID("$FreeBSD: stable/10/contrib/libarchive/libarchive/archive_write_set_format_zip.c 368708 2020-12-16 22:25:40Z mm $"); 34228753Smm 35228753Smm#ifdef HAVE_ERRNO_H 36228753Smm#include <errno.h> 37228753Smm#endif 38232153Smm#ifdef HAVE_LANGINFO_H 39232153Smm#include <langinfo.h> 40232153Smm#endif 41228753Smm#ifdef HAVE_STDLIB_H 42228753Smm#include <stdlib.h> 43228753Smm#endif 44228753Smm#ifdef HAVE_STRING_H 45228753Smm#include <string.h> 46228753Smm#endif 47228753Smm#ifdef HAVE_ZLIB_H 48228753Smm#include <zlib.h> 49228753Smm#endif 50228753Smm 51228753Smm#include "archive.h" 52302001Smm#include "archive_cryptor_private.h" 53228753Smm#include "archive_endian.h" 54228753Smm#include "archive_entry.h" 55232153Smm#include "archive_entry_locale.h" 56302001Smm#include "archive_hmac_private.h" 57228753Smm#include "archive_private.h" 58302001Smm#include "archive_random_private.h" 59228753Smm#include "archive_write_private.h" 60358090Smm#include "archive_write_set_format_private.h" 61228753Smm 62228753Smm#ifndef HAVE_ZLIB_H 63228753Smm#include "archive_crc32.h" 64228753Smm#endif 65228753Smm 66302001Smm#define ZIP_ENTRY_FLAG_ENCRYPTED (1<<0) 67302001Smm#define ZIP_ENTRY_FLAG_LENGTH_AT_END (1<<3) 68302001Smm#define ZIP_ENTRY_FLAG_UTF8_NAME (1 << 11) 69228753Smm 70302001Smm#define ZIP_4GB_MAX ARCHIVE_LITERAL_LL(0xffffffff) 71302001Smm#define ZIP_4GB_MAX_UNCOMPRESSED ARCHIVE_LITERAL_LL(0xff000000) 72302001Smm 73228753Smmenum compression { 74302001Smm COMPRESSION_UNSPECIFIED = -1, 75302001Smm COMPRESSION_STORE = 0, 76302001Smm COMPRESSION_DEFLATE = 8 77302001Smm}; 78302001Smm 79228753Smm#ifdef HAVE_ZLIB_H 80302001Smm#define COMPRESSION_DEFAULT COMPRESSION_DEFLATE 81302001Smm#else 82302001Smm#define COMPRESSION_DEFAULT COMPRESSION_STORE 83228753Smm#endif 84302001Smm 85302001Smmenum encryption { 86302001Smm ENCRYPTION_NONE = 0, 87302001Smm ENCRYPTION_TRADITIONAL, /* Traditional PKWARE encryption. */ 88302001Smm ENCRYPTION_WINZIP_AES128, /* WinZIP AES-128 encryption. */ 89302001Smm ENCRYPTION_WINZIP_AES256, /* WinZIP AES-256 encryption. */ 90228753Smm}; 91228753Smm 92302001Smm#define TRAD_HEADER_SIZE 12 93302001Smm/* 94302001Smm * See "WinZip - AES Encryption Information" 95302001Smm * http://www.winzip.com/aes_info.htm 96302001Smm */ 97302001Smm/* Value used in compression method. */ 98302001Smm#define WINZIP_AES_ENCRYPTION 99 99302001Smm/* A WinZip AES header size which is stored at the beginning of 100302001Smm * file contents. */ 101302001Smm#define WINZIP_AES128_HEADER_SIZE (8 + 2) 102302001Smm#define WINZIP_AES256_HEADER_SIZE (16 + 2) 103302001Smm/* AES vendor version. */ 104302001Smm#define AES_VENDOR_AE_1 0x0001 105302001Smm#define AES_VENDOR_AE_2 0x0002 106302001Smm/* Authentication code size. */ 107302001Smm#define AUTH_CODE_SIZE 10 108302001Smm/**/ 109302001Smm#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2) 110302001Smm 111302001Smmstruct cd_segment { 112302001Smm struct cd_segment *next; 113302001Smm size_t buff_size; 114302001Smm unsigned char *buff; 115302001Smm unsigned char *p; 116302001Smm}; 117302001Smm 118302001Smmstruct trad_enc_ctx { 119302001Smm uint32_t keys[3]; 120302001Smm}; 121302001Smm 122302001Smmstruct zip { 123302001Smm 124302001Smm int64_t entry_offset; 125302001Smm int64_t entry_compressed_size; 126302001Smm int64_t entry_uncompressed_size; 127302001Smm int64_t entry_compressed_written; 128302001Smm int64_t entry_uncompressed_written; 129302001Smm int64_t entry_uncompressed_limit; 130302001Smm struct archive_entry *entry; 131302001Smm uint32_t entry_crc32; 132302001Smm enum compression entry_compression; 133302001Smm enum encryption entry_encryption; 134302001Smm int entry_flags; 135302001Smm int entry_uses_zip64; 136302001Smm int experiments; 137302001Smm struct trad_enc_ctx tctx; 138302001Smm char tctx_valid; 139302001Smm unsigned char trad_chkdat; 140302001Smm unsigned aes_vendor; 141302001Smm archive_crypto_ctx cctx; 142302001Smm char cctx_valid; 143302001Smm archive_hmac_sha1_ctx hctx; 144302001Smm char hctx_valid; 145302001Smm 146302001Smm unsigned char *file_header; 147302001Smm size_t file_header_extra_offset; 148302001Smm unsigned long (*crc32func)(unsigned long crc, const void *buff, size_t len); 149302001Smm 150302001Smm struct cd_segment *central_directory; 151302001Smm struct cd_segment *central_directory_last; 152302001Smm size_t central_directory_bytes; 153302001Smm size_t central_directory_entries; 154302001Smm 155302001Smm int64_t written_bytes; /* Overall position in file. */ 156302001Smm 157302001Smm struct archive_string_conv *opt_sconv; 158302001Smm struct archive_string_conv *sconv_default; 159302001Smm enum compression requested_compression; 160302001Smm int deflate_compression_level; 161302001Smm int init_default_conversion; 162302001Smm enum encryption encryption_type; 163302001Smm 164302001Smm#define ZIP_FLAG_AVOID_ZIP64 1 165302001Smm#define ZIP_FLAG_FORCE_ZIP64 2 166302001Smm#define ZIP_FLAG_EXPERIMENT_xl 4 167302001Smm int flags; 168302001Smm 169302001Smm#ifdef HAVE_ZLIB_H 170302001Smm z_stream stream; 171302001Smm#endif 172302001Smm size_t len_buf; 173302001Smm unsigned char *buf; 174302001Smm}; 175302001Smm 176302001Smm/* Don't call this min or MIN, since those are already defined 177302001Smm on lots of platforms (but not all). */ 178302001Smm#define zipmin(a, b) ((a) > (b) ? (b) : (a)) 179302001Smm 180232153Smmstatic ssize_t archive_write_zip_data(struct archive_write *, 181232153Smm const void *buff, size_t s); 182232153Smmstatic int archive_write_zip_close(struct archive_write *); 183232153Smmstatic int archive_write_zip_free(struct archive_write *); 184228753Smmstatic int archive_write_zip_finish_entry(struct archive_write *); 185232153Smmstatic int archive_write_zip_header(struct archive_write *, 186232153Smm struct archive_entry *); 187232153Smmstatic int archive_write_zip_options(struct archive_write *, 188232153Smm const char *, const char *); 189228753Smmstatic unsigned int dos_time(const time_t); 190228753Smmstatic size_t path_length(struct archive_entry *); 191228753Smmstatic int write_path(struct archive_entry *, struct archive_write *); 192302001Smmstatic void copy_path(struct archive_entry *, unsigned char *); 193302001Smmstatic struct archive_string_conv *get_sconv(struct archive_write *, struct zip *); 194302001Smmstatic int trad_enc_init(struct trad_enc_ctx *, const char *, size_t); 195302001Smmstatic unsigned trad_enc_encrypt_update(struct trad_enc_ctx *, const uint8_t *, 196302001Smm size_t, uint8_t *, size_t); 197302001Smmstatic int init_traditional_pkware_encryption(struct archive_write *); 198302001Smmstatic int is_traditional_pkware_encryption_supported(void); 199302001Smmstatic int init_winzip_aes_encryption(struct archive_write *); 200302001Smmstatic int is_winzip_aes_encryption_supported(int encryption); 201228753Smm 202302001Smmstatic unsigned char * 203302001Smmcd_alloc(struct zip *zip, size_t length) 204302001Smm{ 205302001Smm unsigned char *p; 206228753Smm 207302001Smm if (zip->central_directory == NULL 208302001Smm || (zip->central_directory_last->p + length 209302001Smm > zip->central_directory_last->buff + zip->central_directory_last->buff_size)) { 210302001Smm struct cd_segment *segment = calloc(1, sizeof(*segment)); 211302001Smm if (segment == NULL) 212302001Smm return NULL; 213302001Smm segment->buff_size = 64 * 1024; 214302001Smm segment->buff = malloc(segment->buff_size); 215302001Smm if (segment->buff == NULL) { 216302001Smm free(segment); 217302001Smm return NULL; 218302001Smm } 219302001Smm segment->p = segment->buff; 220228753Smm 221302001Smm if (zip->central_directory == NULL) { 222302001Smm zip->central_directory 223302001Smm = zip->central_directory_last 224302001Smm = segment; 225302001Smm } else { 226302001Smm zip->central_directory_last->next = segment; 227302001Smm zip->central_directory_last = segment; 228302001Smm } 229302001Smm } 230228753Smm 231302001Smm p = zip->central_directory_last->p; 232302001Smm zip->central_directory_last->p += length; 233302001Smm zip->central_directory_bytes += length; 234302001Smm return (p); 235302001Smm} 236228753Smm 237302001Smmstatic unsigned long 238302001Smmreal_crc32(unsigned long crc, const void *buff, size_t len) 239302001Smm{ 240302001Smm return crc32(crc, buff, (unsigned int)len); 241302001Smm} 242228753Smm 243302001Smmstatic unsigned long 244302001Smmfake_crc32(unsigned long crc, const void *buff, size_t len) 245302001Smm{ 246302001Smm (void)crc; /* UNUSED */ 247302001Smm (void)buff; /* UNUSED */ 248302001Smm (void)len; /* UNUSED */ 249302001Smm return 0; 250302001Smm} 251238856Smm 252228753Smmstatic int 253228753Smmarchive_write_zip_options(struct archive_write *a, const char *key, 254232153Smm const char *val) 255228753Smm{ 256228753Smm struct zip *zip = a->format_data; 257232153Smm int ret = ARCHIVE_FAILED; 258228753Smm 259228753Smm if (strcmp(key, "compression") == 0) { 260302001Smm /* 261302001Smm * Set compression to use on all future entries. 262302001Smm * This only affects regular files. 263302001Smm */ 264232153Smm if (val == NULL || val[0] == 0) { 265232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 266232153Smm "%s: compression option needs a compression name", 267232153Smm a->format_name); 268232153Smm } else if (strcmp(val, "deflate") == 0) { 269228753Smm#ifdef HAVE_ZLIB_H 270302001Smm zip->requested_compression = COMPRESSION_DEFLATE; 271232153Smm ret = ARCHIVE_OK; 272228753Smm#else 273228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 274228753Smm "deflate compression not supported"); 275228753Smm#endif 276232153Smm } else if (strcmp(val, "store") == 0) { 277302001Smm zip->requested_compression = COMPRESSION_STORE; 278232153Smm ret = ARCHIVE_OK; 279232153Smm } 280232153Smm return (ret); 281302001Smm } else if (strcmp(key, "compression-level") == 0) { 282302001Smm if (val == NULL || !(val[0] >= '0' && val[0] <= '9') || val[1] != '\0') { 283302001Smm return ARCHIVE_WARN; 284302001Smm } 285302001Smm 286302001Smm if (val[0] == '0') { 287302001Smm zip->requested_compression = COMPRESSION_STORE; 288302001Smm return ARCHIVE_OK; 289302001Smm } else { 290302001Smm#ifdef HAVE_ZLIB_H 291302001Smm zip->requested_compression = COMPRESSION_DEFLATE; 292302001Smm zip->deflate_compression_level = val[0] - '0'; 293302001Smm return ARCHIVE_OK; 294302001Smm#else 295302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 296302001Smm "deflate compression not supported"); 297302001Smm#endif 298302001Smm } 299302001Smm } else if (strcmp(key, "encryption") == 0) { 300302001Smm if (val == NULL) { 301302001Smm zip->encryption_type = ENCRYPTION_NONE; 302302001Smm ret = ARCHIVE_OK; 303302001Smm } else if (val[0] == '1' || strcmp(val, "traditional") == 0 304302001Smm || strcmp(val, "zipcrypt") == 0 305302001Smm || strcmp(val, "ZipCrypt") == 0) { 306302001Smm if (is_traditional_pkware_encryption_supported()) { 307302001Smm zip->encryption_type = ENCRYPTION_TRADITIONAL; 308302001Smm ret = ARCHIVE_OK; 309302001Smm } else { 310302001Smm archive_set_error(&a->archive, 311302001Smm ARCHIVE_ERRNO_MISC, 312302001Smm "encryption not supported"); 313302001Smm } 314302001Smm } else if (strcmp(val, "aes128") == 0) { 315302001Smm if (is_winzip_aes_encryption_supported( 316302001Smm ENCRYPTION_WINZIP_AES128)) { 317302001Smm zip->encryption_type = ENCRYPTION_WINZIP_AES128; 318302001Smm ret = ARCHIVE_OK; 319302001Smm } else { 320302001Smm archive_set_error(&a->archive, 321302001Smm ARCHIVE_ERRNO_MISC, 322302001Smm "encryption not supported"); 323302001Smm } 324302001Smm } else if (strcmp(val, "aes256") == 0) { 325302001Smm if (is_winzip_aes_encryption_supported( 326302001Smm ENCRYPTION_WINZIP_AES256)) { 327302001Smm zip->encryption_type = ENCRYPTION_WINZIP_AES256; 328302001Smm ret = ARCHIVE_OK; 329302001Smm } else { 330302001Smm archive_set_error(&a->archive, 331302001Smm ARCHIVE_ERRNO_MISC, 332302001Smm "encryption not supported"); 333302001Smm } 334302001Smm } else { 335302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 336302001Smm "%s: unknown encryption '%s'", 337302001Smm a->format_name, val); 338302001Smm } 339302001Smm return (ret); 340302001Smm } else if (strcmp(key, "experimental") == 0) { 341302001Smm if (val == NULL || val[0] == 0) { 342302001Smm zip->flags &= ~ ZIP_FLAG_EXPERIMENT_xl; 343302001Smm } else { 344302001Smm zip->flags |= ZIP_FLAG_EXPERIMENT_xl; 345302001Smm } 346302001Smm return (ARCHIVE_OK); 347302001Smm } else if (strcmp(key, "fakecrc32") == 0) { 348302001Smm /* 349302001Smm * FOR TESTING ONLY: disable CRC calculation to speed up 350302001Smm * certain complex tests. 351302001Smm */ 352302001Smm if (val == NULL || val[0] == 0) { 353302001Smm zip->crc32func = real_crc32; 354302001Smm } else { 355302001Smm zip->crc32func = fake_crc32; 356302001Smm } 357302001Smm return (ARCHIVE_OK); 358232153Smm } else if (strcmp(key, "hdrcharset") == 0) { 359302001Smm /* 360302001Smm * Set the character set used in translating filenames. 361302001Smm */ 362232153Smm if (val == NULL || val[0] == 0) { 363232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 364232153Smm "%s: hdrcharset option needs a character-set name", 365232153Smm a->format_name); 366232153Smm } else { 367232153Smm zip->opt_sconv = archive_string_conversion_to_charset( 368232153Smm &a->archive, val, 0); 369232153Smm if (zip->opt_sconv != NULL) 370232153Smm ret = ARCHIVE_OK; 371232153Smm else 372232153Smm ret = ARCHIVE_FATAL; 373232153Smm } 374232153Smm return (ret); 375302001Smm } else if (strcmp(key, "zip64") == 0) { 376302001Smm /* 377302001Smm * Bias decisions about Zip64: force them to be 378302001Smm * generated in certain cases where they are not 379302001Smm * forbidden or avoid them in certain cases where they 380302001Smm * are not strictly required. 381302001Smm */ 382302001Smm if (val != NULL && *val != '\0') { 383302001Smm zip->flags |= ZIP_FLAG_FORCE_ZIP64; 384302001Smm zip->flags &= ~ZIP_FLAG_AVOID_ZIP64; 385302001Smm } else { 386302001Smm zip->flags &= ~ZIP_FLAG_FORCE_ZIP64; 387302001Smm zip->flags |= ZIP_FLAG_AVOID_ZIP64; 388302001Smm } 389302001Smm return (ARCHIVE_OK); 390228753Smm } 391232153Smm 392232153Smm /* Note: The "warn" return is just to inform the options 393232153Smm * supervisor that we didn't handle it. It will generate 394232153Smm * a suitable error if no one used this option. */ 395228753Smm return (ARCHIVE_WARN); 396228753Smm} 397228753Smm 398228753Smmint 399248616Smmarchive_write_zip_set_compression_deflate(struct archive *_a) 400248616Smm{ 401248616Smm struct archive_write *a = (struct archive_write *)_a; 402248616Smm int ret = ARCHIVE_FAILED; 403302001Smm 404248616Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 405302001Smm ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 406248616Smm "archive_write_zip_set_compression_deflate"); 407248616Smm if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { 408248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 409248616Smm "Can only use archive_write_zip_set_compression_deflate" 410248616Smm " with zip format"); 411248616Smm ret = ARCHIVE_FATAL; 412248616Smm } else { 413248616Smm#ifdef HAVE_ZLIB_H 414248616Smm struct zip *zip = a->format_data; 415302001Smm zip->requested_compression = COMPRESSION_DEFLATE; 416248616Smm ret = ARCHIVE_OK; 417248616Smm#else 418248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 419248616Smm "deflate compression not supported"); 420302001Smm ret = ARCHIVE_FAILED; 421248616Smm#endif 422248616Smm } 423248616Smm return (ret); 424248616Smm} 425248616Smm 426248616Smmint 427248616Smmarchive_write_zip_set_compression_store(struct archive *_a) 428248616Smm{ 429248616Smm struct archive_write *a = (struct archive_write *)_a; 430248616Smm struct zip *zip = a->format_data; 431248616Smm int ret = ARCHIVE_FAILED; 432302001Smm 433248616Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 434302001Smm ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 435248616Smm "archive_write_zip_set_compression_deflate"); 436248616Smm if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { 437248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 438248616Smm "Can only use archive_write_zip_set_compression_store" 439248616Smm " with zip format"); 440248616Smm ret = ARCHIVE_FATAL; 441248616Smm } else { 442302001Smm zip->requested_compression = COMPRESSION_STORE; 443248616Smm ret = ARCHIVE_OK; 444248616Smm } 445248616Smm return (ret); 446248616Smm} 447248616Smm 448248616Smmint 449228753Smmarchive_write_set_format_zip(struct archive *_a) 450228753Smm{ 451228753Smm struct archive_write *a = (struct archive_write *)_a; 452228753Smm struct zip *zip; 453228753Smm 454232153Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 455232153Smm ARCHIVE_STATE_NEW, "archive_write_set_format_zip"); 456232153Smm 457228753Smm /* If another format was already registered, unregister it. */ 458232153Smm if (a->format_free != NULL) 459232153Smm (a->format_free)(a); 460228753Smm 461228753Smm zip = (struct zip *) calloc(1, sizeof(*zip)); 462228753Smm if (zip == NULL) { 463232153Smm archive_set_error(&a->archive, ENOMEM, 464232153Smm "Can't allocate zip data"); 465228753Smm return (ARCHIVE_FATAL); 466228753Smm } 467228753Smm 468302001Smm /* "Unspecified" lets us choose the appropriate compression. */ 469302001Smm zip->requested_compression = COMPRESSION_UNSPECIFIED; 470228753Smm#ifdef HAVE_ZLIB_H 471302001Smm zip->deflate_compression_level = Z_DEFAULT_COMPRESSION; 472302001Smm#endif 473302001Smm zip->crc32func = real_crc32; 474302001Smm 475302001Smm /* A buffer used for both compression and encryption. */ 476228753Smm zip->len_buf = 65536; 477228753Smm zip->buf = malloc(zip->len_buf); 478228753Smm if (zip->buf == NULL) { 479238856Smm free(zip); 480232153Smm archive_set_error(&a->archive, ENOMEM, 481232153Smm "Can't allocate compression buffer"); 482228753Smm return (ARCHIVE_FATAL); 483228753Smm } 484228753Smm 485228753Smm a->format_data = zip; 486228753Smm a->format_name = "zip"; 487228753Smm a->format_options = archive_write_zip_options; 488228753Smm a->format_write_header = archive_write_zip_header; 489228753Smm a->format_write_data = archive_write_zip_data; 490228753Smm a->format_finish_entry = archive_write_zip_finish_entry; 491232153Smm a->format_close = archive_write_zip_close; 492232153Smm a->format_free = archive_write_zip_free; 493228753Smm a->archive.archive_format = ARCHIVE_FORMAT_ZIP; 494228753Smm a->archive.archive_format_name = "ZIP"; 495228753Smm 496228753Smm return (ARCHIVE_OK); 497228753Smm} 498228753Smm 499228753Smmstatic int 500232153Smmis_all_ascii(const char *p) 501232153Smm{ 502232153Smm const unsigned char *pp = (const unsigned char *)p; 503232153Smm 504232153Smm while (*pp) { 505232153Smm if (*pp++ > 127) 506232153Smm return (0); 507232153Smm } 508232153Smm return (1); 509232153Smm} 510232153Smm 511232153Smmstatic int 512228753Smmarchive_write_zip_header(struct archive_write *a, struct archive_entry *entry) 513228753Smm{ 514302001Smm unsigned char local_header[32]; 515302001Smm unsigned char local_extra[144]; 516302001Smm struct zip *zip = a->format_data; 517302001Smm unsigned char *e; 518302001Smm unsigned char *cd_extra; 519302001Smm size_t filename_length; 520302001Smm const char *slink = NULL; 521302001Smm size_t slink_size = 0; 522302001Smm struct archive_string_conv *sconv = get_sconv(a, zip); 523232153Smm int ret, ret2 = ARCHIVE_OK; 524228753Smm mode_t type; 525302001Smm int version_needed = 10; 526228753Smm 527302001Smm /* Ignore types of entries that we don't support. */ 528228753Smm type = archive_entry_filetype(entry); 529232153Smm if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { 530358090Smm __archive_write_entry_filetype_unsupported( 531358090Smm &a->archive, entry, "zip"); 532228753Smm return ARCHIVE_FAILED; 533248616Smm }; 534228753Smm 535302001Smm /* If we're not using Zip64, reject large files. */ 536302001Smm if (zip->flags & ZIP_FLAG_AVOID_ZIP64) { 537302001Smm /* Reject entries over 4GB. */ 538302001Smm if (archive_entry_size_is_set(entry) 539302001Smm && (archive_entry_size(entry) > ZIP_4GB_MAX)) { 540302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 541302001Smm "Files > 4GB require Zip64 extensions"); 542302001Smm return ARCHIVE_FAILED; 543302001Smm } 544302001Smm /* Reject entries if archive is > 4GB. */ 545302001Smm if (zip->written_bytes > ZIP_4GB_MAX) { 546302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 547302001Smm "Archives > 4GB require Zip64 extensions"); 548302001Smm return ARCHIVE_FAILED; 549302001Smm } 550302001Smm } 551302001Smm 552302001Smm /* Only regular files can have size > 0. */ 553302001Smm if (type != AE_IFREG) 554228753Smm archive_entry_set_size(entry, 0); 555228753Smm 556302001Smm 557302001Smm /* Reset information from last entry. */ 558302001Smm zip->entry_offset = zip->written_bytes; 559302001Smm zip->entry_uncompressed_limit = INT64_MAX; 560302001Smm zip->entry_compressed_size = 0; 561302001Smm zip->entry_uncompressed_size = 0; 562302001Smm zip->entry_compressed_written = 0; 563302001Smm zip->entry_uncompressed_written = 0; 564302001Smm zip->entry_flags = 0; 565302001Smm zip->entry_uses_zip64 = 0; 566302001Smm zip->entry_crc32 = zip->crc32func(0, NULL, 0); 567302001Smm zip->entry_encryption = 0; 568344674Smm archive_entry_free(zip->entry); 569344674Smm zip->entry = NULL; 570232153Smm 571302001Smm if (zip->cctx_valid) 572302001Smm archive_encrypto_aes_ctr_release(&zip->cctx); 573302001Smm if (zip->hctx_valid) 574302001Smm archive_hmac_sha1_cleanup(&zip->hctx); 575302001Smm zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; 576302001Smm 577302001Smm if (type == AE_IFREG 578302001Smm &&(!archive_entry_size_is_set(entry) 579302001Smm || archive_entry_size(entry) > 0)) { 580302001Smm switch (zip->encryption_type) { 581302001Smm case ENCRYPTION_TRADITIONAL: 582302001Smm case ENCRYPTION_WINZIP_AES128: 583302001Smm case ENCRYPTION_WINZIP_AES256: 584302001Smm zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED; 585302001Smm zip->entry_encryption = zip->encryption_type; 586302001Smm break; 587368708Smm case ENCRYPTION_NONE: 588302001Smm default: 589302001Smm break; 590232153Smm } 591232153Smm } 592228753Smm 593302001Smm 594232153Smm#if defined(_WIN32) && !defined(__CYGWIN__) 595311042Smm /* Make sure the path separators in pathname, hardlink and symlink 596232153Smm * are all slash '/', not the Windows path separator '\'. */ 597302001Smm zip->entry = __la_win_entry_in_posix_pathseparator(entry); 598302001Smm if (zip->entry == entry) 599302001Smm zip->entry = archive_entry_clone(entry); 600232153Smm#else 601302001Smm zip->entry = archive_entry_clone(entry); 602232153Smm#endif 603302001Smm if (zip->entry == NULL) { 604232153Smm archive_set_error(&a->archive, ENOMEM, 605232153Smm "Can't allocate zip header data"); 606232153Smm return (ARCHIVE_FATAL); 607232153Smm } 608302001Smm 609232153Smm if (sconv != NULL) { 610232153Smm const char *p; 611232153Smm size_t len; 612232153Smm 613232153Smm if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) { 614232153Smm if (errno == ENOMEM) { 615232153Smm archive_set_error(&a->archive, ENOMEM, 616232153Smm "Can't allocate memory for Pathname"); 617232153Smm return (ARCHIVE_FATAL); 618232153Smm } 619232153Smm archive_set_error(&a->archive, 620232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 621238856Smm "Can't translate Pathname '%s' to %s", 622232153Smm archive_entry_pathname(entry), 623232153Smm archive_string_conversion_charset_name(sconv)); 624232153Smm ret2 = ARCHIVE_WARN; 625232153Smm } 626232153Smm if (len > 0) 627302001Smm archive_entry_set_pathname(zip->entry, p); 628238856Smm 629238856Smm /* 630302001Smm * There is no standard for symlink handling; we convert 631302001Smm * it using the same character-set translation that we use 632302001Smm * for filename. 633238856Smm */ 634238856Smm if (type == AE_IFLNK) { 635238856Smm if (archive_entry_symlink_l(entry, &p, &len, sconv)) { 636238856Smm if (errno == ENOMEM) { 637238856Smm archive_set_error(&a->archive, ENOMEM, 638238856Smm "Can't allocate memory " 639238856Smm " for Symlink"); 640238856Smm return (ARCHIVE_FATAL); 641238856Smm } 642302001Smm /* No error if we can't convert. */ 643238856Smm } else if (len > 0) 644302001Smm archive_entry_set_symlink(zip->entry, p); 645238856Smm } 646232153Smm } 647232153Smm 648302001Smm /* If filename isn't ASCII and we can use UTF-8, set the UTF-8 flag. */ 649302001Smm if (!is_all_ascii(archive_entry_pathname(zip->entry))) { 650302001Smm if (zip->opt_sconv != NULL) { 651302001Smm if (strcmp(archive_string_conversion_charset_name( 652302001Smm zip->opt_sconv), "UTF-8") == 0) 653302001Smm zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; 654302001Smm#if HAVE_NL_LANGINFO 655302001Smm } else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { 656302001Smm zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; 657302001Smm#endif 658302001Smm } 659302001Smm } 660302001Smm filename_length = path_length(zip->entry); 661302001Smm 662302001Smm /* Determine appropriate compression and size for this entry. */ 663232153Smm if (type == AE_IFLNK) { 664302001Smm slink = archive_entry_symlink(zip->entry); 665302001Smm if (slink != NULL) 666302001Smm slink_size = strlen(slink); 667232153Smm else 668302001Smm slink_size = 0; 669302001Smm zip->entry_uncompressed_limit = slink_size; 670302001Smm zip->entry_compressed_size = slink_size; 671302001Smm zip->entry_uncompressed_size = slink_size; 672302001Smm zip->entry_crc32 = zip->crc32func(zip->entry_crc32, 673302001Smm (const unsigned char *)slink, slink_size); 674302001Smm zip->entry_compression = COMPRESSION_STORE; 675302001Smm version_needed = 20; 676302001Smm } else if (type != AE_IFREG) { 677302001Smm zip->entry_compression = COMPRESSION_STORE; 678302001Smm zip->entry_uncompressed_limit = 0; 679302001Smm version_needed = 20; 680302001Smm } else if (archive_entry_size_is_set(zip->entry)) { 681302001Smm int64_t size = archive_entry_size(zip->entry); 682302001Smm int64_t additional_size = 0; 683302001Smm 684302001Smm zip->entry_uncompressed_limit = size; 685302001Smm zip->entry_compression = zip->requested_compression; 686302001Smm if (zip->entry_compression == COMPRESSION_UNSPECIFIED) { 687302001Smm zip->entry_compression = COMPRESSION_DEFAULT; 688302001Smm } 689302001Smm if (zip->entry_compression == COMPRESSION_STORE) { 690302001Smm zip->entry_compressed_size = size; 691302001Smm zip->entry_uncompressed_size = size; 692302001Smm version_needed = 10; 693302001Smm } else { 694302001Smm zip->entry_uncompressed_size = size; 695302001Smm version_needed = 20; 696302001Smm } 697302001Smm 698302001Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 699302001Smm switch (zip->entry_encryption) { 700302001Smm case ENCRYPTION_TRADITIONAL: 701302001Smm additional_size = TRAD_HEADER_SIZE; 702302001Smm version_needed = 20; 703302001Smm break; 704302001Smm case ENCRYPTION_WINZIP_AES128: 705302001Smm additional_size = WINZIP_AES128_HEADER_SIZE 706302001Smm + AUTH_CODE_SIZE; 707302001Smm version_needed = 20; 708302001Smm break; 709302001Smm case ENCRYPTION_WINZIP_AES256: 710302001Smm additional_size = WINZIP_AES256_HEADER_SIZE 711302001Smm + AUTH_CODE_SIZE; 712302001Smm version_needed = 20; 713302001Smm break; 714368708Smm case ENCRYPTION_NONE: 715302001Smm default: 716302001Smm break; 717302001Smm } 718302001Smm if (zip->entry_compression == COMPRESSION_STORE) 719302001Smm zip->entry_compressed_size += additional_size; 720302001Smm } 721302001Smm 722302001Smm /* 723302001Smm * Set Zip64 extension in any of the following cases 724302001Smm * (this was suggested by discussion on info-zip-dev 725302001Smm * mailing list): 726302001Smm * = Zip64 is being forced by user 727302001Smm * = File is over 4GiB uncompressed 728302001Smm * (including encryption header, if any) 729302001Smm * = File is close to 4GiB and is being compressed 730302001Smm * (compression might make file larger) 731302001Smm */ 732302001Smm if ((zip->flags & ZIP_FLAG_FORCE_ZIP64) 733302001Smm || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX) 734302001Smm || (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED 735302001Smm && zip->entry_compression != COMPRESSION_STORE)) { 736302001Smm zip->entry_uses_zip64 = 1; 737302001Smm version_needed = 45; 738302001Smm } 739302001Smm 740302001Smm /* We may know the size, but never the CRC. */ 741302001Smm zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; 742232153Smm } else { 743302001Smm /* We don't know the size. In this case, we prefer 744302001Smm * deflate (it has a clear end-of-data marker which 745302001Smm * makes length-at-end more reliable) and will 746302001Smm * enable Zip64 extensions unless we're told not to. 747302001Smm */ 748302001Smm zip->entry_compression = COMPRESSION_DEFAULT; 749302001Smm zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; 750302001Smm if ((zip->flags & ZIP_FLAG_AVOID_ZIP64) == 0) { 751302001Smm zip->entry_uses_zip64 = 1; 752302001Smm version_needed = 45; 753302001Smm } else if (zip->entry_compression == COMPRESSION_STORE) { 754302001Smm version_needed = 10; 755302001Smm } else { 756302001Smm version_needed = 20; 757302001Smm } 758302001Smm 759302001Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 760302001Smm switch (zip->entry_encryption) { 761302001Smm case ENCRYPTION_TRADITIONAL: 762302001Smm case ENCRYPTION_WINZIP_AES128: 763302001Smm case ENCRYPTION_WINZIP_AES256: 764302001Smm if (version_needed < 20) 765302001Smm version_needed = 20; 766302001Smm break; 767368708Smm case ENCRYPTION_NONE: 768302001Smm default: 769302001Smm break; 770302001Smm } 771302001Smm } 772232153Smm } 773302001Smm 774302001Smm /* Format the local header. */ 775302001Smm memset(local_header, 0, sizeof(local_header)); 776302001Smm memcpy(local_header, "PK\003\004", 4); 777302001Smm archive_le16enc(local_header + 4, version_needed); 778302001Smm archive_le16enc(local_header + 6, zip->entry_flags); 779302001Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 780302001Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) 781302001Smm archive_le16enc(local_header + 8, WINZIP_AES_ENCRYPTION); 782302001Smm else 783302001Smm archive_le16enc(local_header + 8, zip->entry_compression); 784302001Smm archive_le32enc(local_header + 10, 785302001Smm dos_time(archive_entry_mtime(zip->entry))); 786302001Smm archive_le32enc(local_header + 14, zip->entry_crc32); 787302001Smm if (zip->entry_uses_zip64) { 788302001Smm /* Zip64 data in the local header "must" include both 789302001Smm * compressed and uncompressed sizes AND those fields 790302001Smm * are included only if these are 0xffffffff; 791302001Smm * THEREFORE these must be set this way, even if we 792302001Smm * know one of them is smaller. */ 793302001Smm archive_le32enc(local_header + 18, ZIP_4GB_MAX); 794302001Smm archive_le32enc(local_header + 22, ZIP_4GB_MAX); 795228753Smm } else { 796302001Smm archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size); 797302001Smm archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size); 798228753Smm } 799302001Smm archive_le16enc(local_header + 26, (uint16_t)filename_length); 800228753Smm 801302001Smm if (zip->entry_encryption == ENCRYPTION_TRADITIONAL) { 802302001Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) 803302001Smm zip->trad_chkdat = local_header[11]; 804302001Smm else 805302001Smm zip->trad_chkdat = local_header[17]; 806302001Smm } 807228753Smm 808302001Smm /* Format as much of central directory file header as we can: */ 809302001Smm zip->file_header = cd_alloc(zip, 46); 810302001Smm /* If (zip->file_header == NULL) XXXX */ 811302001Smm ++zip->central_directory_entries; 812302001Smm memset(zip->file_header, 0, 46); 813302001Smm memcpy(zip->file_header, "PK\001\002", 4); 814302001Smm /* "Made by PKZip 2.0 on Unix." */ 815302001Smm archive_le16enc(zip->file_header + 4, 3 * 256 + version_needed); 816302001Smm archive_le16enc(zip->file_header + 6, version_needed); 817302001Smm archive_le16enc(zip->file_header + 8, zip->entry_flags); 818302001Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 819302001Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) 820302001Smm archive_le16enc(zip->file_header + 10, WINZIP_AES_ENCRYPTION); 821302001Smm else 822302001Smm archive_le16enc(zip->file_header + 10, zip->entry_compression); 823302001Smm archive_le32enc(zip->file_header + 12, 824302001Smm dos_time(archive_entry_mtime(zip->entry))); 825302001Smm archive_le16enc(zip->file_header + 28, (uint16_t)filename_length); 826302001Smm /* Following Info-Zip, store mode in the "external attributes" field. */ 827302001Smm archive_le32enc(zip->file_header + 38, 828302001Smm ((uint32_t)archive_entry_mode(zip->entry)) << 16); 829302001Smm e = cd_alloc(zip, filename_length); 830302001Smm /* If (e == NULL) XXXX */ 831302001Smm copy_path(zip->entry, e); 832228753Smm 833302001Smm /* Format extra data. */ 834302001Smm memset(local_extra, 0, sizeof(local_extra)); 835302001Smm e = local_extra; 836228753Smm 837302001Smm /* First, extra blocks that are the same between 838302001Smm * the local file header and the central directory. 839302001Smm * We format them once and then duplicate them. */ 840302001Smm 841302001Smm /* UT timestamp, length depends on what timestamps are set. */ 842302001Smm memcpy(e, "UT", 2); 843302001Smm archive_le16enc(e + 2, 844302001Smm 1 845302001Smm + (archive_entry_mtime_is_set(entry) ? 4 : 0) 846302001Smm + (archive_entry_atime_is_set(entry) ? 4 : 0) 847302001Smm + (archive_entry_ctime_is_set(entry) ? 4 : 0)); 848302001Smm e += 4; 849302001Smm *e++ = 850302001Smm (archive_entry_mtime_is_set(entry) ? 1 : 0) 851302001Smm | (archive_entry_atime_is_set(entry) ? 2 : 0) 852302001Smm | (archive_entry_ctime_is_set(entry) ? 4 : 0); 853302001Smm if (archive_entry_mtime_is_set(entry)) { 854302001Smm archive_le32enc(e, (uint32_t)archive_entry_mtime(entry)); 855302001Smm e += 4; 856228753Smm } 857302001Smm if (archive_entry_atime_is_set(entry)) { 858302001Smm archive_le32enc(e, (uint32_t)archive_entry_atime(entry)); 859302001Smm e += 4; 860302001Smm } 861302001Smm if (archive_entry_ctime_is_set(entry)) { 862302001Smm archive_le32enc(e, (uint32_t)archive_entry_ctime(entry)); 863302001Smm e += 4; 864302001Smm } 865228753Smm 866302001Smm /* ux Unix extra data, length 11, version 1 */ 867302001Smm /* TODO: If uid < 64k, use 2 bytes, ditto for gid. */ 868302001Smm memcpy(e, "ux\013\000\001", 5); 869302001Smm e += 5; 870302001Smm *e++ = 4; /* Length of following UID */ 871302001Smm archive_le32enc(e, (uint32_t)archive_entry_uid(entry)); 872302001Smm e += 4; 873302001Smm *e++ = 4; /* Length of following GID */ 874302001Smm archive_le32enc(e, (uint32_t)archive_entry_gid(entry)); 875302001Smm e += 4; 876228753Smm 877302001Smm /* AES extra data field: WinZIP AES information, ID=0x9901 */ 878302001Smm if ((zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) 879302001Smm && (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 880302001Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) { 881232153Smm 882302001Smm memcpy(e, "\001\231\007\000\001\000AE", 8); 883313571Smm /* AES vendor version AE-2 does not store a CRC. 884302001Smm * WinZip 11 uses AE-1, which does store the CRC, 885302001Smm * but it does not store the CRC when the file size 886302001Smm * is less than 20 bytes. So we simulate what 887302001Smm * WinZip 11 does. 888302001Smm * NOTE: WinZip 9.0 and 10.0 uses AE-2 by default. */ 889302001Smm if (archive_entry_size_is_set(zip->entry) 890302001Smm && archive_entry_size(zip->entry) < 20) { 891302001Smm archive_le16enc(e+4, AES_VENDOR_AE_2); 892302001Smm zip->aes_vendor = AES_VENDOR_AE_2;/* no CRC. */ 893302001Smm } else 894302001Smm zip->aes_vendor = AES_VENDOR_AE_1; 895302001Smm e += 8; 896302001Smm /* AES encryption strength. */ 897302001Smm *e++ = (zip->entry_encryption == ENCRYPTION_WINZIP_AES128)?1:3; 898302001Smm /* Actual compression method. */ 899302001Smm archive_le16enc(e, zip->entry_compression); 900302001Smm e += 2; 901302001Smm } 902228753Smm 903302001Smm /* Copy UT ,ux, and AES-extra into central directory as well. */ 904302001Smm zip->file_header_extra_offset = zip->central_directory_bytes; 905302001Smm cd_extra = cd_alloc(zip, e - local_extra); 906302001Smm memcpy(cd_extra, local_extra, e - local_extra); 907302001Smm 908302001Smm /* 909302001Smm * Following extra blocks vary between local header and 910302001Smm * central directory. These are the local header versions. 911302001Smm * Central directory versions get formatted in 912302001Smm * archive_write_zip_finish_entry() below. 913302001Smm */ 914302001Smm 915302001Smm /* "[Zip64 entry] in the local header MUST include BOTH 916302001Smm * original [uncompressed] and compressed size fields." */ 917302001Smm if (zip->entry_uses_zip64) { 918302001Smm unsigned char *zip64_start = e; 919302001Smm memcpy(e, "\001\000\020\000", 4); 920302001Smm e += 4; 921302001Smm archive_le64enc(e, zip->entry_uncompressed_size); 922302001Smm e += 8; 923302001Smm archive_le64enc(e, zip->entry_compressed_size); 924302001Smm e += 8; 925302001Smm archive_le16enc(zip64_start + 2, (uint16_t)(e - (zip64_start + 4))); 926302001Smm } 927302001Smm 928302001Smm if (zip->flags & ZIP_FLAG_EXPERIMENT_xl) { 929302001Smm /* Experimental 'xl' extension to improve streaming. */ 930302001Smm unsigned char *external_info = e; 931302001Smm int included = 7; 932302001Smm memcpy(e, "xl\000\000", 4); // 0x6c65 + 2-byte length 933302001Smm e += 4; 934302001Smm e[0] = included; /* bitmap of included fields */ 935302001Smm e += 1; 936302001Smm if (included & 1) { 937302001Smm archive_le16enc(e, /* "Version created by" */ 938302001Smm 3 * 256 + version_needed); 939302001Smm e += 2; 940302001Smm } 941302001Smm if (included & 2) { 942302001Smm archive_le16enc(e, 0); /* internal file attributes */ 943302001Smm e += 2; 944302001Smm } 945302001Smm if (included & 4) { 946302001Smm archive_le32enc(e, /* external file attributes */ 947302001Smm ((uint32_t)archive_entry_mode(zip->entry)) << 16); 948302001Smm e += 4; 949302001Smm } 950302001Smm if (included & 8) { 951302001Smm // Libarchive does not currently support file comments. 952302001Smm } 953302001Smm archive_le16enc(external_info + 2, (uint16_t)(e - (external_info + 4))); 954302001Smm } 955302001Smm 956302001Smm /* Update local header with size of extra data and write it all out: */ 957302001Smm archive_le16enc(local_header + 28, (uint16_t)(e - local_extra)); 958302001Smm 959302001Smm ret = __archive_write_output(a, local_header, 30); 960228753Smm if (ret != ARCHIVE_OK) 961228753Smm return (ARCHIVE_FATAL); 962302001Smm zip->written_bytes += 30; 963228753Smm 964302001Smm ret = write_path(zip->entry, a); 965228753Smm if (ret <= ARCHIVE_OK) 966228753Smm return (ARCHIVE_FATAL); 967228753Smm zip->written_bytes += ret; 968228753Smm 969302001Smm ret = __archive_write_output(a, local_extra, e - local_extra); 970228753Smm if (ret != ARCHIVE_OK) 971228753Smm return (ARCHIVE_FATAL); 972302001Smm zip->written_bytes += e - local_extra; 973228753Smm 974302001Smm /* For symlinks, write the body now. */ 975302001Smm if (slink != NULL) { 976302001Smm ret = __archive_write_output(a, slink, slink_size); 977232153Smm if (ret != ARCHIVE_OK) 978232153Smm return (ARCHIVE_FATAL); 979302001Smm zip->entry_compressed_written += slink_size; 980302001Smm zip->entry_uncompressed_written += slink_size; 981302001Smm zip->written_bytes += slink_size; 982232153Smm } 983232153Smm 984302001Smm#ifdef HAVE_ZLIB_H 985302001Smm if (zip->entry_compression == COMPRESSION_DEFLATE) { 986302001Smm zip->stream.zalloc = Z_NULL; 987302001Smm zip->stream.zfree = Z_NULL; 988302001Smm zip->stream.opaque = Z_NULL; 989302001Smm zip->stream.next_out = zip->buf; 990302001Smm zip->stream.avail_out = (uInt)zip->len_buf; 991302001Smm if (deflateInit2(&zip->stream, zip->deflate_compression_level, 992302001Smm Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { 993302001Smm archive_set_error(&a->archive, ENOMEM, 994302001Smm "Can't init deflate compressor"); 995302001Smm return (ARCHIVE_FATAL); 996302001Smm } 997302001Smm } 998302001Smm#endif 999302001Smm 1000302001Smm return (ret2); 1001228753Smm} 1002228753Smm 1003228753Smmstatic ssize_t 1004228753Smmarchive_write_zip_data(struct archive_write *a, const void *buff, size_t s) 1005228753Smm{ 1006228753Smm int ret; 1007228753Smm struct zip *zip = a->format_data; 1008228753Smm 1009302001Smm if ((int64_t)s > zip->entry_uncompressed_limit) 1010302001Smm s = (size_t)zip->entry_uncompressed_limit; 1011302001Smm zip->entry_uncompressed_written += s; 1012228753Smm 1013228753Smm if (s == 0) return 0; 1014228753Smm 1015302001Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 1016302001Smm switch (zip->entry_encryption) { 1017302001Smm case ENCRYPTION_TRADITIONAL: 1018313571Smm /* Initialize traditional PKWARE encryption context. */ 1019302001Smm if (!zip->tctx_valid) { 1020302001Smm ret = init_traditional_pkware_encryption(a); 1021302001Smm if (ret != ARCHIVE_OK) 1022302001Smm return (ret); 1023302001Smm zip->tctx_valid = 1; 1024302001Smm } 1025302001Smm break; 1026302001Smm case ENCRYPTION_WINZIP_AES128: 1027302001Smm case ENCRYPTION_WINZIP_AES256: 1028302001Smm if (!zip->cctx_valid) { 1029302001Smm ret = init_winzip_aes_encryption(a); 1030302001Smm if (ret != ARCHIVE_OK) 1031302001Smm return (ret); 1032302001Smm zip->cctx_valid = zip->hctx_valid = 1; 1033302001Smm } 1034302001Smm break; 1035368708Smm case ENCRYPTION_NONE: 1036302001Smm default: 1037302001Smm break; 1038302001Smm } 1039302001Smm } 1040302001Smm 1041302001Smm switch (zip->entry_compression) { 1042228753Smm case COMPRESSION_STORE: 1043302001Smm if (zip->tctx_valid || zip->cctx_valid) { 1044302001Smm const uint8_t *rb = (const uint8_t *)buff; 1045302001Smm const uint8_t * const re = rb + s; 1046302001Smm 1047302001Smm while (rb < re) { 1048302001Smm size_t l; 1049302001Smm 1050302001Smm if (zip->tctx_valid) { 1051302001Smm l = trad_enc_encrypt_update(&zip->tctx, 1052302001Smm rb, re - rb, 1053302001Smm zip->buf, zip->len_buf); 1054302001Smm } else { 1055302001Smm l = zip->len_buf; 1056302001Smm ret = archive_encrypto_aes_ctr_update( 1057302001Smm &zip->cctx, 1058302001Smm rb, re - rb, zip->buf, &l); 1059302001Smm if (ret < 0) { 1060302001Smm archive_set_error(&a->archive, 1061302001Smm ARCHIVE_ERRNO_MISC, 1062302001Smm "Failed to encrypt file"); 1063302001Smm return (ARCHIVE_FAILED); 1064302001Smm } 1065302001Smm archive_hmac_sha1_update(&zip->hctx, 1066302001Smm zip->buf, l); 1067302001Smm } 1068302001Smm ret = __archive_write_output(a, zip->buf, l); 1069302001Smm if (ret != ARCHIVE_OK) 1070302001Smm return (ret); 1071302001Smm zip->entry_compressed_written += l; 1072302001Smm zip->written_bytes += l; 1073302001Smm rb += l; 1074302001Smm } 1075302001Smm } else { 1076302001Smm ret = __archive_write_output(a, buff, s); 1077302001Smm if (ret != ARCHIVE_OK) 1078302001Smm return (ret); 1079302001Smm zip->written_bytes += s; 1080302001Smm zip->entry_compressed_written += s; 1081302001Smm } 1082302001Smm break; 1083228753Smm#if HAVE_ZLIB_H 1084228753Smm case COMPRESSION_DEFLATE: 1085228753Smm zip->stream.next_in = (unsigned char*)(uintptr_t)buff; 1086248616Smm zip->stream.avail_in = (uInt)s; 1087228753Smm do { 1088228753Smm ret = deflate(&zip->stream, Z_NO_FLUSH); 1089228753Smm if (ret == Z_STREAM_ERROR) 1090228753Smm return (ARCHIVE_FATAL); 1091228753Smm if (zip->stream.avail_out == 0) { 1092302001Smm if (zip->tctx_valid) { 1093302001Smm trad_enc_encrypt_update(&zip->tctx, 1094302001Smm zip->buf, zip->len_buf, 1095302001Smm zip->buf, zip->len_buf); 1096302001Smm } else if (zip->cctx_valid) { 1097302001Smm size_t outl = zip->len_buf; 1098302001Smm ret = archive_encrypto_aes_ctr_update( 1099302001Smm &zip->cctx, 1100302001Smm zip->buf, zip->len_buf, 1101302001Smm zip->buf, &outl); 1102302001Smm if (ret < 0) { 1103302001Smm archive_set_error(&a->archive, 1104302001Smm ARCHIVE_ERRNO_MISC, 1105302001Smm "Failed to encrypt file"); 1106302001Smm return (ARCHIVE_FAILED); 1107302001Smm } 1108302001Smm archive_hmac_sha1_update(&zip->hctx, 1109302001Smm zip->buf, zip->len_buf); 1110302001Smm } 1111232153Smm ret = __archive_write_output(a, zip->buf, 1112232153Smm zip->len_buf); 1113228753Smm if (ret != ARCHIVE_OK) 1114228753Smm return (ret); 1115302001Smm zip->entry_compressed_written += zip->len_buf; 1116228753Smm zip->written_bytes += zip->len_buf; 1117228753Smm zip->stream.next_out = zip->buf; 1118248616Smm zip->stream.avail_out = (uInt)zip->len_buf; 1119228753Smm } 1120228753Smm } while (zip->stream.avail_in != 0); 1121302001Smm break; 1122228753Smm#endif 1123228753Smm 1124368708Smm case COMPRESSION_UNSPECIFIED: 1125228753Smm default: 1126228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1127228753Smm "Invalid ZIP compression type"); 1128228753Smm return ARCHIVE_FATAL; 1129228753Smm } 1130302001Smm 1131302001Smm zip->entry_uncompressed_limit -= s; 1132302001Smm if (!zip->cctx_valid || zip->aes_vendor != AES_VENDOR_AE_2) 1133302001Smm zip->entry_crc32 = 1134302001Smm zip->crc32func(zip->entry_crc32, buff, (unsigned)s); 1135302001Smm return (s); 1136302001Smm 1137228753Smm} 1138228753Smm 1139228753Smmstatic int 1140228753Smmarchive_write_zip_finish_entry(struct archive_write *a) 1141228753Smm{ 1142302001Smm struct zip *zip = a->format_data; 1143228753Smm int ret; 1144228753Smm 1145228753Smm#if HAVE_ZLIB_H 1146302001Smm if (zip->entry_compression == COMPRESSION_DEFLATE) { 1147228753Smm for (;;) { 1148302001Smm size_t remainder; 1149302001Smm 1150228753Smm ret = deflate(&zip->stream, Z_FINISH); 1151228753Smm if (ret == Z_STREAM_ERROR) 1152228753Smm return (ARCHIVE_FATAL); 1153302001Smm remainder = zip->len_buf - zip->stream.avail_out; 1154302001Smm if (zip->tctx_valid) { 1155302001Smm trad_enc_encrypt_update(&zip->tctx, 1156302001Smm zip->buf, remainder, zip->buf, remainder); 1157302001Smm } else if (zip->cctx_valid) { 1158302001Smm size_t outl = remainder; 1159302001Smm ret = archive_encrypto_aes_ctr_update( 1160302001Smm &zip->cctx, zip->buf, remainder, 1161302001Smm zip->buf, &outl); 1162302001Smm if (ret < 0) { 1163302001Smm archive_set_error(&a->archive, 1164302001Smm ARCHIVE_ERRNO_MISC, 1165302001Smm "Failed to encrypt file"); 1166302001Smm return (ARCHIVE_FAILED); 1167302001Smm } 1168302001Smm archive_hmac_sha1_update(&zip->hctx, 1169302001Smm zip->buf, remainder); 1170302001Smm } 1171302001Smm ret = __archive_write_output(a, zip->buf, remainder); 1172228753Smm if (ret != ARCHIVE_OK) 1173228753Smm return (ret); 1174302001Smm zip->entry_compressed_written += remainder; 1175302001Smm zip->written_bytes += remainder; 1176228753Smm zip->stream.next_out = zip->buf; 1177228753Smm if (zip->stream.avail_out != 0) 1178228753Smm break; 1179248616Smm zip->stream.avail_out = (uInt)zip->len_buf; 1180228753Smm } 1181228753Smm deflateEnd(&zip->stream); 1182302001Smm } 1183228753Smm#endif 1184302001Smm if (zip->hctx_valid) { 1185302001Smm uint8_t hmac[20]; 1186302001Smm size_t hmac_len = 20; 1187302001Smm 1188302001Smm archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len); 1189302001Smm ret = __archive_write_output(a, hmac, AUTH_CODE_SIZE); 1190302001Smm if (ret != ARCHIVE_OK) 1191302001Smm return (ret); 1192302001Smm zip->entry_compressed_written += AUTH_CODE_SIZE; 1193302001Smm zip->written_bytes += AUTH_CODE_SIZE; 1194228753Smm } 1195228753Smm 1196302001Smm /* Write trailing data descriptor. */ 1197302001Smm if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) != 0) { 1198302001Smm char d[24]; 1199302001Smm memcpy(d, "PK\007\010", 4); 1200302001Smm if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) 1201302001Smm archive_le32enc(d + 4, 0);/* no CRC.*/ 1202302001Smm else 1203302001Smm archive_le32enc(d + 4, zip->entry_crc32); 1204302001Smm if (zip->entry_uses_zip64) { 1205302001Smm archive_le64enc(d + 8, 1206302001Smm (uint64_t)zip->entry_compressed_written); 1207302001Smm archive_le64enc(d + 16, 1208302001Smm (uint64_t)zip->entry_uncompressed_written); 1209302001Smm ret = __archive_write_output(a, d, 24); 1210302001Smm zip->written_bytes += 24; 1211302001Smm } else { 1212302001Smm archive_le32enc(d + 8, 1213302001Smm (uint32_t)zip->entry_compressed_written); 1214302001Smm archive_le32enc(d + 12, 1215302001Smm (uint32_t)zip->entry_uncompressed_written); 1216302001Smm ret = __archive_write_output(a, d, 16); 1217302001Smm zip->written_bytes += 16; 1218302001Smm } 1219302001Smm if (ret != ARCHIVE_OK) 1220302001Smm return (ARCHIVE_FATAL); 1221302001Smm } 1222302001Smm 1223302001Smm /* Append Zip64 extra data to central directory information. */ 1224302001Smm if (zip->entry_compressed_written > ZIP_4GB_MAX 1225302001Smm || zip->entry_uncompressed_written > ZIP_4GB_MAX 1226302001Smm || zip->entry_offset > ZIP_4GB_MAX) { 1227302001Smm unsigned char zip64[32]; 1228302001Smm unsigned char *z = zip64, *zd; 1229302001Smm memcpy(z, "\001\000\000\000", 4); 1230302001Smm z += 4; 1231302001Smm if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) { 1232302001Smm archive_le64enc(z, zip->entry_uncompressed_written); 1233302001Smm z += 8; 1234302001Smm } 1235302001Smm if (zip->entry_compressed_written >= ZIP_4GB_MAX) { 1236302001Smm archive_le64enc(z, zip->entry_compressed_written); 1237302001Smm z += 8; 1238302001Smm } 1239302001Smm if (zip->entry_offset >= ZIP_4GB_MAX) { 1240302001Smm archive_le64enc(z, zip->entry_offset); 1241302001Smm z += 8; 1242302001Smm } 1243302001Smm archive_le16enc(zip64 + 2, (uint16_t)(z - (zip64 + 4))); 1244302001Smm zd = cd_alloc(zip, z - zip64); 1245302001Smm if (zd == NULL) { 1246302001Smm archive_set_error(&a->archive, ENOMEM, 1247302001Smm "Can't allocate zip data"); 1248302001Smm return (ARCHIVE_FATAL); 1249302001Smm } 1250302001Smm memcpy(zd, zip64, z - zip64); 1251302001Smm /* Zip64 means version needs to be set to at least 4.5 */ 1252302001Smm if (archive_le16dec(zip->file_header + 6) < 45) 1253302001Smm archive_le16enc(zip->file_header + 6, 45); 1254302001Smm } 1255302001Smm 1256302001Smm /* Fix up central directory file header. */ 1257302001Smm if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) 1258302001Smm archive_le32enc(zip->file_header + 16, 0);/* no CRC.*/ 1259302001Smm else 1260302001Smm archive_le32enc(zip->file_header + 16, zip->entry_crc32); 1261302001Smm archive_le32enc(zip->file_header + 20, 1262302001Smm (uint32_t)zipmin(zip->entry_compressed_written, 1263302001Smm ZIP_4GB_MAX)); 1264302001Smm archive_le32enc(zip->file_header + 24, 1265302001Smm (uint32_t)zipmin(zip->entry_uncompressed_written, 1266302001Smm ZIP_4GB_MAX)); 1267302001Smm archive_le16enc(zip->file_header + 30, 1268302001Smm (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset)); 1269302001Smm archive_le32enc(zip->file_header + 42, 1270302001Smm (uint32_t)zipmin(zip->entry_offset, 1271302001Smm ZIP_4GB_MAX)); 1272302001Smm 1273228753Smm return (ARCHIVE_OK); 1274228753Smm} 1275228753Smm 1276228753Smmstatic int 1277232153Smmarchive_write_zip_close(struct archive_write *a) 1278228753Smm{ 1279302001Smm uint8_t buff[64]; 1280232153Smm int64_t offset_start, offset_end; 1281302001Smm struct zip *zip = a->format_data; 1282302001Smm struct cd_segment *segment; 1283228753Smm int ret; 1284228753Smm 1285228753Smm offset_start = zip->written_bytes; 1286302001Smm segment = zip->central_directory; 1287302001Smm while (segment != NULL) { 1288302001Smm ret = __archive_write_output(a, 1289302001Smm segment->buff, segment->p - segment->buff); 1290228753Smm if (ret != ARCHIVE_OK) 1291228753Smm return (ARCHIVE_FATAL); 1292302001Smm zip->written_bytes += segment->p - segment->buff; 1293302001Smm segment = segment->next; 1294302001Smm } 1295302001Smm offset_end = zip->written_bytes; 1296228753Smm 1297302001Smm /* If central dir info is too large, write Zip64 end-of-cd */ 1298302001Smm if (offset_end - offset_start > ZIP_4GB_MAX 1299302001Smm || offset_start > ZIP_4GB_MAX 1300302001Smm || zip->central_directory_entries > 0xffffUL 1301302001Smm || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) { 1302302001Smm /* Zip64 end-of-cd record */ 1303302001Smm memset(buff, 0, 56); 1304302001Smm memcpy(buff, "PK\006\006", 4); 1305302001Smm archive_le64enc(buff + 4, 44); 1306302001Smm archive_le16enc(buff + 12, 45); 1307302001Smm archive_le16enc(buff + 14, 45); 1308302001Smm /* This is disk 0 of 0. */ 1309302001Smm archive_le64enc(buff + 24, zip->central_directory_entries); 1310302001Smm archive_le64enc(buff + 32, zip->central_directory_entries); 1311302001Smm archive_le64enc(buff + 40, offset_end - offset_start); 1312302001Smm archive_le64enc(buff + 48, offset_start); 1313302001Smm ret = __archive_write_output(a, buff, 56); 1314302001Smm if (ret != ARCHIVE_OK) 1315302001Smm return (ARCHIVE_FATAL); 1316302001Smm zip->written_bytes += 56; 1317228753Smm 1318302001Smm /* Zip64 end-of-cd locator record. */ 1319302001Smm memset(buff, 0, 20); 1320302001Smm memcpy(buff, "PK\006\007", 4); 1321302001Smm archive_le32enc(buff + 4, 0); 1322302001Smm archive_le64enc(buff + 8, offset_end); 1323302001Smm archive_le32enc(buff + 16, 1); 1324302001Smm ret = __archive_write_output(a, buff, 20); 1325302001Smm if (ret != ARCHIVE_OK) 1326302001Smm return (ARCHIVE_FATAL); 1327302001Smm zip->written_bytes += 20; 1328228753Smm 1329228753Smm } 1330228753Smm 1331302001Smm /* Format and write end of central directory. */ 1332302001Smm memset(buff, 0, sizeof(buff)); 1333302001Smm memcpy(buff, "PK\005\006", 4); 1334302001Smm archive_le16enc(buff + 8, (uint16_t)zipmin(0xffffU, 1335302001Smm zip->central_directory_entries)); 1336302001Smm archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU, 1337302001Smm zip->central_directory_entries)); 1338302001Smm archive_le32enc(buff + 12, 1339302001Smm (uint32_t)zipmin(ZIP_4GB_MAX, (offset_end - offset_start))); 1340302001Smm archive_le32enc(buff + 16, 1341302001Smm (uint32_t)zipmin(ZIP_4GB_MAX, offset_start)); 1342302001Smm ret = __archive_write_output(a, buff, 22); 1343228753Smm if (ret != ARCHIVE_OK) 1344228753Smm return (ARCHIVE_FATAL); 1345302001Smm zip->written_bytes += 22; 1346228753Smm return (ARCHIVE_OK); 1347228753Smm} 1348228753Smm 1349228753Smmstatic int 1350232153Smmarchive_write_zip_free(struct archive_write *a) 1351228753Smm{ 1352228753Smm struct zip *zip; 1353302001Smm struct cd_segment *segment; 1354228753Smm 1355228753Smm zip = a->format_data; 1356228753Smm while (zip->central_directory != NULL) { 1357302001Smm segment = zip->central_directory; 1358302001Smm zip->central_directory = segment->next; 1359302001Smm free(segment->buff); 1360302001Smm free(segment); 1361228753Smm } 1362228753Smm free(zip->buf); 1363302001Smm archive_entry_free(zip->entry); 1364302001Smm if (zip->cctx_valid) 1365302001Smm archive_encrypto_aes_ctr_release(&zip->cctx); 1366302001Smm if (zip->hctx_valid) 1367302001Smm archive_hmac_sha1_cleanup(&zip->hctx); 1368302001Smm /* TODO: Free opt_sconv, sconv_default */ 1369302001Smm 1370228753Smm free(zip); 1371228753Smm a->format_data = NULL; 1372228753Smm return (ARCHIVE_OK); 1373228753Smm} 1374228753Smm 1375228753Smm/* Convert into MSDOS-style date/time. */ 1376228753Smmstatic unsigned int 1377228753Smmdos_time(const time_t unix_time) 1378228753Smm{ 1379228753Smm struct tm *t; 1380228753Smm unsigned int dt; 1381358090Smm#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) 1382358090Smm struct tm tmbuf; 1383358090Smm#endif 1384358090Smm#if defined(HAVE__LOCALTIME64_S) 1385358090Smm errno_t terr; 1386358090Smm __time64_t tmptime; 1387358090Smm#endif 1388228753Smm 1389228753Smm /* This will not preserve time when creating/extracting the archive 1390228753Smm * on two systems with different time zones. */ 1391358090Smm#if defined(HAVE_LOCALTIME_R) 1392358090Smm t = localtime_r(&unix_time, &tmbuf); 1393358090Smm#elif defined(HAVE__LOCALTIME64_S) 1394358090Smm tmptime = unix_time; 1395358090Smm terr = _localtime64_s(&tmbuf, &tmptime); 1396358090Smm if (terr) 1397358090Smm t = NULL; 1398358090Smm else 1399358090Smm t = &tmbuf; 1400358090Smm#else 1401228753Smm t = localtime(&unix_time); 1402358090Smm#endif 1403228753Smm 1404232153Smm /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */ 1405232153Smm if (t->tm_year < 1980 - 1900) 1406232153Smm /* Set minimum date/time '1980-01-01 00:00:00'. */ 1407232153Smm dt = 0x00210000U; 1408232153Smm else if (t->tm_year > 2107 - 1900) 1409232153Smm /* Set maximum date/time '2107-12-31 23:59:58'. */ 1410232153Smm dt = 0xff9fbf7dU; 1411232153Smm else { 1412232153Smm dt = 0; 1413232153Smm dt += ((t->tm_year - 80) & 0x7f) << 9; 1414232153Smm dt += ((t->tm_mon + 1) & 0x0f) << 5; 1415232153Smm dt += (t->tm_mday & 0x1f); 1416232153Smm dt <<= 16; 1417232153Smm dt += (t->tm_hour & 0x1f) << 11; 1418232153Smm dt += (t->tm_min & 0x3f) << 5; 1419232153Smm dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ 1420232153Smm } 1421228753Smm return dt; 1422228753Smm} 1423228753Smm 1424228753Smmstatic size_t 1425228753Smmpath_length(struct archive_entry *entry) 1426228753Smm{ 1427228753Smm mode_t type; 1428228753Smm const char *path; 1429358090Smm size_t len; 1430228753Smm 1431228753Smm type = archive_entry_filetype(entry); 1432228753Smm path = archive_entry_pathname(entry); 1433228753Smm 1434248616Smm if (path == NULL) 1435248616Smm return (0); 1436358090Smm len = strlen(path); 1437358090Smm if (type == AE_IFDIR && (path[0] == '\0' || path[len - 1] != '/')) 1438358090Smm ++len; /* Space for the trailing / */ 1439358090Smm return len; 1440228753Smm} 1441228753Smm 1442228753Smmstatic int 1443228753Smmwrite_path(struct archive_entry *entry, struct archive_write *archive) 1444228753Smm{ 1445228753Smm int ret; 1446228753Smm const char *path; 1447228753Smm mode_t type; 1448228753Smm size_t written_bytes; 1449228753Smm 1450228753Smm path = archive_entry_pathname(entry); 1451228753Smm type = archive_entry_filetype(entry); 1452228753Smm written_bytes = 0; 1453228753Smm 1454344674Smm if (path == NULL) 1455344674Smm return (ARCHIVE_FATAL); 1456344674Smm 1457232153Smm ret = __archive_write_output(archive, path, strlen(path)); 1458228753Smm if (ret != ARCHIVE_OK) 1459228753Smm return (ARCHIVE_FATAL); 1460228753Smm written_bytes += strlen(path); 1461228753Smm 1462302001Smm /* Folders are recognized by a trailing slash. */ 1463228753Smm if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { 1464232153Smm ret = __archive_write_output(archive, "/", 1); 1465228753Smm if (ret != ARCHIVE_OK) 1466228753Smm return (ARCHIVE_FATAL); 1467228753Smm written_bytes += 1; 1468228753Smm } 1469228753Smm 1470228753Smm return ((int)written_bytes); 1471228753Smm} 1472302001Smm 1473302001Smmstatic void 1474302001Smmcopy_path(struct archive_entry *entry, unsigned char *p) 1475302001Smm{ 1476302001Smm const char *path; 1477302001Smm size_t pathlen; 1478302001Smm mode_t type; 1479302001Smm 1480302001Smm path = archive_entry_pathname(entry); 1481302001Smm pathlen = strlen(path); 1482302001Smm type = archive_entry_filetype(entry); 1483302001Smm 1484302001Smm memcpy(p, path, pathlen); 1485302001Smm 1486302001Smm /* Folders are recognized by a trailing slash. */ 1487358090Smm if ((type == AE_IFDIR) && (path[pathlen - 1] != '/')) 1488302001Smm p[pathlen] = '/'; 1489302001Smm} 1490302001Smm 1491302001Smm 1492302001Smmstatic struct archive_string_conv * 1493302001Smmget_sconv(struct archive_write *a, struct zip *zip) 1494302001Smm{ 1495302001Smm if (zip->opt_sconv != NULL) 1496302001Smm return (zip->opt_sconv); 1497302001Smm 1498302001Smm if (!zip->init_default_conversion) { 1499302001Smm zip->sconv_default = 1500302001Smm archive_string_default_conversion_for_write(&(a->archive)); 1501302001Smm zip->init_default_conversion = 1; 1502302001Smm } 1503302001Smm return (zip->sconv_default); 1504302001Smm} 1505302001Smm 1506302001Smm/* 1507302001Smm Traditional PKWARE Decryption functions. 1508302001Smm */ 1509302001Smm 1510302001Smmstatic void 1511302001Smmtrad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) 1512302001Smm{ 1513302001Smm uint8_t t; 1514302001Smm#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL) 1515302001Smm 1516302001Smm ctx->keys[0] = CRC32(ctx->keys[0], c); 1517302001Smm ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1; 1518302001Smm t = (ctx->keys[1] >> 24) & 0xff; 1519302001Smm ctx->keys[2] = CRC32(ctx->keys[2], t); 1520302001Smm#undef CRC32 1521302001Smm} 1522302001Smm 1523302001Smmstatic uint8_t 1524313571Smmtrad_enc_decrypt_byte(struct trad_enc_ctx *ctx) 1525302001Smm{ 1526302001Smm unsigned temp = ctx->keys[2] | 2; 1527302001Smm return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; 1528302001Smm} 1529302001Smm 1530302001Smmstatic unsigned 1531302001Smmtrad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, 1532302001Smm size_t in_len, uint8_t *out, size_t out_len) 1533302001Smm{ 1534302001Smm unsigned i, max; 1535302001Smm 1536302001Smm max = (unsigned)((in_len < out_len)? in_len: out_len); 1537302001Smm 1538302001Smm for (i = 0; i < max; i++) { 1539302001Smm uint8_t t = in[i]; 1540313571Smm out[i] = t ^ trad_enc_decrypt_byte(ctx); 1541302001Smm trad_enc_update_keys(ctx, t); 1542302001Smm } 1543302001Smm return i; 1544302001Smm} 1545302001Smm 1546302001Smmstatic int 1547302001Smmtrad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len) 1548302001Smm{ 1549302001Smm 1550302001Smm ctx->keys[0] = 305419896L; 1551302001Smm ctx->keys[1] = 591751049L; 1552302001Smm ctx->keys[2] = 878082192L; 1553302001Smm 1554302001Smm for (;pw_len; --pw_len) 1555302001Smm trad_enc_update_keys(ctx, *pw++); 1556302001Smm return 0; 1557302001Smm} 1558302001Smm 1559302001Smmstatic int 1560302001Smmis_traditional_pkware_encryption_supported(void) 1561302001Smm{ 1562302001Smm uint8_t key[TRAD_HEADER_SIZE]; 1563302001Smm 1564302001Smm if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) 1565302001Smm return (0); 1566302001Smm return (1); 1567302001Smm} 1568302001Smm 1569302001Smmstatic int 1570302001Smminit_traditional_pkware_encryption(struct archive_write *a) 1571302001Smm{ 1572302001Smm struct zip *zip = a->format_data; 1573302001Smm const char *passphrase; 1574302001Smm uint8_t key[TRAD_HEADER_SIZE]; 1575302001Smm uint8_t key_encrypted[TRAD_HEADER_SIZE]; 1576302001Smm int ret; 1577302001Smm 1578302001Smm passphrase = __archive_write_get_passphrase(a); 1579302001Smm if (passphrase == NULL) { 1580302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1581302001Smm "Encryption needs passphrase"); 1582302001Smm return ARCHIVE_FAILED; 1583302001Smm } 1584302001Smm if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) { 1585302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1586302001Smm "Can't generate random number for encryption"); 1587302001Smm return ARCHIVE_FATAL; 1588302001Smm } 1589302001Smm trad_enc_init(&zip->tctx, passphrase, strlen(passphrase)); 1590302001Smm /* Set the last key code which will be used as a check code 1591302001Smm * for verifying passphrase in decryption. */ 1592302001Smm key[TRAD_HEADER_SIZE-1] = zip->trad_chkdat; 1593302001Smm trad_enc_encrypt_update(&zip->tctx, key, TRAD_HEADER_SIZE, 1594302001Smm key_encrypted, TRAD_HEADER_SIZE); 1595302001Smm /* Write encrypted keys in the top of the file content. */ 1596302001Smm ret = __archive_write_output(a, key_encrypted, TRAD_HEADER_SIZE); 1597302001Smm if (ret != ARCHIVE_OK) 1598302001Smm return (ret); 1599302001Smm zip->written_bytes += TRAD_HEADER_SIZE; 1600302001Smm zip->entry_compressed_written += TRAD_HEADER_SIZE; 1601302001Smm return (ret); 1602302001Smm} 1603302001Smm 1604302001Smmstatic int 1605302001Smminit_winzip_aes_encryption(struct archive_write *a) 1606302001Smm{ 1607302001Smm struct zip *zip = a->format_data; 1608302001Smm const char *passphrase; 1609302001Smm size_t key_len, salt_len; 1610302001Smm uint8_t salt[16 + 2]; 1611302001Smm uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; 1612302001Smm int ret; 1613302001Smm 1614302001Smm passphrase = __archive_write_get_passphrase(a); 1615302001Smm if (passphrase == NULL) { 1616302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1617302001Smm "Encryption needs passphrase"); 1618302001Smm return (ARCHIVE_FAILED); 1619302001Smm } 1620302001Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128) { 1621302001Smm salt_len = 8; 1622302001Smm key_len = 16; 1623302001Smm } else { 1624302001Smm /* AES 256 */ 1625302001Smm salt_len = 16; 1626302001Smm key_len = 32; 1627302001Smm } 1628302001Smm if (archive_random(salt, salt_len) != ARCHIVE_OK) { 1629302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1630302001Smm "Can't generate random number for encryption"); 1631302001Smm return (ARCHIVE_FATAL); 1632302001Smm } 1633302001Smm archive_pbkdf2_sha1(passphrase, strlen(passphrase), 1634302001Smm salt, salt_len, 1000, derived_key, key_len * 2 + 2); 1635302001Smm 1636302001Smm ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); 1637302001Smm if (ret != 0) { 1638302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1639302001Smm "Decryption is unsupported due to lack of crypto library"); 1640302001Smm return (ARCHIVE_FAILED); 1641302001Smm } 1642302001Smm ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, 1643302001Smm key_len); 1644302001Smm if (ret != 0) { 1645302001Smm archive_encrypto_aes_ctr_release(&zip->cctx); 1646302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1647302001Smm "Failed to initialize HMAC-SHA1"); 1648302001Smm return (ARCHIVE_FAILED); 1649302001Smm } 1650302001Smm 1651313571Smm /* Set a password verification value after the 'salt'. */ 1652302001Smm salt[salt_len] = derived_key[key_len * 2]; 1653302001Smm salt[salt_len + 1] = derived_key[key_len * 2 + 1]; 1654302001Smm 1655302001Smm /* Write encrypted keys in the top of the file content. */ 1656302001Smm ret = __archive_write_output(a, salt, salt_len + 2); 1657302001Smm if (ret != ARCHIVE_OK) 1658302001Smm return (ret); 1659302001Smm zip->written_bytes += salt_len + 2; 1660302001Smm zip->entry_compressed_written += salt_len + 2; 1661302001Smm 1662302001Smm return (ARCHIVE_OK); 1663302001Smm} 1664302001Smm 1665302001Smmstatic int 1666302001Smmis_winzip_aes_encryption_supported(int encryption) 1667302001Smm{ 1668302001Smm size_t key_len, salt_len; 1669302001Smm uint8_t salt[16 + 2]; 1670302001Smm uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; 1671302001Smm archive_crypto_ctx cctx; 1672302001Smm archive_hmac_sha1_ctx hctx; 1673302001Smm int ret; 1674302001Smm 1675302001Smm if (encryption == ENCRYPTION_WINZIP_AES128) { 1676302001Smm salt_len = 8; 1677302001Smm key_len = 16; 1678302001Smm } else { 1679302001Smm /* AES 256 */ 1680302001Smm salt_len = 16; 1681302001Smm key_len = 32; 1682302001Smm } 1683302001Smm if (archive_random(salt, salt_len) != ARCHIVE_OK) 1684302001Smm return (0); 1685302001Smm ret = archive_pbkdf2_sha1("p", 1, salt, salt_len, 1000, 1686302001Smm derived_key, key_len * 2 + 2); 1687302001Smm if (ret != 0) 1688302001Smm return (0); 1689302001Smm 1690302001Smm ret = archive_encrypto_aes_ctr_init(&cctx, derived_key, key_len); 1691302001Smm if (ret != 0) 1692302001Smm return (0); 1693302001Smm ret = archive_hmac_sha1_init(&hctx, derived_key + key_len, 1694302001Smm key_len); 1695302001Smm archive_encrypto_aes_ctr_release(&cctx); 1696302001Smm if (ret != 0) 1697302001Smm return (0); 1698302001Smm archive_hmac_sha1_cleanup(&hctx); 1699302001Smm return (1); 1700302001Smm} 1701