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