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