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: releng/11.0/contrib/libarchive/libarchive/archive_write_set_format_zip.c 299529 2016-05-12 10:16:16Z 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" 60228753Smm 61228753Smm#ifndef HAVE_ZLIB_H 62228753Smm#include "archive_crc32.h" 63228753Smm#endif 64228753Smm 65299529Smm#define ZIP_ENTRY_FLAG_ENCRYPTED (1<<0) 66299529Smm#define ZIP_ENTRY_FLAG_LENGTH_AT_END (1<<3) 67299529Smm#define ZIP_ENTRY_FLAG_UTF8_NAME (1 << 11) 68228753Smm 69299529Smm#define ZIP_4GB_MAX ARCHIVE_LITERAL_LL(0xffffffff) 70299529Smm#define ZIP_4GB_MAX_UNCOMPRESSED ARCHIVE_LITERAL_LL(0xff000000) 71299529Smm 72228753Smmenum compression { 73299529Smm COMPRESSION_UNSPECIFIED = -1, 74299529Smm COMPRESSION_STORE = 0, 75299529Smm COMPRESSION_DEFLATE = 8 76299529Smm}; 77299529Smm 78228753Smm#ifdef HAVE_ZLIB_H 79299529Smm#define COMPRESSION_DEFAULT COMPRESSION_DEFLATE 80299529Smm#else 81299529Smm#define COMPRESSION_DEFAULT COMPRESSION_STORE 82228753Smm#endif 83299529Smm 84299529Smmenum encryption { 85299529Smm ENCRYPTION_NONE = 0, 86299529Smm ENCRYPTION_TRADITIONAL, /* Traditional PKWARE encryption. */ 87299529Smm ENCRYPTION_WINZIP_AES128, /* WinZIP AES-128 encryption. */ 88299529Smm ENCRYPTION_WINZIP_AES256, /* WinZIP AES-256 encryption. */ 89228753Smm}; 90228753Smm 91299529Smm#define TRAD_HEADER_SIZE 12 92299529Smm/* 93299529Smm * See "WinZip - AES Encryption Information" 94299529Smm * http://www.winzip.com/aes_info.htm 95299529Smm */ 96299529Smm/* Value used in compression method. */ 97299529Smm#define WINZIP_AES_ENCRYPTION 99 98299529Smm/* A WinZip AES header size which is stored at the beginning of 99299529Smm * file contents. */ 100299529Smm#define WINZIP_AES128_HEADER_SIZE (8 + 2) 101299529Smm#define WINZIP_AES256_HEADER_SIZE (16 + 2) 102299529Smm/* AES vendor version. */ 103299529Smm#define AES_VENDOR_AE_1 0x0001 104299529Smm#define AES_VENDOR_AE_2 0x0002 105299529Smm/* Authentication code size. */ 106299529Smm#define AUTH_CODE_SIZE 10 107299529Smm/**/ 108299529Smm#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2) 109299529Smm 110299529Smmstruct cd_segment { 111299529Smm struct cd_segment *next; 112299529Smm size_t buff_size; 113299529Smm unsigned char *buff; 114299529Smm unsigned char *p; 115299529Smm}; 116299529Smm 117299529Smmstruct trad_enc_ctx { 118299529Smm uint32_t keys[3]; 119299529Smm}; 120299529Smm 121299529Smmstruct zip { 122299529Smm 123299529Smm int64_t entry_offset; 124299529Smm int64_t entry_compressed_size; 125299529Smm int64_t entry_uncompressed_size; 126299529Smm int64_t entry_compressed_written; 127299529Smm int64_t entry_uncompressed_written; 128299529Smm int64_t entry_uncompressed_limit; 129299529Smm struct archive_entry *entry; 130299529Smm uint32_t entry_crc32; 131299529Smm enum compression entry_compression; 132299529Smm enum encryption entry_encryption; 133299529Smm int entry_flags; 134299529Smm int entry_uses_zip64; 135299529Smm int experiments; 136299529Smm struct trad_enc_ctx tctx; 137299529Smm char tctx_valid; 138299529Smm unsigned char trad_chkdat; 139299529Smm unsigned aes_vendor; 140299529Smm archive_crypto_ctx cctx; 141299529Smm char cctx_valid; 142299529Smm archive_hmac_sha1_ctx hctx; 143299529Smm char hctx_valid; 144299529Smm 145299529Smm unsigned char *file_header; 146299529Smm size_t file_header_extra_offset; 147299529Smm unsigned long (*crc32func)(unsigned long crc, const void *buff, size_t len); 148299529Smm 149299529Smm struct cd_segment *central_directory; 150299529Smm struct cd_segment *central_directory_last; 151299529Smm size_t central_directory_bytes; 152299529Smm size_t central_directory_entries; 153299529Smm 154299529Smm int64_t written_bytes; /* Overall position in file. */ 155299529Smm 156299529Smm struct archive_string_conv *opt_sconv; 157299529Smm struct archive_string_conv *sconv_default; 158299529Smm enum compression requested_compression; 159299529Smm int deflate_compression_level; 160299529Smm int init_default_conversion; 161299529Smm enum encryption encryption_type; 162299529Smm 163299529Smm#define ZIP_FLAG_AVOID_ZIP64 1 164299529Smm#define ZIP_FLAG_FORCE_ZIP64 2 165299529Smm#define ZIP_FLAG_EXPERIMENT_xl 4 166299529Smm int flags; 167299529Smm 168299529Smm#ifdef HAVE_ZLIB_H 169299529Smm z_stream stream; 170299529Smm#endif 171299529Smm size_t len_buf; 172299529Smm unsigned char *buf; 173299529Smm}; 174299529Smm 175299529Smm/* Don't call this min or MIN, since those are already defined 176299529Smm on lots of platforms (but not all). */ 177299529Smm#define zipmin(a, b) ((a) > (b) ? (b) : (a)) 178299529Smm 179232153Smmstatic ssize_t archive_write_zip_data(struct archive_write *, 180232153Smm const void *buff, size_t s); 181232153Smmstatic int archive_write_zip_close(struct archive_write *); 182232153Smmstatic int archive_write_zip_free(struct archive_write *); 183228753Smmstatic int archive_write_zip_finish_entry(struct archive_write *); 184232153Smmstatic int archive_write_zip_header(struct archive_write *, 185232153Smm struct archive_entry *); 186232153Smmstatic int archive_write_zip_options(struct archive_write *, 187232153Smm const char *, const char *); 188228753Smmstatic unsigned int dos_time(const time_t); 189228753Smmstatic size_t path_length(struct archive_entry *); 190228753Smmstatic int write_path(struct archive_entry *, struct archive_write *); 191299529Smmstatic void copy_path(struct archive_entry *, unsigned char *); 192299529Smmstatic struct archive_string_conv *get_sconv(struct archive_write *, struct zip *); 193299529Smmstatic int trad_enc_init(struct trad_enc_ctx *, const char *, size_t); 194299529Smmstatic unsigned trad_enc_encrypt_update(struct trad_enc_ctx *, const uint8_t *, 195299529Smm size_t, uint8_t *, size_t); 196299529Smmstatic int init_traditional_pkware_encryption(struct archive_write *); 197299529Smmstatic int is_traditional_pkware_encryption_supported(void); 198299529Smmstatic int init_winzip_aes_encryption(struct archive_write *); 199299529Smmstatic int is_winzip_aes_encryption_supported(int encryption); 200228753Smm 201299529Smmstatic unsigned char * 202299529Smmcd_alloc(struct zip *zip, size_t length) 203299529Smm{ 204299529Smm unsigned char *p; 205228753Smm 206299529Smm if (zip->central_directory == NULL 207299529Smm || (zip->central_directory_last->p + length 208299529Smm > zip->central_directory_last->buff + zip->central_directory_last->buff_size)) { 209299529Smm struct cd_segment *segment = calloc(1, sizeof(*segment)); 210299529Smm if (segment == NULL) 211299529Smm return NULL; 212299529Smm segment->buff_size = 64 * 1024; 213299529Smm segment->buff = malloc(segment->buff_size); 214299529Smm if (segment->buff == NULL) { 215299529Smm free(segment); 216299529Smm return NULL; 217299529Smm } 218299529Smm segment->p = segment->buff; 219228753Smm 220299529Smm if (zip->central_directory == NULL) { 221299529Smm zip->central_directory 222299529Smm = zip->central_directory_last 223299529Smm = segment; 224299529Smm } else { 225299529Smm zip->central_directory_last->next = segment; 226299529Smm zip->central_directory_last = segment; 227299529Smm } 228299529Smm } 229228753Smm 230299529Smm p = zip->central_directory_last->p; 231299529Smm zip->central_directory_last->p += length; 232299529Smm zip->central_directory_bytes += length; 233299529Smm return (p); 234299529Smm} 235228753Smm 236299529Smmstatic unsigned long 237299529Smmreal_crc32(unsigned long crc, const void *buff, size_t len) 238299529Smm{ 239299529Smm return crc32(crc, buff, (unsigned int)len); 240299529Smm} 241228753Smm 242299529Smmstatic unsigned long 243299529Smmfake_crc32(unsigned long crc, const void *buff, size_t len) 244299529Smm{ 245299529Smm (void)crc; /* UNUSED */ 246299529Smm (void)buff; /* UNUSED */ 247299529Smm (void)len; /* UNUSED */ 248299529Smm return 0; 249299529Smm} 250238856Smm 251228753Smmstatic int 252228753Smmarchive_write_zip_options(struct archive_write *a, const char *key, 253232153Smm const char *val) 254228753Smm{ 255228753Smm struct zip *zip = a->format_data; 256232153Smm int ret = ARCHIVE_FAILED; 257228753Smm 258228753Smm if (strcmp(key, "compression") == 0) { 259299529Smm /* 260299529Smm * Set compression to use on all future entries. 261299529Smm * This only affects regular files. 262299529Smm */ 263232153Smm if (val == NULL || val[0] == 0) { 264232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 265232153Smm "%s: compression option needs a compression name", 266232153Smm a->format_name); 267232153Smm } else if (strcmp(val, "deflate") == 0) { 268228753Smm#ifdef HAVE_ZLIB_H 269299529Smm zip->requested_compression = COMPRESSION_DEFLATE; 270232153Smm ret = ARCHIVE_OK; 271228753Smm#else 272228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 273228753Smm "deflate compression not supported"); 274228753Smm#endif 275232153Smm } else if (strcmp(val, "store") == 0) { 276299529Smm zip->requested_compression = COMPRESSION_STORE; 277232153Smm ret = ARCHIVE_OK; 278232153Smm } 279232153Smm return (ret); 280299529Smm } else if (strcmp(key, "compression-level") == 0) { 281299529Smm if (val == NULL || !(val[0] >= '0' && val[0] <= '9') || val[1] != '\0') { 282299529Smm return ARCHIVE_WARN; 283299529Smm } 284299529Smm 285299529Smm if (val[0] == '0') { 286299529Smm zip->requested_compression = COMPRESSION_STORE; 287299529Smm return ARCHIVE_OK; 288299529Smm } else { 289299529Smm#ifdef HAVE_ZLIB_H 290299529Smm zip->requested_compression = COMPRESSION_DEFLATE; 291299529Smm zip->deflate_compression_level = val[0] - '0'; 292299529Smm return ARCHIVE_OK; 293299529Smm#else 294299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 295299529Smm "deflate compression not supported"); 296299529Smm#endif 297299529Smm } 298299529Smm } else if (strcmp(key, "encryption") == 0) { 299299529Smm if (val == NULL) { 300299529Smm zip->encryption_type = ENCRYPTION_NONE; 301299529Smm ret = ARCHIVE_OK; 302299529Smm } else if (val[0] == '1' || strcmp(val, "traditional") == 0 303299529Smm || strcmp(val, "zipcrypt") == 0 304299529Smm || strcmp(val, "ZipCrypt") == 0) { 305299529Smm if (is_traditional_pkware_encryption_supported()) { 306299529Smm zip->encryption_type = ENCRYPTION_TRADITIONAL; 307299529Smm ret = ARCHIVE_OK; 308299529Smm } else { 309299529Smm archive_set_error(&a->archive, 310299529Smm ARCHIVE_ERRNO_MISC, 311299529Smm "encryption not supported"); 312299529Smm } 313299529Smm } else if (strcmp(val, "aes128") == 0) { 314299529Smm if (is_winzip_aes_encryption_supported( 315299529Smm ENCRYPTION_WINZIP_AES128)) { 316299529Smm zip->encryption_type = ENCRYPTION_WINZIP_AES128; 317299529Smm ret = ARCHIVE_OK; 318299529Smm } else { 319299529Smm archive_set_error(&a->archive, 320299529Smm ARCHIVE_ERRNO_MISC, 321299529Smm "encryption not supported"); 322299529Smm } 323299529Smm } else if (strcmp(val, "aes256") == 0) { 324299529Smm if (is_winzip_aes_encryption_supported( 325299529Smm ENCRYPTION_WINZIP_AES256)) { 326299529Smm zip->encryption_type = ENCRYPTION_WINZIP_AES256; 327299529Smm ret = ARCHIVE_OK; 328299529Smm } else { 329299529Smm archive_set_error(&a->archive, 330299529Smm ARCHIVE_ERRNO_MISC, 331299529Smm "encryption not supported"); 332299529Smm } 333299529Smm } else { 334299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 335299529Smm "%s: unknown encryption '%s'", 336299529Smm a->format_name, val); 337299529Smm } 338299529Smm return (ret); 339299529Smm } else if (strcmp(key, "experimental") == 0) { 340299529Smm if (val == NULL || val[0] == 0) { 341299529Smm zip->flags &= ~ ZIP_FLAG_EXPERIMENT_xl; 342299529Smm } else { 343299529Smm zip->flags |= ZIP_FLAG_EXPERIMENT_xl; 344299529Smm } 345299529Smm return (ARCHIVE_OK); 346299529Smm } else if (strcmp(key, "fakecrc32") == 0) { 347299529Smm /* 348299529Smm * FOR TESTING ONLY: disable CRC calculation to speed up 349299529Smm * certain complex tests. 350299529Smm */ 351299529Smm if (val == NULL || val[0] == 0) { 352299529Smm zip->crc32func = real_crc32; 353299529Smm } else { 354299529Smm zip->crc32func = fake_crc32; 355299529Smm } 356299529Smm return (ARCHIVE_OK); 357232153Smm } else if (strcmp(key, "hdrcharset") == 0) { 358299529Smm /* 359299529Smm * Set the character set used in translating filenames. 360299529Smm */ 361232153Smm if (val == NULL || val[0] == 0) { 362232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 363232153Smm "%s: hdrcharset option needs a character-set name", 364232153Smm a->format_name); 365232153Smm } else { 366232153Smm zip->opt_sconv = archive_string_conversion_to_charset( 367232153Smm &a->archive, val, 0); 368232153Smm if (zip->opt_sconv != NULL) 369232153Smm ret = ARCHIVE_OK; 370232153Smm else 371232153Smm ret = ARCHIVE_FATAL; 372232153Smm } 373232153Smm return (ret); 374299529Smm } else if (strcmp(key, "zip64") == 0) { 375299529Smm /* 376299529Smm * Bias decisions about Zip64: force them to be 377299529Smm * generated in certain cases where they are not 378299529Smm * forbidden or avoid them in certain cases where they 379299529Smm * are not strictly required. 380299529Smm */ 381299529Smm if (val != NULL && *val != '\0') { 382299529Smm zip->flags |= ZIP_FLAG_FORCE_ZIP64; 383299529Smm zip->flags &= ~ZIP_FLAG_AVOID_ZIP64; 384299529Smm } else { 385299529Smm zip->flags &= ~ZIP_FLAG_FORCE_ZIP64; 386299529Smm zip->flags |= ZIP_FLAG_AVOID_ZIP64; 387299529Smm } 388299529Smm return (ARCHIVE_OK); 389228753Smm } 390232153Smm 391232153Smm /* Note: The "warn" return is just to inform the options 392232153Smm * supervisor that we didn't handle it. It will generate 393232153Smm * a suitable error if no one used this option. */ 394228753Smm return (ARCHIVE_WARN); 395228753Smm} 396228753Smm 397228753Smmint 398248616Smmarchive_write_zip_set_compression_deflate(struct archive *_a) 399248616Smm{ 400248616Smm struct archive_write *a = (struct archive_write *)_a; 401248616Smm int ret = ARCHIVE_FAILED; 402299529Smm 403248616Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 404299529Smm ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 405248616Smm "archive_write_zip_set_compression_deflate"); 406248616Smm if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { 407248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 408248616Smm "Can only use archive_write_zip_set_compression_deflate" 409248616Smm " with zip format"); 410248616Smm ret = ARCHIVE_FATAL; 411248616Smm } else { 412248616Smm#ifdef HAVE_ZLIB_H 413248616Smm struct zip *zip = a->format_data; 414299529Smm zip->requested_compression = COMPRESSION_DEFLATE; 415248616Smm ret = ARCHIVE_OK; 416248616Smm#else 417248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 418248616Smm "deflate compression not supported"); 419299529Smm ret = ARCHIVE_FAILED; 420248616Smm#endif 421248616Smm } 422248616Smm return (ret); 423248616Smm} 424248616Smm 425248616Smmint 426248616Smmarchive_write_zip_set_compression_store(struct archive *_a) 427248616Smm{ 428248616Smm struct archive_write *a = (struct archive_write *)_a; 429248616Smm struct zip *zip = a->format_data; 430248616Smm int ret = ARCHIVE_FAILED; 431299529Smm 432248616Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 433299529Smm ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, 434248616Smm "archive_write_zip_set_compression_deflate"); 435248616Smm if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { 436248616Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 437248616Smm "Can only use archive_write_zip_set_compression_store" 438248616Smm " with zip format"); 439248616Smm ret = ARCHIVE_FATAL; 440248616Smm } else { 441299529Smm zip->requested_compression = COMPRESSION_STORE; 442248616Smm ret = ARCHIVE_OK; 443248616Smm } 444248616Smm return (ret); 445248616Smm} 446248616Smm 447248616Smmint 448228753Smmarchive_write_set_format_zip(struct archive *_a) 449228753Smm{ 450228753Smm struct archive_write *a = (struct archive_write *)_a; 451228753Smm struct zip *zip; 452228753Smm 453232153Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 454232153Smm ARCHIVE_STATE_NEW, "archive_write_set_format_zip"); 455232153Smm 456228753Smm /* If another format was already registered, unregister it. */ 457232153Smm if (a->format_free != NULL) 458232153Smm (a->format_free)(a); 459228753Smm 460228753Smm zip = (struct zip *) calloc(1, sizeof(*zip)); 461228753Smm if (zip == NULL) { 462232153Smm archive_set_error(&a->archive, ENOMEM, 463232153Smm "Can't allocate zip data"); 464228753Smm return (ARCHIVE_FATAL); 465228753Smm } 466228753Smm 467299529Smm /* "Unspecified" lets us choose the appropriate compression. */ 468299529Smm zip->requested_compression = COMPRESSION_UNSPECIFIED; 469228753Smm#ifdef HAVE_ZLIB_H 470299529Smm zip->deflate_compression_level = Z_DEFAULT_COMPRESSION; 471299529Smm#endif 472299529Smm zip->crc32func = real_crc32; 473299529Smm 474299529Smm /* A buffer used for both compression and encryption. */ 475228753Smm zip->len_buf = 65536; 476228753Smm zip->buf = malloc(zip->len_buf); 477228753Smm if (zip->buf == NULL) { 478238856Smm free(zip); 479232153Smm archive_set_error(&a->archive, ENOMEM, 480232153Smm "Can't allocate compression buffer"); 481228753Smm return (ARCHIVE_FATAL); 482228753Smm } 483228753Smm 484228753Smm a->format_data = zip; 485228753Smm a->format_name = "zip"; 486228753Smm a->format_options = archive_write_zip_options; 487228753Smm a->format_write_header = archive_write_zip_header; 488228753Smm a->format_write_data = archive_write_zip_data; 489228753Smm a->format_finish_entry = archive_write_zip_finish_entry; 490232153Smm a->format_close = archive_write_zip_close; 491232153Smm a->format_free = archive_write_zip_free; 492228753Smm a->archive.archive_format = ARCHIVE_FORMAT_ZIP; 493228753Smm a->archive.archive_format_name = "ZIP"; 494228753Smm 495228753Smm return (ARCHIVE_OK); 496228753Smm} 497228753Smm 498228753Smmstatic int 499232153Smmis_all_ascii(const char *p) 500232153Smm{ 501232153Smm const unsigned char *pp = (const unsigned char *)p; 502232153Smm 503232153Smm while (*pp) { 504232153Smm if (*pp++ > 127) 505232153Smm return (0); 506232153Smm } 507232153Smm return (1); 508232153Smm} 509232153Smm 510232153Smmstatic int 511228753Smmarchive_write_zip_header(struct archive_write *a, struct archive_entry *entry) 512228753Smm{ 513299529Smm unsigned char local_header[32]; 514299529Smm unsigned char local_extra[144]; 515299529Smm struct zip *zip = a->format_data; 516299529Smm unsigned char *e; 517299529Smm unsigned char *cd_extra; 518299529Smm size_t filename_length; 519299529Smm const char *slink = NULL; 520299529Smm size_t slink_size = 0; 521299529Smm struct archive_string_conv *sconv = get_sconv(a, zip); 522232153Smm int ret, ret2 = ARCHIVE_OK; 523228753Smm mode_t type; 524299529Smm int version_needed = 10; 525228753Smm 526299529Smm /* Ignore types of entries that we don't support. */ 527228753Smm type = archive_entry_filetype(entry); 528232153Smm if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { 529232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 530232153Smm "Filetype not supported"); 531228753Smm return ARCHIVE_FAILED; 532248616Smm }; 533228753Smm 534299529Smm /* If we're not using Zip64, reject large files. */ 535299529Smm if (zip->flags & ZIP_FLAG_AVOID_ZIP64) { 536299529Smm /* Reject entries over 4GB. */ 537299529Smm if (archive_entry_size_is_set(entry) 538299529Smm && (archive_entry_size(entry) > ZIP_4GB_MAX)) { 539299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 540299529Smm "Files > 4GB require Zip64 extensions"); 541299529Smm return ARCHIVE_FAILED; 542299529Smm } 543299529Smm /* Reject entries if archive is > 4GB. */ 544299529Smm if (zip->written_bytes > ZIP_4GB_MAX) { 545299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 546299529Smm "Archives > 4GB require Zip64 extensions"); 547299529Smm return ARCHIVE_FAILED; 548299529Smm } 549299529Smm } 550299529Smm 551299529Smm /* Only regular files can have size > 0. */ 552299529Smm if (type != AE_IFREG) 553228753Smm archive_entry_set_size(entry, 0); 554228753Smm 555299529Smm 556299529Smm /* Reset information from last entry. */ 557299529Smm zip->entry_offset = zip->written_bytes; 558299529Smm zip->entry_uncompressed_limit = INT64_MAX; 559299529Smm zip->entry_compressed_size = 0; 560299529Smm zip->entry_uncompressed_size = 0; 561299529Smm zip->entry_compressed_written = 0; 562299529Smm zip->entry_uncompressed_written = 0; 563299529Smm zip->entry_flags = 0; 564299529Smm zip->entry_uses_zip64 = 0; 565299529Smm zip->entry_crc32 = zip->crc32func(0, NULL, 0); 566299529Smm zip->entry_encryption = 0; 567299529Smm if (zip->entry != NULL) { 568299529Smm archive_entry_free(zip->entry); 569299529Smm zip->entry = NULL; 570232153Smm } 571232153Smm 572299529Smm if (zip->cctx_valid) 573299529Smm archive_encrypto_aes_ctr_release(&zip->cctx); 574299529Smm if (zip->hctx_valid) 575299529Smm archive_hmac_sha1_cleanup(&zip->hctx); 576299529Smm zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; 577299529Smm 578299529Smm if (type == AE_IFREG 579299529Smm &&(!archive_entry_size_is_set(entry) 580299529Smm || archive_entry_size(entry) > 0)) { 581299529Smm switch (zip->encryption_type) { 582299529Smm case ENCRYPTION_TRADITIONAL: 583299529Smm case ENCRYPTION_WINZIP_AES128: 584299529Smm case ENCRYPTION_WINZIP_AES256: 585299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED; 586299529Smm zip->entry_encryption = zip->encryption_type; 587299529Smm break; 588299529Smm default: 589299529Smm break; 590232153Smm } 591232153Smm } 592228753Smm 593299529Smm 594232153Smm#if defined(_WIN32) && !defined(__CYGWIN__) 595232153Smm /* Make sure the path separators in pahtname, 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; 714299529Smm default: 715299529Smm break; 716299529Smm } 717299529Smm if (zip->entry_compression == COMPRESSION_STORE) 718299529Smm zip->entry_compressed_size += additional_size; 719299529Smm } 720299529Smm 721299529Smm /* 722299529Smm * Set Zip64 extension in any of the following cases 723299529Smm * (this was suggested by discussion on info-zip-dev 724299529Smm * mailing list): 725299529Smm * = Zip64 is being forced by user 726299529Smm * = File is over 4GiB uncompressed 727299529Smm * (including encryption header, if any) 728299529Smm * = File is close to 4GiB and is being compressed 729299529Smm * (compression might make file larger) 730299529Smm */ 731299529Smm if ((zip->flags & ZIP_FLAG_FORCE_ZIP64) 732299529Smm || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX) 733299529Smm || (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED 734299529Smm && zip->entry_compression != COMPRESSION_STORE)) { 735299529Smm zip->entry_uses_zip64 = 1; 736299529Smm version_needed = 45; 737299529Smm } 738299529Smm 739299529Smm /* We may know the size, but never the CRC. */ 740299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; 741232153Smm } else { 742299529Smm /* We don't know the size. In this case, we prefer 743299529Smm * deflate (it has a clear end-of-data marker which 744299529Smm * makes length-at-end more reliable) and will 745299529Smm * enable Zip64 extensions unless we're told not to. 746299529Smm */ 747299529Smm zip->entry_compression = COMPRESSION_DEFAULT; 748299529Smm zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; 749299529Smm if ((zip->flags & ZIP_FLAG_AVOID_ZIP64) == 0) { 750299529Smm zip->entry_uses_zip64 = 1; 751299529Smm version_needed = 45; 752299529Smm } else if (zip->entry_compression == COMPRESSION_STORE) { 753299529Smm version_needed = 10; 754299529Smm } else { 755299529Smm version_needed = 20; 756299529Smm } 757299529Smm 758299529Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 759299529Smm switch (zip->entry_encryption) { 760299529Smm case ENCRYPTION_TRADITIONAL: 761299529Smm case ENCRYPTION_WINZIP_AES128: 762299529Smm case ENCRYPTION_WINZIP_AES256: 763299529Smm if (version_needed < 20) 764299529Smm version_needed = 20; 765299529Smm break; 766299529Smm default: 767299529Smm break; 768299529Smm } 769299529Smm } 770232153Smm } 771299529Smm 772299529Smm /* Format the local header. */ 773299529Smm memset(local_header, 0, sizeof(local_header)); 774299529Smm memcpy(local_header, "PK\003\004", 4); 775299529Smm archive_le16enc(local_header + 4, version_needed); 776299529Smm archive_le16enc(local_header + 6, zip->entry_flags); 777299529Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 778299529Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) 779299529Smm archive_le16enc(local_header + 8, WINZIP_AES_ENCRYPTION); 780299529Smm else 781299529Smm archive_le16enc(local_header + 8, zip->entry_compression); 782299529Smm archive_le32enc(local_header + 10, 783299529Smm dos_time(archive_entry_mtime(zip->entry))); 784299529Smm archive_le32enc(local_header + 14, zip->entry_crc32); 785299529Smm if (zip->entry_uses_zip64) { 786299529Smm /* Zip64 data in the local header "must" include both 787299529Smm * compressed and uncompressed sizes AND those fields 788299529Smm * are included only if these are 0xffffffff; 789299529Smm * THEREFORE these must be set this way, even if we 790299529Smm * know one of them is smaller. */ 791299529Smm archive_le32enc(local_header + 18, ZIP_4GB_MAX); 792299529Smm archive_le32enc(local_header + 22, ZIP_4GB_MAX); 793228753Smm } else { 794299529Smm archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size); 795299529Smm archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size); 796228753Smm } 797299529Smm archive_le16enc(local_header + 26, (uint16_t)filename_length); 798228753Smm 799299529Smm if (zip->entry_encryption == ENCRYPTION_TRADITIONAL) { 800299529Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) 801299529Smm zip->trad_chkdat = local_header[11]; 802299529Smm else 803299529Smm zip->trad_chkdat = local_header[17]; 804299529Smm } 805228753Smm 806299529Smm /* Format as much of central directory file header as we can: */ 807299529Smm zip->file_header = cd_alloc(zip, 46); 808299529Smm /* If (zip->file_header == NULL) XXXX */ 809299529Smm ++zip->central_directory_entries; 810299529Smm memset(zip->file_header, 0, 46); 811299529Smm memcpy(zip->file_header, "PK\001\002", 4); 812299529Smm /* "Made by PKZip 2.0 on Unix." */ 813299529Smm archive_le16enc(zip->file_header + 4, 3 * 256 + version_needed); 814299529Smm archive_le16enc(zip->file_header + 6, version_needed); 815299529Smm archive_le16enc(zip->file_header + 8, zip->entry_flags); 816299529Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 817299529Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) 818299529Smm archive_le16enc(zip->file_header + 10, WINZIP_AES_ENCRYPTION); 819299529Smm else 820299529Smm archive_le16enc(zip->file_header + 10, zip->entry_compression); 821299529Smm archive_le32enc(zip->file_header + 12, 822299529Smm dos_time(archive_entry_mtime(zip->entry))); 823299529Smm archive_le16enc(zip->file_header + 28, (uint16_t)filename_length); 824299529Smm /* Following Info-Zip, store mode in the "external attributes" field. */ 825299529Smm archive_le32enc(zip->file_header + 38, 826299529Smm ((uint32_t)archive_entry_mode(zip->entry)) << 16); 827299529Smm e = cd_alloc(zip, filename_length); 828299529Smm /* If (e == NULL) XXXX */ 829299529Smm copy_path(zip->entry, e); 830228753Smm 831299529Smm /* Format extra data. */ 832299529Smm memset(local_extra, 0, sizeof(local_extra)); 833299529Smm e = local_extra; 834228753Smm 835299529Smm /* First, extra blocks that are the same between 836299529Smm * the local file header and the central directory. 837299529Smm * We format them once and then duplicate them. */ 838299529Smm 839299529Smm /* UT timestamp, length depends on what timestamps are set. */ 840299529Smm memcpy(e, "UT", 2); 841299529Smm archive_le16enc(e + 2, 842299529Smm 1 843299529Smm + (archive_entry_mtime_is_set(entry) ? 4 : 0) 844299529Smm + (archive_entry_atime_is_set(entry) ? 4 : 0) 845299529Smm + (archive_entry_ctime_is_set(entry) ? 4 : 0)); 846299529Smm e += 4; 847299529Smm *e++ = 848299529Smm (archive_entry_mtime_is_set(entry) ? 1 : 0) 849299529Smm | (archive_entry_atime_is_set(entry) ? 2 : 0) 850299529Smm | (archive_entry_ctime_is_set(entry) ? 4 : 0); 851299529Smm if (archive_entry_mtime_is_set(entry)) { 852299529Smm archive_le32enc(e, (uint32_t)archive_entry_mtime(entry)); 853299529Smm e += 4; 854228753Smm } 855299529Smm if (archive_entry_atime_is_set(entry)) { 856299529Smm archive_le32enc(e, (uint32_t)archive_entry_atime(entry)); 857299529Smm e += 4; 858299529Smm } 859299529Smm if (archive_entry_ctime_is_set(entry)) { 860299529Smm archive_le32enc(e, (uint32_t)archive_entry_ctime(entry)); 861299529Smm e += 4; 862299529Smm } 863228753Smm 864299529Smm /* ux Unix extra data, length 11, version 1 */ 865299529Smm /* TODO: If uid < 64k, use 2 bytes, ditto for gid. */ 866299529Smm memcpy(e, "ux\013\000\001", 5); 867299529Smm e += 5; 868299529Smm *e++ = 4; /* Length of following UID */ 869299529Smm archive_le32enc(e, (uint32_t)archive_entry_uid(entry)); 870299529Smm e += 4; 871299529Smm *e++ = 4; /* Length of following GID */ 872299529Smm archive_le32enc(e, (uint32_t)archive_entry_gid(entry)); 873299529Smm e += 4; 874228753Smm 875299529Smm /* AES extra data field: WinZIP AES information, ID=0x9901 */ 876299529Smm if ((zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) 877299529Smm && (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 878299529Smm || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) { 879232153Smm 880299529Smm memcpy(e, "\001\231\007\000\001\000AE", 8); 881299529Smm /* AES vendoer version AE-2 does not store a CRC. 882299529Smm * WinZip 11 uses AE-1, which does store the CRC, 883299529Smm * but it does not store the CRC when the file size 884299529Smm * is less than 20 bytes. So we simulate what 885299529Smm * WinZip 11 does. 886299529Smm * NOTE: WinZip 9.0 and 10.0 uses AE-2 by default. */ 887299529Smm if (archive_entry_size_is_set(zip->entry) 888299529Smm && archive_entry_size(zip->entry) < 20) { 889299529Smm archive_le16enc(e+4, AES_VENDOR_AE_2); 890299529Smm zip->aes_vendor = AES_VENDOR_AE_2;/* no CRC. */ 891299529Smm } else 892299529Smm zip->aes_vendor = AES_VENDOR_AE_1; 893299529Smm e += 8; 894299529Smm /* AES encryption strength. */ 895299529Smm *e++ = (zip->entry_encryption == ENCRYPTION_WINZIP_AES128)?1:3; 896299529Smm /* Actual compression method. */ 897299529Smm archive_le16enc(e, zip->entry_compression); 898299529Smm e += 2; 899299529Smm } 900228753Smm 901299529Smm /* Copy UT ,ux, and AES-extra into central directory as well. */ 902299529Smm zip->file_header_extra_offset = zip->central_directory_bytes; 903299529Smm cd_extra = cd_alloc(zip, e - local_extra); 904299529Smm memcpy(cd_extra, local_extra, e - local_extra); 905299529Smm 906299529Smm /* 907299529Smm * Following extra blocks vary between local header and 908299529Smm * central directory. These are the local header versions. 909299529Smm * Central directory versions get formatted in 910299529Smm * archive_write_zip_finish_entry() below. 911299529Smm */ 912299529Smm 913299529Smm /* "[Zip64 entry] in the local header MUST include BOTH 914299529Smm * original [uncompressed] and compressed size fields." */ 915299529Smm if (zip->entry_uses_zip64) { 916299529Smm unsigned char *zip64_start = e; 917299529Smm memcpy(e, "\001\000\020\000", 4); 918299529Smm e += 4; 919299529Smm archive_le64enc(e, zip->entry_uncompressed_size); 920299529Smm e += 8; 921299529Smm archive_le64enc(e, zip->entry_compressed_size); 922299529Smm e += 8; 923299529Smm archive_le16enc(zip64_start + 2, (uint16_t)(e - (zip64_start + 4))); 924299529Smm } 925299529Smm 926299529Smm if (zip->flags & ZIP_FLAG_EXPERIMENT_xl) { 927299529Smm /* Experimental 'xl' extension to improve streaming. */ 928299529Smm unsigned char *external_info = e; 929299529Smm int included = 7; 930299529Smm memcpy(e, "xl\000\000", 4); // 0x6c65 + 2-byte length 931299529Smm e += 4; 932299529Smm e[0] = included; /* bitmap of included fields */ 933299529Smm e += 1; 934299529Smm if (included & 1) { 935299529Smm archive_le16enc(e, /* "Version created by" */ 936299529Smm 3 * 256 + version_needed); 937299529Smm e += 2; 938299529Smm } 939299529Smm if (included & 2) { 940299529Smm archive_le16enc(e, 0); /* internal file attributes */ 941299529Smm e += 2; 942299529Smm } 943299529Smm if (included & 4) { 944299529Smm archive_le32enc(e, /* external file attributes */ 945299529Smm ((uint32_t)archive_entry_mode(zip->entry)) << 16); 946299529Smm e += 4; 947299529Smm } 948299529Smm if (included & 8) { 949299529Smm // Libarchive does not currently support file comments. 950299529Smm } 951299529Smm archive_le16enc(external_info + 2, (uint16_t)(e - (external_info + 4))); 952299529Smm } 953299529Smm 954299529Smm /* Update local header with size of extra data and write it all out: */ 955299529Smm archive_le16enc(local_header + 28, (uint16_t)(e - local_extra)); 956299529Smm 957299529Smm ret = __archive_write_output(a, local_header, 30); 958228753Smm if (ret != ARCHIVE_OK) 959228753Smm return (ARCHIVE_FATAL); 960299529Smm zip->written_bytes += 30; 961228753Smm 962299529Smm ret = write_path(zip->entry, a); 963228753Smm if (ret <= ARCHIVE_OK) 964228753Smm return (ARCHIVE_FATAL); 965228753Smm zip->written_bytes += ret; 966228753Smm 967299529Smm ret = __archive_write_output(a, local_extra, e - local_extra); 968228753Smm if (ret != ARCHIVE_OK) 969228753Smm return (ARCHIVE_FATAL); 970299529Smm zip->written_bytes += e - local_extra; 971228753Smm 972299529Smm /* For symlinks, write the body now. */ 973299529Smm if (slink != NULL) { 974299529Smm ret = __archive_write_output(a, slink, slink_size); 975232153Smm if (ret != ARCHIVE_OK) 976232153Smm return (ARCHIVE_FATAL); 977299529Smm zip->entry_compressed_written += slink_size; 978299529Smm zip->entry_uncompressed_written += slink_size; 979299529Smm zip->written_bytes += slink_size; 980232153Smm } 981232153Smm 982299529Smm#ifdef HAVE_ZLIB_H 983299529Smm if (zip->entry_compression == COMPRESSION_DEFLATE) { 984299529Smm zip->stream.zalloc = Z_NULL; 985299529Smm zip->stream.zfree = Z_NULL; 986299529Smm zip->stream.opaque = Z_NULL; 987299529Smm zip->stream.next_out = zip->buf; 988299529Smm zip->stream.avail_out = (uInt)zip->len_buf; 989299529Smm if (deflateInit2(&zip->stream, zip->deflate_compression_level, 990299529Smm Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { 991299529Smm archive_set_error(&a->archive, ENOMEM, 992299529Smm "Can't init deflate compressor"); 993299529Smm return (ARCHIVE_FATAL); 994299529Smm } 995299529Smm } 996299529Smm#endif 997299529Smm 998299529Smm return (ret2); 999228753Smm} 1000228753Smm 1001228753Smmstatic ssize_t 1002228753Smmarchive_write_zip_data(struct archive_write *a, const void *buff, size_t s) 1003228753Smm{ 1004228753Smm int ret; 1005228753Smm struct zip *zip = a->format_data; 1006228753Smm 1007299529Smm if ((int64_t)s > zip->entry_uncompressed_limit) 1008299529Smm s = (size_t)zip->entry_uncompressed_limit; 1009299529Smm zip->entry_uncompressed_written += s; 1010228753Smm 1011228753Smm if (s == 0) return 0; 1012228753Smm 1013299529Smm if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { 1014299529Smm switch (zip->entry_encryption) { 1015299529Smm case ENCRYPTION_TRADITIONAL: 1016299529Smm /* Initialize traditoinal PKWARE encryption context. */ 1017299529Smm if (!zip->tctx_valid) { 1018299529Smm ret = init_traditional_pkware_encryption(a); 1019299529Smm if (ret != ARCHIVE_OK) 1020299529Smm return (ret); 1021299529Smm zip->tctx_valid = 1; 1022299529Smm } 1023299529Smm break; 1024299529Smm case ENCRYPTION_WINZIP_AES128: 1025299529Smm case ENCRYPTION_WINZIP_AES256: 1026299529Smm if (!zip->cctx_valid) { 1027299529Smm ret = init_winzip_aes_encryption(a); 1028299529Smm if (ret != ARCHIVE_OK) 1029299529Smm return (ret); 1030299529Smm zip->cctx_valid = zip->hctx_valid = 1; 1031299529Smm } 1032299529Smm break; 1033299529Smm default: 1034299529Smm break; 1035299529Smm } 1036299529Smm } 1037299529Smm 1038299529Smm switch (zip->entry_compression) { 1039228753Smm case COMPRESSION_STORE: 1040299529Smm if (zip->tctx_valid || zip->cctx_valid) { 1041299529Smm const uint8_t *rb = (const uint8_t *)buff; 1042299529Smm const uint8_t * const re = rb + s; 1043299529Smm 1044299529Smm while (rb < re) { 1045299529Smm size_t l; 1046299529Smm 1047299529Smm if (zip->tctx_valid) { 1048299529Smm l = trad_enc_encrypt_update(&zip->tctx, 1049299529Smm rb, re - rb, 1050299529Smm zip->buf, zip->len_buf); 1051299529Smm } else { 1052299529Smm l = zip->len_buf; 1053299529Smm ret = archive_encrypto_aes_ctr_update( 1054299529Smm &zip->cctx, 1055299529Smm rb, re - rb, zip->buf, &l); 1056299529Smm if (ret < 0) { 1057299529Smm archive_set_error(&a->archive, 1058299529Smm ARCHIVE_ERRNO_MISC, 1059299529Smm "Failed to encrypt file"); 1060299529Smm return (ARCHIVE_FAILED); 1061299529Smm } 1062299529Smm archive_hmac_sha1_update(&zip->hctx, 1063299529Smm zip->buf, l); 1064299529Smm } 1065299529Smm ret = __archive_write_output(a, zip->buf, l); 1066299529Smm if (ret != ARCHIVE_OK) 1067299529Smm return (ret); 1068299529Smm zip->entry_compressed_written += l; 1069299529Smm zip->written_bytes += l; 1070299529Smm rb += l; 1071299529Smm } 1072299529Smm } else { 1073299529Smm ret = __archive_write_output(a, buff, s); 1074299529Smm if (ret != ARCHIVE_OK) 1075299529Smm return (ret); 1076299529Smm zip->written_bytes += s; 1077299529Smm zip->entry_compressed_written += s; 1078299529Smm } 1079299529Smm break; 1080228753Smm#if HAVE_ZLIB_H 1081228753Smm case COMPRESSION_DEFLATE: 1082228753Smm zip->stream.next_in = (unsigned char*)(uintptr_t)buff; 1083248616Smm zip->stream.avail_in = (uInt)s; 1084228753Smm do { 1085228753Smm ret = deflate(&zip->stream, Z_NO_FLUSH); 1086228753Smm if (ret == Z_STREAM_ERROR) 1087228753Smm return (ARCHIVE_FATAL); 1088228753Smm if (zip->stream.avail_out == 0) { 1089299529Smm if (zip->tctx_valid) { 1090299529Smm trad_enc_encrypt_update(&zip->tctx, 1091299529Smm zip->buf, zip->len_buf, 1092299529Smm zip->buf, zip->len_buf); 1093299529Smm } else if (zip->cctx_valid) { 1094299529Smm size_t outl = zip->len_buf; 1095299529Smm ret = archive_encrypto_aes_ctr_update( 1096299529Smm &zip->cctx, 1097299529Smm zip->buf, zip->len_buf, 1098299529Smm zip->buf, &outl); 1099299529Smm if (ret < 0) { 1100299529Smm archive_set_error(&a->archive, 1101299529Smm ARCHIVE_ERRNO_MISC, 1102299529Smm "Failed to encrypt file"); 1103299529Smm return (ARCHIVE_FAILED); 1104299529Smm } 1105299529Smm archive_hmac_sha1_update(&zip->hctx, 1106299529Smm zip->buf, zip->len_buf); 1107299529Smm } 1108232153Smm ret = __archive_write_output(a, zip->buf, 1109232153Smm zip->len_buf); 1110228753Smm if (ret != ARCHIVE_OK) 1111228753Smm return (ret); 1112299529Smm zip->entry_compressed_written += zip->len_buf; 1113228753Smm zip->written_bytes += zip->len_buf; 1114228753Smm zip->stream.next_out = zip->buf; 1115248616Smm zip->stream.avail_out = (uInt)zip->len_buf; 1116228753Smm } 1117228753Smm } while (zip->stream.avail_in != 0); 1118299529Smm break; 1119228753Smm#endif 1120228753Smm 1121228753Smm default: 1122228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1123228753Smm "Invalid ZIP compression type"); 1124228753Smm return ARCHIVE_FATAL; 1125228753Smm } 1126299529Smm 1127299529Smm zip->entry_uncompressed_limit -= s; 1128299529Smm if (!zip->cctx_valid || zip->aes_vendor != AES_VENDOR_AE_2) 1129299529Smm zip->entry_crc32 = 1130299529Smm zip->crc32func(zip->entry_crc32, buff, (unsigned)s); 1131299529Smm return (s); 1132299529Smm 1133228753Smm} 1134228753Smm 1135228753Smmstatic int 1136228753Smmarchive_write_zip_finish_entry(struct archive_write *a) 1137228753Smm{ 1138299529Smm struct zip *zip = a->format_data; 1139228753Smm int ret; 1140228753Smm 1141228753Smm#if HAVE_ZLIB_H 1142299529Smm if (zip->entry_compression == COMPRESSION_DEFLATE) { 1143228753Smm for (;;) { 1144299529Smm size_t remainder; 1145299529Smm 1146228753Smm ret = deflate(&zip->stream, Z_FINISH); 1147228753Smm if (ret == Z_STREAM_ERROR) 1148228753Smm return (ARCHIVE_FATAL); 1149299529Smm remainder = zip->len_buf - zip->stream.avail_out; 1150299529Smm if (zip->tctx_valid) { 1151299529Smm trad_enc_encrypt_update(&zip->tctx, 1152299529Smm zip->buf, remainder, zip->buf, remainder); 1153299529Smm } else if (zip->cctx_valid) { 1154299529Smm size_t outl = remainder; 1155299529Smm ret = archive_encrypto_aes_ctr_update( 1156299529Smm &zip->cctx, zip->buf, remainder, 1157299529Smm zip->buf, &outl); 1158299529Smm if (ret < 0) { 1159299529Smm archive_set_error(&a->archive, 1160299529Smm ARCHIVE_ERRNO_MISC, 1161299529Smm "Failed to encrypt file"); 1162299529Smm return (ARCHIVE_FAILED); 1163299529Smm } 1164299529Smm archive_hmac_sha1_update(&zip->hctx, 1165299529Smm zip->buf, remainder); 1166299529Smm } 1167299529Smm ret = __archive_write_output(a, zip->buf, remainder); 1168228753Smm if (ret != ARCHIVE_OK) 1169228753Smm return (ret); 1170299529Smm zip->entry_compressed_written += remainder; 1171299529Smm zip->written_bytes += remainder; 1172228753Smm zip->stream.next_out = zip->buf; 1173228753Smm if (zip->stream.avail_out != 0) 1174228753Smm break; 1175248616Smm zip->stream.avail_out = (uInt)zip->len_buf; 1176228753Smm } 1177228753Smm deflateEnd(&zip->stream); 1178299529Smm } 1179228753Smm#endif 1180299529Smm if (zip->hctx_valid) { 1181299529Smm uint8_t hmac[20]; 1182299529Smm size_t hmac_len = 20; 1183299529Smm 1184299529Smm archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len); 1185299529Smm ret = __archive_write_output(a, hmac, AUTH_CODE_SIZE); 1186299529Smm if (ret != ARCHIVE_OK) 1187299529Smm return (ret); 1188299529Smm zip->entry_compressed_written += AUTH_CODE_SIZE; 1189299529Smm zip->written_bytes += AUTH_CODE_SIZE; 1190228753Smm } 1191228753Smm 1192299529Smm /* Write trailing data descriptor. */ 1193299529Smm if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) != 0) { 1194299529Smm char d[24]; 1195299529Smm memcpy(d, "PK\007\010", 4); 1196299529Smm if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) 1197299529Smm archive_le32enc(d + 4, 0);/* no CRC.*/ 1198299529Smm else 1199299529Smm archive_le32enc(d + 4, zip->entry_crc32); 1200299529Smm if (zip->entry_uses_zip64) { 1201299529Smm archive_le64enc(d + 8, 1202299529Smm (uint64_t)zip->entry_compressed_written); 1203299529Smm archive_le64enc(d + 16, 1204299529Smm (uint64_t)zip->entry_uncompressed_written); 1205299529Smm ret = __archive_write_output(a, d, 24); 1206299529Smm zip->written_bytes += 24; 1207299529Smm } else { 1208299529Smm archive_le32enc(d + 8, 1209299529Smm (uint32_t)zip->entry_compressed_written); 1210299529Smm archive_le32enc(d + 12, 1211299529Smm (uint32_t)zip->entry_uncompressed_written); 1212299529Smm ret = __archive_write_output(a, d, 16); 1213299529Smm zip->written_bytes += 16; 1214299529Smm } 1215299529Smm if (ret != ARCHIVE_OK) 1216299529Smm return (ARCHIVE_FATAL); 1217299529Smm } 1218299529Smm 1219299529Smm /* Append Zip64 extra data to central directory information. */ 1220299529Smm if (zip->entry_compressed_written > ZIP_4GB_MAX 1221299529Smm || zip->entry_uncompressed_written > ZIP_4GB_MAX 1222299529Smm || zip->entry_offset > ZIP_4GB_MAX) { 1223299529Smm unsigned char zip64[32]; 1224299529Smm unsigned char *z = zip64, *zd; 1225299529Smm memcpy(z, "\001\000\000\000", 4); 1226299529Smm z += 4; 1227299529Smm if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) { 1228299529Smm archive_le64enc(z, zip->entry_uncompressed_written); 1229299529Smm z += 8; 1230299529Smm } 1231299529Smm if (zip->entry_compressed_written >= ZIP_4GB_MAX) { 1232299529Smm archive_le64enc(z, zip->entry_compressed_written); 1233299529Smm z += 8; 1234299529Smm } 1235299529Smm if (zip->entry_offset >= ZIP_4GB_MAX) { 1236299529Smm archive_le64enc(z, zip->entry_offset); 1237299529Smm z += 8; 1238299529Smm } 1239299529Smm archive_le16enc(zip64 + 2, (uint16_t)(z - (zip64 + 4))); 1240299529Smm zd = cd_alloc(zip, z - zip64); 1241299529Smm if (zd == NULL) { 1242299529Smm archive_set_error(&a->archive, ENOMEM, 1243299529Smm "Can't allocate zip data"); 1244299529Smm return (ARCHIVE_FATAL); 1245299529Smm } 1246299529Smm memcpy(zd, zip64, z - zip64); 1247299529Smm /* Zip64 means version needs to be set to at least 4.5 */ 1248299529Smm if (archive_le16dec(zip->file_header + 6) < 45) 1249299529Smm archive_le16enc(zip->file_header + 6, 45); 1250299529Smm } 1251299529Smm 1252299529Smm /* Fix up central directory file header. */ 1253299529Smm if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) 1254299529Smm archive_le32enc(zip->file_header + 16, 0);/* no CRC.*/ 1255299529Smm else 1256299529Smm archive_le32enc(zip->file_header + 16, zip->entry_crc32); 1257299529Smm archive_le32enc(zip->file_header + 20, 1258299529Smm (uint32_t)zipmin(zip->entry_compressed_written, 1259299529Smm ZIP_4GB_MAX)); 1260299529Smm archive_le32enc(zip->file_header + 24, 1261299529Smm (uint32_t)zipmin(zip->entry_uncompressed_written, 1262299529Smm ZIP_4GB_MAX)); 1263299529Smm archive_le16enc(zip->file_header + 30, 1264299529Smm (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset)); 1265299529Smm archive_le32enc(zip->file_header + 42, 1266299529Smm (uint32_t)zipmin(zip->entry_offset, 1267299529Smm ZIP_4GB_MAX)); 1268299529Smm 1269228753Smm return (ARCHIVE_OK); 1270228753Smm} 1271228753Smm 1272228753Smmstatic int 1273232153Smmarchive_write_zip_close(struct archive_write *a) 1274228753Smm{ 1275299529Smm uint8_t buff[64]; 1276232153Smm int64_t offset_start, offset_end; 1277299529Smm struct zip *zip = a->format_data; 1278299529Smm struct cd_segment *segment; 1279228753Smm int ret; 1280228753Smm 1281228753Smm offset_start = zip->written_bytes; 1282299529Smm segment = zip->central_directory; 1283299529Smm while (segment != NULL) { 1284299529Smm ret = __archive_write_output(a, 1285299529Smm segment->buff, segment->p - segment->buff); 1286228753Smm if (ret != ARCHIVE_OK) 1287228753Smm return (ARCHIVE_FATAL); 1288299529Smm zip->written_bytes += segment->p - segment->buff; 1289299529Smm segment = segment->next; 1290299529Smm } 1291299529Smm offset_end = zip->written_bytes; 1292228753Smm 1293299529Smm /* If central dir info is too large, write Zip64 end-of-cd */ 1294299529Smm if (offset_end - offset_start > ZIP_4GB_MAX 1295299529Smm || offset_start > ZIP_4GB_MAX 1296299529Smm || zip->central_directory_entries > 0xffffUL 1297299529Smm || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) { 1298299529Smm /* Zip64 end-of-cd record */ 1299299529Smm memset(buff, 0, 56); 1300299529Smm memcpy(buff, "PK\006\006", 4); 1301299529Smm archive_le64enc(buff + 4, 44); 1302299529Smm archive_le16enc(buff + 12, 45); 1303299529Smm archive_le16enc(buff + 14, 45); 1304299529Smm /* This is disk 0 of 0. */ 1305299529Smm archive_le64enc(buff + 24, zip->central_directory_entries); 1306299529Smm archive_le64enc(buff + 32, zip->central_directory_entries); 1307299529Smm archive_le64enc(buff + 40, offset_end - offset_start); 1308299529Smm archive_le64enc(buff + 48, offset_start); 1309299529Smm ret = __archive_write_output(a, buff, 56); 1310299529Smm if (ret != ARCHIVE_OK) 1311299529Smm return (ARCHIVE_FATAL); 1312299529Smm zip->written_bytes += 56; 1313228753Smm 1314299529Smm /* Zip64 end-of-cd locator record. */ 1315299529Smm memset(buff, 0, 20); 1316299529Smm memcpy(buff, "PK\006\007", 4); 1317299529Smm archive_le32enc(buff + 4, 0); 1318299529Smm archive_le64enc(buff + 8, offset_end); 1319299529Smm archive_le32enc(buff + 16, 1); 1320299529Smm ret = __archive_write_output(a, buff, 20); 1321299529Smm if (ret != ARCHIVE_OK) 1322299529Smm return (ARCHIVE_FATAL); 1323299529Smm zip->written_bytes += 20; 1324228753Smm 1325228753Smm } 1326228753Smm 1327299529Smm /* Format and write end of central directory. */ 1328299529Smm memset(buff, 0, sizeof(buff)); 1329299529Smm memcpy(buff, "PK\005\006", 4); 1330299529Smm archive_le16enc(buff + 8, (uint16_t)zipmin(0xffffU, 1331299529Smm zip->central_directory_entries)); 1332299529Smm archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU, 1333299529Smm zip->central_directory_entries)); 1334299529Smm archive_le32enc(buff + 12, 1335299529Smm (uint32_t)zipmin(ZIP_4GB_MAX, (offset_end - offset_start))); 1336299529Smm archive_le32enc(buff + 16, 1337299529Smm (uint32_t)zipmin(ZIP_4GB_MAX, offset_start)); 1338299529Smm ret = __archive_write_output(a, buff, 22); 1339228753Smm if (ret != ARCHIVE_OK) 1340228753Smm return (ARCHIVE_FATAL); 1341299529Smm zip->written_bytes += 22; 1342228753Smm return (ARCHIVE_OK); 1343228753Smm} 1344228753Smm 1345228753Smmstatic int 1346232153Smmarchive_write_zip_free(struct archive_write *a) 1347228753Smm{ 1348228753Smm struct zip *zip; 1349299529Smm struct cd_segment *segment; 1350228753Smm 1351228753Smm zip = a->format_data; 1352228753Smm while (zip->central_directory != NULL) { 1353299529Smm segment = zip->central_directory; 1354299529Smm zip->central_directory = segment->next; 1355299529Smm free(segment->buff); 1356299529Smm free(segment); 1357228753Smm } 1358228753Smm free(zip->buf); 1359299529Smm archive_entry_free(zip->entry); 1360299529Smm if (zip->cctx_valid) 1361299529Smm archive_encrypto_aes_ctr_release(&zip->cctx); 1362299529Smm if (zip->hctx_valid) 1363299529Smm archive_hmac_sha1_cleanup(&zip->hctx); 1364299529Smm /* TODO: Free opt_sconv, sconv_default */ 1365299529Smm 1366228753Smm free(zip); 1367228753Smm a->format_data = NULL; 1368228753Smm return (ARCHIVE_OK); 1369228753Smm} 1370228753Smm 1371228753Smm/* Convert into MSDOS-style date/time. */ 1372228753Smmstatic unsigned int 1373228753Smmdos_time(const time_t unix_time) 1374228753Smm{ 1375228753Smm struct tm *t; 1376228753Smm unsigned int dt; 1377228753Smm 1378228753Smm /* This will not preserve time when creating/extracting the archive 1379228753Smm * on two systems with different time zones. */ 1380228753Smm t = localtime(&unix_time); 1381228753Smm 1382232153Smm /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */ 1383232153Smm if (t->tm_year < 1980 - 1900) 1384232153Smm /* Set minimum date/time '1980-01-01 00:00:00'. */ 1385232153Smm dt = 0x00210000U; 1386232153Smm else if (t->tm_year > 2107 - 1900) 1387232153Smm /* Set maximum date/time '2107-12-31 23:59:58'. */ 1388232153Smm dt = 0xff9fbf7dU; 1389232153Smm else { 1390232153Smm dt = 0; 1391232153Smm dt += ((t->tm_year - 80) & 0x7f) << 9; 1392232153Smm dt += ((t->tm_mon + 1) & 0x0f) << 5; 1393232153Smm dt += (t->tm_mday & 0x1f); 1394232153Smm dt <<= 16; 1395232153Smm dt += (t->tm_hour & 0x1f) << 11; 1396232153Smm dt += (t->tm_min & 0x3f) << 5; 1397232153Smm dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ 1398232153Smm } 1399228753Smm return dt; 1400228753Smm} 1401228753Smm 1402228753Smmstatic size_t 1403228753Smmpath_length(struct archive_entry *entry) 1404228753Smm{ 1405228753Smm mode_t type; 1406228753Smm const char *path; 1407228753Smm 1408228753Smm type = archive_entry_filetype(entry); 1409228753Smm path = archive_entry_pathname(entry); 1410228753Smm 1411248616Smm if (path == NULL) 1412248616Smm return (0); 1413248616Smm if (type == AE_IFDIR && 1414248616Smm (path[0] == '\0' || path[strlen(path) - 1] != '/')) { 1415228753Smm return strlen(path) + 1; 1416228753Smm } else { 1417228753Smm return strlen(path); 1418228753Smm } 1419228753Smm} 1420228753Smm 1421228753Smmstatic int 1422228753Smmwrite_path(struct archive_entry *entry, struct archive_write *archive) 1423228753Smm{ 1424228753Smm int ret; 1425228753Smm const char *path; 1426228753Smm mode_t type; 1427228753Smm size_t written_bytes; 1428228753Smm 1429228753Smm path = archive_entry_pathname(entry); 1430228753Smm type = archive_entry_filetype(entry); 1431228753Smm written_bytes = 0; 1432228753Smm 1433232153Smm ret = __archive_write_output(archive, path, strlen(path)); 1434228753Smm if (ret != ARCHIVE_OK) 1435228753Smm return (ARCHIVE_FATAL); 1436228753Smm written_bytes += strlen(path); 1437228753Smm 1438299529Smm /* Folders are recognized by a trailing slash. */ 1439228753Smm if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { 1440232153Smm ret = __archive_write_output(archive, "/", 1); 1441228753Smm if (ret != ARCHIVE_OK) 1442228753Smm return (ARCHIVE_FATAL); 1443228753Smm written_bytes += 1; 1444228753Smm } 1445228753Smm 1446228753Smm return ((int)written_bytes); 1447228753Smm} 1448299529Smm 1449299529Smmstatic void 1450299529Smmcopy_path(struct archive_entry *entry, unsigned char *p) 1451299529Smm{ 1452299529Smm const char *path; 1453299529Smm size_t pathlen; 1454299529Smm mode_t type; 1455299529Smm 1456299529Smm path = archive_entry_pathname(entry); 1457299529Smm pathlen = strlen(path); 1458299529Smm type = archive_entry_filetype(entry); 1459299529Smm 1460299529Smm memcpy(p, path, pathlen); 1461299529Smm 1462299529Smm /* Folders are recognized by a trailing slash. */ 1463299529Smm if ((type == AE_IFDIR) & (path[pathlen - 1] != '/')) { 1464299529Smm p[pathlen] = '/'; 1465299529Smm p[pathlen + 1] = '\0'; 1466299529Smm } 1467299529Smm} 1468299529Smm 1469299529Smm 1470299529Smmstatic struct archive_string_conv * 1471299529Smmget_sconv(struct archive_write *a, struct zip *zip) 1472299529Smm{ 1473299529Smm if (zip->opt_sconv != NULL) 1474299529Smm return (zip->opt_sconv); 1475299529Smm 1476299529Smm if (!zip->init_default_conversion) { 1477299529Smm zip->sconv_default = 1478299529Smm archive_string_default_conversion_for_write(&(a->archive)); 1479299529Smm zip->init_default_conversion = 1; 1480299529Smm } 1481299529Smm return (zip->sconv_default); 1482299529Smm} 1483299529Smm 1484299529Smm/* 1485299529Smm Traditional PKWARE Decryption functions. 1486299529Smm */ 1487299529Smm 1488299529Smmstatic void 1489299529Smmtrad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) 1490299529Smm{ 1491299529Smm uint8_t t; 1492299529Smm#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL) 1493299529Smm 1494299529Smm ctx->keys[0] = CRC32(ctx->keys[0], c); 1495299529Smm ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1; 1496299529Smm t = (ctx->keys[1] >> 24) & 0xff; 1497299529Smm ctx->keys[2] = CRC32(ctx->keys[2], t); 1498299529Smm#undef CRC32 1499299529Smm} 1500299529Smm 1501299529Smmstatic uint8_t 1502299529Smmtrad_enc_decypt_byte(struct trad_enc_ctx *ctx) 1503299529Smm{ 1504299529Smm unsigned temp = ctx->keys[2] | 2; 1505299529Smm return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; 1506299529Smm} 1507299529Smm 1508299529Smmstatic unsigned 1509299529Smmtrad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, 1510299529Smm size_t in_len, uint8_t *out, size_t out_len) 1511299529Smm{ 1512299529Smm unsigned i, max; 1513299529Smm 1514299529Smm max = (unsigned)((in_len < out_len)? in_len: out_len); 1515299529Smm 1516299529Smm for (i = 0; i < max; i++) { 1517299529Smm uint8_t t = in[i]; 1518299529Smm out[i] = t ^ trad_enc_decypt_byte(ctx); 1519299529Smm trad_enc_update_keys(ctx, t); 1520299529Smm } 1521299529Smm return i; 1522299529Smm} 1523299529Smm 1524299529Smmstatic int 1525299529Smmtrad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len) 1526299529Smm{ 1527299529Smm 1528299529Smm ctx->keys[0] = 305419896L; 1529299529Smm ctx->keys[1] = 591751049L; 1530299529Smm ctx->keys[2] = 878082192L; 1531299529Smm 1532299529Smm for (;pw_len; --pw_len) 1533299529Smm trad_enc_update_keys(ctx, *pw++); 1534299529Smm return 0; 1535299529Smm} 1536299529Smm 1537299529Smmstatic int 1538299529Smmis_traditional_pkware_encryption_supported(void) 1539299529Smm{ 1540299529Smm uint8_t key[TRAD_HEADER_SIZE]; 1541299529Smm 1542299529Smm if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) 1543299529Smm return (0); 1544299529Smm return (1); 1545299529Smm} 1546299529Smm 1547299529Smmstatic int 1548299529Smminit_traditional_pkware_encryption(struct archive_write *a) 1549299529Smm{ 1550299529Smm struct zip *zip = a->format_data; 1551299529Smm const char *passphrase; 1552299529Smm uint8_t key[TRAD_HEADER_SIZE]; 1553299529Smm uint8_t key_encrypted[TRAD_HEADER_SIZE]; 1554299529Smm int ret; 1555299529Smm 1556299529Smm passphrase = __archive_write_get_passphrase(a); 1557299529Smm if (passphrase == NULL) { 1558299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1559299529Smm "Encryption needs passphrase"); 1560299529Smm return ARCHIVE_FAILED; 1561299529Smm } 1562299529Smm if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) { 1563299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1564299529Smm "Can't generate random number for encryption"); 1565299529Smm return ARCHIVE_FATAL; 1566299529Smm } 1567299529Smm trad_enc_init(&zip->tctx, passphrase, strlen(passphrase)); 1568299529Smm /* Set the last key code which will be used as a check code 1569299529Smm * for verifying passphrase in decryption. */ 1570299529Smm key[TRAD_HEADER_SIZE-1] = zip->trad_chkdat; 1571299529Smm trad_enc_encrypt_update(&zip->tctx, key, TRAD_HEADER_SIZE, 1572299529Smm key_encrypted, TRAD_HEADER_SIZE); 1573299529Smm /* Write encrypted keys in the top of the file content. */ 1574299529Smm ret = __archive_write_output(a, key_encrypted, TRAD_HEADER_SIZE); 1575299529Smm if (ret != ARCHIVE_OK) 1576299529Smm return (ret); 1577299529Smm zip->written_bytes += TRAD_HEADER_SIZE; 1578299529Smm zip->entry_compressed_written += TRAD_HEADER_SIZE; 1579299529Smm return (ret); 1580299529Smm} 1581299529Smm 1582299529Smmstatic int 1583299529Smminit_winzip_aes_encryption(struct archive_write *a) 1584299529Smm{ 1585299529Smm struct zip *zip = a->format_data; 1586299529Smm const char *passphrase; 1587299529Smm size_t key_len, salt_len; 1588299529Smm uint8_t salt[16 + 2]; 1589299529Smm uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; 1590299529Smm int ret; 1591299529Smm 1592299529Smm passphrase = __archive_write_get_passphrase(a); 1593299529Smm if (passphrase == NULL) { 1594299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1595299529Smm "Encryption needs passphrase"); 1596299529Smm return (ARCHIVE_FAILED); 1597299529Smm } 1598299529Smm if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128) { 1599299529Smm salt_len = 8; 1600299529Smm key_len = 16; 1601299529Smm } else { 1602299529Smm /* AES 256 */ 1603299529Smm salt_len = 16; 1604299529Smm key_len = 32; 1605299529Smm } 1606299529Smm if (archive_random(salt, salt_len) != ARCHIVE_OK) { 1607299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1608299529Smm "Can't generate random number for encryption"); 1609299529Smm return (ARCHIVE_FATAL); 1610299529Smm } 1611299529Smm archive_pbkdf2_sha1(passphrase, strlen(passphrase), 1612299529Smm salt, salt_len, 1000, derived_key, key_len * 2 + 2); 1613299529Smm 1614299529Smm ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); 1615299529Smm if (ret != 0) { 1616299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1617299529Smm "Decryption is unsupported due to lack of crypto library"); 1618299529Smm return (ARCHIVE_FAILED); 1619299529Smm } 1620299529Smm ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, 1621299529Smm key_len); 1622299529Smm if (ret != 0) { 1623299529Smm archive_encrypto_aes_ctr_release(&zip->cctx); 1624299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1625299529Smm "Failed to initialize HMAC-SHA1"); 1626299529Smm return (ARCHIVE_FAILED); 1627299529Smm } 1628299529Smm 1629299529Smm /* Set a passowrd verification value after the 'salt'. */ 1630299529Smm salt[salt_len] = derived_key[key_len * 2]; 1631299529Smm salt[salt_len + 1] = derived_key[key_len * 2 + 1]; 1632299529Smm 1633299529Smm /* Write encrypted keys in the top of the file content. */ 1634299529Smm ret = __archive_write_output(a, salt, salt_len + 2); 1635299529Smm if (ret != ARCHIVE_OK) 1636299529Smm return (ret); 1637299529Smm zip->written_bytes += salt_len + 2; 1638299529Smm zip->entry_compressed_written += salt_len + 2; 1639299529Smm 1640299529Smm return (ARCHIVE_OK); 1641299529Smm} 1642299529Smm 1643299529Smmstatic int 1644299529Smmis_winzip_aes_encryption_supported(int encryption) 1645299529Smm{ 1646299529Smm size_t key_len, salt_len; 1647299529Smm uint8_t salt[16 + 2]; 1648299529Smm uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; 1649299529Smm archive_crypto_ctx cctx; 1650299529Smm archive_hmac_sha1_ctx hctx; 1651299529Smm int ret; 1652299529Smm 1653299529Smm if (encryption == ENCRYPTION_WINZIP_AES128) { 1654299529Smm salt_len = 8; 1655299529Smm key_len = 16; 1656299529Smm } else { 1657299529Smm /* AES 256 */ 1658299529Smm salt_len = 16; 1659299529Smm key_len = 32; 1660299529Smm } 1661299529Smm if (archive_random(salt, salt_len) != ARCHIVE_OK) 1662299529Smm return (0); 1663299529Smm ret = archive_pbkdf2_sha1("p", 1, salt, salt_len, 1000, 1664299529Smm derived_key, key_len * 2 + 2); 1665299529Smm if (ret != 0) 1666299529Smm return (0); 1667299529Smm 1668299529Smm ret = archive_encrypto_aes_ctr_init(&cctx, derived_key, key_len); 1669299529Smm if (ret != 0) 1670299529Smm return (0); 1671299529Smm ret = archive_hmac_sha1_init(&hctx, derived_key + key_len, 1672299529Smm key_len); 1673299529Smm archive_encrypto_aes_ctr_release(&cctx); 1674299529Smm if (ret != 0) 1675299529Smm return (0); 1676299529Smm archive_hmac_sha1_cleanup(&hctx); 1677299529Smm return (1); 1678299529Smm} 1679