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