xref: /PHP-7.4/ext/phar/util.c (revision a53d67ce)
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   | http://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);
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 phar_save_resolve_path(filename, filename_len);
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 phar_save_resolve_path(filename, filename_len);
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 phar_save_resolve_path(filename, filename_len);
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)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) /* {{{ */
1385 {
1386 	zend_fcall_info fci;
1387 	zend_fcall_info_cache fcc;
1388 	zval retval, zp[3], 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 	ZVAL_STRINGL(&zp[1], *signature, *signature_len);
1393 	ZVAL_STRINGL(&zp[2], key, key_len);
1394 	php_stream_rewind(fp);
1395 	str = php_stream_copy_to_mem(fp, (size_t) end, 0);
1396 	if (str) {
1397 		ZVAL_STR(&zp[0], str);
1398 	} else {
1399 		ZVAL_EMPTY_STRING(&zp[0]);
1400 	}
1401 
1402 	if ((size_t)end != Z_STRLEN(zp[0])) {
1403 		zval_ptr_dtor_str(&zp[0]);
1404 		zval_ptr_dtor_str(&zp[1]);
1405 		zval_ptr_dtor_str(&zp[2]);
1406 		zval_ptr_dtor_str(&openssl);
1407 		return FAILURE;
1408 	}
1409 
1410 	if (FAILURE == zend_fcall_info_init(&openssl, 0, &fci, &fcc, NULL, NULL)) {
1411 		zval_ptr_dtor_str(&zp[0]);
1412 		zval_ptr_dtor_str(&zp[1]);
1413 		zval_ptr_dtor_str(&zp[2]);
1414 		zval_ptr_dtor_str(&openssl);
1415 		return FAILURE;
1416 	}
1417 
1418 	fci.param_count = 3;
1419 	fci.params = zp;
1420 	Z_ADDREF(zp[0]);
1421 	if (is_sign) {
1422 		ZVAL_NEW_REF(&zp[1], &zp[1]);
1423 	} else {
1424 		Z_ADDREF(zp[1]);
1425 	}
1426 	Z_ADDREF(zp[2]);
1427 
1428 	fci.retval = &retval;
1429 
1430 	if (FAILURE == zend_call_function(&fci, &fcc)) {
1431 		zval_ptr_dtor_str(&zp[0]);
1432 		zval_ptr_dtor(&zp[1]);
1433 		zval_ptr_dtor_str(&zp[2]);
1434 		zval_ptr_dtor_str(&openssl);
1435 		return FAILURE;
1436 	}
1437 
1438 	zval_ptr_dtor_str(&openssl);
1439 	Z_DELREF(zp[0]);
1440 
1441 	if (is_sign) {
1442 		ZVAL_UNREF(&zp[1]);
1443 	} else {
1444 		Z_DELREF(zp[1]);
1445 	}
1446 	Z_DELREF(zp[2]);
1447 
1448 	zval_ptr_dtor_str(&zp[0]);
1449 	zval_ptr_dtor_str(&zp[2]);
1450 
1451 	switch (Z_TYPE(retval)) {
1452 		default:
1453 		case IS_LONG:
1454 			zval_ptr_dtor(&zp[1]);
1455 			if (1 == Z_LVAL(retval)) {
1456 				return SUCCESS;
1457 			}
1458 			return FAILURE;
1459 		case IS_TRUE:
1460 			*signature = estrndup(Z_STRVAL(zp[1]), Z_STRLEN(zp[1]));
1461 			*signature_len = Z_STRLEN(zp[1]);
1462 			zval_ptr_dtor(&zp[1]);
1463 			return SUCCESS;
1464 		case IS_FALSE:
1465 			zval_ptr_dtor(&zp[1]);
1466 			return FAILURE;
1467 	}
1468 }
1469 /* }}} */
1470 #endif /* #ifndef PHAR_HAVE_OPENSSL */
1471 
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)1472 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) /* {{{ */
1473 {
1474 	size_t read_size, len;
1475 	zend_off_t read_len;
1476 	unsigned char buf[1024];
1477 
1478 	php_stream_rewind(fp);
1479 
1480 	switch (sig_type) {
1481 		case PHAR_SIG_OPENSSL: {
1482 #ifdef PHAR_HAVE_OPENSSL
1483 			BIO *in;
1484 			EVP_PKEY *key;
1485 			EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
1486 			EVP_MD_CTX *md_ctx;
1487 #else
1488 			size_t tempsig;
1489 #endif
1490 			zend_string *pubkey = NULL;
1491 			char *pfile;
1492 			php_stream *pfp;
1493 #ifndef PHAR_HAVE_OPENSSL
1494 			if (!zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) {
1495 				if (error) {
1496 					spprintf(error, 0, "openssl not loaded");
1497 				}
1498 				return FAILURE;
1499 			}
1500 #endif
1501 			/* use __FILE__ . '.pubkey' for public key file */
1502 			spprintf(&pfile, 0, "%s.pubkey", fname);
1503 			pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
1504 			efree(pfile);
1505 
1506 			if (!pfp || !(pubkey = php_stream_copy_to_mem(pfp, PHP_STREAM_COPY_ALL, 0)) || !ZSTR_LEN(pubkey)) {
1507 				if (pfp) {
1508 					php_stream_close(pfp);
1509 				}
1510 				if (error) {
1511 					spprintf(error, 0, "openssl public key could not be read");
1512 				}
1513 				return FAILURE;
1514 			}
1515 
1516 			php_stream_close(pfp);
1517 #ifndef PHAR_HAVE_OPENSSL
1518 			tempsig = sig_len;
1519 
1520 			if (FAILURE == phar_call_openssl_signverify(0, fp, end_of_phar, pubkey ? ZSTR_VAL(pubkey) : NULL, pubkey ? ZSTR_LEN(pubkey) : 0, &sig, &tempsig)) {
1521 				if (pubkey) {
1522 					zend_string_release_ex(pubkey, 0);
1523 				}
1524 
1525 				if (error) {
1526 					spprintf(error, 0, "openssl signature could not be verified");
1527 				}
1528 
1529 				return FAILURE;
1530 			}
1531 
1532 			if (pubkey) {
1533 				zend_string_release_ex(pubkey, 0);
1534 			}
1535 
1536 			sig_len = tempsig;
1537 #else
1538 			in = BIO_new_mem_buf(pubkey ? ZSTR_VAL(pubkey) : NULL, pubkey ? ZSTR_LEN(pubkey) : 0);
1539 
1540 			if (NULL == in) {
1541 				zend_string_release_ex(pubkey, 0);
1542 				if (error) {
1543 					spprintf(error, 0, "openssl signature could not be processed");
1544 				}
1545 				return FAILURE;
1546 			}
1547 
1548 			key = PEM_read_bio_PUBKEY(in, NULL, NULL, NULL);
1549 			BIO_free(in);
1550 			zend_string_release_ex(pubkey, 0);
1551 
1552 			if (NULL == key) {
1553 				if (error) {
1554 					spprintf(error, 0, "openssl signature could not be processed");
1555 				}
1556 				return FAILURE;
1557 			}
1558 
1559 			md_ctx = EVP_MD_CTX_create();
1560 			EVP_VerifyInit(md_ctx, mdtype);
1561 			read_len = end_of_phar;
1562 
1563 			if ((size_t)read_len > sizeof(buf)) {
1564 				read_size = sizeof(buf);
1565 			} else {
1566 				read_size = (size_t)read_len;
1567 			}
1568 
1569 			php_stream_seek(fp, 0, SEEK_SET);
1570 
1571 			while (read_size && (len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1572 				EVP_VerifyUpdate (md_ctx, buf, len);
1573 				read_len -= (zend_off_t)len;
1574 
1575 				if (read_len < read_size) {
1576 					read_size = (size_t)read_len;
1577 				}
1578 			}
1579 
1580 			if (EVP_VerifyFinal(md_ctx, (unsigned char *)sig, sig_len, key) != 1) {
1581 				/* 1: signature verified, 0: signature does not match, -1: failed signature operation */
1582 				EVP_PKEY_free(key);
1583 				EVP_MD_CTX_destroy(md_ctx);
1584 
1585 				if (error) {
1586 					spprintf(error, 0, "broken openssl signature");
1587 				}
1588 
1589 				return FAILURE;
1590 			}
1591 
1592 			EVP_PKEY_free(key);
1593 			EVP_MD_CTX_destroy(md_ctx);
1594 #endif
1595 
1596 			*signature_len = phar_hex_str((const char*)sig, sig_len, signature);
1597 		}
1598 		break;
1599 		case PHAR_SIG_SHA512: {
1600 			unsigned char digest[64];
1601 			PHP_SHA512_CTX context;
1602 
1603 			if (sig_len < sizeof(digest)) {
1604 				if (error) {
1605 					spprintf(error, 0, "broken signature");
1606 				}
1607 				return FAILURE;
1608 			}
1609 
1610 			PHP_SHA512Init(&context);
1611 			read_len = end_of_phar;
1612 
1613 			if ((size_t)read_len > sizeof(buf)) {
1614 				read_size = sizeof(buf);
1615 			} else {
1616 				read_size = (size_t)read_len;
1617 			}
1618 
1619 			while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1620 				PHP_SHA512Update(&context, buf, len);
1621 				read_len -= (zend_off_t)len;
1622 				if ((size_t)read_len < read_size) {
1623 					read_size = (size_t)read_len;
1624 				}
1625 			}
1626 
1627 			PHP_SHA512Final(digest, &context);
1628 
1629 			if (memcmp(digest, sig, sizeof(digest))) {
1630 				if (error) {
1631 					spprintf(error, 0, "broken signature");
1632 				}
1633 				return FAILURE;
1634 			}
1635 
1636 			*signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1637 			break;
1638 		}
1639 		case PHAR_SIG_SHA256: {
1640 			unsigned char digest[32];
1641 			PHP_SHA256_CTX context;
1642 
1643 			if (sig_len < sizeof(digest)) {
1644 				if (error) {
1645 					spprintf(error, 0, "broken signature");
1646 				}
1647 				return FAILURE;
1648 			}
1649 
1650 			PHP_SHA256Init(&context);
1651 			read_len = end_of_phar;
1652 
1653 			if ((size_t)read_len > sizeof(buf)) {
1654 				read_size = sizeof(buf);
1655 			} else {
1656 				read_size = (size_t)read_len;
1657 			}
1658 
1659 			while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1660 				PHP_SHA256Update(&context, buf, len);
1661 				read_len -= (zend_off_t)len;
1662 				if ((size_t)read_len < read_size) {
1663 					read_size = (size_t)read_len;
1664 				}
1665 			}
1666 
1667 			PHP_SHA256Final(digest, &context);
1668 
1669 			if (memcmp(digest, sig, sizeof(digest))) {
1670 				if (error) {
1671 					spprintf(error, 0, "broken signature");
1672 				}
1673 				return FAILURE;
1674 			}
1675 
1676 			*signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1677 			break;
1678 		}
1679 		case PHAR_SIG_SHA1: {
1680 			unsigned char digest[20];
1681 			PHP_SHA1_CTX  context;
1682 
1683 			if (sig_len < sizeof(digest)) {
1684 				if (error) {
1685 					spprintf(error, 0, "broken signature");
1686 				}
1687 				return FAILURE;
1688 			}
1689 
1690 			PHP_SHA1Init(&context);
1691 			read_len = end_of_phar;
1692 
1693 			if ((size_t)read_len > sizeof(buf)) {
1694 				read_size = sizeof(buf);
1695 			} else {
1696 				read_size = (size_t)read_len;
1697 			}
1698 
1699 			while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1700 				PHP_SHA1Update(&context, buf, len);
1701 				read_len -= (zend_off_t)len;
1702 				if ((size_t)read_len < read_size) {
1703 					read_size = (size_t)read_len;
1704 				}
1705 			}
1706 
1707 			PHP_SHA1Final(digest, &context);
1708 
1709 			if (memcmp(digest, sig, sizeof(digest))) {
1710 				if (error) {
1711 					spprintf(error, 0, "broken signature");
1712 				}
1713 				return FAILURE;
1714 			}
1715 
1716 			*signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1717 			break;
1718 		}
1719 		case PHAR_SIG_MD5: {
1720 			unsigned char digest[16];
1721 			PHP_MD5_CTX   context;
1722 
1723 			if (sig_len < sizeof(digest)) {
1724 				if (error) {
1725 					spprintf(error, 0, "broken signature");
1726 				}
1727 				return FAILURE;
1728 			}
1729 
1730 			PHP_MD5Init(&context);
1731 			read_len = end_of_phar;
1732 
1733 			if ((size_t)read_len > sizeof(buf)) {
1734 				read_size = sizeof(buf);
1735 			} else {
1736 				read_size = (size_t)read_len;
1737 			}
1738 
1739 			while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1740 				PHP_MD5Update(&context, buf, len);
1741 				read_len -= (zend_off_t)len;
1742 				if ((size_t)read_len < read_size) {
1743 					read_size = (size_t)read_len;
1744 				}
1745 			}
1746 
1747 			PHP_MD5Final(digest, &context);
1748 
1749 			if (memcmp(digest, sig, sizeof(digest))) {
1750 				if (error) {
1751 					spprintf(error, 0, "broken signature");
1752 				}
1753 				return FAILURE;
1754 			}
1755 
1756 			*signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
1757 			break;
1758 		}
1759 		default:
1760 			if (error) {
1761 				spprintf(error, 0, "broken or unsupported signature");
1762 			}
1763 			return FAILURE;
1764 	}
1765 	return SUCCESS;
1766 }
1767 /* }}} */
1768 
phar_create_signature(phar_archive_data * phar,php_stream * fp,char ** signature,size_t * signature_length,char ** error)1769 int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */
1770 {
1771 	unsigned char buf[1024];
1772 	size_t sig_len;
1773 
1774 	php_stream_rewind(fp);
1775 
1776 	if (phar->signature) {
1777 		efree(phar->signature);
1778 		phar->signature = NULL;
1779 	}
1780 
1781 	switch(phar->sig_flags) {
1782 		case PHAR_SIG_SHA512: {
1783 			unsigned char digest[64];
1784 			PHP_SHA512_CTX context;
1785 
1786 			PHP_SHA512Init(&context);
1787 
1788 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1789 				PHP_SHA512Update(&context, buf, sig_len);
1790 			}
1791 
1792 			PHP_SHA512Final(digest, &context);
1793 			*signature = estrndup((char *) digest, 64);
1794 			*signature_length = 64;
1795 			break;
1796 		}
1797 		case PHAR_SIG_SHA256: {
1798 			unsigned char digest[32];
1799 			PHP_SHA256_CTX  context;
1800 
1801 			PHP_SHA256Init(&context);
1802 
1803 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1804 				PHP_SHA256Update(&context, buf, sig_len);
1805 			}
1806 
1807 			PHP_SHA256Final(digest, &context);
1808 			*signature = estrndup((char *) digest, 32);
1809 			*signature_length = 32;
1810 			break;
1811 		}
1812 		case PHAR_SIG_OPENSSL: {
1813 			unsigned char *sigbuf;
1814 #ifdef PHAR_HAVE_OPENSSL
1815 			unsigned int siglen;
1816 			BIO *in;
1817 			EVP_PKEY *key;
1818 			EVP_MD_CTX *md_ctx;
1819 
1820 			in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len));
1821 
1822 			if (in == NULL) {
1823 				if (error) {
1824 					spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname);
1825 				}
1826 				return FAILURE;
1827 			}
1828 
1829 			key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
1830 			BIO_free(in);
1831 
1832 			if (!key) {
1833 				if (error) {
1834 					spprintf(error, 0, "unable to process private key");
1835 				}
1836 				return FAILURE;
1837 			}
1838 
1839 			md_ctx = EVP_MD_CTX_create();
1840 
1841 			siglen = EVP_PKEY_size(key);
1842 			sigbuf = emalloc(siglen + 1);
1843 
1844 			if (!EVP_SignInit(md_ctx, EVP_sha1())) {
1845 				EVP_PKEY_free(key);
1846 				efree(sigbuf);
1847 				if (error) {
1848 					spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname);
1849 				}
1850 				return FAILURE;
1851 			}
1852 
1853 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1854 				if (!EVP_SignUpdate(md_ctx, buf, sig_len)) {
1855 					EVP_PKEY_free(key);
1856 					efree(sigbuf);
1857 					if (error) {
1858 						spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", phar->fname);
1859 					}
1860 					return FAILURE;
1861 				}
1862 			}
1863 
1864 			if (!EVP_SignFinal (md_ctx, sigbuf, &siglen, key)) {
1865 				EVP_PKEY_free(key);
1866 				efree(sigbuf);
1867 				if (error) {
1868 					spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
1869 				}
1870 				return FAILURE;
1871 			}
1872 
1873 			sigbuf[siglen] = '\0';
1874 			EVP_PKEY_free(key);
1875 			EVP_MD_CTX_destroy(md_ctx);
1876 #else
1877 			size_t siglen;
1878 			sigbuf = NULL;
1879 			siglen = 0;
1880 			php_stream_seek(fp, 0, SEEK_END);
1881 
1882 			if (FAILURE == phar_call_openssl_signverify(1, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen)) {
1883 				if (error) {
1884 					spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
1885 				}
1886 				return FAILURE;
1887 			}
1888 #endif
1889 			*signature = (char *) sigbuf;
1890 			*signature_length = siglen;
1891 		}
1892 		break;
1893 		default:
1894 			phar->sig_flags = PHAR_SIG_SHA1;
1895 		case PHAR_SIG_SHA1: {
1896 			unsigned char digest[20];
1897 			PHP_SHA1_CTX  context;
1898 
1899 			PHP_SHA1Init(&context);
1900 
1901 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1902 				PHP_SHA1Update(&context, buf, sig_len);
1903 			}
1904 
1905 			PHP_SHA1Final(digest, &context);
1906 			*signature = estrndup((char *) digest, 20);
1907 			*signature_length = 20;
1908 			break;
1909 		}
1910 		case PHAR_SIG_MD5: {
1911 			unsigned char digest[16];
1912 			PHP_MD5_CTX   context;
1913 
1914 			PHP_MD5Init(&context);
1915 
1916 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1917 				PHP_MD5Update(&context, buf, sig_len);
1918 			}
1919 
1920 			PHP_MD5Final(digest, &context);
1921 			*signature = estrndup((char *) digest, 16);
1922 			*signature_length = 16;
1923 			break;
1924 		}
1925 	}
1926 
1927 	phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature);
1928 	return SUCCESS;
1929 }
1930 /* }}} */
1931 
phar_add_virtual_dirs(phar_archive_data * phar,char * filename,size_t filename_len)1932 void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len) /* {{{ */
1933 {
1934 	const char *s;
1935 	zend_string *str;
1936 	zval *ret;
1937 
1938 	while ((s = zend_memrchr(filename, '/', filename_len))) {
1939 		filename_len = s - filename;
1940 		if (!filename_len) {
1941 			break;
1942 		}
1943 		if (GC_FLAGS(&phar->virtual_dirs) & GC_PERSISTENT) {
1944 			str = zend_string_init_interned(filename, filename_len, 1);
1945 		} else {
1946 			str = zend_string_init(filename, filename_len, 0);
1947 		}
1948 		ret = zend_hash_add_empty_element(&phar->virtual_dirs, str);
1949 		zend_string_release(str);
1950 		if (ret == NULL) {
1951 			break;
1952 		}
1953 	}
1954 }
1955 /* }}} */
1956 
phar_update_cached_entry(zval * data,void * argument)1957 static int phar_update_cached_entry(zval *data, void *argument) /* {{{ */
1958 {
1959 	phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(data);
1960 
1961 	entry->phar = (phar_archive_data *)argument;
1962 
1963 	if (entry->link) {
1964 		entry->link = estrdup(entry->link);
1965 	}
1966 
1967 	if (entry->tmp) {
1968 		entry->tmp = estrdup(entry->tmp);
1969 	}
1970 
1971 	entry->metadata_str.s = NULL;
1972 	entry->filename = estrndup(entry->filename, entry->filename_len);
1973 	entry->is_persistent = 0;
1974 
1975 	if (Z_TYPE(entry->metadata) != IS_UNDEF) {
1976 		if (entry->metadata_len) {
1977 			char *buf = estrndup((char *) Z_PTR(entry->metadata), entry->metadata_len);
1978 			/* assume success, we would have failed before */
1979 			phar_parse_metadata((char **) &buf, &entry->metadata, entry->metadata_len);
1980 			efree(buf);
1981 		} else {
1982 			zval_copy_ctor(&entry->metadata);
1983 			entry->metadata_str.s = NULL;
1984 		}
1985 	}
1986 	return ZEND_HASH_APPLY_KEEP;
1987 }
1988 /* }}} */
1989 
phar_manifest_copy_ctor(zval * zv)1990 static void phar_manifest_copy_ctor(zval *zv) /* {{{ */
1991 {
1992 	phar_entry_info *info = emalloc(sizeof(phar_entry_info));
1993 	memcpy(info, Z_PTR_P(zv), sizeof(phar_entry_info));
1994 	Z_PTR_P(zv) = info;
1995 }
1996 /* }}} */
1997 
phar_copy_cached_phar(phar_archive_data ** pphar)1998 static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */
1999 {
2000 	phar_archive_data *phar;
2001 	HashTable newmanifest;
2002 	char *fname;
2003 	phar_archive_object *objphar;
2004 
2005 	phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
2006 	*phar = **pphar;
2007 	phar->is_persistent = 0;
2008 	fname = phar->fname;
2009 	phar->fname = estrndup(phar->fname, phar->fname_len);
2010 	phar->ext = phar->fname + (phar->ext - fname);
2011 
2012 	if (phar->alias) {
2013 		phar->alias = estrndup(phar->alias, phar->alias_len);
2014 	}
2015 
2016 	if (phar->signature) {
2017 		phar->signature = estrdup(phar->signature);
2018 	}
2019 
2020 	if (Z_TYPE(phar->metadata) != IS_UNDEF) {
2021 		/* assume success, we would have failed before */
2022 		if (phar->metadata_len) {
2023 			char *buf = estrndup((char *) Z_PTR(phar->metadata), phar->metadata_len);
2024 			phar_parse_metadata(&buf, &phar->metadata, phar->metadata_len);
2025 			efree(buf);
2026 		} else {
2027 			zval_copy_ctor(&phar->metadata);
2028 		}
2029 	}
2030 
2031 	zend_hash_init(&newmanifest, sizeof(phar_entry_info),
2032 		zend_get_hash_value, destroy_phar_manifest_entry, 0);
2033 	zend_hash_copy(&newmanifest, &(*pphar)->manifest, phar_manifest_copy_ctor);
2034 	zend_hash_apply_with_argument(&newmanifest, phar_update_cached_entry, (void *)phar);
2035 	phar->manifest = newmanifest;
2036 	zend_hash_init(&phar->mounted_dirs, sizeof(char *),
2037 		zend_get_hash_value, NULL, 0);
2038 	zend_hash_init(&phar->virtual_dirs, sizeof(char *),
2039 		zend_get_hash_value, NULL, 0);
2040 	zend_hash_copy(&phar->virtual_dirs, &(*pphar)->virtual_dirs, NULL);
2041 	*pphar = phar;
2042 
2043 	/* now, scan the list of persistent Phar objects referencing this phar and update the pointers */
2044 	ZEND_HASH_FOREACH_PTR(&PHAR_G(phar_persist_map), objphar) {
2045 		if (objphar->archive->fname_len == phar->fname_len && !memcmp(objphar->archive->fname, phar->fname, phar->fname_len)) {
2046 			objphar->archive = phar;
2047 		}
2048 	} ZEND_HASH_FOREACH_END();
2049 }
2050 /* }}} */
2051 
phar_copy_on_write(phar_archive_data ** pphar)2052 int phar_copy_on_write(phar_archive_data **pphar) /* {{{ */
2053 {
2054 	zval zv, *pzv;
2055 	phar_archive_data *newpphar;
2056 
2057 	ZVAL_PTR(&zv, *pphar);
2058 	if (NULL == (pzv = zend_hash_str_add(&(PHAR_G(phar_fname_map)), (*pphar)->fname, (*pphar)->fname_len, &zv))) {
2059 		return FAILURE;
2060 	}
2061 
2062 	phar_copy_cached_phar((phar_archive_data **)&Z_PTR_P(pzv));
2063 	newpphar = Z_PTR_P(pzv);
2064 	/* invalidate phar cache */
2065 	PHAR_G(last_phar) = NULL;
2066 	PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
2067 
2068 	if (newpphar->alias_len && NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), newpphar->alias, newpphar->alias_len, newpphar)) {
2069 		zend_hash_str_del(&(PHAR_G(phar_fname_map)), (*pphar)->fname, (*pphar)->fname_len);
2070 		return FAILURE;
2071 	}
2072 
2073 	*pphar = newpphar;
2074 	return SUCCESS;
2075 }
2076 /* }}} */
2077