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