1 /*- 2 * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA 3 * Copyright (c) 2003-2007 Tim Kientzle 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "archive_platform.h" 28 29 #ifdef HAVE_SYS_TYPES_H 30 #include <sys/types.h> 31 #endif 32 #ifdef HAVE_ERRNO_H 33 #include <errno.h> 34 #endif 35 #ifdef HAVE_FCNTL_H 36 #include <fcntl.h> 37 #endif 38 #ifdef HAVE_STDLIB_H 39 #include <stdlib.h> 40 #endif 41 #ifdef HAVE_STRING_H 42 #include <string.h> 43 #endif 44 #if defined(_WIN32) && !defined(__CYGWIN__) 45 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 46 /* don't use bcrypt when XP needs to be supported */ 47 #include <bcrypt.h> 48 49 /* Common in other bcrypt implementations, but missing from VS2008. */ 50 #ifndef BCRYPT_SUCCESS 51 #define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS) 52 #endif 53 54 #elif defined(HAVE_WINCRYPT_H) 55 #include <wincrypt.h> 56 #endif 57 #endif 58 #ifdef HAVE_ZLIB_H 59 #include <zlib.h> 60 #endif 61 #ifdef HAVE_LZMA_H 62 #include <lzma.h> 63 #endif 64 #ifdef HAVE_BZLIB_H 65 #include <bzlib.h> 66 #endif 67 #ifdef HAVE_LZ4_H 68 #include <lz4.h> 69 #endif 70 71 #include "archive.h" 72 #include "archive_private.h" 73 #include "archive_random_private.h" 74 #include "archive_string.h" 75 76 #ifndef O_CLOEXEC 77 #define O_CLOEXEC 0 78 #endif 79 80 #if ARCHIVE_VERSION_NUMBER < 4000000 81 static int __LA_LIBC_CC archive_utility_string_sort_helper(const void *, const void *); 82 #endif 83 84 /* Generic initialization of 'struct archive' objects. */ 85 int 86 __archive_clean(struct archive *a) 87 { 88 archive_string_conversion_free(a); 89 return (ARCHIVE_OK); 90 } 91 92 int 93 archive_version_number(void) 94 { 95 return (ARCHIVE_VERSION_NUMBER); 96 } 97 98 const char * 99 archive_version_string(void) 100 { 101 return (ARCHIVE_VERSION_STRING); 102 } 103 104 int 105 archive_errno(struct archive *a) 106 { 107 return (a->archive_error_number); 108 } 109 110 const char * 111 archive_error_string(struct archive *a) 112 { 113 114 if (a->error != NULL && *a->error != '\0') 115 return (a->error); 116 else 117 return (NULL); 118 } 119 120 int 121 archive_file_count(struct archive *a) 122 { 123 return (a->file_count); 124 } 125 126 int 127 archive_format(struct archive *a) 128 { 129 return (a->archive_format); 130 } 131 132 const char * 133 archive_format_name(struct archive *a) 134 { 135 return (a->archive_format_name); 136 } 137 138 139 int 140 archive_compression(struct archive *a) 141 { 142 return archive_filter_code(a, 0); 143 } 144 145 const char * 146 archive_compression_name(struct archive *a) 147 { 148 return archive_filter_name(a, 0); 149 } 150 151 152 /* 153 * Return a count of the number of compressed bytes processed. 154 */ 155 la_int64_t 156 archive_position_compressed(struct archive *a) 157 { 158 return archive_filter_bytes(a, -1); 159 } 160 161 /* 162 * Return a count of the number of uncompressed bytes processed. 163 */ 164 la_int64_t 165 archive_position_uncompressed(struct archive *a) 166 { 167 return archive_filter_bytes(a, 0); 168 } 169 170 void 171 archive_clear_error(struct archive *a) 172 { 173 archive_string_empty(&a->error_string); 174 a->error = NULL; 175 a->archive_error_number = 0; 176 } 177 178 void 179 archive_set_error(struct archive *a, int error_number, const char *fmt, ...) 180 { 181 va_list ap; 182 183 a->archive_error_number = error_number; 184 if (fmt == NULL) { 185 a->error = NULL; 186 return; 187 } 188 189 archive_string_empty(&(a->error_string)); 190 va_start(ap, fmt); 191 archive_string_vsprintf(&(a->error_string), fmt, ap); 192 va_end(ap); 193 a->error = a->error_string.s; 194 } 195 196 void 197 archive_copy_error(struct archive *dest, struct archive *src) 198 { 199 dest->archive_error_number = src->archive_error_number; 200 201 archive_string_copy(&dest->error_string, &src->error_string); 202 dest->error = dest->error_string.s; 203 } 204 205 void 206 __archive_errx(int retvalue, const char *msg) 207 { 208 static const char msg1[] = "Fatal Internal Error in libarchive: "; 209 size_t s; 210 211 s = write(2, msg1, strlen(msg1)); 212 (void)s; /* UNUSED */ 213 s = write(2, msg, strlen(msg)); 214 (void)s; /* UNUSED */ 215 s = write(2, "\n", 1); 216 (void)s; /* UNUSED */ 217 exit(retvalue); 218 } 219 220 /* 221 * Create a temporary file 222 */ 223 #if defined(_WIN32) && !defined(__CYGWIN__) 224 225 /* 226 * Do not use Windows tmpfile() function. 227 * It will make a temporary file under the root directory 228 * and it'll cause permission error if a user who is 229 * non-Administrator creates temporary files. 230 * Also Windows version of mktemp family including _mktemp_s 231 * are not secure. 232 */ 233 static int 234 __archive_mktempx(const char *tmpdir, wchar_t *template) 235 { 236 static const wchar_t prefix[] = L"libarchive_"; 237 static const wchar_t suffix[] = L"XXXXXXXXXX"; 238 static const wchar_t num[] = { 239 L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', 240 L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F', 241 L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N', 242 L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V', 243 L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd', 244 L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l', 245 L'm', L'n', L'o', L'p', L'q', L'r', L's', L't', 246 L'u', L'v', L'w', L'x', L'y', L'z' 247 }; 248 struct archive_wstring temp_name; 249 wchar_t *ws; 250 DWORD attr; 251 wchar_t *xp, *ep; 252 int fd; 253 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 254 BCRYPT_ALG_HANDLE hAlg = NULL; 255 #else 256 HCRYPTPROV hProv = (HCRYPTPROV)NULL; 257 #endif 258 fd = -1; 259 ws = NULL; 260 archive_string_init(&temp_name); 261 262 if (template == NULL) { 263 /* Get a temporary directory. */ 264 if (tmpdir == NULL) { 265 size_t l; 266 wchar_t *tmp; 267 268 l = GetTempPathW(0, NULL); 269 if (l == 0) { 270 la_dosmaperr(GetLastError()); 271 goto exit_tmpfile; 272 } 273 tmp = malloc(l*sizeof(wchar_t)); 274 if (tmp == NULL) { 275 errno = ENOMEM; 276 goto exit_tmpfile; 277 } 278 GetTempPathW((DWORD)l, tmp); 279 archive_wstrcpy(&temp_name, tmp); 280 free(tmp); 281 } else { 282 if (archive_wstring_append_from_mbs(&temp_name, tmpdir, 283 strlen(tmpdir)) < 0) 284 goto exit_tmpfile; 285 if (temp_name.length == 0 || 286 temp_name.s[temp_name.length-1] != L'/') 287 archive_wstrappend_wchar(&temp_name, L'/'); 288 } 289 290 /* Check if temp_name is a directory. */ 291 attr = GetFileAttributesW(temp_name.s); 292 if (attr == (DWORD)-1) { 293 if (GetLastError() != ERROR_FILE_NOT_FOUND) { 294 la_dosmaperr(GetLastError()); 295 goto exit_tmpfile; 296 } 297 ws = __la_win_permissive_name_w(temp_name.s); 298 if (ws == NULL) { 299 errno = EINVAL; 300 goto exit_tmpfile; 301 } 302 attr = GetFileAttributesW(ws); 303 if (attr == (DWORD)-1) { 304 la_dosmaperr(GetLastError()); 305 goto exit_tmpfile; 306 } 307 } 308 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { 309 errno = ENOTDIR; 310 goto exit_tmpfile; 311 } 312 313 /* 314 * Create a temporary file. 315 */ 316 archive_wstrcat(&temp_name, prefix); 317 archive_wstrcat(&temp_name, suffix); 318 ep = temp_name.s + archive_strlen(&temp_name); 319 xp = ep - wcslen(suffix); 320 template = temp_name.s; 321 } else { 322 xp = wcschr(template, L'X'); 323 if (xp == NULL) /* No X, programming error */ 324 abort(); 325 for (ep = xp; *ep == L'X'; ep++) 326 continue; 327 if (*ep) /* X followed by non X, programming error */ 328 abort(); 329 } 330 331 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 332 if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, 333 NULL, 0))) { 334 la_dosmaperr(GetLastError()); 335 goto exit_tmpfile; 336 } 337 #else 338 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 339 CRYPT_VERIFYCONTEXT)) { 340 la_dosmaperr(GetLastError()); 341 goto exit_tmpfile; 342 } 343 #endif 344 345 for (;;) { 346 wchar_t *p; 347 HANDLE h; 348 # if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */ 349 CREATEFILE2_EXTENDED_PARAMETERS createExParams; 350 #endif 351 352 /* Generate a random file name through CryptGenRandom(). */ 353 p = xp; 354 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 355 if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p, 356 (DWORD)(ep - p)*sizeof(wchar_t), 0))) { 357 la_dosmaperr(GetLastError()); 358 goto exit_tmpfile; 359 } 360 #else 361 if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), 362 (BYTE*)p)) { 363 la_dosmaperr(GetLastError()); 364 goto exit_tmpfile; 365 } 366 #endif 367 for (; p < ep; p++) 368 *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; 369 370 free(ws); 371 ws = __la_win_permissive_name_w(template); 372 if (ws == NULL) { 373 errno = EINVAL; 374 goto exit_tmpfile; 375 } 376 if (template == temp_name.s) { 377 attr = FILE_ATTRIBUTE_TEMPORARY | 378 FILE_FLAG_DELETE_ON_CLOSE; 379 } else { 380 /* mkstemp */ 381 attr = FILE_ATTRIBUTE_NORMAL; 382 } 383 # if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */ 384 ZeroMemory(&createExParams, sizeof(createExParams)); 385 createExParams.dwSize = sizeof(createExParams); 386 createExParams.dwFileAttributes = attr & 0xFFFF; 387 createExParams.dwFileFlags = attr & 0xFFF00000; 388 h = CreateFile2(ws, 389 GENERIC_READ | GENERIC_WRITE | DELETE, 390 0,/* Not share */ 391 CREATE_NEW, 392 &createExParams); 393 #else 394 h = CreateFileW(ws, 395 GENERIC_READ | GENERIC_WRITE | DELETE, 396 0,/* Not share */ 397 NULL, 398 CREATE_NEW,/* Create a new file only */ 399 attr, 400 NULL); 401 #endif 402 if (h == INVALID_HANDLE_VALUE) { 403 /* The same file already exists. retry with 404 * a new filename. */ 405 if (GetLastError() == ERROR_FILE_EXISTS) 406 continue; 407 /* Otherwise, fail creation temporary file. */ 408 la_dosmaperr(GetLastError()); 409 goto exit_tmpfile; 410 } 411 fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); 412 if (fd == -1) { 413 la_dosmaperr(GetLastError()); 414 CloseHandle(h); 415 goto exit_tmpfile; 416 } else 417 break;/* success! */ 418 } 419 exit_tmpfile: 420 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 421 if (hAlg != NULL) 422 BCryptCloseAlgorithmProvider(hAlg, 0); 423 #else 424 if (hProv != (HCRYPTPROV)NULL) 425 CryptReleaseContext(hProv, 0); 426 #endif 427 free(ws); 428 if (template == temp_name.s) 429 archive_wstring_free(&temp_name); 430 return (fd); 431 } 432 433 int 434 __archive_mktemp(const char *tmpdir) 435 { 436 return __archive_mktempx(tmpdir, NULL); 437 } 438 439 int 440 __archive_mkstemp(wchar_t *template) 441 { 442 return __archive_mktempx(NULL, template); 443 } 444 445 #else 446 447 static int 448 __archive_issetugid(void) 449 { 450 #ifdef HAVE_ISSETUGID 451 return (issetugid()); 452 #elif HAVE_GETRESUID 453 uid_t ruid, euid, suid; 454 gid_t rgid, egid, sgid; 455 if (getresuid(&ruid, &euid, &suid) != 0) 456 return (-1); 457 if (ruid != euid || ruid != suid) 458 return (1); 459 if (getresgid(&ruid, &egid, &sgid) != 0) 460 return (-1); 461 if (rgid != egid || rgid != sgid) 462 return (1); 463 #elif HAVE_GETEUID 464 if (geteuid() != getuid()) 465 return (1); 466 #if HAVE_GETEGID 467 if (getegid() != getgid()) 468 return (1); 469 #endif 470 #endif 471 return (0); 472 } 473 474 int 475 __archive_get_tempdir(struct archive_string *temppath) 476 { 477 const char *tmp = NULL; 478 479 if (__archive_issetugid() == 0) 480 tmp = getenv("TMPDIR"); 481 if (tmp == NULL) 482 #ifdef _PATH_TMP 483 tmp = _PATH_TMP; 484 #else 485 tmp = "/tmp"; 486 #endif 487 archive_strcpy(temppath, tmp); 488 if (temppath->length == 0 || temppath->s[temppath->length-1] != '/') 489 archive_strappend_char(temppath, '/'); 490 return (ARCHIVE_OK); 491 } 492 493 #if defined(HAVE_MKSTEMP) 494 495 /* 496 * We can use mkstemp(). 497 */ 498 499 int 500 __archive_mktemp(const char *tmpdir) 501 { 502 struct archive_string temp_name; 503 int fd = -1; 504 505 archive_string_init(&temp_name); 506 if (tmpdir == NULL) { 507 if (__archive_get_tempdir(&temp_name) != ARCHIVE_OK) 508 goto exit_tmpfile; 509 } else { 510 archive_strcpy(&temp_name, tmpdir); 511 if (temp_name.length == 0 || 512 temp_name.s[temp_name.length-1] != '/') 513 archive_strappend_char(&temp_name, '/'); 514 } 515 #ifdef O_TMPFILE 516 fd = open(temp_name.s, O_RDWR|O_CLOEXEC|O_TMPFILE|O_EXCL, 0600); 517 if(fd >= 0) 518 goto exit_tmpfile; 519 #endif 520 archive_strcat(&temp_name, "libarchive_XXXXXX"); 521 fd = mkstemp(temp_name.s); 522 if (fd < 0) 523 goto exit_tmpfile; 524 __archive_ensure_cloexec_flag(fd); 525 unlink(temp_name.s); 526 exit_tmpfile: 527 archive_string_free(&temp_name); 528 return (fd); 529 } 530 531 int 532 __archive_mkstemp(char *template) 533 { 534 int fd = -1; 535 fd = mkstemp(template); 536 if (fd >= 0) 537 __archive_ensure_cloexec_flag(fd); 538 return (fd); 539 } 540 541 #else /* !HAVE_MKSTEMP */ 542 543 /* 544 * We use a private routine. 545 */ 546 547 static int 548 __archive_mktempx(const char *tmpdir, char *template) 549 { 550 static const char num[] = { 551 '0', '1', '2', '3', '4', '5', '6', '7', 552 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 553 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 554 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 555 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 556 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 557 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 558 'u', 'v', 'w', 'x', 'y', 'z' 559 }; 560 struct archive_string temp_name; 561 struct stat st; 562 int fd; 563 char *tp, *ep; 564 565 fd = -1; 566 if (template == NULL) { 567 archive_string_init(&temp_name); 568 if (tmpdir == NULL) { 569 if (__archive_get_tempdir(&temp_name) != ARCHIVE_OK) 570 goto exit_tmpfile; 571 } else 572 archive_strcpy(&temp_name, tmpdir); 573 if (temp_name.length > 0 && temp_name.s[temp_name.length-1] == '/') { 574 temp_name.s[temp_name.length-1] = '\0'; 575 temp_name.length --; 576 } 577 if (la_stat(temp_name.s, &st) < 0) 578 goto exit_tmpfile; 579 if (!S_ISDIR(st.st_mode)) { 580 errno = ENOTDIR; 581 goto exit_tmpfile; 582 } 583 archive_strcat(&temp_name, "/libarchive_"); 584 tp = temp_name.s + archive_strlen(&temp_name); 585 archive_strcat(&temp_name, "XXXXXXXXXX"); 586 ep = temp_name.s + archive_strlen(&temp_name); 587 template = temp_name.s; 588 } else { 589 tp = strchr(template, 'X'); 590 if (tp == NULL) /* No X, programming error */ 591 abort(); 592 for (ep = tp; *ep == 'X'; ep++) 593 continue; 594 if (*ep) /* X followed by non X, programming error */ 595 abort(); 596 } 597 598 do { 599 char *p; 600 601 p = tp; 602 archive_random(p, ep - p); 603 while (p < ep) { 604 int d = *((unsigned char *)p) % sizeof(num); 605 *p++ = num[d]; 606 } 607 fd = open(template, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 608 0600); 609 } while (fd < 0 && errno == EEXIST); 610 if (fd < 0) 611 goto exit_tmpfile; 612 __archive_ensure_cloexec_flag(fd); 613 if (template == temp_name.s) 614 unlink(temp_name.s); 615 exit_tmpfile: 616 if (template == temp_name.s) 617 archive_string_free(&temp_name); 618 return (fd); 619 } 620 621 int 622 __archive_mktemp(const char *tmpdir) 623 { 624 return __archive_mktempx(tmpdir, NULL); 625 } 626 627 int 628 __archive_mkstemp(char *template) 629 { 630 return __archive_mktempx(NULL, template); 631 } 632 633 #endif /* !HAVE_MKSTEMP */ 634 #endif /* !_WIN32 || __CYGWIN__ */ 635 636 /* 637 * Set FD_CLOEXEC flag to a file descriptor if it is not set. 638 * We have to set the flag if the platform does not provide O_CLOEXEC 639 * or F_DUPFD_CLOEXEC flags. 640 * 641 * Note: This function is absolutely called after creating a new file 642 * descriptor even if the platform seemingly provides O_CLOEXEC or 643 * F_DUPFD_CLOEXEC macros because it is possible that the platform 644 * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it. 645 */ 646 void 647 __archive_ensure_cloexec_flag(int fd) 648 { 649 #if defined(_WIN32) && !defined(__CYGWIN__) 650 (void)fd; /* UNUSED */ 651 #else 652 int flags; 653 654 if (fd >= 0) { 655 flags = fcntl(fd, F_GETFD); 656 if (flags != -1 && (flags & FD_CLOEXEC) == 0) 657 fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 658 } 659 #endif 660 } 661 662 #if ARCHIVE_VERSION_NUMBER < 4000000 663 /* 664 * Utility functions to sort a group of strings using quicksort. 665 */ 666 static int 667 __LA_LIBC_CC 668 archive_utility_string_sort_helper(const void *p1, const void *p2) 669 { 670 const char * const * const s1 = p1; 671 const char * const * const s2 = p2; 672 673 return strcmp(*s1, *s2); 674 } 675 676 int 677 archive_utility_string_sort(char **strings) 678 { 679 size_t size = 0; 680 while (strings[size] != NULL) 681 size++; 682 qsort(strings, size, sizeof(char *), 683 archive_utility_string_sort_helper); 684 return (ARCHIVE_OK); 685 } 686 #endif 687