1 /*
2 +----------------------------------------------------------------------+
3 | phar php single-file executable PHP extension |
4 | utility functions |
5 +----------------------------------------------------------------------+
6 | Copyright (c) The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | https://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Authors: Gregory Beaver <cellog@php.net> |
17 | Marcus Boerger <helly@php.net> |
18 +----------------------------------------------------------------------+
19 */
20
21 #include "phar_internal.h"
22 #include "ext/hash/php_hash_sha.h"
23
24 #ifdef PHAR_HAVE_OPENSSL
25 /* OpenSSL includes */
26 #include <openssl/evp.h>
27 #include <openssl/x509.h>
28 #include <openssl/x509v3.h>
29 #include <openssl/crypto.h>
30 #include <openssl/pem.h>
31 #include <openssl/err.h>
32 #include <openssl/conf.h>
33 #include <openssl/rand.h>
34 #include <openssl/ssl.h>
35 #include <openssl/pkcs12.h>
36 #else
37 static int phar_call_openssl_signverify(int is_sign, php_stream *fp, zend_off_t end, char *key, size_t key_len, char **signature, size_t *signature_len, php_uint32 sig_type);
38 #endif
39
40 /* for links to relative location, prepend cwd of the entry */
phar_get_link_location(phar_entry_info * entry)41 static char *phar_get_link_location(phar_entry_info *entry) /* {{{ */
42 {
43 char *p, *ret = NULL;
44 if (!entry->link) {
45 return NULL;
46 }
47 if (entry->link[0] == '/') {
48 return estrdup(entry->link + 1);
49 }
50 p = strrchr(entry->filename, '/');
51 if (p) {
52 *p = '\0';
53 spprintf(&ret, 0, "%s/%s", entry->filename, entry->link);
54 return ret;
55 }
56 return entry->link;
57 }
58 /* }}} */
59
phar_get_link_source(phar_entry_info * entry)60 phar_entry_info *phar_get_link_source(phar_entry_info *entry) /* {{{ */
61 {
62 phar_entry_info *link_entry;
63 char *link;
64
65 if (!entry->link) {
66 return entry;
67 }
68
69 link = phar_get_link_location(entry);
70 if (NULL != (link_entry = zend_hash_str_find_ptr(&(entry->phar->manifest), entry->link, strlen(entry->link))) ||
71 NULL != (link_entry = zend_hash_str_find_ptr(&(entry->phar->manifest), link, strlen(link)))) {
72 if (link != entry->link) {
73 efree(link);
74 }
75 return phar_get_link_source(link_entry);
76 } else {
77 if (link != entry->link) {
78 efree(link);
79 }
80 return NULL;
81 }
82 }
83 /* }}} */
84
85 /* retrieve a phar_entry_info's current file pointer for reading contents */
phar_get_efp(phar_entry_info * entry,int follow_links)86 php_stream *phar_get_efp(phar_entry_info *entry, int follow_links) /* {{{ */
87 {
88 if (follow_links && entry->link) {
89 phar_entry_info *link_entry = phar_get_link_source(entry);
90
91 if (link_entry && link_entry != entry) {
92 return phar_get_efp(link_entry, 1);
93 }
94 }
95
96 if (phar_get_fp_type(entry) == PHAR_FP) {
97 if (!phar_get_entrypfp(entry)) {
98 /* re-open just in time for cases where our refcount reached 0 on the phar archive */
99 phar_open_archive_fp(entry->phar);
100 }
101 return phar_get_entrypfp(entry);
102 } else if (phar_get_fp_type(entry) == PHAR_UFP) {
103 return phar_get_entrypufp(entry);
104 } else if (entry->fp_type == PHAR_MOD) {
105 return entry->fp;
106 } else {
107 /* temporary manifest entry */
108 if (!entry->fp) {
109 entry->fp = php_stream_open_wrapper(entry->tmp, "rb", STREAM_MUST_SEEK|0, NULL);
110 }
111 return entry->fp;
112 }
113 }
114 /* }}} */
115
phar_seek_efp(phar_entry_info * entry,zend_off_t offset,int whence,zend_off_t position,int follow_links)116 int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links) /* {{{ */
117 {
118 php_stream *fp = phar_get_efp(entry, follow_links);
119 zend_off_t temp, eoffset;
120
121 if (!fp) {
122 return -1;
123 }
124
125 if (follow_links) {
126 phar_entry_info *t;
127 t = phar_get_link_source(entry);
128 if (t) {
129 entry = t;
130 }
131 }
132
133 if (entry->is_dir) {
134 return 0;
135 }
136
137 eoffset = phar_get_fp_offset(entry);
138
139 switch (whence) {
140 case SEEK_END:
141 temp = eoffset + entry->uncompressed_filesize + offset;
142 break;
143 case SEEK_CUR:
144 temp = eoffset + position + offset;
145 break;
146 case SEEK_SET:
147 temp = eoffset + offset;
148 break;
149 default:
150 temp = 0;
151 }
152
153 if (temp > eoffset + (zend_off_t) entry->uncompressed_filesize) {
154 return -1;
155 }
156
157 if (temp < eoffset) {
158 return -1;
159 }
160
161 return php_stream_seek(fp, temp, SEEK_SET);
162 }
163 /* }}} */
164
165 /* mount an absolute path or uri to a path internal to the phar archive */
phar_mount_entry(phar_archive_data * phar,char * filename,size_t filename_len,char * path,size_t path_len)166 int phar_mount_entry(phar_archive_data *phar, char *filename, size_t filename_len, char *path, size_t path_len) /* {{{ */
167 {
168 phar_entry_info entry = {0};
169 php_stream_statbuf ssb;
170 int is_phar;
171 const char *err;
172
173 if (phar_path_check(&path, &path_len, &err) > pcr_is_ok) {
174 return FAILURE;
175 }
176
177 if (path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", sizeof(".phar")-1)) {
178 /* no creating magic phar files by mounting them */
179 return FAILURE;
180 }
181
182 is_phar = (filename_len > 7 && !memcmp(filename, "phar://", 7));
183
184 entry.phar = phar;
185 entry.filename = estrndup(path, path_len);
186 #ifdef PHP_WIN32
187 phar_unixify_path_separators(entry.filename, path_len);
188 #endif
189 entry.filename_len = path_len;
190 if (is_phar) {
191 entry.tmp = estrndup(filename, filename_len);
192 } else {
193 entry.tmp = expand_filepath(filename, NULL);
194 if (!entry.tmp) {
195 entry.tmp = estrndup(filename, filename_len);
196 }
197 }
198 filename = entry.tmp;
199
200 /* only check openbasedir for files, not for phar streams */
201 if (!is_phar && php_check_open_basedir(filename)) {
202 efree(entry.tmp);
203 efree(entry.filename);
204 return FAILURE;
205 }
206
207 entry.is_mounted = 1;
208 entry.is_crc_checked = 1;
209 entry.fp_type = PHAR_TMP;
210
211 if (SUCCESS != php_stream_stat_path(filename, &ssb)) {
212 efree(entry.tmp);
213 efree(entry.filename);
214 return FAILURE;
215 }
216
217 if (ssb.sb.st_mode & S_IFDIR) {
218 entry.is_dir = 1;
219 if (NULL == zend_hash_str_add_ptr(&phar->mounted_dirs, entry.filename, path_len, entry.filename)) {
220 /* directory already mounted */
221 efree(entry.tmp);
222 efree(entry.filename);
223 return FAILURE;
224 }
225 } else {
226 entry.is_dir = 0;
227 entry.uncompressed_filesize = entry.compressed_filesize = ssb.sb.st_size;
228 }
229
230 entry.flags = ssb.sb.st_mode;
231
232 if (NULL != zend_hash_str_add_mem(&phar->manifest, entry.filename, path_len, (void*)&entry, sizeof(phar_entry_info))) {
233 return SUCCESS;
234 }
235
236 efree(entry.tmp);
237 efree(entry.filename);
238 return FAILURE;
239 }
240 /* }}} */
241
phar_find_in_include_path(zend_string * filename,phar_archive_data ** pphar)242 zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data **pphar) /* {{{ */
243 {
244 zend_string *ret;
245 char *path, *arch, *entry, *test;
246 size_t arch_len, entry_len;
247 phar_archive_data *phar;
248
249 if (pphar) {
250 *pphar = NULL;
251 } else {
252 pphar = &phar;
253 }
254
255 if (!zend_is_executing() || !PHAR_G(cwd)) {
256 return NULL;
257 }
258
259 zend_string *fname = zend_get_executed_filename_ex();
260 if (!fname) {
261 return NULL;
262 }
263
264 bool is_file_a_phar_wrapper = zend_string_starts_with_literal_ci(fname, "phar://");
265 size_t length_phar_protocol = strlen("phar://");
266
267 if (
268 PHAR_G(last_phar)
269 && is_file_a_phar_wrapper
270 && ZSTR_LEN(fname) - length_phar_protocol >= PHAR_G(last_phar_name_len)
271 && !memcmp(ZSTR_VAL(fname) + length_phar_protocol, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))
272 ) {
273 arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
274 arch_len = PHAR_G(last_phar_name_len);
275 phar = PHAR_G(last_phar);
276 goto splitted;
277 }
278
279 if (!is_file_a_phar_wrapper || SUCCESS != phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, &entry, &entry_len, 1, 0)) {
280 return NULL;
281 }
282
283 efree(entry);
284
285 if (*ZSTR_VAL(filename) == '.') {
286 size_t try_len;
287
288 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
289 efree(arch);
290 return NULL;
291 }
292 splitted:
293 if (pphar) {
294 *pphar = phar;
295 }
296
297 try_len = ZSTR_LEN(filename);
298 test = phar_fix_filepath(estrndup(ZSTR_VAL(filename), ZSTR_LEN(filename)), &try_len, 1);
299
300 if (*test == '/') {
301 if (zend_hash_str_exists(&(phar->manifest), test + 1, try_len - 1)) {
302 ret = strpprintf(0, "phar://%s%s", arch, test);
303 efree(arch);
304 efree(test);
305 return ret;
306 }
307 } else {
308 if (zend_hash_str_exists(&(phar->manifest), test, try_len)) {
309 ret = strpprintf(0, "phar://%s/%s", arch, test);
310 efree(arch);
311 efree(test);
312 return ret;
313 }
314 }
315 efree(test);
316 }
317
318 spprintf(&path, MAXPATHLEN + 1 + strlen(PG(include_path)), "phar://%s/%s%c%s", arch, PHAR_G(cwd), DEFAULT_DIR_SEPARATOR, PG(include_path));
319 efree(arch);
320 ret = php_resolve_path(ZSTR_VAL(filename), ZSTR_LEN(filename), path);
321 efree(path);
322
323 if (ret && zend_string_starts_with_literal_ci(ret, "phar://")) {
324 /* found phar:// */
325 if (SUCCESS != phar_split_fname(ZSTR_VAL(ret), ZSTR_LEN(ret), &arch, &arch_len, &entry, &entry_len, 1, 0)) {
326 return ret;
327 }
328
329 *pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), arch, arch_len);
330
331 if (!*pphar && PHAR_G(manifest_cached)) {
332 *pphar = zend_hash_str_find_ptr(&cached_phars, arch, arch_len);
333 }
334
335 efree(arch);
336 efree(entry);
337 }
338
339 return ret;
340 }
341 /* }}} */
342
343 /**
344 * Retrieve a copy of the file information on a single file within a phar, or null.
345 * This also transfers the open file pointer, if any, to the entry.
346 *
347 * If the file does not already exist, this will fail. Pre-existing files can be
348 * appended, truncated, or read. For read, if the entry is marked unmodified, it is
349 * assumed that the file pointer, if present, is opened for reading
350 */
phar_get_entry_data(phar_entry_data ** ret,char * fname,size_t fname_len,char * path,size_t path_len,const char * mode,char allow_dir,char ** error,int security)351 int phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */
352 {
353 phar_archive_data *phar;
354 phar_entry_info *entry;
355 int for_write = mode[0] != 'r' || mode[1] == '+';
356 int for_append = mode[0] == 'a';
357 int for_create = mode[0] != 'r';
358 int for_trunc = mode[0] == 'w';
359
360 if (!ret) {
361 return FAILURE;
362 }
363
364 *ret = NULL;
365
366 if (error) {
367 *error = NULL;
368 }
369
370 if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) {
371 return FAILURE;
372 }
373
374 if (for_write && PHAR_G(readonly) && !phar->is_data) {
375 if (error) {
376 spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, fname);
377 }
378 return FAILURE;
379 }
380
381 if (!path_len) {
382 if (error) {
383 spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" cannot be empty", fname);
384 }
385 return FAILURE;
386 }
387 really_get_entry:
388 if (allow_dir) {
389 if ((entry = phar_get_entry_info_dir(phar, path, path_len, allow_dir, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, security)) == NULL) {
390 if (for_create && (!PHAR_G(readonly) || phar->is_data)) {
391 return SUCCESS;
392 }
393 return FAILURE;
394 }
395 } else {
396 if ((entry = phar_get_entry_info(phar, path, path_len, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, security)) == NULL) {
397 if (for_create && (!PHAR_G(readonly) || phar->is_data)) {
398 return SUCCESS;
399 }
400 return FAILURE;
401 }
402 }
403
404 if (for_write && phar->is_persistent) {
405 if (FAILURE == phar_copy_on_write(&phar)) {
406 if (error) {
407 spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, could not make cached phar writeable", path, fname);
408 }
409 return FAILURE;
410 } else {
411 goto really_get_entry;
412 }
413 }
414
415 if (entry->is_modified && !for_write) {
416 if (error) {
417 spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, fname);
418 }
419 return FAILURE;
420 }
421
422 if (entry->fp_refcount && for_write) {
423 if (error) {
424 spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, fname);
425 }
426 return FAILURE;
427 }
428
429 if (entry->is_deleted) {
430 if (!for_create) {
431 return FAILURE;
432 }
433 entry->is_deleted = 0;
434 }
435
436 if (entry->is_dir) {
437 *ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
438 (*ret)->position = 0;
439 (*ret)->fp = NULL;
440 (*ret)->phar = phar;
441 (*ret)->for_write = for_write;
442 (*ret)->internal_file = entry;
443 (*ret)->is_zip = entry->is_zip;
444 (*ret)->is_tar = entry->is_tar;
445
446 if (!phar->is_persistent) {
447 ++(entry->phar->refcount);
448 ++(entry->fp_refcount);
449 }
450
451 return SUCCESS;
452 }
453
454 if (entry->fp_type == PHAR_MOD) {
455 if (for_trunc) {
456 if (FAILURE == phar_create_writeable_entry(phar, entry, error)) {
457 return FAILURE;
458 }
459 } else if (for_append) {
460 phar_seek_efp(entry, 0, SEEK_END, 0, 0);
461 }
462 } else {
463 if (for_write) {
464 if (entry->link) {
465 efree(entry->link);
466 entry->link = NULL;
467 entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
468 }
469
470 if (for_trunc) {
471 if (FAILURE == phar_create_writeable_entry(phar, entry, error)) {
472 return FAILURE;
473 }
474 } else {
475 if (FAILURE == phar_separate_entry_fp(entry, error)) {
476 return FAILURE;
477 }
478 }
479 } else {
480 if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
481 return FAILURE;
482 }
483 }
484 }
485
486 *ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
487 (*ret)->position = 0;
488 (*ret)->phar = phar;
489 (*ret)->for_write = for_write;
490 (*ret)->internal_file = entry;
491 (*ret)->is_zip = entry->is_zip;
492 (*ret)->is_tar = entry->is_tar;
493 (*ret)->fp = phar_get_efp(entry, 1);
494 if (entry->link) {
495 phar_entry_info *link = phar_get_link_source(entry);
496 if(!link) {
497 efree(*ret);
498 return FAILURE;
499 }
500 (*ret)->zero = phar_get_fp_offset(link);
501 } else {
502 (*ret)->zero = phar_get_fp_offset(entry);
503 }
504
505 if (!phar->is_persistent) {
506 ++(entry->fp_refcount);
507 ++(entry->phar->refcount);
508 }
509
510 return SUCCESS;
511 }
512 /* }}} */
513
514 /**
515 * Create a new dummy file slot within a writeable phar for a newly created file
516 */
phar_get_or_create_entry_data(char * fname,size_t fname_len,char * path,size_t path_len,const char * mode,char allow_dir,char ** error,int security)517 phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */
518 {
519 phar_archive_data *phar;
520 phar_entry_info *entry, etemp;
521 phar_entry_data *ret;
522 const char *pcr_error;
523 char is_dir;
524
525 #ifdef PHP_WIN32
526 phar_unixify_path_separators(path, path_len);
527 #endif
528
529 is_dir = (path_len && path[path_len - 1] == '/') ? 1 : 0;
530
531 if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) {
532 return NULL;
533 }
534
535 if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, allow_dir, error, security)) {
536 return NULL;
537 } else if (ret) {
538 return ret;
539 }
540
541 if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
542 if (error) {
543 spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
544 }
545 return NULL;
546 }
547
548 if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar)) {
549 if (error) {
550 spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be created, could not make cached phar writeable", path, fname);
551 }
552 return NULL;
553 }
554
555 /* create a new phar data holder */
556 ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
557
558 /* create an entry, this is a new file */
559 memset(&etemp, 0, sizeof(phar_entry_info));
560 etemp.filename_len = path_len;
561 etemp.fp_type = PHAR_MOD;
562 etemp.fp = php_stream_fopen_tmpfile();
563
564 if (!etemp.fp) {
565 if (error) {
566 spprintf(error, 0, "phar error: unable to create temporary file");
567 }
568 efree(ret);
569 return NULL;
570 }
571
572 etemp.fp_refcount = 1;
573
574 if (allow_dir == 2) {
575 etemp.is_dir = 1;
576 etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_DIR;
577 } else {
578 etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_FILE;
579 }
580 if (is_dir && path_len) {
581 etemp.filename_len--; /* strip trailing / */
582 path_len--;
583 }
584
585 phar_add_virtual_dirs(phar, path, path_len);
586 etemp.is_modified = 1;
587 etemp.timestamp = time(0);
588 etemp.is_crc_checked = 1;
589 etemp.phar = phar;
590 etemp.filename = estrndup(path, path_len);
591 etemp.is_zip = phar->is_zip;
592
593 if (phar->is_tar) {
594 etemp.is_tar = phar->is_tar;
595 etemp.tar_type = etemp.is_dir ? TAR_DIR : TAR_FILE;
596 }
597
598 if (NULL == (entry = zend_hash_str_add_mem(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info)))) {
599 php_stream_close(etemp.fp);
600 if (error) {
601 spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", etemp.filename, phar->fname);
602 }
603 efree(ret);
604 efree(etemp.filename);
605 return NULL;
606 }
607
608 if (!entry) {
609 php_stream_close(etemp.fp);
610 efree(etemp.filename);
611 efree(ret);
612 return NULL;
613 }
614
615 ++(phar->refcount);
616 ret->phar = phar;
617 ret->fp = entry->fp;
618 ret->position = ret->zero = 0;
619 ret->for_write = 1;
620 ret->is_zip = entry->is_zip;
621 ret->is_tar = entry->is_tar;
622 ret->internal_file = entry;
623
624 return ret;
625 }
626 /* }}} */
627
628 /* initialize a phar_archive_data's read-only fp for existing phar data */
phar_open_archive_fp(phar_archive_data * phar)629 int phar_open_archive_fp(phar_archive_data *phar) /* {{{ */
630 {
631 if (phar_get_pharfp(phar)) {
632 return SUCCESS;
633 }
634
635 if (php_check_open_basedir(phar->fname)) {
636 return FAILURE;
637 }
638
639 phar_set_pharfp(phar, php_stream_open_wrapper(phar->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL));
640
641 if (!phar_get_pharfp(phar)) {
642 return FAILURE;
643 }
644
645 return SUCCESS;
646 }
647 /* }}} */
648
649 /* copy file data from an existing to a new phar_entry_info that is not in the manifest */
phar_copy_entry_fp(phar_entry_info * source,phar_entry_info * dest,char ** error)650 int phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error) /* {{{ */
651 {
652 phar_entry_info *link;
653
654 if (FAILURE == phar_open_entry_fp(source, error, 1)) {
655 return FAILURE;
656 }
657
658 if (dest->link) {
659 efree(dest->link);
660 dest->link = NULL;
661 dest->tar_type = (dest->is_tar ? TAR_FILE : '\0');
662 }
663
664 dest->fp_type = PHAR_MOD;
665 dest->offset = 0;
666 dest->is_modified = 1;
667 dest->fp = php_stream_fopen_tmpfile();
668 if (dest->fp == NULL) {
669 spprintf(error, 0, "phar error: unable to create temporary file");
670 return EOF;
671 }
672 phar_seek_efp(source, 0, SEEK_SET, 0, 1);
673 link = phar_get_link_source(source);
674
675 if (!link) {
676 link = source;
677 }
678
679 if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), dest->fp, link->uncompressed_filesize, NULL)) {
680 php_stream_close(dest->fp);
681 dest->fp_type = PHAR_FP;
682 if (error) {
683 spprintf(error, 4096, "phar error: unable to copy contents of file \"%s\" to \"%s\" in phar archive \"%s\"", source->filename, dest->filename, source->phar->fname);
684 }
685 return FAILURE;
686 }
687
688 return SUCCESS;
689 }
690 /* }}} */
691
692 /* open and decompress a compressed phar entry
693 */
phar_open_entry_fp(phar_entry_info * entry,char ** error,int follow_links)694 int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links) /* {{{ */
695 {
696 php_stream_filter *filter;
697 phar_archive_data *phar = entry->phar;
698 char *filtername;
699 zend_off_t loc;
700 php_stream *ufp;
701 phar_entry_data dummy;
702
703 if (follow_links && entry->link) {
704 phar_entry_info *link_entry = phar_get_link_source(entry);
705 if (link_entry && link_entry != entry) {
706 return phar_open_entry_fp(link_entry, error, 1);
707 }
708 }
709
710 if (entry->is_modified) {
711 return SUCCESS;
712 }
713
714 if (entry->fp_type == PHAR_TMP) {
715 if (!entry->fp) {
716 entry->fp = php_stream_open_wrapper(entry->tmp, "rb", STREAM_MUST_SEEK|0, NULL);
717 }
718 return SUCCESS;
719 }
720
721 if (entry->fp_type != PHAR_FP) {
722 /* either newly created or already modified */
723 return SUCCESS;
724 }
725
726 if (!phar_get_pharfp(phar)) {
727 if (FAILURE == phar_open_archive_fp(phar)) {
728 spprintf(error, 4096, "phar error: Cannot open phar archive \"%s\" for reading", phar->fname);
729 return FAILURE;
730 }
731 }
732
733 if ((entry->old_flags && !(entry->old_flags & PHAR_ENT_COMPRESSION_MASK)) || !(entry->flags & PHAR_ENT_COMPRESSION_MASK)) {
734 dummy.internal_file = entry;
735 dummy.phar = phar;
736 dummy.zero = entry->offset;
737 dummy.fp = phar_get_pharfp(phar);
738 if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 1)) {
739 return FAILURE;
740 }
741 return SUCCESS;
742 }
743
744 if (!phar_get_entrypufp(entry)) {
745 phar_set_entrypufp(entry, php_stream_fopen_tmpfile());
746 if (!phar_get_entrypufp(entry)) {
747 spprintf(error, 4096, "phar error: Cannot open temporary file for decompressing phar archive \"%s\" file \"%s\"", phar->fname, entry->filename);
748 return FAILURE;
749 }
750 }
751
752 dummy.internal_file = entry;
753 dummy.phar = phar;
754 dummy.zero = entry->offset;
755 dummy.fp = phar_get_pharfp(phar);
756 if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 1)) {
757 return FAILURE;
758 }
759
760 ufp = phar_get_entrypufp(entry);
761
762 if ((filtername = phar_decompress_filter(entry, 0)) != NULL) {
763 filter = php_stream_filter_create(filtername, NULL, 0);
764 } else {
765 filter = NULL;
766 }
767
768 if (!filter) {
769 spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry->filename);
770 return FAILURE;
771 }
772
773 /* now we can safely use proper decompression */
774 /* save the new offset location within ufp */
775 php_stream_seek(ufp, 0, SEEK_END);
776 loc = php_stream_tell(ufp);
777 php_stream_filter_append(&ufp->writefilters, filter);
778 php_stream_seek(phar_get_entrypfp(entry), phar_get_fp_offset(entry), SEEK_SET);
779
780 if (entry->uncompressed_filesize) {
781 if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_entrypfp(entry), ufp, entry->compressed_filesize, NULL)) {
782 spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
783 php_stream_filter_remove(filter, 1);
784 return FAILURE;
785 }
786 }
787
788 php_stream_filter_flush(filter, 1);
789 php_stream_flush(ufp);
790 php_stream_filter_remove(filter, 1);
791
792 if (php_stream_tell(ufp) - loc != (zend_off_t) entry->uncompressed_filesize) {
793 spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
794 return FAILURE;
795 }
796
797 entry->old_flags = entry->flags;
798
799 /* this is now the new location of the file contents within this fp */
800 phar_set_fp_type(entry, PHAR_UFP, loc);
801 dummy.zero = entry->offset;
802 dummy.fp = ufp;
803 if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 0)) {
804 return FAILURE;
805 }
806 return SUCCESS;
807 }
808 /* }}} */
809
phar_create_writeable_entry(phar_archive_data * phar,phar_entry_info * entry,char ** error)810 int phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */
811 {
812 if (entry->fp_type == PHAR_MOD) {
813 /* already newly created, truncate */
814 php_stream_truncate_set_size(entry->fp, 0);
815
816 entry->old_flags = entry->flags;
817 entry->is_modified = 1;
818 phar->is_modified = 1;
819 /* reset file size */
820 entry->uncompressed_filesize = 0;
821 entry->compressed_filesize = 0;
822 entry->crc32 = 0;
823 entry->flags = PHAR_ENT_PERM_DEF_FILE;
824 entry->fp_type = PHAR_MOD;
825 entry->offset = 0;
826 return SUCCESS;
827 }
828
829 if (error) {
830 *error = NULL;
831 }
832
833 /* open a new temp file for writing */
834 if (entry->link) {
835 efree(entry->link);
836 entry->link = NULL;
837 entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
838 }
839
840 entry->fp = php_stream_fopen_tmpfile();
841
842 if (!entry->fp) {
843 if (error) {
844 spprintf(error, 0, "phar error: unable to create temporary file");
845 }
846 return FAILURE;
847 }
848
849 entry->old_flags = entry->flags;
850 entry->is_modified = 1;
851 phar->is_modified = 1;
852 /* reset file size */
853 entry->uncompressed_filesize = 0;
854 entry->compressed_filesize = 0;
855 entry->crc32 = 0;
856 entry->flags = PHAR_ENT_PERM_DEF_FILE;
857 entry->fp_type = PHAR_MOD;
858 entry->offset = 0;
859 return SUCCESS;
860 }
861 /* }}} */
862
phar_separate_entry_fp(phar_entry_info * entry,char ** error)863 int phar_separate_entry_fp(phar_entry_info *entry, char **error) /* {{{ */
864 {
865 php_stream *fp;
866 phar_entry_info *link;
867
868 if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
869 return FAILURE;
870 }
871
872 if (entry->fp_type == PHAR_MOD) {
873 return SUCCESS;
874 }
875
876 fp = php_stream_fopen_tmpfile();
877 if (fp == NULL) {
878 spprintf(error, 0, "phar error: unable to create temporary file");
879 return FAILURE;
880 }
881 phar_seek_efp(entry, 0, SEEK_SET, 0, 1);
882 link = phar_get_link_source(entry);
883
884 if (!link) {
885 link = entry;
886 }
887
888 if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) {
889 if (error) {
890 spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname);
891 }
892 return FAILURE;
893 }
894
895 if (entry->link) {
896 efree(entry->link);
897 entry->link = NULL;
898 entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
899 }
900
901 entry->offset = 0;
902 entry->fp = fp;
903 entry->fp_type = PHAR_MOD;
904 entry->is_modified = 1;
905 return SUCCESS;
906 }
907 /* }}} */
908
909 /**
910 * helper function to open an internal file's fp just-in-time
911 */
phar_open_jit(phar_archive_data * phar,phar_entry_info * entry,char ** error)912 phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */
913 {
914 if (error) {
915 *error = NULL;
916 }
917 /* seek to start of internal file and read it */
918 if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
919 return NULL;
920 }
921 if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1)) {
922 spprintf(error, 4096, "phar error: cannot seek to start of file \"%s\" in phar \"%s\"", entry->filename, phar->fname);
923 return NULL;
924 }
925 return entry;
926 }
927 /* }}} */
928
phar_resolve_alias(char * alias,size_t alias_len,char ** filename,size_t * filename_len)929 PHP_PHAR_API int phar_resolve_alias(char *alias, size_t alias_len, char **filename, size_t *filename_len) /* {{{ */ {
930 phar_archive_data *fd_ptr;
931 if (HT_IS_INITIALIZED(&PHAR_G(phar_alias_map))
932 && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
933 *filename = fd_ptr->fname;
934 *filename_len = fd_ptr->fname_len;
935 return SUCCESS;
936 }
937 return FAILURE;
938 }
939 /* }}} */
940
phar_free_alias(phar_archive_data * phar,char * alias,size_t alias_len)941 int phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len) /* {{{ */
942 {
943 if (phar->refcount || phar->is_persistent) {
944 return FAILURE;
945 }
946
947 /* this archive has no open references, so emit a notice and remove it */
948 if (zend_hash_str_del(&(PHAR_G(phar_fname_map)), phar->fname, phar->fname_len) != SUCCESS) {
949 return FAILURE;
950 }
951
952 /* invalidate phar cache */
953 PHAR_G(last_phar) = NULL;
954 PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
955
956 return SUCCESS;
957 }
958 /* }}} */
959
960 /**
961 * Looks up a phar archive in the filename map, connecting it to the alias
962 * (if any) or returns null
963 */
phar_get_archive(phar_archive_data ** archive,char * fname,size_t fname_len,char * alias,size_t alias_len,char ** error)964 int phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error) /* {{{ */
965 {
966 phar_archive_data *fd, *fd_ptr;
967 char *my_realpath, *save;
968 size_t save_len;
969
970 phar_request_initialize();
971
972 if (error) {
973 *error = NULL;
974 }
975
976 *archive = NULL;
977
978 if (PHAR_G(last_phar) && fname_len == PHAR_G(last_phar_name_len) && !memcmp(fname, PHAR_G(last_phar_name), fname_len)) {
979 *archive = PHAR_G(last_phar);
980 if (alias && alias_len) {
981
982 if (!PHAR_G(last_phar)->is_temporary_alias && (alias_len != PHAR_G(last_phar)->alias_len || memcmp(PHAR_G(last_phar)->alias, alias, alias_len))) {
983 if (error) {
984 spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, PHAR_G(last_phar)->fname, fname);
985 }
986 *archive = NULL;
987 return FAILURE;
988 }
989
990 if (PHAR_G(last_phar)->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len))) {
991 zend_hash_str_del(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len);
992 }
993
994 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, *archive);
995 PHAR_G(last_alias) = alias;
996 PHAR_G(last_alias_len) = alias_len;
997 }
998
999 return SUCCESS;
1000 }
1001
1002 if (alias && alias_len && PHAR_G(last_phar) && alias_len == PHAR_G(last_alias_len) && !memcmp(alias, PHAR_G(last_alias), alias_len)) {
1003 fd = PHAR_G(last_phar);
1004 fd_ptr = fd;
1005 goto alias_success;
1006 }
1007
1008 if (alias && alias_len) {
1009 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
1010 alias_success:
1011 if (fname && (fname_len != fd_ptr->fname_len || strncmp(fname, fd_ptr->fname, fname_len))) {
1012 if (error) {
1013 spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname);
1014 }
1015 if (SUCCESS == phar_free_alias(fd_ptr, alias, alias_len)) {
1016 if (error) {
1017 efree(*error);
1018 *error = NULL;
1019 }
1020 }
1021 return FAILURE;
1022 }
1023
1024 *archive = fd_ptr;
1025 fd = fd_ptr;
1026 PHAR_G(last_phar) = fd;
1027 PHAR_G(last_phar_name) = fd->fname;
1028 PHAR_G(last_phar_name_len) = fd->fname_len;
1029 PHAR_G(last_alias) = alias;
1030 PHAR_G(last_alias_len) = alias_len;
1031
1032 return SUCCESS;
1033 }
1034
1035 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_alias, alias, alias_len))) {
1036 goto alias_success;
1037 }
1038 }
1039
1040 my_realpath = NULL;
1041 save = fname;
1042 save_len = fname_len;
1043
1044 if (fname && fname_len) {
1045 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len))) {
1046 *archive = fd_ptr;
1047 fd = fd_ptr;
1048
1049 if (alias && alias_len) {
1050 if (!fd->is_temporary_alias && (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len))) {
1051 if (error) {
1052 spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname);
1053 }
1054 return FAILURE;
1055 }
1056
1057 if (fd->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), fd->alias, fd->alias_len))) {
1058 zend_hash_str_del(&(PHAR_G(phar_alias_map)), fd->alias, fd->alias_len);
1059 }
1060
1061 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd);
1062 }
1063
1064 PHAR_G(last_phar) = fd;
1065 PHAR_G(last_phar_name) = fd->fname;
1066 PHAR_G(last_phar_name_len) = fd->fname_len;
1067 PHAR_G(last_alias) = fd->alias;
1068 PHAR_G(last_alias_len) = fd->alias_len;
1069
1070 return SUCCESS;
1071 }
1072
1073 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) {
1074 *archive = fd_ptr;
1075 fd = fd_ptr;
1076
1077 /* this could be problematic - alias should never be different from manifest alias
1078 for cached phars */
1079 if (!fd->is_temporary_alias && alias && alias_len) {
1080 if (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len)) {
1081 if (error) {
1082 spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname);
1083 }
1084 return FAILURE;
1085 }
1086 }
1087
1088 PHAR_G(last_phar) = fd;
1089 PHAR_G(last_phar_name) = fd->fname;
1090 PHAR_G(last_phar_name_len) = fd->fname_len;
1091 PHAR_G(last_alias) = fd->alias;
1092 PHAR_G(last_alias_len) = fd->alias_len;
1093
1094 return SUCCESS;
1095 }
1096
1097 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), save, save_len))) {
1098 fd = *archive = fd_ptr;
1099
1100 PHAR_G(last_phar) = fd;
1101 PHAR_G(last_phar_name) = fd->fname;
1102 PHAR_G(last_phar_name_len) = fd->fname_len;
1103 PHAR_G(last_alias) = fd->alias;
1104 PHAR_G(last_alias_len) = fd->alias_len;
1105
1106 return SUCCESS;
1107 }
1108
1109 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_alias, save, save_len))) {
1110 fd = *archive = fd_ptr;
1111
1112 PHAR_G(last_phar) = fd;
1113 PHAR_G(last_phar_name) = fd->fname;
1114 PHAR_G(last_phar_name_len) = fd->fname_len;
1115 PHAR_G(last_alias) = fd->alias;
1116 PHAR_G(last_alias_len) = fd->alias_len;
1117
1118 return SUCCESS;
1119 }
1120
1121 /* not found, try converting \ to / */
1122 my_realpath = expand_filepath(fname, my_realpath);
1123
1124 if (my_realpath) {
1125 fname_len = strlen(my_realpath);
1126 fname = my_realpath;
1127 } else {
1128 return FAILURE;
1129 }
1130 #ifdef PHP_WIN32
1131 phar_unixify_path_separators(fname, fname_len);
1132 #endif
1133
1134 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len))) {
1135 realpath_success:
1136 *archive = fd_ptr;
1137 fd = fd_ptr;
1138
1139 if (alias && alias_len) {
1140 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd);
1141 }
1142
1143 efree(my_realpath);
1144
1145 PHAR_G(last_phar) = fd;
1146 PHAR_G(last_phar_name) = fd->fname;
1147 PHAR_G(last_phar_name_len) = fd->fname_len;
1148 PHAR_G(last_alias) = fd->alias;
1149 PHAR_G(last_alias_len) = fd->alias_len;
1150
1151 return SUCCESS;
1152 }
1153
1154 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) {
1155 goto realpath_success;
1156 }
1157
1158 efree(my_realpath);
1159 }
1160
1161 return FAILURE;
1162 }
1163 /* }}} */
1164
1165 /**
1166 * Determine which stream compression filter (if any) we need to read this file
1167 */
phar_compress_filter(phar_entry_info * entry,int return_unknown)1168 char * phar_compress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */
1169 {
1170 switch (entry->flags & PHAR_ENT_COMPRESSION_MASK) {
1171 case PHAR_ENT_COMPRESSED_GZ:
1172 return "zlib.deflate";
1173 case PHAR_ENT_COMPRESSED_BZ2:
1174 return "bzip2.compress";
1175 default:
1176 return return_unknown ? "unknown" : NULL;
1177 }
1178 }
1179 /* }}} */
1180
1181 /**
1182 * Determine which stream decompression filter (if any) we need to read this file
1183 */
phar_decompress_filter(phar_entry_info * entry,int return_unknown)1184 char * phar_decompress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */
1185 {
1186 uint32_t flags;
1187
1188 if (entry->is_modified) {
1189 flags = entry->old_flags;
1190 } else {
1191 flags = entry->flags;
1192 }
1193
1194 switch (flags & PHAR_ENT_COMPRESSION_MASK) {
1195 case PHAR_ENT_COMPRESSED_GZ:
1196 return "zlib.inflate";
1197 case PHAR_ENT_COMPRESSED_BZ2:
1198 return "bzip2.decompress";
1199 default:
1200 return return_unknown ? "unknown" : NULL;
1201 }
1202 }
1203 /* }}} */
1204
1205 /**
1206 * retrieve information on a file contained within a phar, or null if it ain't there
1207 */
phar_get_entry_info(phar_archive_data * phar,char * path,size_t path_len,char ** error,int security)1208 phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t path_len, char **error, int security) /* {{{ */
1209 {
1210 return phar_get_entry_info_dir(phar, path, path_len, 0, error, security);
1211 }
1212 /* }}} */
1213 /**
1214 * retrieve information on a file or directory contained within a phar, or null if none found
1215 * allow_dir is 0 for none, 1 for both empty directories in the phar and temp directories, and 2 for only
1216 * valid pre-existing empty directory entries
1217 */
phar_get_entry_info_dir(phar_archive_data * phar,char * path,size_t path_len,char dir,char ** error,int security)1218 phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, int security) /* {{{ */
1219 {
1220 const char *pcr_error;
1221 phar_entry_info *entry;
1222 int is_dir;
1223
1224 #ifdef PHP_WIN32
1225 phar_unixify_path_separators(path, path_len);
1226 #endif
1227
1228 is_dir = (path_len && (path[path_len - 1] == '/')) ? 1 : 0;
1229
1230 if (error) {
1231 *error = NULL;
1232 }
1233
1234 if (security && path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", sizeof(".phar")-1)) {
1235 if (error) {
1236 spprintf(error, 4096, "phar error: cannot directly access magic \".phar\" directory or files within it");
1237 }
1238 return NULL;
1239 }
1240
1241 if (!path_len && !dir) {
1242 if (error) {
1243 spprintf(error, 4096, "phar error: invalid path \"%s\" must not be empty", path);
1244 }
1245 return NULL;
1246 }
1247
1248 if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
1249 if (error) {
1250 spprintf(error, 4096, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
1251 }
1252 return NULL;
1253 }
1254
1255 if (!HT_IS_INITIALIZED(&phar->manifest)) {
1256 return NULL;
1257 }
1258
1259 if (is_dir) {
1260 if (path_len <= 1) {
1261 return NULL;
1262 }
1263 path_len--;
1264 }
1265
1266 if (NULL != (entry = zend_hash_str_find_ptr(&phar->manifest, path, path_len))) {
1267 if (entry->is_deleted) {
1268 /* entry is deleted, but has not been flushed to disk yet */
1269 return NULL;
1270 }
1271 if (entry->is_dir && !dir) {
1272 if (error) {
1273 spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
1274 }
1275 return NULL;
1276 }
1277 if (!entry->is_dir && dir == 2) {
1278 /* user requested a directory, we must return one */
1279 if (error) {
1280 spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
1281 }
1282 return NULL;
1283 }
1284 return entry;
1285 }
1286
1287 if (dir) {
1288 if (zend_hash_str_exists(&phar->virtual_dirs, path, path_len)) {
1289 /* a file or directory exists in a sub-directory of this path */
1290 entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info));
1291 /* this next line tells PharFileInfo->__destruct() to efree the filename */
1292 entry->is_temp_dir = entry->is_dir = 1;
1293 entry->filename = (char *) estrndup(path, path_len + 1);
1294 entry->filename_len = path_len;
1295 entry->phar = phar;
1296 return entry;
1297 }
1298 }
1299
1300 if (HT_IS_INITIALIZED(&phar->mounted_dirs) && zend_hash_num_elements(&phar->mounted_dirs)) {
1301 zend_string *str_key;
1302
1303 ZEND_HASH_MAP_FOREACH_STR_KEY(&phar->mounted_dirs, str_key) {
1304 if (ZSTR_LEN(str_key) >= path_len || strncmp(ZSTR_VAL(str_key), path, ZSTR_LEN(str_key))) {
1305 continue;
1306 } else {
1307 char *test;
1308 size_t test_len;
1309 php_stream_statbuf ssb;
1310
1311 if (NULL == (entry = zend_hash_find_ptr(&phar->manifest, str_key))) {
1312 if (error) {
1313 spprintf(error, 4096, "phar internal error: mounted path \"%s\" could not be retrieved from manifest", ZSTR_VAL(str_key));
1314 }
1315 return NULL;
1316 }
1317
1318 if (!entry->tmp || !entry->is_mounted) {
1319 if (error) {
1320 spprintf(error, 4096, "phar internal error: mounted path \"%s\" is not properly initialized as a mounted path", ZSTR_VAL(str_key));
1321 }
1322 return NULL;
1323 }
1324
1325 test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, path + ZSTR_LEN(str_key));
1326
1327 if (SUCCESS != php_stream_stat_path(test, &ssb)) {
1328 efree(test);
1329 return NULL;
1330 }
1331
1332 if ((ssb.sb.st_mode & S_IFDIR) && !dir) {
1333 efree(test);
1334 if (error) {
1335 spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
1336 }
1337 return NULL;
1338 }
1339
1340 if ((ssb.sb.st_mode & S_IFDIR) == 0 && dir) {
1341 efree(test);
1342 /* user requested a directory, we must return one */
1343 if (error) {
1344 spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
1345 }
1346 return NULL;
1347 }
1348
1349 /* mount the file just in time */
1350 if (SUCCESS != phar_mount_entry(phar, test, test_len, path, path_len)) {
1351 efree(test);
1352 if (error) {
1353 spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be mounted", path, test);
1354 }
1355 return NULL;
1356 }
1357
1358 efree(test);
1359
1360 if (NULL == (entry = zend_hash_str_find_ptr(&phar->manifest, path, path_len))) {
1361 if (error) {
1362 spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be retrieved after being mounted", path, test);
1363 }
1364 return NULL;
1365 }
1366 return entry;
1367 }
1368 } ZEND_HASH_FOREACH_END();
1369 }
1370
1371 return NULL;
1372 }
1373 /* }}} */
1374
1375 static const char hexChars[] = "0123456789ABCDEF";
1376
phar_hex_str(const char * digest,size_t digest_len,char ** signature)1377 static int phar_hex_str(const char *digest, size_t digest_len, char **signature) /* {{{ */
1378 {
1379 int pos = -1;
1380 size_t len = 0;
1381
1382 *signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
1383
1384 for (; len < digest_len; ++len) {
1385 (*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] >> 4];
1386 (*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] & 0x0F];
1387 }
1388 (*signature)[++pos] = '\0';
1389 return pos;
1390 }
1391 /* }}} */
1392
1393 #ifndef PHAR_HAVE_OPENSSL
phar_call_openssl_signverify(int is_sign,php_stream * fp,zend_off_t end,char * key,size_t key_len,char ** signature,size_t * signature_len,php_uint32 sig_type)1394 static int phar_call_openssl_signverify(int is_sign, php_stream *fp, zend_off_t end, char *key, size_t key_len, char **signature, size_t *signature_len, php_uint32 sig_type) /* {{{ */
1395 {
1396 zend_fcall_info fci;
1397 zend_fcall_info_cache fcc;
1398 zval retval, zp[4], openssl;
1399 zend_string *str;
1400
1401 ZVAL_STRINGL(&openssl, is_sign ? "openssl_sign" : "openssl_verify", is_sign ? sizeof("openssl_sign")-1 : sizeof("openssl_verify")-1);
1402 if (*signature_len) {
1403 ZVAL_STRINGL(&zp[1], *signature, *signature_len);
1404 } else {
1405 ZVAL_EMPTY_STRING(&zp[1]);
1406 }
1407 ZVAL_STRINGL(&zp[2], key, key_len);
1408 php_stream_rewind(fp);
1409 str = php_stream_copy_to_mem(fp, (size_t) end, 0);
1410 if (str) {
1411 ZVAL_STR(&zp[0], str);
1412 } else {
1413 ZVAL_EMPTY_STRING(&zp[0]);
1414 }
1415 if (sig_type == PHAR_SIG_OPENSSL_SHA512) {
1416 ZVAL_LONG(&zp[3], 9); /* value from openssl.c #define OPENSSL_ALGO_SHA512 9 */
1417 } else if (sig_type == PHAR_SIG_OPENSSL_SHA256) {
1418 ZVAL_LONG(&zp[3], 7); /* value from openssl.c #define OPENSSL_ALGO_SHA256 7 */
1419 } else {
1420 /* don't rely on default value which may change in the future */
1421 ZVAL_LONG(&zp[3], 1); /* value from openssl.c #define OPENSSL_ALGO_SHA1 1 */
1422 }
1423
1424 if ((size_t)end != Z_STRLEN(zp[0])) {
1425 zval_ptr_dtor_str(&zp[0]);
1426 zval_ptr_dtor_str(&zp[1]);
1427 zval_ptr_dtor_str(&zp[2]);
1428 zval_ptr_dtor_str(&openssl);
1429 return FAILURE;
1430 }
1431
1432 if (FAILURE == zend_fcall_info_init(&openssl, 0, &fci, &fcc, NULL, NULL)) {
1433 zval_ptr_dtor_str(&zp[0]);
1434 zval_ptr_dtor_str(&zp[1]);
1435 zval_ptr_dtor_str(&zp[2]);
1436 zval_ptr_dtor_str(&openssl);
1437 return FAILURE;
1438 }
1439
1440 fci.param_count = 4;
1441 fci.params = zp;
1442 Z_ADDREF(zp[0]);
1443 if (is_sign) {
1444 ZVAL_NEW_REF(&zp[1], &zp[1]);
1445 } else {
1446 Z_ADDREF(zp[1]);
1447 }
1448 Z_ADDREF(zp[2]);
1449
1450 fci.retval = &retval;
1451
1452 if (FAILURE == zend_call_function(&fci, &fcc)) {
1453 zval_ptr_dtor_str(&zp[0]);
1454 zval_ptr_dtor(&zp[1]);
1455 zval_ptr_dtor_str(&zp[2]);
1456 zval_ptr_dtor_str(&openssl);
1457 return FAILURE;
1458 }
1459
1460 zval_ptr_dtor_str(&openssl);
1461 Z_DELREF(zp[0]);
1462
1463 if (is_sign) {
1464 ZVAL_UNREF(&zp[1]);
1465 } else {
1466 Z_DELREF(zp[1]);
1467 }
1468 Z_DELREF(zp[2]);
1469
1470 zval_ptr_dtor_str(&zp[0]);
1471 zval_ptr_dtor_str(&zp[2]);
1472
1473 switch (Z_TYPE(retval)) {
1474 default:
1475 case IS_LONG:
1476 zval_ptr_dtor(&zp[1]);
1477 if (1 == Z_LVAL(retval)) {
1478 return SUCCESS;
1479 }
1480 return FAILURE;
1481 case IS_TRUE:
1482 *signature = estrndup(Z_STRVAL(zp[1]), Z_STRLEN(zp[1]));
1483 *signature_len = Z_STRLEN(zp[1]);
1484 zval_ptr_dtor(&zp[1]);
1485 return SUCCESS;
1486 case IS_FALSE:
1487 zval_ptr_dtor(&zp[1]);
1488 return FAILURE;
1489 }
1490 }
1491 /* }}} */
1492 #endif /* #ifndef PHAR_HAVE_OPENSSL */
1493
phar_verify_signature(php_stream * fp,size_t end_of_phar,uint32_t sig_type,char * sig,size_t sig_len,char * fname,char ** signature,size_t * signature_len,char ** error)1494 int phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, char *fname, char **signature, size_t *signature_len, char **error) /* {{{ */
1495 {
1496 size_t read_size, len;
1497 zend_off_t read_len;
1498 unsigned char buf[1024];
1499
1500 php_stream_rewind(fp);
1501
1502 switch (sig_type) {
1503 case PHAR_SIG_OPENSSL_SHA512:
1504 case PHAR_SIG_OPENSSL_SHA256:
1505 case PHAR_SIG_OPENSSL: {
1506 #ifdef PHAR_HAVE_OPENSSL
1507 BIO *in;
1508 EVP_PKEY *key;
1509 const EVP_MD *mdtype;
1510 EVP_MD_CTX *md_ctx;
1511
1512 if (sig_type == PHAR_SIG_OPENSSL_SHA512) {
1513 mdtype = EVP_sha512();
1514 } else if (sig_type == PHAR_SIG_OPENSSL_SHA256) {
1515 mdtype = EVP_sha256();
1516 } else {
1517 mdtype = EVP_sha1();
1518 }
1519 #else
1520 size_t tempsig;
1521 #endif
1522 zend_string *pubkey = NULL;
1523 char *pfile;
1524 php_stream *pfp;
1525 #ifndef PHAR_HAVE_OPENSSL
1526 if (!zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) {
1527 if (error) {
1528 spprintf(error, 0, "openssl not loaded");
1529 }
1530 return FAILURE;
1531 }
1532 #endif
1533 /* use __FILE__ . '.pubkey' for public key file */
1534 spprintf(&pfile, 0, "%s.pubkey", fname);
1535 pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
1536 efree(pfile);
1537
1538 if (!pfp || !(pubkey = php_stream_copy_to_mem(pfp, PHP_STREAM_COPY_ALL, 0)) || !ZSTR_LEN(pubkey)) {
1539 if (pfp) {
1540 php_stream_close(pfp);
1541 }
1542 if (error) {
1543 spprintf(error, 0, "openssl public key could not be read");
1544 }
1545 return FAILURE;
1546 }
1547
1548 php_stream_close(pfp);
1549 #ifndef PHAR_HAVE_OPENSSL
1550 tempsig = sig_len;
1551
1552 if (FAILURE == phar_call_openssl_signverify(0, fp, end_of_phar, ZSTR_VAL(pubkey), ZSTR_LEN(pubkey), &sig, &tempsig, sig_type)) {
1553 zend_string_release_ex(pubkey, 0);
1554
1555 if (error) {
1556 spprintf(error, 0, "openssl signature could not be verified");
1557 }
1558
1559 return FAILURE;
1560 }
1561
1562 zend_string_release_ex(pubkey, 0);
1563
1564 sig_len = tempsig;
1565 #else
1566 in = BIO_new_mem_buf(ZSTR_VAL(pubkey), ZSTR_LEN(pubkey));
1567
1568 if (NULL == in) {
1569 zend_string_release_ex(pubkey, 0);
1570 if (error) {
1571 spprintf(error, 0, "openssl signature could not be processed");
1572 }
1573 return FAILURE;
1574 }
1575
1576 key = PEM_read_bio_PUBKEY(in, NULL, NULL, NULL);
1577 BIO_free(in);
1578 zend_string_release_ex(pubkey, 0);
1579
1580 if (NULL == key) {
1581 if (error) {
1582 spprintf(error, 0, "openssl signature could not be processed");
1583 }
1584 return FAILURE;
1585 }
1586
1587 md_ctx = EVP_MD_CTX_create();
1588 if (!md_ctx || !EVP_VerifyInit(md_ctx, mdtype)) {
1589 if (md_ctx) {
1590 EVP_MD_CTX_destroy(md_ctx);
1591 }
1592 if (error) {
1593 spprintf(error, 0, "openssl signature could not be verified");
1594 }
1595 return FAILURE;
1596 }
1597 read_len = end_of_phar;
1598
1599 if ((size_t)read_len > sizeof(buf)) {
1600 read_size = sizeof(buf);
1601 } else {
1602 read_size = (size_t)read_len;
1603 }
1604
1605 php_stream_seek(fp, 0, SEEK_SET);
1606
1607 while (read_size && (len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1608 if (UNEXPECTED(EVP_VerifyUpdate (md_ctx, buf, len) == 0)) {
1609 goto failure;
1610 }
1611 read_len -= (zend_off_t)len;
1612
1613 if (read_len < read_size) {
1614 read_size = (size_t)read_len;
1615 }
1616 }
1617
1618 if (EVP_VerifyFinal(md_ctx, (unsigned char *)sig, sig_len, key) != 1) {
1619 failure:
1620 /* 1: signature verified, 0: signature does not match, -1: failed signature operation */
1621 EVP_PKEY_free(key);
1622 EVP_MD_CTX_destroy(md_ctx);
1623
1624 if (error) {
1625 spprintf(error, 0, "broken openssl signature");
1626 }
1627
1628 return FAILURE;
1629 }
1630
1631 EVP_PKEY_free(key);
1632 EVP_MD_CTX_destroy(md_ctx);
1633 #endif
1634
1635 *signature_len = phar_hex_str((const char*)sig, sig_len, signature);
1636 }
1637 break;
1638 case PHAR_SIG_SHA512: {
1639 unsigned char digest[64];
1640 PHP_SHA512_CTX context;
1641
1642 if (sig_len < sizeof(digest)) {
1643 if (error) {
1644 spprintf(error, 0, "broken signature");
1645 }
1646 return FAILURE;
1647 }
1648
1649 PHP_SHA512Init(&context);
1650 read_len = end_of_phar;
1651
1652 if ((size_t)read_len > sizeof(buf)) {
1653 read_size = sizeof(buf);
1654 } else {
1655 read_size = (size_t)read_len;
1656 }
1657
1658 while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1659 PHP_SHA512Update(&context, buf, len);
1660 read_len -= (zend_off_t)len;
1661 if ((size_t)read_len < read_size) {
1662 read_size = (size_t)read_len;
1663 }
1664 }
1665
1666 PHP_SHA512Final(digest, &context);
1667
1668 if (memcmp(digest, sig, sizeof(digest))) {
1669 if (error) {
1670 spprintf(error, 0, "broken signature");
1671 }
1672 return FAILURE;
1673 }
1674
1675 *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1676 break;
1677 }
1678 case PHAR_SIG_SHA256: {
1679 unsigned char digest[32];
1680 PHP_SHA256_CTX context;
1681
1682 if (sig_len < sizeof(digest)) {
1683 if (error) {
1684 spprintf(error, 0, "broken signature");
1685 }
1686 return FAILURE;
1687 }
1688
1689 PHP_SHA256Init(&context);
1690 read_len = end_of_phar;
1691
1692 if ((size_t)read_len > sizeof(buf)) {
1693 read_size = sizeof(buf);
1694 } else {
1695 read_size = (size_t)read_len;
1696 }
1697
1698 while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1699 PHP_SHA256Update(&context, buf, len);
1700 read_len -= (zend_off_t)len;
1701 if ((size_t)read_len < read_size) {
1702 read_size = (size_t)read_len;
1703 }
1704 }
1705
1706 PHP_SHA256Final(digest, &context);
1707
1708 if (memcmp(digest, sig, sizeof(digest))) {
1709 if (error) {
1710 spprintf(error, 0, "broken signature");
1711 }
1712 return FAILURE;
1713 }
1714
1715 *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1716 break;
1717 }
1718 case PHAR_SIG_SHA1: {
1719 unsigned char digest[20];
1720 PHP_SHA1_CTX context;
1721
1722 if (sig_len < sizeof(digest)) {
1723 if (error) {
1724 spprintf(error, 0, "broken signature");
1725 }
1726 return FAILURE;
1727 }
1728
1729 PHP_SHA1Init(&context);
1730 read_len = end_of_phar;
1731
1732 if ((size_t)read_len > sizeof(buf)) {
1733 read_size = sizeof(buf);
1734 } else {
1735 read_size = (size_t)read_len;
1736 }
1737
1738 while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1739 PHP_SHA1Update(&context, buf, len);
1740 read_len -= (zend_off_t)len;
1741 if ((size_t)read_len < read_size) {
1742 read_size = (size_t)read_len;
1743 }
1744 }
1745
1746 PHP_SHA1Final(digest, &context);
1747
1748 if (memcmp(digest, sig, sizeof(digest))) {
1749 if (error) {
1750 spprintf(error, 0, "broken signature");
1751 }
1752 return FAILURE;
1753 }
1754
1755 *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1756 break;
1757 }
1758 case PHAR_SIG_MD5: {
1759 unsigned char digest[16];
1760 PHP_MD5_CTX context;
1761
1762 if (sig_len < sizeof(digest)) {
1763 if (error) {
1764 spprintf(error, 0, "broken signature");
1765 }
1766 return FAILURE;
1767 }
1768
1769 PHP_MD5Init(&context);
1770 read_len = end_of_phar;
1771
1772 if ((size_t)read_len > sizeof(buf)) {
1773 read_size = sizeof(buf);
1774 } else {
1775 read_size = (size_t)read_len;
1776 }
1777
1778 while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1779 PHP_MD5Update(&context, buf, len);
1780 read_len -= (zend_off_t)len;
1781 if ((size_t)read_len < read_size) {
1782 read_size = (size_t)read_len;
1783 }
1784 }
1785
1786 PHP_MD5Final(digest, &context);
1787
1788 if (memcmp(digest, sig, sizeof(digest))) {
1789 if (error) {
1790 spprintf(error, 0, "broken signature");
1791 }
1792 return FAILURE;
1793 }
1794
1795 *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1796 break;
1797 }
1798 default:
1799 if (error) {
1800 spprintf(error, 0, "broken or unsupported signature");
1801 }
1802 return FAILURE;
1803 }
1804 return SUCCESS;
1805 }
1806 /* }}} */
1807
phar_create_signature(phar_archive_data * phar,php_stream * fp,char ** signature,size_t * signature_length,char ** error)1808 int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */
1809 {
1810 unsigned char buf[1024];
1811 size_t sig_len;
1812
1813 php_stream_rewind(fp);
1814
1815 if (phar->signature) {
1816 efree(phar->signature);
1817 phar->signature = NULL;
1818 }
1819
1820 switch(phar->sig_flags) {
1821 case PHAR_SIG_SHA512: {
1822 unsigned char digest[64];
1823 PHP_SHA512_CTX context;
1824
1825 PHP_SHA512Init(&context);
1826
1827 while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1828 PHP_SHA512Update(&context, buf, sig_len);
1829 }
1830
1831 PHP_SHA512Final(digest, &context);
1832 *signature = estrndup((char *) digest, 64);
1833 *signature_length = 64;
1834 break;
1835 }
1836 default:
1837 phar->sig_flags = PHAR_SIG_SHA256;
1838 ZEND_FALLTHROUGH;
1839 case PHAR_SIG_SHA256: {
1840 unsigned char digest[32];
1841 PHP_SHA256_CTX context;
1842
1843 PHP_SHA256Init(&context);
1844
1845 while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1846 PHP_SHA256Update(&context, buf, sig_len);
1847 }
1848
1849 PHP_SHA256Final(digest, &context);
1850 *signature = estrndup((char *) digest, 32);
1851 *signature_length = 32;
1852 break;
1853 }
1854 case PHAR_SIG_OPENSSL_SHA512:
1855 case PHAR_SIG_OPENSSL_SHA256:
1856 case PHAR_SIG_OPENSSL: {
1857 unsigned char *sigbuf;
1858 #ifdef PHAR_HAVE_OPENSSL
1859 unsigned int siglen;
1860 BIO *in;
1861 EVP_PKEY *key;
1862 EVP_MD_CTX *md_ctx;
1863 const EVP_MD *mdtype;
1864
1865 if (phar->sig_flags == PHAR_SIG_OPENSSL_SHA512) {
1866 mdtype = EVP_sha512();
1867 } else if (phar->sig_flags == PHAR_SIG_OPENSSL_SHA256) {
1868 mdtype = EVP_sha256();
1869 } else {
1870 mdtype = EVP_sha1();
1871 }
1872
1873 in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len));
1874
1875 if (in == NULL) {
1876 if (error) {
1877 spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname);
1878 }
1879 return FAILURE;
1880 }
1881
1882 key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
1883 BIO_free(in);
1884
1885 if (!key) {
1886 if (error) {
1887 spprintf(error, 0, "unable to process private key");
1888 }
1889 return FAILURE;
1890 }
1891
1892 md_ctx = EVP_MD_CTX_create();
1893 if (md_ctx == NULL) {
1894 EVP_PKEY_free(key);
1895 if (error) {
1896 spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname);
1897 }
1898 return FAILURE;
1899 }
1900
1901 siglen = EVP_PKEY_size(key);
1902 sigbuf = emalloc(siglen + 1);
1903
1904 if (!EVP_SignInit(md_ctx, mdtype)) {
1905 EVP_PKEY_free(key);
1906 efree(sigbuf);
1907 if (error) {
1908 spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname);
1909 }
1910 return FAILURE;
1911 }
1912
1913 while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1914 if (!EVP_SignUpdate(md_ctx, buf, sig_len)) {
1915 EVP_PKEY_free(key);
1916 efree(sigbuf);
1917 if (error) {
1918 spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", phar->fname);
1919 }
1920 return FAILURE;
1921 }
1922 }
1923
1924 if (!EVP_SignFinal (md_ctx, sigbuf, &siglen, key)) {
1925 EVP_PKEY_free(key);
1926 efree(sigbuf);
1927 if (error) {
1928 spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
1929 }
1930 return FAILURE;
1931 }
1932
1933 sigbuf[siglen] = '\0';
1934 EVP_PKEY_free(key);
1935 EVP_MD_CTX_destroy(md_ctx);
1936 #else
1937 size_t siglen;
1938 sigbuf = NULL;
1939 siglen = 0;
1940 php_stream_seek(fp, 0, SEEK_END);
1941
1942 if (FAILURE == phar_call_openssl_signverify(1, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen, phar->sig_flags)) {
1943 if (error) {
1944 spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
1945 }
1946 return FAILURE;
1947 }
1948 #endif
1949 *signature = (char *) sigbuf;
1950 *signature_length = siglen;
1951 }
1952 break;
1953 case PHAR_SIG_SHA1: {
1954 unsigned char digest[20];
1955 PHP_SHA1_CTX context;
1956
1957 PHP_SHA1Init(&context);
1958
1959 while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1960 PHP_SHA1Update(&context, buf, sig_len);
1961 }
1962
1963 PHP_SHA1Final(digest, &context);
1964 *signature = estrndup((char *) digest, 20);
1965 *signature_length = 20;
1966 break;
1967 }
1968 case PHAR_SIG_MD5: {
1969 unsigned char digest[16];
1970 PHP_MD5_CTX context;
1971
1972 PHP_MD5Init(&context);
1973
1974 while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1975 PHP_MD5Update(&context, buf, sig_len);
1976 }
1977
1978 PHP_MD5Final(digest, &context);
1979 *signature = estrndup((char *) digest, 16);
1980 *signature_length = 16;
1981 break;
1982 }
1983 }
1984
1985 phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature);
1986 return SUCCESS;
1987 }
1988 /* }}} */
1989
phar_add_virtual_dirs(phar_archive_data * phar,char * filename,size_t filename_len)1990 void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len) /* {{{ */
1991 {
1992 const char *s;
1993 zend_string *str;
1994 zval *ret;
1995
1996 while ((s = zend_memrchr(filename, '/', filename_len))) {
1997 filename_len = s - filename;
1998 if (!filename_len) {
1999 break;
2000 }
2001 if (GC_FLAGS(&phar->virtual_dirs) & GC_PERSISTENT) {
2002 str = zend_string_init_interned(filename, filename_len, 1);
2003 } else {
2004 str = zend_string_init(filename, filename_len, 0);
2005 }
2006 ret = zend_hash_add_empty_element(&phar->virtual_dirs, str);
2007 zend_string_release(str);
2008 if (ret == NULL) {
2009 break;
2010 }
2011 }
2012 }
2013 /* }}} */
2014
phar_update_cached_entry(zval * data,void * argument)2015 static int phar_update_cached_entry(zval *data, void *argument) /* {{{ */
2016 {
2017 phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(data);
2018
2019 entry->phar = (phar_archive_data *)argument;
2020
2021 if (entry->link) {
2022 entry->link = estrdup(entry->link);
2023 }
2024
2025 if (entry->tmp) {
2026 entry->tmp = estrdup(entry->tmp);
2027 }
2028
2029 entry->filename = estrndup(entry->filename, entry->filename_len);
2030 entry->is_persistent = 0;
2031
2032 /* Replace metadata with non-persistent clones of the metadata. */
2033 phar_metadata_tracker_clone(&entry->metadata_tracker);
2034 return ZEND_HASH_APPLY_KEEP;
2035 }
2036 /* }}} */
2037
phar_manifest_copy_ctor(zval * zv)2038 static void phar_manifest_copy_ctor(zval *zv) /* {{{ */
2039 {
2040 phar_entry_info *info = emalloc(sizeof(phar_entry_info));
2041 memcpy(info, Z_PTR_P(zv), sizeof(phar_entry_info));
2042 Z_PTR_P(zv) = info;
2043 }
2044 /* }}} */
2045
phar_copy_cached_phar(phar_archive_data ** pphar)2046 static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */
2047 {
2048 phar_archive_data *phar;
2049 HashTable newmanifest;
2050 char *fname;
2051 phar_archive_object *objphar;
2052
2053 phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
2054 *phar = **pphar;
2055 phar->is_persistent = 0;
2056 fname = phar->fname;
2057 phar->fname = estrndup(phar->fname, phar->fname_len);
2058 phar->ext = phar->fname + (phar->ext - fname);
2059
2060 if (phar->alias) {
2061 phar->alias = estrndup(phar->alias, phar->alias_len);
2062 }
2063
2064 if (phar->signature) {
2065 phar->signature = estrdup(phar->signature);
2066 }
2067
2068 phar_metadata_tracker_clone(&phar->metadata_tracker);
2069
2070 zend_hash_init(&newmanifest, sizeof(phar_entry_info),
2071 zend_get_hash_value, destroy_phar_manifest_entry, 0);
2072 zend_hash_copy(&newmanifest, &(*pphar)->manifest, phar_manifest_copy_ctor);
2073 zend_hash_apply_with_argument(&newmanifest, phar_update_cached_entry, (void *)phar);
2074 phar->manifest = newmanifest;
2075 zend_hash_init(&phar->mounted_dirs, sizeof(char *),
2076 zend_get_hash_value, NULL, 0);
2077 zend_hash_init(&phar->virtual_dirs, sizeof(char *),
2078 zend_get_hash_value, NULL, 0);
2079 zend_hash_copy(&phar->virtual_dirs, &(*pphar)->virtual_dirs, NULL);
2080 *pphar = phar;
2081
2082 /* now, scan the list of persistent Phar objects referencing this phar and update the pointers */
2083 ZEND_HASH_MAP_FOREACH_PTR(&PHAR_G(phar_persist_map), objphar) {
2084 if (objphar->archive->fname_len == phar->fname_len && !memcmp(objphar->archive->fname, phar->fname, phar->fname_len)) {
2085 objphar->archive = phar;
2086 }
2087 } ZEND_HASH_FOREACH_END();
2088 }
2089 /* }}} */
2090
phar_copy_on_write(phar_archive_data ** pphar)2091 int phar_copy_on_write(phar_archive_data **pphar) /* {{{ */
2092 {
2093 zval zv, *pzv;
2094 phar_archive_data *newpphar;
2095
2096 ZVAL_PTR(&zv, *pphar);
2097 if (NULL == (pzv = zend_hash_str_add(&(PHAR_G(phar_fname_map)), (*pphar)->fname, (*pphar)->fname_len, &zv))) {
2098 return FAILURE;
2099 }
2100
2101 phar_copy_cached_phar((phar_archive_data **)&Z_PTR_P(pzv));
2102 newpphar = Z_PTR_P(pzv);
2103 /* invalidate phar cache */
2104 PHAR_G(last_phar) = NULL;
2105 PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
2106
2107 if (newpphar->alias_len && NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), newpphar->alias, newpphar->alias_len, newpphar)) {
2108 zend_hash_str_del(&(PHAR_G(phar_fname_map)), (*pphar)->fname, (*pphar)->fname_len);
2109 return FAILURE;
2110 }
2111
2112 *pphar = newpphar;
2113 return SUCCESS;
2114 }
2115 /* }}} */
2116