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
__archive_clean(struct archive * a)86 __archive_clean(struct archive *a)
87 {
88 archive_string_conversion_free(a);
89 return (ARCHIVE_OK);
90 }
91
92 int
archive_version_number(void)93 archive_version_number(void)
94 {
95 return (ARCHIVE_VERSION_NUMBER);
96 }
97
98 const char *
archive_version_string(void)99 archive_version_string(void)
100 {
101 return (ARCHIVE_VERSION_STRING);
102 }
103
104 int
archive_errno(struct archive * a)105 archive_errno(struct archive *a)
106 {
107 return (a->archive_error_number);
108 }
109
110 const char *
archive_error_string(struct archive * a)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
archive_file_count(struct archive * a)121 archive_file_count(struct archive *a)
122 {
123 return (a->file_count);
124 }
125
126 int
archive_format(struct archive * a)127 archive_format(struct archive *a)
128 {
129 return (a->archive_format);
130 }
131
132 const char *
archive_format_name(struct archive * a)133 archive_format_name(struct archive *a)
134 {
135 return (a->archive_format_name);
136 }
137
138
139 int
archive_compression(struct archive * a)140 archive_compression(struct archive *a)
141 {
142 return archive_filter_code(a, 0);
143 }
144
145 const char *
archive_compression_name(struct archive * a)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
archive_position_compressed(struct archive * a)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
archive_position_uncompressed(struct archive * a)165 archive_position_uncompressed(struct archive *a)
166 {
167 return archive_filter_bytes(a, 0);
168 }
169
170 void
archive_clear_error(struct archive * a)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
archive_set_error(struct archive * a,int error_number,const char * fmt,...)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
archive_copy_error(struct archive * dest,struct archive * src)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
__archive_errx(int retvalue,const char * msg)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
__archive_mktempx(const char * tmpdir,wchar_t * template)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
__archive_mktemp(const char * tmpdir)434 __archive_mktemp(const char *tmpdir)
435 {
436 return __archive_mktempx(tmpdir, NULL);
437 }
438
439 int
__archive_mkstemp(wchar_t * template)440 __archive_mkstemp(wchar_t *template)
441 {
442 return __archive_mktempx(NULL, template);
443 }
444
445 #else
446
447 static int
__archive_issetugid(void)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
__archive_get_tempdir(struct archive_string * temppath)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
__archive_mktemp(const char * tmpdir)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
__archive_mkstemp(char * template)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
__archive_mktempx(const char * tmpdir,char * template)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
__archive_mktemp(const char * tmpdir)622 __archive_mktemp(const char *tmpdir)
623 {
624 return __archive_mktempx(tmpdir, NULL);
625 }
626
627 int
__archive_mkstemp(char * template)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
__archive_ensure_cloexec_flag(int fd)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
archive_utility_string_sort_helper(const void * p1,const void * p2)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
archive_utility_string_sort(char ** strings)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