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