1228753Smm/*- 2228753Smm * Copyright (c) 2008 Anselm Strauss 3228753Smm * Copyright (c) 2009 Joerg Sonnenberger 4299529Smm * 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/11/contrib/libarchive/libarchive/archive_write_set_format_zip.c 368707 2020-12-16 22:25:20Z 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" 52299529Smm#include "archive_cryptor_private.h" 53228753Smm#include "archive_endian.h" 54228753Smm#include "archive_entry.h" 55232153Smm#include "archive_entry_locale.h" 56299529Smm#include "archive_hmac_private.h" 57228753Smm#include "archive_private.h" 58299529Smm#include "archive_random_private.h" 59228753Smm#include "archive_write_private.h" 60358088Smm#include "archive_write_set_format_private.h" 61228753Smm 62228753Smm#ifndef HAVE_ZLIB_H 63228753Smm#include "archive_crc32.h" 64228753Smm#endif 65228753Smm 66299529Smm#define ZIP_ENTRY_FLAG_ENCRYPTED (1<<0) 67299529Smm#define ZIP_ENTRY_FLAG_LENGTH_AT_END (1<<3) 68299529Smm#define ZIP_ENTRY_FLAG_UTF8_NAME (1 << 11) 69228753Smm 70299529Smm#define ZIP_4GB_MAX ARCHIVE_LITERAL_LL(0xffffffff) 71299529Smm#define ZIP_4GB_MAX_UNCOMPRESSED ARCHIVE_LITERAL_LL(0xff000000) 72299529Smm 73228753Smmenum compression { 74299529Smm COMPRESSION_UNSPECIFIED = -1, 75299529Smm COMPRESSION_STORE = 0, 76299529Smm COMPRESSION_DEFLATE = 8 77299529Smm}; 78299529Smm 79228753Smm#ifdef HAVE_ZLIB_H 80299529Smm#define COMPRESSION_DEFAULT COMPRESSION_DEFLATE 81299529Smm#else 82299529Smm#define COMPRESSION_DEFAULT COMPRESSION_STORE 83228753Smm#endif 84299529Smm 85299529Smmenum encryption { 86299529Smm ENCRYPTION_NONE = 0, 87299529Smm ENCRYPTION_TRADITIONAL, /* Traditional PKWARE encryption. */ 88299529Smm ENCRYPTION_WINZIP_AES128, /* WinZIP AES-128 encryption. */ 89299529Smm ENCRYPTION_WINZIP_AES256, /* WinZIP AES-256 encryption. */ 90228753Smm}; 91228753Smm 92299529Smm#define TRAD_HEADER_SIZE 12 93299529Smm/* 94299529Smm * See "WinZip - AES Encryption Information" 95299529Smm * http://www.winzip.com/aes_info.htm 96299529Smm */ 97299529Smm/* Value used in compression method. */ 98299529Smm#define WINZIP_AES_ENCRYPTION 99 99299529Smm/* A WinZip AES header size which is stored at the beginning of 100299529Smm * file contents. */ 101299529Smm#define WINZIP_AES128_HEADER_SIZE (8 + 2) 102299529Smm#define WINZIP_AES256_HEADER_SIZE (16 + 2) 103299529Smm/* AES vendor version. */ 104299529Smm#define AES_VENDOR_AE_1 0x0001 105299529Smm#define AES_VENDOR_AE_2 0x0002 106299529Smm/* Authentication code size. */ 107299529Smm#define AUTH_CODE_SIZE 10 108299529Smm/**/ 109299529Smm#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2) 110299529Smm 111299529Smmstruct cd_segment { 112299529Smm struct cd_segment *next; 113299529Smm size_t buff_size; 114299529Smm unsigned char *buff; 115299529Smm unsigned char *p; 116299529Smm}; 117299529Smm 118299529Smmstruct trad_enc_ctx { 119299529Smm uint32_t keys[3]; 120299529Smm}; 121299529Smm 122299529Smmstruct zip { 123299529Smm 124299529Smm int64_t entry_offset; 125299529Smm int64_t entry_compressed_size; 126299529Smm int64_t entry_uncompressed_size; 127299529Smm int64_t entry_compressed_written; 128299529Smm int64_t entry_uncompressed_written; 129299529Smm int64_t entry_uncompressed_limit; 130299529Smm struct archive_entry *entry; 131299529Smm uint32_t entry_crc32; 132299529Smm enum compression entry_compression; 133299529Smm enum encryption entry_encryption; 134299529Smm int entry_flags; 135299529Smm int entry_uses_zip64; 136299529Smm int experiments; 137299529Smm struct trad_enc_ctx tctx; 138299529Smm char tctx_valid; 139299529Smm unsigned char trad_chkdat; 140299529Smm unsigned aes_vendor; 141299529Smm archive_crypto_ctx cctx; 142299529Smm char cctx_valid; 143299529Smm archive_hmac_sha1_ctx hctx; 144299529Smm char hctx_valid; 145299529Smm 146299529Smm unsigned char *file_header; 147299529Smm size_t file_header_extra_offset; 148299529Smm unsigned long (*crc32func)(unsigned long crc, const void *buff, size_t len); 149299529Smm 150299529Smm struct cd_segment *central_directory; 151299529Smm struct cd_segment *central_directory_last; 152299529Smm size_t central_directory_bytes; 153299529Smm size_t central_directory_entries; 154299529Smm 155299529Smm int64_t written_bytes; /* Overall position in file. */ 156299529Smm 157299529Smm struct archive_string_conv *opt_sconv; 158299529Smm struct archive_string_conv *sconv_default; 159299529Smm enum compression requested_compression; 160299529Smm int deflate_compression_level; 161299529Smm int init_default_conversion; 162299529Smm enum encryption encryption_type; 163299529Smm 164299529Smm#define ZIP_FLAG_AVOID_ZIP64 1 165299529Smm#define ZIP_FLAG_FORCE_ZIP64 2 166299529Smm#define ZIP_FLAG_EXPERIMENT_xl 4 167299529Smm int flags; 168299529Smm 169299529Smm#ifdef HAVE_ZLIB_H 170299529Smm z_stream stream; 171299529Smm#endif 172299529Smm size_t len_buf; 173299529Smm unsigned char *buf; 174299529Smm}; 175299529Smm 176299529Smm/* Don't call this min or MIN, since those are already defined 177299529Smm on lots of platforms (but not all). */ 178299529Smm#define zipmin(a, b) ((a) > (b) ? (b) : (a)) 179299529Smm 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 *); 192299529Smmstatic void copy_path(struct archive_entry *, unsigned char *); 193299529Smmstatic struct archive_string_conv *get_sconv(struct archive_write *, struct zip *); 194299529Smmstatic int trad_enc_init(struct trad_enc_ctx *, const char *, size_t); 195299529Smmstatic unsigned trad_enc_encrypt_update(struct trad_enc_ctx *, const uint8_t *, 196299529Smm size_t, uint8_t *, size_t); 197299529Smmstatic int init_traditional_pkware_encryption(struct archive_write *); 198299529Smmstatic int is_traditional_pkware_encryption_supported(void); 199299529Smmstatic int init_winzip_aes_encryption(struct archive_write *); 200299529Smmstatic int is_winzip_aes_encryption_supported(int encryption); 201228753Smm 202299529Smmstatic unsigned char * 203299529Smmcd_alloc(struct zip *zip, size_t length) 204299529Smm{ 205299529Smm unsigned char *p; 206228753Smm 207299529Smm if (zip->central_directory == NULL 208299529Smm || (zip->central_directory_last->p + length 209299529Smm > zip->central_directory_last->buff + zip->central_directory_last->buff_size)) { 210299529Smm struct cd_segment *segment = calloc(1, sizeof(*segment)); 211299529Smm if (segment == NULL) 212299529Smm return NULL; 213299529Smm segment->buff_size = 64 * 1024; 214299529Smm segment->buff = malloc(segment->buff_size); 215299529Smm if (segment->buff == NULL) { 216299529Smm free(segment); 217299529Smm return NULL; 218299529Smm } 219299529Smm segment->p = segment->buff; 220228753Smm 221299529Smm if (zip->central_directory == NULL) { 222299529Smm zip->central_directory 223299529Smm = zip->central_directory_last 224299529Smm = segment; 225299529Smm } else { 226299529Smm zip->central_directory_last->next = segment; 227299529Smm zip->central_directory_last = segment; 228299529Smm } 229299529Smm } 230228753Smm 231299529Smm p = zip->central_directory_last->p; 232299529Smm zip->central_directory_last->p += length; 233299529Smm zip->central_directory_bytes += length; 234299529Smm return (p); 235299529Smm} 236228753Smm 237299529Smmstatic unsigned long 238299529Smmreal_crc32(unsigned long crc, const void *buff, size_t len) 239299529Smm{ 240299529Smm return crc32(crc, buff, (unsigned int)len); 241299529Smm} 242228753Smm 243299529Smmstatic unsigned long 244299529Smmfake_crc32(unsigned long crc, const void *buff, size_t len) 245299529Smm{ 246299529Smm (void)crc; /* UNUSED */ 247299529Smm (void)buff; /* UNUSED */ 248299529Smm (void)len; /* UNUSED */ 249299529Smm return 0; 250299529Smm} 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) { 260299529Smm /* 261299529Smm * Set compression to use on all future entries. 262299529Smm * This only affects regular files. 263299529Smm */ 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 270299529Smm 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) { 277299529Smm zip->requested_compression = COMPRESSION_STORE; 278232153Smm ret = ARCHIVE_OK; 279232153Smm } 280232153Smm return (ret); 281299529Smm } else if (strcmp(key, "compression-level") == 0) { 282299529Smm if (val == NULL || !(val[0] >= '0' && val[0] <= '9') || val[1] != '\0') { 283299529Smm return ARCHIVE_WARN; 284299529Smm } 285299529Smm 286299529Smm if (val[0] == '0') { 287299529Smm zip->requested_compression = COMPRESSION_STORE; 288299529Smm return ARCHIVE_OK; 289299529Smm } else { 290299529Smm#ifdef HAVE_ZLIB_H 291299529Smm zip->requested_compression = COMPRESSION_DEFLATE; 292299529Smm zip->deflate_compression_level = val[0] - '0'; 293299529Smm return ARCHIVE_OK; 294299529Smm#else 295299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 296299529Smm "deflate compression not supported"); 297299529Smm#endif 298299529Smm } 299299529Smm } else if (strcmp(key, "encryption") == 0) { 300299529Smm if (val == NULL) { 301299529Smm zip->encryption_type = ENCRYPTION_NONE; 302299529Smm ret = ARCHIVE_OK; 303299529Smm } else if (val[0] == '1' || strcmp(val, "traditional") == 0 304299529Smm || strcmp(val, "zipcrypt") == 0 305299529Smm || strcmp(val, "ZipCrypt") == 0) { 306299529Smm if (is_traditional_pkware_encryption_supported()) { 307299529Smm zip->encryption_type = ENCRYPTION_TRADITIONAL; 308299529Smm ret = ARCHIVE_OK; 309299529Smm } else { 310299529Smm archive_set_error(&a->archive, 311299529Smm ARCHIVE_ERRNO_MISC, 312299529Smm "encryption not supported"); 313299529Smm } 314299529Smm } else if (strcmp(val, "aes128") == 0) { 315299529Smm if (is_winzip_aes_encryption_supported( 316299529Smm ENCRYPTION_WINZIP_AES128)) { 317299529Smm zip->encryption_type = ENCRYPTION_WINZIP_AES128; 318299529Smm ret = ARCHIVE_OK; 319299529Smm } else { 320299529Smm archive_set_error(&a->archive, 321299529Smm ARCHIVE_ERRNO_MISC, 322299529Smm "encryption not supported"); 323299529Smm } 324299529Smm } else if (strcmp(val, "aes256") == 0) { 325299529Smm if (is_winzip_aes_encryption_supported( 326299529Smm ENCRYPTION_WINZIP_AES256)) { 327299529Smm zip->encryption_type = ENCRYPTION_WINZIP_AES256; 328299529Smm ret = ARCHIVE_OK; 329299529Smm } else { 330299529Smm archive_set_error(&a->archive, 331299529Smm ARCHIVE_ERRNO_MISC, 332299529Smm "encryption not supported"); 333299529Smm } 334299529Smm } else { 335299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 336299529Smm "%s: unknown encryption '%s'", 337299529Smm a->format_name, val); 338299529Smm } 339299529Smm return (ret); 340299529Smm } else if (strcmp(key, "experimental") == 0) { 341299529Smm if (val == NULL || val[0] == 0) { 342299529Smm zip->flags &= ~ ZIP_FLAG_EXPERIMENT_xl; 343299529Smm } else { 344299529Smm zip->flags |= ZIP_FLAG_EXPERIMENT_xl; 345299529Smm } 346299529Smm return (ARCHIVE_OK); 347299529Smm } else if (strcmp(key, "fakecrc32") == 0) { 348299529Smm /* 349299529Smm * FOR TESTING ONLY: disable CRC calculation to speed up 350299529Smm * certain complex tests. 351299529Smm */ 352299529Smm if (val == NULL || val[0] == 0) { 353299529Smm zip->crc32func = real_crc32; 354299529Smm } else { 355299529Smm zip->crc32func = fake_crc32; 356299529Smm } 357299529Smm return (ARCHIVE_OK); 358232153Smm } else if (strcmp(key, "hdrcharset") == 0) { 359299529Smm /* 360299529Smm * Set the character set used in translating filenames. 361299529Smm */ 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); 375299529Smm } else if (strcmp(key, "zip64") == 0) { 376299529Smm /* 377299529Smm * Bias decisions about Zip64: force them to be 378299529Smm * generated in certain cases where they are not 379299529Smm * forbidden or avoid them in certain cases where they 380299529Smm * are not strictly required. 381299529Smm */ 382299529Smm if (val != NULL && *val != '\0') { 383299529Smm zip->flags |= ZIP_FLAG_FORCE_ZIP64; 384299529Smm zip->flags &= ~ZIP_FLAG_AVOID_ZIP64; 385299529Smm } else { 386299529Smm zip->flags &= ~ZIP_FLAG_FORCE_ZIP64; 387299529Smm zip->flags |= ZIP_FLAG_AVOID_ZIP64; 388299529Smm } 389299529Smm 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; 403299529Smm 404248616Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 405299529Smm 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; 415299529Smm 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"); 420299529Smm 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; 432299529Smm 433248616Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 434299529Smm 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 { 442299529Smm 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 468299529Smm /* "Unspecified" lets us choose the appropriate compression. */ 469299529Smm zip->requested_compression = COMPRESSION_UNSPECIFIED; 470228753Smm#ifdef HAVE_ZLIB_H 471299529Smm zip->deflate_compression_level = Z_DEFAULT_COMPRESSION; 472299529Smm#endif 473299529Smm zip->crc32func = real_crc32; 474299529Smm 475299529Smm /* 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{ 514299529Smm unsigned char local_header[32]; 515299529Smm unsigned char local_extra[144]; 516299529Smm struct zip *zip = a->format_data; 517299529Smm unsigned char *e; 518299529Smm unsigned char *cd_extra; 519299529Smm size_t filename_length; 520299529Smm const char *slink = NULL; 521299529Smm size_t slink_size = 0; 522299529Smm struct archive_string_conv *sconv = get_sconv(a, zip); 523232153Smm int ret, ret2 = ARCHIVE_OK; 524228753Smm mode_t type; 525299529Smm int version_needed = 10; 526228753Smm 527299529Smm /* 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) { 530358088Smm __archive_write_entry_filetype_unsupported( 531358088Smm &a->archive, entry, "zip"); 532228753Smm return ARCHIVE_FAILED; 533248616Smm }; 534228753Smm 535299529Smm /* If we're not using Zip64, reject large files. */ 536299529Smm if (zip->flags & ZIP_FLAG_AVOID_ZIP64) { 537299529Smm /* Reject entries over 4GB. */ 538299529Smm if (archive_entry_size_is_set(entry) 539299529Smm && (archive_entry_size(entry) > ZIP_4GB_MAX)) { 540299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 541299529Smm "Files > 4GB require Zip64 extensions"); 542299529Smm return ARCHIVE_FAILED; 543299529Smm } 544299529Smm /* Reject entries if archive is > 4GB. */ 545299529Smm if (zip->written_bytes > ZIP_4GB_MAX) { 546299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 547299529Smm "Archives > 4GB require Zip64 extensions"); 548299529Smm return ARCHIVE_FAILED; 549299529Smm } 550299529Smm } 551299529Smm 552299529Smm /* Only regular files can have size > 0. */ 553299529Smm if (type != AE_IFREG) 554228753Smm archive_entry_set_size(entry, 0); 555228753Smm 556299529Smm 557299529Smm /* Reset information from last entry. */ 558299529Smm zip->entry_offset = zip->written_bytes; 559299529Smm zip->entry_uncompressed_limit = INT64_MAX; 560299529Smm zip->entry_compressed_size = 0; 561299529Smm zip->entry_uncompressed_size = 0; 562299529Smm zip->entry_compressed_written = 0; 563299529Smm zip->entry_uncompressed_written = 0; 564299529Smm zip->entry_flags = 0; 565299529Smm zip->entry_uses_zip64 = 0; 566299529Smm zip->entry_crc32 = zip->crc32func(0, NULL, 0); 567299529Smm zip->entry_encryption = 0; 568344673Smm archive_entry_free(zip->entry); 569344673Smm zip->entry = NULL; 570232153Smm 571299529Smm if (zip->cctx_valid) 572299529Smm archive_encrypto_aes_ctr_release(&zip->cctx); 573299529Smm if (zip->hctx_valid) 574299529Smm archive_hmac_sha1_cleanup(&zip->hctx); 575299529Smm zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; 576299529Smm 577299529Smm if (type == AE_IFREG 578299529Smm &&(!archive_entry_size_is_set(entry) 579299529Smm || archive_entry_size(entry) > 0)) { 580299529Smm switch (zip->encryption_type) { 581299529Smm case ENCRYPTION_TRADITIONAL: 582299529Smm case ENCRYPTION_WINZIP_AES128: 583299529Smm case ENCRYPTION_WINZIP_AES256: 584299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED; 585299529Smm zip->entry_encryption = zip->encryption_type; 586299529Smm break; 587368707Smm case ENCRYPTION_NONE: 588299529Smm default: 589299529Smm break; 590232153Smm } 591232153Smm } 592228753Smm 593299529Smm 594232153Smm#if defined(_WIN32) && !defined(__CYGWIN__) 595311041Smm /* Make sure the path separators in pathname, hardlink and symlink 596232153Smm * are all slash '/', not the Windows path separator '\'. */ 597299529Smm zip->entry = __la_win_entry_in_posix_pathseparator(entry); 598299529Smm if (zip->entry == entry) 599299529Smm zip->entry = archive_entry_clone(entry); 600232153Smm#else 601299529Smm zip->entry = archive_entry_clone(entry); 602232153Smm#endif 603299529Smm if (zip->entry == NULL) { 604232153Smm archive_set_error(&a->archive, ENOMEM, 605232153Smm "Can't allocate zip header data"); 606232153Smm return (ARCHIVE_FATAL); 607232153Smm } 608299529Smm 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) 627299529Smm archive_entry_set_pathname(zip->entry, p); 628238856Smm 629238856Smm /* 630299529Smm * There is no standard for symlink handling; we convert 631299529Smm * it using the same character-set translation that we use 632299529Smm * 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 } 642299529Smm /* No error if we can't convert. */ 643238856Smm } else if (len > 0) 644299529Smm archive_entry_set_symlink(zip->entry, p); 645238856Smm } 646232153Smm } 647232153Smm 648299529Smm /* If filename isn't ASCII and we can use UTF-8, set the UTF-8 flag. */ 649299529Smm if (!is_all_ascii(archive_entry_pathname(zip->entry))) { 650299529Smm if (zip->opt_sconv != NULL) { 651299529Smm if (strcmp(archive_string_conversion_charset_name( 652299529Smm zip->opt_sconv), "UTF-8") == 0) 653299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; 654299529Smm#if HAVE_NL_LANGINFO 655299529Smm } else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { 656299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; 657299529Smm#endif 658299529Smm } 659299529Smm } 660299529Smm filename_length = path_length(zip->entry); 661299529Smm 662299529Smm /* Determine appropriate compression and size for this entry. */ 663232153Smm if (type == AE_IFLNK) { 664299529Smm slink = archive_entry_symlink(zip->entry); 665299529Smm if (slink != NULL) 666299529Smm slink_size = strlen(slink); 667232153Smm else 668299529Smm slink_size = 0; 669299529Smm zip->entry_uncompressed_limit = slink_size; 670299529Smm zip->entry_compressed_size = slink_size; 671299529Smm zip->entry_uncompressed_size = slink_size; 672299529Smm zip->entry_crc32 = zip->crc32func(zip->entry_crc32, 673299529Smm (const unsigned char *)slink, slink_size); 674299529Smm zip->entry_compression = COMPRESSION_STORE; 675299529Smm version_needed = 20; 676299529Smm } else if (type != AE_IFREG) { 677299529Smm zip->entry_compression = COMPRESSION_STORE; 678299529Smm zip->entry_uncompressed_limit = 0; 679299529Smm version_needed = 20; 680299529Smm } else if (archive_entry_size_is_set(zip->entry)) { 681299529Smm int64_t size = archive_entry_size(zip->entry); 682299529Smm int64_t additional_size = 0; 683299529Smm 684299529Smm zip->entry_uncompressed_limit = size; 685299529Smm zip->entry_compression = zip->requested_compression; 686299529Smm if (zip->entry_compression == COMPRESSION_UNSPECIFIED) { 687299529Smm zip->entry_compression = COMPRESSION_DEFAULT; 688299529Smm } 689299529Smm if (zip->entry_compression == COMPRESSION_STORE) { 690299529Smm zip->entry_compressed_size = size; 691299529Smm zip->entry_uncompressed_size = size; 692299529Smm version_needed = 10; 693299529Smm } else { 694299529Smm zip->entry_uncompressed_size = size; 695299529Smm version_needed = 20; 696299529Smm } 697299529Smm 698299529Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 699299529Smm switch (zip->entry_encryption) { 700299529Smm case ENCRYPTION_TRADITIONAL: 701299529Smm additional_size = TRAD_HEADER_SIZE; 702299529Smm version_needed = 20; 703299529Smm break; 704299529Smm case ENCRYPTION_WINZIP_AES128: 705299529Smm additional_size = WINZIP_AES128_HEADER_SIZE 706299529Smm + AUTH_CODE_SIZE; 707299529Smm version_needed = 20; 708299529Smm break; 709299529Smm case ENCRYPTION_WINZIP_AES256: 710299529Smm additional_size = WINZIP_AES256_HEADER_SIZE 711299529Smm + AUTH_CODE_SIZE; 712299529Smm version_needed = 20; 713299529Smm break; 714368707Smm case ENCRYPTION_NONE: 715299529Smm default: 716299529Smm break; 717299529Smm } 718299529Smm if (zip->entry_compression == COMPRESSION_STORE) 719299529Smm zip->entry_compressed_size += additional_size; 720299529Smm } 721299529Smm 722299529Smm /* 723299529Smm * Set Zip64 extension in any of the following cases 724299529Smm * (this was suggested by discussion on info-zip-dev 725299529Smm * mailing list): 726299529Smm * = Zip64 is being forced by user 727299529Smm * = File is over 4GiB uncompressed 728299529Smm * (including encryption header, if any) 729299529Smm * = File is close to 4GiB and is being compressed 730299529Smm * (compression might make file larger) 731299529Smm */ 732299529Smm if ((zip->flags & ZIP_FLAG_FORCE_ZIP64) 733299529Smm || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX) 734299529Smm || (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED 735299529Smm && zip->entry_compression != COMPRESSION_STORE)) { 736299529Smm zip->entry_uses_zip64 = 1; 737299529Smm version_needed = 45; 738299529Smm } 739299529Smm 740299529Smm /* We may know the size, but never the CRC. */ 741299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; 742232153Smm } else { 743299529Smm /* We don't know the size. In this case, we prefer 744299529Smm * deflate (it has a clear end-of-data marker which 745299529Smm * makes length-at-end more reliable) and will 746299529Smm * enable Zip64 extensions unless we're told not to. 747299529Smm */ 748299529Smm zip->entry_compression = COMPRESSION_DEFAULT; 749299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; 750299529Smm if ((zip->flags & ZIP_FLAG_AVOID_ZIP64) == 0) { 751299529Smm zip->entry_uses_zip64 = 1; 752299529Smm version_needed = 45; 753299529Smm } else if (zip->entry_compression == COMPRESSION_STORE) { 754299529Smm version_needed = 10; 755299529Smm } else { 756299529Smm version_needed = 20; 757299529Smm } 758299529Smm 759299529Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 760299529Smm switch (zip->entry_encryption) { 761299529Smm case ENCRYPTION_TRADITIONAL: 762299529Smm case ENCRYPTION_WINZIP_AES128: 763299529Smm case ENCRYPTION_WINZIP_AES256: 764299529Smm if (version_needed < 20) 765299529Smm version_needed = 20; 766299529Smm break; 767368707Smm case ENCRYPTION_NONE: 768299529Smm default: 769299529Smm break; 770299529Smm } 771299529Smm } 772232153Smm } 773299529Smm 774299529Smm /* Format the local header. */ 775299529Smm memset(local_header, 0, sizeof(local_header)); 776299529Smm memcpy(local_header, "PK\003\004", 4); 777299529Smm archive_le16enc(local_header + 4, version_needed); 778299529Smm archive_le16enc(local_header + 6, zip->entry_flags); 779299529Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 780299529Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) 781299529Smm archive_le16enc(local_header + 8, WINZIP_AES_ENCRYPTION); 782299529Smm else 783299529Smm archive_le16enc(local_header + 8, zip->entry_compression); 784299529Smm archive_le32enc(local_header + 10, 785299529Smm dos_time(archive_entry_mtime(zip->entry))); 786299529Smm archive_le32enc(local_header + 14, zip->entry_crc32); 787299529Smm if (zip->entry_uses_zip64) { 788299529Smm /* Zip64 data in the local header "must" include both 789299529Smm * compressed and uncompressed sizes AND those fields 790299529Smm * are included only if these are 0xffffffff; 791299529Smm * THEREFORE these must be set this way, even if we 792299529Smm * know one of them is smaller. */ 793299529Smm archive_le32enc(local_header + 18, ZIP_4GB_MAX); 794299529Smm archive_le32enc(local_header + 22, ZIP_4GB_MAX); 795228753Smm } else { 796299529Smm archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size); 797299529Smm archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size); 798228753Smm } 799299529Smm archive_le16enc(local_header + 26, (uint16_t)filename_length); 800228753Smm 801299529Smm if (zip->entry_encryption == ENCRYPTION_TRADITIONAL) { 802299529Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) 803299529Smm zip->trad_chkdat = local_header[11]; 804299529Smm else 805299529Smm zip->trad_chkdat = local_header[17]; 806299529Smm } 807228753Smm 808299529Smm /* Format as much of central directory file header as we can: */ 809299529Smm zip->file_header = cd_alloc(zip, 46); 810299529Smm /* If (zip->file_header == NULL) XXXX */ 811299529Smm ++zip->central_directory_entries; 812299529Smm memset(zip->file_header, 0, 46); 813299529Smm memcpy(zip->file_header, "PK\001\002", 4); 814299529Smm /* "Made by PKZip 2.0 on Unix." */ 815299529Smm archive_le16enc(zip->file_header + 4, 3 * 256 + version_needed); 816299529Smm archive_le16enc(zip->file_header + 6, version_needed); 817299529Smm archive_le16enc(zip->file_header + 8, zip->entry_flags); 818299529Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 819299529Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) 820299529Smm archive_le16enc(zip->file_header + 10, WINZIP_AES_ENCRYPTION); 821299529Smm else 822299529Smm archive_le16enc(zip->file_header + 10, zip->entry_compression); 823299529Smm archive_le32enc(zip->file_header + 12, 824299529Smm dos_time(archive_entry_mtime(zip->entry))); 825299529Smm archive_le16enc(zip->file_header + 28, (uint16_t)filename_length); 826299529Smm /* Following Info-Zip, store mode in the "external attributes" field. */ 827299529Smm archive_le32enc(zip->file_header + 38, 828299529Smm ((uint32_t)archive_entry_mode(zip->entry)) << 16); 829299529Smm e = cd_alloc(zip, filename_length); 830299529Smm /* If (e == NULL) XXXX */ 831299529Smm copy_path(zip->entry, e); 832228753Smm 833299529Smm /* Format extra data. */ 834299529Smm memset(local_extra, 0, sizeof(local_extra)); 835299529Smm e = local_extra; 836228753Smm 837299529Smm /* First, extra blocks that are the same between 838299529Smm * the local file header and the central directory. 839299529Smm * We format them once and then duplicate them. */ 840299529Smm 841299529Smm /* UT timestamp, length depends on what timestamps are set. */ 842299529Smm memcpy(e, "UT", 2); 843299529Smm archive_le16enc(e + 2, 844299529Smm 1 845299529Smm + (archive_entry_mtime_is_set(entry) ? 4 : 0) 846299529Smm + (archive_entry_atime_is_set(entry) ? 4 : 0) 847299529Smm + (archive_entry_ctime_is_set(entry) ? 4 : 0)); 848299529Smm e += 4; 849299529Smm *e++ = 850299529Smm (archive_entry_mtime_is_set(entry) ? 1 : 0) 851299529Smm | (archive_entry_atime_is_set(entry) ? 2 : 0) 852299529Smm | (archive_entry_ctime_is_set(entry) ? 4 : 0); 853299529Smm if (archive_entry_mtime_is_set(entry)) { 854299529Smm archive_le32enc(e, (uint32_t)archive_entry_mtime(entry)); 855299529Smm e += 4; 856228753Smm } 857299529Smm if (archive_entry_atime_is_set(entry)) { 858299529Smm archive_le32enc(e, (uint32_t)archive_entry_atime(entry)); 859299529Smm e += 4; 860299529Smm } 861299529Smm if (archive_entry_ctime_is_set(entry)) { 862299529Smm archive_le32enc(e, (uint32_t)archive_entry_ctime(entry)); 863299529Smm e += 4; 864299529Smm } 865228753Smm 866299529Smm /* ux Unix extra data, length 11, version 1 */ 867299529Smm /* TODO: If uid < 64k, use 2 bytes, ditto for gid. */ 868299529Smm memcpy(e, "ux\013\000\001", 5); 869299529Smm e += 5; 870299529Smm *e++ = 4; /* Length of following UID */ 871299529Smm archive_le32enc(e, (uint32_t)archive_entry_uid(entry)); 872299529Smm e += 4; 873299529Smm *e++ = 4; /* Length of following GID */ 874299529Smm archive_le32enc(e, (uint32_t)archive_entry_gid(entry)); 875299529Smm e += 4; 876228753Smm 877299529Smm /* AES extra data field: WinZIP AES information, ID=0x9901 */ 878299529Smm if ((zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) 879299529Smm && (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 880299529Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) { 881232153Smm 882299529Smm memcpy(e, "\001\231\007\000\001\000AE", 8); 883313570Smm /* AES vendor version AE-2 does not store a CRC. 884299529Smm * WinZip 11 uses AE-1, which does store the CRC, 885299529Smm * but it does not store the CRC when the file size 886299529Smm * is less than 20 bytes. So we simulate what 887299529Smm * WinZip 11 does. 888299529Smm * NOTE: WinZip 9.0 and 10.0 uses AE-2 by default. */ 889299529Smm if (archive_entry_size_is_set(zip->entry) 890299529Smm && archive_entry_size(zip->entry) < 20) { 891299529Smm archive_le16enc(e+4, AES_VENDOR_AE_2); 892299529Smm zip->aes_vendor = AES_VENDOR_AE_2;/* no CRC. */ 893299529Smm } else 894299529Smm zip->aes_vendor = AES_VENDOR_AE_1; 895299529Smm e += 8; 896299529Smm /* AES encryption strength. */ 897299529Smm *e++ = (zip->entry_encryption == ENCRYPTION_WINZIP_AES128)?1:3; 898299529Smm /* Actual compression method. */ 899299529Smm archive_le16enc(e, zip->entry_compression); 900299529Smm e += 2; 901299529Smm } 902228753Smm 903299529Smm /* Copy UT ,ux, and AES-extra into central directory as well. */ 904299529Smm zip->file_header_extra_offset = zip->central_directory_bytes; 905299529Smm cd_extra = cd_alloc(zip, e - local_extra); 906299529Smm memcpy(cd_extra, local_extra, e - local_extra); 907299529Smm 908299529Smm /* 909299529Smm * Following extra blocks vary between local header and 910299529Smm * central directory. These are the local header versions. 911299529Smm * Central directory versions get formatted in 912299529Smm * archive_write_zip_finish_entry() below. 913299529Smm */ 914299529Smm 915299529Smm /* "[Zip64 entry] in the local header MUST include BOTH 916299529Smm * original [uncompressed] and compressed size fields." */ 917299529Smm if (zip->entry_uses_zip64) { 918299529Smm unsigned char *zip64_start = e; 919299529Smm memcpy(e, "\001\000\020\000", 4); 920299529Smm e += 4; 921299529Smm archive_le64enc(e, zip->entry_uncompressed_size); 922299529Smm e += 8; 923299529Smm archive_le64enc(e, zip->entry_compressed_size); 924299529Smm e += 8; 925299529Smm archive_le16enc(zip64_start + 2, (uint16_t)(e - (zip64_start + 4))); 926299529Smm } 927299529Smm 928299529Smm if (zip->flags & ZIP_FLAG_EXPERIMENT_xl) { 929299529Smm /* Experimental 'xl' extension to improve streaming. */ 930299529Smm unsigned char *external_info = e; 931299529Smm int included = 7; 932299529Smm memcpy(e, "xl\000\000", 4); // 0x6c65 + 2-byte length 933299529Smm e += 4; 934299529Smm e[0] = included; /* bitmap of included fields */ 935299529Smm e += 1; 936299529Smm if (included & 1) { 937299529Smm archive_le16enc(e, /* "Version created by" */ 938299529Smm 3 * 256 + version_needed); 939299529Smm e += 2; 940299529Smm } 941299529Smm if (included & 2) { 942299529Smm archive_le16enc(e, 0); /* internal file attributes */ 943299529Smm e += 2; 944299529Smm } 945299529Smm if (included & 4) { 946299529Smm archive_le32enc(e, /* external file attributes */ 947299529Smm ((uint32_t)archive_entry_mode(zip->entry)) << 16); 948299529Smm e += 4; 949299529Smm } 950299529Smm if (included & 8) { 951299529Smm // Libarchive does not currently support file comments. 952299529Smm } 953299529Smm archive_le16enc(external_info + 2, (uint16_t)(e - (external_info + 4))); 954299529Smm } 955299529Smm 956299529Smm /* Update local header with size of extra data and write it all out: */ 957299529Smm archive_le16enc(local_header + 28, (uint16_t)(e - local_extra)); 958299529Smm 959299529Smm ret = __archive_write_output(a, local_header, 30); 960228753Smm if (ret != ARCHIVE_OK) 961228753Smm return (ARCHIVE_FATAL); 962299529Smm zip->written_bytes += 30; 963228753Smm 964299529Smm ret = write_path(zip->entry, a); 965228753Smm if (ret <= ARCHIVE_OK) 966228753Smm return (ARCHIVE_FATAL); 967228753Smm zip->written_bytes += ret; 968228753Smm 969299529Smm ret = __archive_write_output(a, local_extra, e - local_extra); 970228753Smm if (ret != ARCHIVE_OK) 971228753Smm return (ARCHIVE_FATAL); 972299529Smm zip->written_bytes += e - local_extra; 973228753Smm 974299529Smm /* For symlinks, write the body now. */ 975299529Smm if (slink != NULL) { 976299529Smm ret = __archive_write_output(a, slink, slink_size); 977232153Smm if (ret != ARCHIVE_OK) 978232153Smm return (ARCHIVE_FATAL); 979299529Smm zip->entry_compressed_written += slink_size; 980299529Smm zip->entry_uncompressed_written += slink_size; 981299529Smm zip->written_bytes += slink_size; 982232153Smm } 983232153Smm 984299529Smm#ifdef HAVE_ZLIB_H 985299529Smm if (zip->entry_compression == COMPRESSION_DEFLATE) { 986299529Smm zip->stream.zalloc = Z_NULL; 987299529Smm zip->stream.zfree = Z_NULL; 988299529Smm zip->stream.opaque = Z_NULL; 989299529Smm zip->stream.next_out = zip->buf; 990299529Smm zip->stream.avail_out = (uInt)zip->len_buf; 991299529Smm if (deflateInit2(&zip->stream, zip->deflate_compression_level, 992299529Smm Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { 993299529Smm archive_set_error(&a->archive, ENOMEM, 994299529Smm "Can't init deflate compressor"); 995299529Smm return (ARCHIVE_FATAL); 996299529Smm } 997299529Smm } 998299529Smm#endif 999299529Smm 1000299529Smm 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 1009299529Smm if ((int64_t)s > zip->entry_uncompressed_limit) 1010299529Smm s = (size_t)zip->entry_uncompressed_limit; 1011299529Smm zip->entry_uncompressed_written += s; 1012228753Smm 1013228753Smm if (s == 0) return 0; 1014228753Smm 1015299529Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 1016299529Smm switch (zip->entry_encryption) { 1017299529Smm case ENCRYPTION_TRADITIONAL: 1018313570Smm /* Initialize traditional PKWARE encryption context. */ 1019299529Smm if (!zip->tctx_valid) { 1020299529Smm ret = init_traditional_pkware_encryption(a); 1021299529Smm if (ret != ARCHIVE_OK) 1022299529Smm return (ret); 1023299529Smm zip->tctx_valid = 1; 1024299529Smm } 1025299529Smm break; 1026299529Smm case ENCRYPTION_WINZIP_AES128: 1027299529Smm case ENCRYPTION_WINZIP_AES256: 1028299529Smm if (!zip->cctx_valid) { 1029299529Smm ret = init_winzip_aes_encryption(a); 1030299529Smm if (ret != ARCHIVE_OK) 1031299529Smm return (ret); 1032299529Smm zip->cctx_valid = zip->hctx_valid = 1; 1033299529Smm } 1034299529Smm break; 1035368707Smm case ENCRYPTION_NONE: 1036299529Smm default: 1037299529Smm break; 1038299529Smm } 1039299529Smm } 1040299529Smm 1041299529Smm switch (zip->entry_compression) { 1042228753Smm case COMPRESSION_STORE: 1043299529Smm if (zip->tctx_valid || zip->cctx_valid) { 1044299529Smm const uint8_t *rb = (const uint8_t *)buff; 1045299529Smm const uint8_t * const re = rb + s; 1046299529Smm 1047299529Smm while (rb < re) { 1048299529Smm size_t l; 1049299529Smm 1050299529Smm if (zip->tctx_valid) { 1051299529Smm l = trad_enc_encrypt_update(&zip->tctx, 1052299529Smm rb, re - rb, 1053299529Smm zip->buf, zip->len_buf); 1054299529Smm } else { 1055299529Smm l = zip->len_buf; 1056299529Smm ret = archive_encrypto_aes_ctr_update( 1057299529Smm &zip->cctx, 1058299529Smm rb, re - rb, zip->buf, &l); 1059299529Smm if (ret < 0) { 1060299529Smm archive_set_error(&a->archive, 1061299529Smm ARCHIVE_ERRNO_MISC, 1062299529Smm "Failed to encrypt file"); 1063299529Smm return (ARCHIVE_FAILED); 1064299529Smm } 1065299529Smm archive_hmac_sha1_update(&zip->hctx, 1066299529Smm zip->buf, l); 1067299529Smm } 1068299529Smm ret = __archive_write_output(a, zip->buf, l); 1069299529Smm if (ret != ARCHIVE_OK) 1070299529Smm return (ret); 1071299529Smm zip->entry_compressed_written += l; 1072299529Smm zip->written_bytes += l; 1073299529Smm rb += l; 1074299529Smm } 1075299529Smm } else { 1076299529Smm ret = __archive_write_output(a, buff, s); 1077299529Smm if (ret != ARCHIVE_OK) 1078299529Smm return (ret); 1079299529Smm zip->written_bytes += s; 1080299529Smm zip->entry_compressed_written += s; 1081299529Smm } 1082299529Smm 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) { 1092299529Smm if (zip->tctx_valid) { 1093299529Smm trad_enc_encrypt_update(&zip->tctx, 1094299529Smm zip->buf, zip->len_buf, 1095299529Smm zip->buf, zip->len_buf); 1096299529Smm } else if (zip->cctx_valid) { 1097299529Smm size_t outl = zip->len_buf; 1098299529Smm ret = archive_encrypto_aes_ctr_update( 1099299529Smm &zip->cctx, 1100299529Smm zip->buf, zip->len_buf, 1101299529Smm zip->buf, &outl); 1102299529Smm if (ret < 0) { 1103299529Smm archive_set_error(&a->archive, 1104299529Smm ARCHIVE_ERRNO_MISC, 1105299529Smm "Failed to encrypt file"); 1106299529Smm return (ARCHIVE_FAILED); 1107299529Smm } 1108299529Smm archive_hmac_sha1_update(&zip->hctx, 1109299529Smm zip->buf, zip->len_buf); 1110299529Smm } 1111232153Smm ret = __archive_write_output(a, zip->buf, 1112232153Smm zip->len_buf); 1113228753Smm if (ret != ARCHIVE_OK) 1114228753Smm return (ret); 1115299529Smm 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); 1121299529Smm break; 1122228753Smm#endif 1123228753Smm 1124368707Smm case COMPRESSION_UNSPECIFIED: 1125228753Smm default: 1126228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1127228753Smm "Invalid ZIP compression type"); 1128228753Smm return ARCHIVE_FATAL; 1129228753Smm } 1130299529Smm 1131299529Smm zip->entry_uncompressed_limit -= s; 1132299529Smm if (!zip->cctx_valid || zip->aes_vendor != AES_VENDOR_AE_2) 1133299529Smm zip->entry_crc32 = 1134299529Smm zip->crc32func(zip->entry_crc32, buff, (unsigned)s); 1135299529Smm return (s); 1136299529Smm 1137228753Smm} 1138228753Smm 1139228753Smmstatic int 1140228753Smmarchive_write_zip_finish_entry(struct archive_write *a) 1141228753Smm{ 1142299529Smm struct zip *zip = a->format_data; 1143228753Smm int ret; 1144228753Smm 1145228753Smm#if HAVE_ZLIB_H 1146299529Smm if (zip->entry_compression == COMPRESSION_DEFLATE) { 1147228753Smm for (;;) { 1148299529Smm size_t remainder; 1149299529Smm 1150228753Smm ret = deflate(&zip->stream, Z_FINISH); 1151228753Smm if (ret == Z_STREAM_ERROR) 1152228753Smm return (ARCHIVE_FATAL); 1153299529Smm remainder = zip->len_buf - zip->stream.avail_out; 1154299529Smm if (zip->tctx_valid) { 1155299529Smm trad_enc_encrypt_update(&zip->tctx, 1156299529Smm zip->buf, remainder, zip->buf, remainder); 1157299529Smm } else if (zip->cctx_valid) { 1158299529Smm size_t outl = remainder; 1159299529Smm ret = archive_encrypto_aes_ctr_update( 1160299529Smm &zip->cctx, zip->buf, remainder, 1161299529Smm zip->buf, &outl); 1162299529Smm if (ret < 0) { 1163299529Smm archive_set_error(&a->archive, 1164299529Smm ARCHIVE_ERRNO_MISC, 1165299529Smm "Failed to encrypt file"); 1166299529Smm return (ARCHIVE_FAILED); 1167299529Smm } 1168299529Smm archive_hmac_sha1_update(&zip->hctx, 1169299529Smm zip->buf, remainder); 1170299529Smm } 1171299529Smm ret = __archive_write_output(a, zip->buf, remainder); 1172228753Smm if (ret != ARCHIVE_OK) 1173228753Smm return (ret); 1174299529Smm zip->entry_compressed_written += remainder; 1175299529Smm 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); 1182299529Smm } 1183228753Smm#endif 1184299529Smm if (zip->hctx_valid) { 1185299529Smm uint8_t hmac[20]; 1186299529Smm size_t hmac_len = 20; 1187299529Smm 1188299529Smm archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len); 1189299529Smm ret = __archive_write_output(a, hmac, AUTH_CODE_SIZE); 1190299529Smm if (ret != ARCHIVE_OK) 1191299529Smm return (ret); 1192299529Smm zip->entry_compressed_written += AUTH_CODE_SIZE; 1193299529Smm zip->written_bytes += AUTH_CODE_SIZE; 1194228753Smm } 1195228753Smm 1196299529Smm /* Write trailing data descriptor. */ 1197299529Smm if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) != 0) { 1198299529Smm char d[24]; 1199299529Smm memcpy(d, "PK\007\010", 4); 1200299529Smm if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) 1201299529Smm archive_le32enc(d + 4, 0);/* no CRC.*/ 1202299529Smm else 1203299529Smm archive_le32enc(d + 4, zip->entry_crc32); 1204299529Smm if (zip->entry_uses_zip64) { 1205299529Smm archive_le64enc(d + 8, 1206299529Smm (uint64_t)zip->entry_compressed_written); 1207299529Smm archive_le64enc(d + 16, 1208299529Smm (uint64_t)zip->entry_uncompressed_written); 1209299529Smm ret = __archive_write_output(a, d, 24); 1210299529Smm zip->written_bytes += 24; 1211299529Smm } else { 1212299529Smm archive_le32enc(d + 8, 1213299529Smm (uint32_t)zip->entry_compressed_written); 1214299529Smm archive_le32enc(d + 12, 1215299529Smm (uint32_t)zip->entry_uncompressed_written); 1216299529Smm ret = __archive_write_output(a, d, 16); 1217299529Smm zip->written_bytes += 16; 1218299529Smm } 1219299529Smm if (ret != ARCHIVE_OK) 1220299529Smm return (ARCHIVE_FATAL); 1221299529Smm } 1222299529Smm 1223299529Smm /* Append Zip64 extra data to central directory information. */ 1224299529Smm if (zip->entry_compressed_written > ZIP_4GB_MAX 1225299529Smm || zip->entry_uncompressed_written > ZIP_4GB_MAX 1226299529Smm || zip->entry_offset > ZIP_4GB_MAX) { 1227299529Smm unsigned char zip64[32]; 1228299529Smm unsigned char *z = zip64, *zd; 1229299529Smm memcpy(z, "\001\000\000\000", 4); 1230299529Smm z += 4; 1231299529Smm if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) { 1232299529Smm archive_le64enc(z, zip->entry_uncompressed_written); 1233299529Smm z += 8; 1234299529Smm } 1235299529Smm if (zip->entry_compressed_written >= ZIP_4GB_MAX) { 1236299529Smm archive_le64enc(z, zip->entry_compressed_written); 1237299529Smm z += 8; 1238299529Smm } 1239299529Smm if (zip->entry_offset >= ZIP_4GB_MAX) { 1240299529Smm archive_le64enc(z, zip->entry_offset); 1241299529Smm z += 8; 1242299529Smm } 1243299529Smm archive_le16enc(zip64 + 2, (uint16_t)(z - (zip64 + 4))); 1244299529Smm zd = cd_alloc(zip, z - zip64); 1245299529Smm if (zd == NULL) { 1246299529Smm archive_set_error(&a->archive, ENOMEM, 1247299529Smm "Can't allocate zip data"); 1248299529Smm return (ARCHIVE_FATAL); 1249299529Smm } 1250299529Smm memcpy(zd, zip64, z - zip64); 1251299529Smm /* Zip64 means version needs to be set to at least 4.5 */ 1252299529Smm if (archive_le16dec(zip->file_header + 6) < 45) 1253299529Smm archive_le16enc(zip->file_header + 6, 45); 1254299529Smm } 1255299529Smm 1256299529Smm /* Fix up central directory file header. */ 1257299529Smm if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) 1258299529Smm archive_le32enc(zip->file_header + 16, 0);/* no CRC.*/ 1259299529Smm else 1260299529Smm archive_le32enc(zip->file_header + 16, zip->entry_crc32); 1261299529Smm archive_le32enc(zip->file_header + 20, 1262299529Smm (uint32_t)zipmin(zip->entry_compressed_written, 1263299529Smm ZIP_4GB_MAX)); 1264299529Smm archive_le32enc(zip->file_header + 24, 1265299529Smm (uint32_t)zipmin(zip->entry_uncompressed_written, 1266299529Smm ZIP_4GB_MAX)); 1267299529Smm archive_le16enc(zip->file_header + 30, 1268299529Smm (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset)); 1269299529Smm archive_le32enc(zip->file_header + 42, 1270299529Smm (uint32_t)zipmin(zip->entry_offset, 1271299529Smm ZIP_4GB_MAX)); 1272299529Smm 1273228753Smm return (ARCHIVE_OK); 1274228753Smm} 1275228753Smm 1276228753Smmstatic int 1277232153Smmarchive_write_zip_close(struct archive_write *a) 1278228753Smm{ 1279299529Smm uint8_t buff[64]; 1280232153Smm int64_t offset_start, offset_end; 1281299529Smm struct zip *zip = a->format_data; 1282299529Smm struct cd_segment *segment; 1283228753Smm int ret; 1284228753Smm 1285228753Smm offset_start = zip->written_bytes; 1286299529Smm segment = zip->central_directory; 1287299529Smm while (segment != NULL) { 1288299529Smm ret = __archive_write_output(a, 1289299529Smm segment->buff, segment->p - segment->buff); 1290228753Smm if (ret != ARCHIVE_OK) 1291228753Smm return (ARCHIVE_FATAL); 1292299529Smm zip->written_bytes += segment->p - segment->buff; 1293299529Smm segment = segment->next; 1294299529Smm } 1295299529Smm offset_end = zip->written_bytes; 1296228753Smm 1297299529Smm /* If central dir info is too large, write Zip64 end-of-cd */ 1298299529Smm if (offset_end - offset_start > ZIP_4GB_MAX 1299299529Smm || offset_start > ZIP_4GB_MAX 1300299529Smm || zip->central_directory_entries > 0xffffUL 1301299529Smm || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) { 1302299529Smm /* Zip64 end-of-cd record */ 1303299529Smm memset(buff, 0, 56); 1304299529Smm memcpy(buff, "PK\006\006", 4); 1305299529Smm archive_le64enc(buff + 4, 44); 1306299529Smm archive_le16enc(buff + 12, 45); 1307299529Smm archive_le16enc(buff + 14, 45); 1308299529Smm /* This is disk 0 of 0. */ 1309299529Smm archive_le64enc(buff + 24, zip->central_directory_entries); 1310299529Smm archive_le64enc(buff + 32, zip->central_directory_entries); 1311299529Smm archive_le64enc(buff + 40, offset_end - offset_start); 1312299529Smm archive_le64enc(buff + 48, offset_start); 1313299529Smm ret = __archive_write_output(a, buff, 56); 1314299529Smm if (ret != ARCHIVE_OK) 1315299529Smm return (ARCHIVE_FATAL); 1316299529Smm zip->written_bytes += 56; 1317228753Smm 1318299529Smm /* Zip64 end-of-cd locator record. */ 1319299529Smm memset(buff, 0, 20); 1320299529Smm memcpy(buff, "PK\006\007", 4); 1321299529Smm archive_le32enc(buff + 4, 0); 1322299529Smm archive_le64enc(buff + 8, offset_end); 1323299529Smm archive_le32enc(buff + 16, 1); 1324299529Smm ret = __archive_write_output(a, buff, 20); 1325299529Smm if (ret != ARCHIVE_OK) 1326299529Smm return (ARCHIVE_FATAL); 1327299529Smm zip->written_bytes += 20; 1328228753Smm 1329228753Smm } 1330228753Smm 1331299529Smm /* Format and write end of central directory. */ 1332299529Smm memset(buff, 0, sizeof(buff)); 1333299529Smm memcpy(buff, "PK\005\006", 4); 1334299529Smm archive_le16enc(buff + 8, (uint16_t)zipmin(0xffffU, 1335299529Smm zip->central_directory_entries)); 1336299529Smm archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU, 1337299529Smm zip->central_directory_entries)); 1338299529Smm archive_le32enc(buff + 12, 1339299529Smm (uint32_t)zipmin(ZIP_4GB_MAX, (offset_end - offset_start))); 1340299529Smm archive_le32enc(buff + 16, 1341299529Smm (uint32_t)zipmin(ZIP_4GB_MAX, offset_start)); 1342299529Smm ret = __archive_write_output(a, buff, 22); 1343228753Smm if (ret != ARCHIVE_OK) 1344228753Smm return (ARCHIVE_FATAL); 1345299529Smm 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; 1353299529Smm struct cd_segment *segment; 1354228753Smm 1355228753Smm zip = a->format_data; 1356228753Smm while (zip->central_directory != NULL) { 1357299529Smm segment = zip->central_directory; 1358299529Smm zip->central_directory = segment->next; 1359299529Smm free(segment->buff); 1360299529Smm free(segment); 1361228753Smm } 1362228753Smm free(zip->buf); 1363299529Smm archive_entry_free(zip->entry); 1364299529Smm if (zip->cctx_valid) 1365299529Smm archive_encrypto_aes_ctr_release(&zip->cctx); 1366299529Smm if (zip->hctx_valid) 1367299529Smm archive_hmac_sha1_cleanup(&zip->hctx); 1368299529Smm /* TODO: Free opt_sconv, sconv_default */ 1369299529Smm 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; 1381358088Smm#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S) 1382358088Smm struct tm tmbuf; 1383358088Smm#endif 1384358088Smm#if defined(HAVE__LOCALTIME64_S) 1385358088Smm errno_t terr; 1386358088Smm __time64_t tmptime; 1387358088Smm#endif 1388228753Smm 1389228753Smm /* This will not preserve time when creating/extracting the archive 1390228753Smm * on two systems with different time zones. */ 1391358088Smm#if defined(HAVE_LOCALTIME_R) 1392358088Smm t = localtime_r(&unix_time, &tmbuf); 1393358088Smm#elif defined(HAVE__LOCALTIME64_S) 1394358088Smm tmptime = unix_time; 1395358088Smm terr = _localtime64_s(&tmbuf, &tmptime); 1396358088Smm if (terr) 1397358088Smm t = NULL; 1398358088Smm else 1399358088Smm t = &tmbuf; 1400358088Smm#else 1401228753Smm t = localtime(&unix_time); 1402358088Smm#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; 1429358088Smm size_t len; 1430228753Smm 1431228753Smm type = archive_entry_filetype(entry); 1432228753Smm path = archive_entry_pathname(entry); 1433228753Smm 1434248616Smm if (path == NULL) 1435248616Smm return (0); 1436358088Smm len = strlen(path); 1437358088Smm if (type == AE_IFDIR && (path[0] == '\0' || path[len - 1] != '/')) 1438358088Smm ++len; /* Space for the trailing / */ 1439358088Smm 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 1454344673Smm if (path == NULL) 1455344673Smm return (ARCHIVE_FATAL); 1456344673Smm 1457232153Smm ret = __archive_write_output(archive, path, strlen(path)); 1458228753Smm if (ret != ARCHIVE_OK) 1459228753Smm return (ARCHIVE_FATAL); 1460228753Smm written_bytes += strlen(path); 1461228753Smm 1462299529Smm /* 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} 1472299529Smm 1473299529Smmstatic void 1474299529Smmcopy_path(struct archive_entry *entry, unsigned char *p) 1475299529Smm{ 1476299529Smm const char *path; 1477299529Smm size_t pathlen; 1478299529Smm mode_t type; 1479299529Smm 1480299529Smm path = archive_entry_pathname(entry); 1481299529Smm pathlen = strlen(path); 1482299529Smm type = archive_entry_filetype(entry); 1483299529Smm 1484299529Smm memcpy(p, path, pathlen); 1485299529Smm 1486299529Smm /* Folders are recognized by a trailing slash. */ 1487358088Smm if ((type == AE_IFDIR) && (path[pathlen - 1] != '/')) 1488299529Smm p[pathlen] = '/'; 1489299529Smm} 1490299529Smm 1491299529Smm 1492299529Smmstatic struct archive_string_conv * 1493299529Smmget_sconv(struct archive_write *a, struct zip *zip) 1494299529Smm{ 1495299529Smm if (zip->opt_sconv != NULL) 1496299529Smm return (zip->opt_sconv); 1497299529Smm 1498299529Smm if (!zip->init_default_conversion) { 1499299529Smm zip->sconv_default = 1500299529Smm archive_string_default_conversion_for_write(&(a->archive)); 1501299529Smm zip->init_default_conversion = 1; 1502299529Smm } 1503299529Smm return (zip->sconv_default); 1504299529Smm} 1505299529Smm 1506299529Smm/* 1507299529Smm Traditional PKWARE Decryption functions. 1508299529Smm */ 1509299529Smm 1510299529Smmstatic void 1511299529Smmtrad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) 1512299529Smm{ 1513299529Smm uint8_t t; 1514299529Smm#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL) 1515299529Smm 1516299529Smm ctx->keys[0] = CRC32(ctx->keys[0], c); 1517299529Smm ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1; 1518299529Smm t = (ctx->keys[1] >> 24) & 0xff; 1519299529Smm ctx->keys[2] = CRC32(ctx->keys[2], t); 1520299529Smm#undef CRC32 1521299529Smm} 1522299529Smm 1523299529Smmstatic uint8_t 1524313570Smmtrad_enc_decrypt_byte(struct trad_enc_ctx *ctx) 1525299529Smm{ 1526299529Smm unsigned temp = ctx->keys[2] | 2; 1527299529Smm return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; 1528299529Smm} 1529299529Smm 1530299529Smmstatic unsigned 1531299529Smmtrad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, 1532299529Smm size_t in_len, uint8_t *out, size_t out_len) 1533299529Smm{ 1534299529Smm unsigned i, max; 1535299529Smm 1536299529Smm max = (unsigned)((in_len < out_len)? in_len: out_len); 1537299529Smm 1538299529Smm for (i = 0; i < max; i++) { 1539299529Smm uint8_t t = in[i]; 1540313570Smm out[i] = t ^ trad_enc_decrypt_byte(ctx); 1541299529Smm trad_enc_update_keys(ctx, t); 1542299529Smm } 1543299529Smm return i; 1544299529Smm} 1545299529Smm 1546299529Smmstatic int 1547299529Smmtrad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len) 1548299529Smm{ 1549299529Smm 1550299529Smm ctx->keys[0] = 305419896L; 1551299529Smm ctx->keys[1] = 591751049L; 1552299529Smm ctx->keys[2] = 878082192L; 1553299529Smm 1554299529Smm for (;pw_len; --pw_len) 1555299529Smm trad_enc_update_keys(ctx, *pw++); 1556299529Smm return 0; 1557299529Smm} 1558299529Smm 1559299529Smmstatic int 1560299529Smmis_traditional_pkware_encryption_supported(void) 1561299529Smm{ 1562299529Smm uint8_t key[TRAD_HEADER_SIZE]; 1563299529Smm 1564299529Smm if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) 1565299529Smm return (0); 1566299529Smm return (1); 1567299529Smm} 1568299529Smm 1569299529Smmstatic int 1570299529Smminit_traditional_pkware_encryption(struct archive_write *a) 1571299529Smm{ 1572299529Smm struct zip *zip = a->format_data; 1573299529Smm const char *passphrase; 1574299529Smm uint8_t key[TRAD_HEADER_SIZE]; 1575299529Smm uint8_t key_encrypted[TRAD_HEADER_SIZE]; 1576299529Smm int ret; 1577299529Smm 1578299529Smm passphrase = __archive_write_get_passphrase(a); 1579299529Smm if (passphrase == NULL) { 1580299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1581299529Smm "Encryption needs passphrase"); 1582299529Smm return ARCHIVE_FAILED; 1583299529Smm } 1584299529Smm if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) { 1585299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1586299529Smm "Can't generate random number for encryption"); 1587299529Smm return ARCHIVE_FATAL; 1588299529Smm } 1589299529Smm trad_enc_init(&zip->tctx, passphrase, strlen(passphrase)); 1590299529Smm /* Set the last key code which will be used as a check code 1591299529Smm * for verifying passphrase in decryption. */ 1592299529Smm key[TRAD_HEADER_SIZE-1] = zip->trad_chkdat; 1593299529Smm trad_enc_encrypt_update(&zip->tctx, key, TRAD_HEADER_SIZE, 1594299529Smm key_encrypted, TRAD_HEADER_SIZE); 1595299529Smm /* Write encrypted keys in the top of the file content. */ 1596299529Smm ret = __archive_write_output(a, key_encrypted, TRAD_HEADER_SIZE); 1597299529Smm if (ret != ARCHIVE_OK) 1598299529Smm return (ret); 1599299529Smm zip->written_bytes += TRAD_HEADER_SIZE; 1600299529Smm zip->entry_compressed_written += TRAD_HEADER_SIZE; 1601299529Smm return (ret); 1602299529Smm} 1603299529Smm 1604299529Smmstatic int 1605299529Smminit_winzip_aes_encryption(struct archive_write *a) 1606299529Smm{ 1607299529Smm struct zip *zip = a->format_data; 1608299529Smm const char *passphrase; 1609299529Smm size_t key_len, salt_len; 1610299529Smm uint8_t salt[16 + 2]; 1611299529Smm uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; 1612299529Smm int ret; 1613299529Smm 1614299529Smm passphrase = __archive_write_get_passphrase(a); 1615299529Smm if (passphrase == NULL) { 1616299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1617299529Smm "Encryption needs passphrase"); 1618299529Smm return (ARCHIVE_FAILED); 1619299529Smm } 1620299529Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128) { 1621299529Smm salt_len = 8; 1622299529Smm key_len = 16; 1623299529Smm } else { 1624299529Smm /* AES 256 */ 1625299529Smm salt_len = 16; 1626299529Smm key_len = 32; 1627299529Smm } 1628299529Smm if (archive_random(salt, salt_len) != ARCHIVE_OK) { 1629299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1630299529Smm "Can't generate random number for encryption"); 1631299529Smm return (ARCHIVE_FATAL); 1632299529Smm } 1633299529Smm archive_pbkdf2_sha1(passphrase, strlen(passphrase), 1634299529Smm salt, salt_len, 1000, derived_key, key_len * 2 + 2); 1635299529Smm 1636299529Smm ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); 1637299529Smm if (ret != 0) { 1638299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1639299529Smm "Decryption is unsupported due to lack of crypto library"); 1640299529Smm return (ARCHIVE_FAILED); 1641299529Smm } 1642299529Smm ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, 1643299529Smm key_len); 1644299529Smm if (ret != 0) { 1645299529Smm archive_encrypto_aes_ctr_release(&zip->cctx); 1646299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1647299529Smm "Failed to initialize HMAC-SHA1"); 1648299529Smm return (ARCHIVE_FAILED); 1649299529Smm } 1650299529Smm 1651313570Smm /* Set a password verification value after the 'salt'. */ 1652299529Smm salt[salt_len] = derived_key[key_len * 2]; 1653299529Smm salt[salt_len + 1] = derived_key[key_len * 2 + 1]; 1654299529Smm 1655299529Smm /* Write encrypted keys in the top of the file content. */ 1656299529Smm ret = __archive_write_output(a, salt, salt_len + 2); 1657299529Smm if (ret != ARCHIVE_OK) 1658299529Smm return (ret); 1659299529Smm zip->written_bytes += salt_len + 2; 1660299529Smm zip->entry_compressed_written += salt_len + 2; 1661299529Smm 1662299529Smm return (ARCHIVE_OK); 1663299529Smm} 1664299529Smm 1665299529Smmstatic int 1666299529Smmis_winzip_aes_encryption_supported(int encryption) 1667299529Smm{ 1668299529Smm size_t key_len, salt_len; 1669299529Smm uint8_t salt[16 + 2]; 1670299529Smm uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; 1671299529Smm archive_crypto_ctx cctx; 1672299529Smm archive_hmac_sha1_ctx hctx; 1673299529Smm int ret; 1674299529Smm 1675299529Smm if (encryption == ENCRYPTION_WINZIP_AES128) { 1676299529Smm salt_len = 8; 1677299529Smm key_len = 16; 1678299529Smm } else { 1679299529Smm /* AES 256 */ 1680299529Smm salt_len = 16; 1681299529Smm key_len = 32; 1682299529Smm } 1683299529Smm if (archive_random(salt, salt_len) != ARCHIVE_OK) 1684299529Smm return (0); 1685299529Smm ret = archive_pbkdf2_sha1("p", 1, salt, salt_len, 1000, 1686299529Smm derived_key, key_len * 2 + 2); 1687299529Smm if (ret != 0) 1688299529Smm return (0); 1689299529Smm 1690299529Smm ret = archive_encrypto_aes_ctr_init(&cctx, derived_key, key_len); 1691299529Smm if (ret != 0) 1692299529Smm return (0); 1693299529Smm ret = archive_hmac_sha1_init(&hctx, derived_key + key_len, 1694299529Smm key_len); 1695299529Smm archive_encrypto_aes_ctr_release(&cctx); 1696299529Smm if (ret != 0) 1697299529Smm return (0); 1698299529Smm archive_hmac_sha1_cleanup(&hctx); 1699299529Smm return (1); 1700299529Smm} 1701