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