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