xref: /php-src/ext/phar/util.c (revision 234219dc)
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