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