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