xref: /PHP-5.6/ext/phar/util.c (revision 223266e4)
1 /*
2   +----------------------------------------------------------------------+
3   | phar php single-file executable PHP extension                        |
4   | utility functions                                                    |
5   +----------------------------------------------------------------------+
6   | Copyright (c) 2005-2016 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,const 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, const 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,const 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, const 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 != php_stream_copy_to_stream_ex(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 != php_stream_copy_to_stream_ex(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 != php_stream_copy_to_stream_ex(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 		char *str_key;
1308 		ulong unused;
1309 		uint keylen;
1310 
1311 		zend_hash_internal_pointer_reset(&phar->mounted_dirs);
1312 		while (FAILURE != zend_hash_has_more_elements(&phar->mounted_dirs)) {
1313 			if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &str_key, &keylen, &unused, 0, NULL)) {
1314 				break;
1315 			}
1316 
1317 			if ((int)keylen >= path_len || strncmp(str_key, path, keylen)) {
1318 				continue;
1319 			} else {
1320 				char *test;
1321 				int test_len;
1322 				php_stream_statbuf ssb;
1323 
1324 				if (SUCCESS != zend_hash_find(&phar->manifest, str_key, keylen, (void **) &entry)) {
1325 					if (error) {
1326 						spprintf(error, 4096, "phar internal error: mounted path \"%s\" could not be retrieved from manifest", str_key);
1327 					}
1328 					return NULL;
1329 				}
1330 
1331 				if (!entry->tmp || !entry->is_mounted) {
1332 					if (error) {
1333 						spprintf(error, 4096, "phar internal error: mounted path \"%s\" is not properly initialized as a mounted path", str_key);
1334 					}
1335 					return NULL;
1336 				}
1337 
1338 				test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, path + keylen);
1339 
1340 				if (SUCCESS != php_stream_stat_path(test, &ssb)) {
1341 					efree(test);
1342 					return NULL;
1343 				}
1344 
1345 				if (ssb.sb.st_mode & S_IFDIR && !dir) {
1346 					efree(test);
1347 					if (error) {
1348 						spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
1349 					}
1350 					return NULL;
1351 				}
1352 
1353 				if ((ssb.sb.st_mode & S_IFDIR) == 0 && dir) {
1354 					efree(test);
1355 					/* user requested a directory, we must return one */
1356 					if (error) {
1357 						spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
1358 					}
1359 					return NULL;
1360 				}
1361 
1362 				/* mount the file just in time */
1363 				if (SUCCESS != phar_mount_entry(phar, test, test_len, path, path_len TSRMLS_CC)) {
1364 					efree(test);
1365 					if (error) {
1366 						spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be mounted", path, test);
1367 					}
1368 					return NULL;
1369 				}
1370 
1371 				efree(test);
1372 
1373 				if (SUCCESS != zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) {
1374 					if (error) {
1375 						spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be retrieved after being mounted", path, test);
1376 					}
1377 					return NULL;
1378 				}
1379 				return entry;
1380 			}
1381 		}
1382 	}
1383 
1384 	return NULL;
1385 }
1386 /* }}} */
1387 
1388 static const char hexChars[] = "0123456789ABCDEF";
1389 
phar_hex_str(const char * digest,size_t digest_len,char ** signature TSRMLS_DC)1390 static int phar_hex_str(const char *digest, size_t digest_len, char **signature TSRMLS_DC) /* {{{ */
1391 {
1392 	int pos = -1;
1393 	size_t len = 0;
1394 
1395 	*signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
1396 
1397 	for (; len < digest_len; ++len) {
1398 		(*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] >> 4];
1399 		(*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] & 0x0F];
1400 	}
1401 	(*signature)[++pos] = '\0';
1402 	return pos;
1403 }
1404 /* }}} */
1405 
1406 #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)1407 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) /* {{{ */
1408 {
1409 	zend_fcall_info fci;
1410 	zend_fcall_info_cache fcc;
1411 	zval *zdata, *zsig, *zkey, *retval_ptr, **zp[3], *openssl;
1412 
1413 	MAKE_STD_ZVAL(zdata);
1414 	MAKE_STD_ZVAL(openssl);
1415 	ZVAL_STRINGL(openssl, is_sign ? "openssl_sign" : "openssl_verify", is_sign ? sizeof("openssl_sign")-1 : sizeof("openssl_verify")-1, 1);
1416 	MAKE_STD_ZVAL(zsig);
1417 	ZVAL_STRINGL(zsig, *signature, *signature_len, 1);
1418 	MAKE_STD_ZVAL(zkey);
1419 	ZVAL_STRINGL(zkey, key, key_len, 1);
1420 	zp[0] = &zdata;
1421 	zp[1] = &zsig;
1422 	zp[2] = &zkey;
1423 
1424 	php_stream_rewind(fp);
1425 	Z_TYPE_P(zdata) = IS_STRING;
1426 	Z_STRLEN_P(zdata) = end;
1427 
1428 	if (end != (off_t) php_stream_copy_to_mem(fp, &(Z_STRVAL_P(zdata)), (size_t) end, 0)) {
1429 		zval_dtor(zdata);
1430 		zval_dtor(zsig);
1431 		zval_dtor(zkey);
1432 		zval_dtor(openssl);
1433 		efree(openssl);
1434 		efree(zdata);
1435 		efree(zkey);
1436 		efree(zsig);
1437 		return FAILURE;
1438 	}
1439 
1440 	if (FAILURE == zend_fcall_info_init(openssl, 0, &fci, &fcc, NULL, NULL TSRMLS_CC)) {
1441 		zval_dtor(zdata);
1442 		zval_dtor(zsig);
1443 		zval_dtor(zkey);
1444 		zval_dtor(openssl);
1445 		efree(openssl);
1446 		efree(zdata);
1447 		efree(zkey);
1448 		efree(zsig);
1449 		return FAILURE;
1450 	}
1451 
1452 	fci.param_count = 3;
1453 	fci.params = zp;
1454 	Z_ADDREF_P(zdata);
1455 	if (is_sign) {
1456 		Z_SET_ISREF_P(zsig);
1457 	} else {
1458 		Z_ADDREF_P(zsig);
1459 	}
1460 	Z_ADDREF_P(zkey);
1461 
1462 	fci.retval_ptr_ptr = &retval_ptr;
1463 
1464 	if (FAILURE == zend_call_function(&fci, &fcc TSRMLS_CC)) {
1465 		zval_dtor(zdata);
1466 		zval_dtor(zsig);
1467 		zval_dtor(zkey);
1468 		zval_dtor(openssl);
1469 		efree(openssl);
1470 		efree(zdata);
1471 		efree(zkey);
1472 		efree(zsig);
1473 		return FAILURE;
1474 	}
1475 
1476 	zval_dtor(openssl);
1477 	efree(openssl);
1478 	Z_DELREF_P(zdata);
1479 
1480 	if (is_sign) {
1481 		Z_UNSET_ISREF_P(zsig);
1482 	} else {
1483 		Z_DELREF_P(zsig);
1484 	}
1485 	Z_DELREF_P(zkey);
1486 
1487 	zval_dtor(zdata);
1488 	efree(zdata);
1489 	zval_dtor(zkey);
1490 	efree(zkey);
1491 
1492 	switch (Z_TYPE_P(retval_ptr)) {
1493 		default:
1494 		case IS_LONG:
1495 			zval_dtor(zsig);
1496 			efree(zsig);
1497 			if (1 == Z_LVAL_P(retval_ptr)) {
1498 				efree(retval_ptr);
1499 				return SUCCESS;
1500 			}
1501 			efree(retval_ptr);
1502 			return FAILURE;
1503 		case IS_BOOL:
1504 			efree(retval_ptr);
1505 			if (Z_BVAL_P(retval_ptr)) {
1506 				*signature = estrndup(Z_STRVAL_P(zsig), Z_STRLEN_P(zsig));
1507 				*signature_len = Z_STRLEN_P(zsig);
1508 				zval_dtor(zsig);
1509 				efree(zsig);
1510 				return SUCCESS;
1511 			}
1512 			zval_dtor(zsig);
1513 			efree(zsig);
1514 			return FAILURE;
1515 	}
1516 }
1517 /* }}} */
1518 #endif /* #ifndef PHAR_HAVE_OPENSSL */
1519 
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)1520 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) /* {{{ */
1521 {
1522 	int read_size, len;
1523 	off_t read_len;
1524 	unsigned char buf[1024];
1525 
1526 	php_stream_rewind(fp);
1527 
1528 	switch (sig_type) {
1529 		case PHAR_SIG_OPENSSL: {
1530 #ifdef PHAR_HAVE_OPENSSL
1531 			BIO *in;
1532 			EVP_PKEY *key;
1533 			EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
1534 			EVP_MD_CTX md_ctx;
1535 #else
1536 			int tempsig;
1537 #endif
1538 			php_uint32 pubkey_len;
1539 			char *pubkey = NULL, *pfile;
1540 			php_stream *pfp;
1541 #ifndef PHAR_HAVE_OPENSSL
1542 			if (!zend_hash_exists(&module_registry, "openssl", sizeof("openssl"))) {
1543 				if (error) {
1544 					spprintf(error, 0, "openssl not loaded");
1545 				}
1546 				return FAILURE;
1547 			}
1548 #endif
1549 			/* use __FILE__ . '.pubkey' for public key file */
1550 			spprintf(&pfile, 0, "%s.pubkey", fname);
1551 			pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
1552 			efree(pfile);
1553 
1554 #if PHP_MAJOR_VERSION > 5
1555 			if (!pfp || !(pubkey_len = php_stream_copy_to_mem(pfp, (void **) &pubkey, PHP_STREAM_COPY_ALL, 0)) || !pubkey) {
1556 #else
1557 			if (!pfp || !(pubkey_len = php_stream_copy_to_mem(pfp, &pubkey, PHP_STREAM_COPY_ALL, 0)) || !pubkey) {
1558 #endif
1559 				if (pfp) {
1560 					php_stream_close(pfp);
1561 				}
1562 				if (error) {
1563 					spprintf(error, 0, "openssl public key could not be read");
1564 				}
1565 				return FAILURE;
1566 			}
1567 
1568 			php_stream_close(pfp);
1569 #ifndef PHAR_HAVE_OPENSSL
1570 			tempsig = sig_len;
1571 
1572 			if (FAILURE == phar_call_openssl_signverify(0, fp, end_of_phar, pubkey, pubkey_len, &sig, &tempsig TSRMLS_CC)) {
1573 				if (pubkey) {
1574 					efree(pubkey);
1575 				}
1576 
1577 				if (error) {
1578 					spprintf(error, 0, "openssl signature could not be verified");
1579 				}
1580 
1581 				return FAILURE;
1582 			}
1583 
1584 			if (pubkey) {
1585 				efree(pubkey);
1586 			}
1587 
1588 			sig_len = tempsig;
1589 #else
1590 			in = BIO_new_mem_buf(pubkey, pubkey_len);
1591 
1592 			if (NULL == in) {
1593 				efree(pubkey);
1594 				if (error) {
1595 					spprintf(error, 0, "openssl signature could not be processed");
1596 				}
1597 				return FAILURE;
1598 			}
1599 
1600 			key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
1601 			BIO_free(in);
1602 			efree(pubkey);
1603 
1604 			if (NULL == key) {
1605 				if (error) {
1606 					spprintf(error, 0, "openssl signature could not be processed");
1607 				}
1608 				return FAILURE;
1609 			}
1610 
1611 			EVP_VerifyInit(&md_ctx, mdtype);
1612 			read_len = end_of_phar;
1613 
1614 			if (read_len > sizeof(buf)) {
1615 				read_size = sizeof(buf);
1616 			} else {
1617 				read_size = (int)read_len;
1618 			}
1619 
1620 			php_stream_seek(fp, 0, SEEK_SET);
1621 
1622 			while (read_size && (len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1623 				EVP_VerifyUpdate (&md_ctx, buf, len);
1624 				read_len -= (off_t)len;
1625 
1626 				if (read_len < read_size) {
1627 					read_size = (int)read_len;
1628 				}
1629 			}
1630 
1631 			if (EVP_VerifyFinal(&md_ctx, (unsigned char *)sig, sig_len, key) != 1) {
1632 				/* 1: signature verified, 0: signature does not match, -1: failed signature operation */
1633 				EVP_MD_CTX_cleanup(&md_ctx);
1634 
1635 				if (error) {
1636 					spprintf(error, 0, "broken openssl signature");
1637 				}
1638 
1639 				return FAILURE;
1640 			}
1641 
1642 			EVP_MD_CTX_cleanup(&md_ctx);
1643 #endif
1644 
1645 			*signature_len = phar_hex_str((const char*)sig, sig_len, signature TSRMLS_CC);
1646 		}
1647 		break;
1648 #ifdef PHAR_HASH_OK
1649 		case PHAR_SIG_SHA512: {
1650 			unsigned char digest[64];
1651 			PHP_SHA512_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_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 			if (sig_len < sizeof(digest)) {
1694 				if (error) {
1695 					spprintf(error, 0, "broken signature");
1696 				}
1697 				return FAILURE;
1698 			}
1699 
1700 			PHP_SHA256Init(&context);
1701 			read_len = end_of_phar;
1702 
1703 			if (read_len > sizeof(buf)) {
1704 				read_size = sizeof(buf);
1705 			} else {
1706 				read_size = (int)read_len;
1707 			}
1708 
1709 			while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1710 				PHP_SHA256Update(&context, buf, len);
1711 				read_len -= (off_t)len;
1712 				if (read_len < read_size) {
1713 					read_size = (int)read_len;
1714 				}
1715 			}
1716 
1717 			PHP_SHA256Final(digest, &context);
1718 
1719 			if (memcmp(digest, sig, sizeof(digest))) {
1720 				if (error) {
1721 					spprintf(error, 0, "broken signature");
1722 				}
1723 				return FAILURE;
1724 			}
1725 
1726 			*signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature TSRMLS_CC);
1727 			break;
1728 		}
1729 #else
1730 		case PHAR_SIG_SHA512:
1731 		case PHAR_SIG_SHA256:
1732 			if (error) {
1733 				spprintf(error, 0, "unsupported signature");
1734 			}
1735 			return FAILURE;
1736 #endif
1737 		case PHAR_SIG_SHA1: {
1738 			unsigned char digest[20];
1739 			PHP_SHA1_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_SHA1Init(&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_SHA1Update(&context, buf, len);
1759 				read_len -= (off_t)len;
1760 				if (read_len < read_size) {
1761 					read_size = (int)read_len;
1762 				}
1763 			}
1764 
1765 			PHP_SHA1Final(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 TSRMLS_CC);
1775 			break;
1776 		}
1777 		case PHAR_SIG_MD5: {
1778 			unsigned char digest[16];
1779 			PHP_MD5_CTX   context;
1780 
1781 			if (sig_len < sizeof(digest)) {
1782 				if (error) {
1783 					spprintf(error, 0, "broken signature");
1784 				}
1785 				return FAILURE;
1786 			}
1787 
1788 			PHP_MD5Init(&context);
1789 			read_len = end_of_phar;
1790 
1791 			if (read_len > sizeof(buf)) {
1792 				read_size = sizeof(buf);
1793 			} else {
1794 				read_size = (int)read_len;
1795 			}
1796 
1797 			while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
1798 				PHP_MD5Update(&context, buf, len);
1799 				read_len -= (off_t)len;
1800 				if (read_len < read_size) {
1801 					read_size = (int)read_len;
1802 				}
1803 			}
1804 
1805 			PHP_MD5Final(digest, &context);
1806 
1807 			if (memcmp(digest, sig, sizeof(digest))) {
1808 				if (error) {
1809 					spprintf(error, 0, "broken signature");
1810 				}
1811 				return FAILURE;
1812 			}
1813 
1814 			*signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature TSRMLS_CC);
1815 			break;
1816 		}
1817 		default:
1818 			if (error) {
1819 				spprintf(error, 0, "broken or unsupported signature");
1820 			}
1821 			return FAILURE;
1822 	}
1823 	return SUCCESS;
1824 }
1825 /* }}} */
1826 
1827 int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, int *signature_length, char **error TSRMLS_DC) /* {{{ */
1828 {
1829 	unsigned char buf[1024];
1830 	int sig_len;
1831 
1832 	php_stream_rewind(fp);
1833 
1834 	if (phar->signature) {
1835 		efree(phar->signature);
1836 		phar->signature = NULL;
1837 	}
1838 
1839 	switch(phar->sig_flags) {
1840 #ifdef PHAR_HASH_OK
1841 		case PHAR_SIG_SHA512: {
1842 			unsigned char digest[64];
1843 			PHP_SHA512_CTX context;
1844 
1845 			PHP_SHA512Init(&context);
1846 
1847 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1848 				PHP_SHA512Update(&context, buf, sig_len);
1849 			}
1850 
1851 			PHP_SHA512Final(digest, &context);
1852 			*signature = estrndup((char *) digest, 64);
1853 			*signature_length = 64;
1854 			break;
1855 		}
1856 		case PHAR_SIG_SHA256: {
1857 			unsigned char digest[32];
1858 			PHP_SHA256_CTX  context;
1859 
1860 			PHP_SHA256Init(&context);
1861 
1862 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1863 				PHP_SHA256Update(&context, buf, sig_len);
1864 			}
1865 
1866 			PHP_SHA256Final(digest, &context);
1867 			*signature = estrndup((char *) digest, 32);
1868 			*signature_length = 32;
1869 			break;
1870 		}
1871 #else
1872 		case PHAR_SIG_SHA512:
1873 		case PHAR_SIG_SHA256:
1874 			if (error) {
1875 				spprintf(error, 0, "unable to write to phar \"%s\" with requested hash type", phar->fname);
1876 			}
1877 
1878 			return FAILURE;
1879 #endif
1880 		case PHAR_SIG_OPENSSL: {
1881 			int siglen;
1882 			unsigned char *sigbuf;
1883 #ifdef PHAR_HAVE_OPENSSL
1884 			BIO *in;
1885 			EVP_PKEY *key;
1886 			EVP_MD_CTX *md_ctx;
1887 
1888 			in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len));
1889 
1890 			if (in == NULL) {
1891 				if (error) {
1892 					spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname);
1893 				}
1894 				return FAILURE;
1895 			}
1896 
1897 			key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
1898 			BIO_free(in);
1899 
1900 			if (!key) {
1901 				if (error) {
1902 					spprintf(error, 0, "unable to process private key");
1903 				}
1904 				return FAILURE;
1905 			}
1906 
1907 			md_ctx = EVP_MD_CTX_create();
1908 
1909 			siglen = EVP_PKEY_size(key);
1910 			sigbuf = emalloc(siglen + 1);
1911 
1912 			if (!EVP_SignInit(md_ctx, EVP_sha1())) {
1913 				efree(sigbuf);
1914 				if (error) {
1915 					spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname);
1916 				}
1917 				return FAILURE;
1918 			}
1919 
1920 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1921 				if (!EVP_SignUpdate(md_ctx, buf, sig_len)) {
1922 					efree(sigbuf);
1923 					if (error) {
1924 						spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", phar->fname);
1925 					}
1926 					return FAILURE;
1927 				}
1928 			}
1929 
1930 			if (!EVP_SignFinal (md_ctx, sigbuf,(unsigned int *)&siglen, key)) {
1931 				efree(sigbuf);
1932 				if (error) {
1933 					spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
1934 				}
1935 				return FAILURE;
1936 			}
1937 
1938 			sigbuf[siglen] = '\0';
1939 			EVP_MD_CTX_destroy(md_ctx);
1940 #else
1941 			sigbuf = NULL;
1942 			siglen = 0;
1943 			php_stream_seek(fp, 0, SEEK_END);
1944 
1945 			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)) {
1946 				if (error) {
1947 					spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
1948 				}
1949 				return FAILURE;
1950 			}
1951 #endif
1952 			*signature = (char *) sigbuf;
1953 			*signature_length = siglen;
1954 		}
1955 		break;
1956 		default:
1957 			phar->sig_flags = PHAR_SIG_SHA1;
1958 		case PHAR_SIG_SHA1: {
1959 			unsigned char digest[20];
1960 			PHP_SHA1_CTX  context;
1961 
1962 			PHP_SHA1Init(&context);
1963 
1964 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1965 				PHP_SHA1Update(&context, buf, sig_len);
1966 			}
1967 
1968 			PHP_SHA1Final(digest, &context);
1969 			*signature = estrndup((char *) digest, 20);
1970 			*signature_length = 20;
1971 			break;
1972 		}
1973 		case PHAR_SIG_MD5: {
1974 			unsigned char digest[16];
1975 			PHP_MD5_CTX   context;
1976 
1977 			PHP_MD5Init(&context);
1978 
1979 			while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
1980 				PHP_MD5Update(&context, buf, sig_len);
1981 			}
1982 
1983 			PHP_MD5Final(digest, &context);
1984 			*signature = estrndup((char *) digest, 16);
1985 			*signature_length = 16;
1986 			break;
1987 		}
1988 	}
1989 
1990 	phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature TSRMLS_CC);
1991 	return SUCCESS;
1992 }
1993 /* }}} */
1994 
1995 void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC) /* {{{ */
1996 {
1997 	const char *s;
1998 
1999 	while ((s = zend_memrchr(filename, '/', filename_len))) {
2000 		filename_len = s - filename;
2001 		if (!filename_len || FAILURE == zend_hash_add_empty_element(&phar->virtual_dirs, filename, filename_len)) {
2002 			break;
2003 		}
2004 	}
2005 }
2006 /* }}} */
2007 
2008 static int phar_update_cached_entry(void *data, void *argument) /* {{{ */
2009 {
2010 	phar_entry_info *entry = (phar_entry_info *)data;
2011 	TSRMLS_FETCH();
2012 
2013 	entry->phar = (phar_archive_data *)argument;
2014 
2015 	if (entry->link) {
2016 		entry->link = estrdup(entry->link);
2017 	}
2018 
2019 	if (entry->tmp) {
2020 		entry->tmp = estrdup(entry->tmp);
2021 	}
2022 
2023 	entry->metadata_str.c = 0;
2024 	entry->filename = estrndup(entry->filename, entry->filename_len);
2025 	entry->is_persistent = 0;
2026 
2027 	if (entry->metadata) {
2028 		if (entry->metadata_len) {
2029 			char *buf = estrndup((char *) entry->metadata, entry->metadata_len);
2030 			/* assume success, we would have failed before */
2031 			phar_parse_metadata((char **) &buf, &entry->metadata, entry->metadata_len TSRMLS_CC);
2032 			efree(buf);
2033 		} else {
2034 			zval *t;
2035 
2036 			t = entry->metadata;
2037 			ALLOC_ZVAL(entry->metadata);
2038 			*entry->metadata = *t;
2039 			zval_copy_ctor(entry->metadata);
2040 			Z_SET_REFCOUNT_P(entry->metadata, 1);
2041 			entry->metadata_str.c = NULL;
2042 			entry->metadata_str.len = 0;
2043 		}
2044 	}
2045 	return ZEND_HASH_APPLY_KEEP;
2046 }
2047 /* }}} */
2048 
2049 static void phar_copy_cached_phar(phar_archive_data **pphar TSRMLS_DC) /* {{{ */
2050 {
2051 	phar_archive_data *phar;
2052 	HashTable newmanifest;
2053 	char *fname;
2054 	phar_archive_object **objphar;
2055 
2056 	phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
2057 	*phar = **pphar;
2058 	phar->is_persistent = 0;
2059 	fname = phar->fname;
2060 	phar->fname = estrndup(phar->fname, phar->fname_len);
2061 	phar->ext = phar->fname + (phar->ext - fname);
2062 
2063 	if (phar->alias) {
2064 		phar->alias = estrndup(phar->alias, phar->alias_len);
2065 	}
2066 
2067 	if (phar->signature) {
2068 		phar->signature = estrdup(phar->signature);
2069 	}
2070 
2071 	if (phar->metadata) {
2072 		/* assume success, we would have failed before */
2073 		if (phar->metadata_len) {
2074 			char *buf = estrndup((char *) phar->metadata, phar->metadata_len);
2075 			phar_parse_metadata(&buf, &phar->metadata, phar->metadata_len TSRMLS_CC);
2076 			efree(buf);
2077 		} else {
2078 			zval *t;
2079 
2080 			t = phar->metadata;
2081 			ALLOC_ZVAL(phar->metadata);
2082 			*phar->metadata = *t;
2083 			zval_copy_ctor(phar->metadata);
2084 			Z_SET_REFCOUNT_P(phar->metadata, 1);
2085 		}
2086 	}
2087 
2088 	zend_hash_init(&newmanifest, sizeof(phar_entry_info),
2089 		zend_get_hash_value, destroy_phar_manifest_entry, 0);
2090 	zend_hash_copy(&newmanifest, &(*pphar)->manifest, NULL, NULL, sizeof(phar_entry_info));
2091 	zend_hash_apply_with_argument(&newmanifest, (apply_func_arg_t) phar_update_cached_entry, (void *)phar TSRMLS_CC);
2092 	phar->manifest = newmanifest;
2093 	zend_hash_init(&phar->mounted_dirs, sizeof(char *),
2094 		zend_get_hash_value, NULL, 0);
2095 	zend_hash_init(&phar->virtual_dirs, sizeof(char *),
2096 		zend_get_hash_value, NULL, 0);
2097 	zend_hash_copy(&phar->virtual_dirs, &(*pphar)->virtual_dirs, NULL, NULL, sizeof(void *));
2098 	*pphar = phar;
2099 
2100 	/* now, scan the list of persistent Phar objects referencing this phar and update the pointers */
2101 	for (zend_hash_internal_pointer_reset(&PHAR_GLOBALS->phar_persist_map);
2102 	SUCCESS == zend_hash_get_current_data(&PHAR_GLOBALS->phar_persist_map, (void **) &objphar);
2103 	zend_hash_move_forward(&PHAR_GLOBALS->phar_persist_map)) {
2104 		if (objphar[0]->arc.archive->fname_len == phar->fname_len && !memcmp(objphar[0]->arc.archive->fname, phar->fname, phar->fname_len)) {
2105 			objphar[0]->arc.archive = phar;
2106 		}
2107 	}
2108 }
2109 /* }}} */
2110 
2111 int phar_copy_on_write(phar_archive_data **pphar TSRMLS_DC) /* {{{ */
2112 {
2113 	phar_archive_data **newpphar, *newphar = NULL;
2114 
2115 	if (SUCCESS != zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), (*pphar)->fname, (*pphar)->fname_len, (void *)&newphar, sizeof(phar_archive_data *), (void **)&newpphar)) {
2116 		return FAILURE;
2117 	}
2118 
2119 	*newpphar = *pphar;
2120 	phar_copy_cached_phar(newpphar TSRMLS_CC);
2121 	/* invalidate phar cache */
2122 	PHAR_G(last_phar) = NULL;
2123 	PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
2124 
2125 	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)) {
2126 		zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), (*pphar)->fname, (*pphar)->fname_len);
2127 		return FAILURE;
2128 	}
2129 
2130 	*pphar = *newpphar;
2131 	return SUCCESS;
2132 }
2133 /* }}} */
2134 
2135 /*
2136  * Local variables:
2137  * tab-width: 4
2138  * c-basic-offset: 4
2139  * End:
2140  * vim600: noet sw=4 ts=4 fdm=marker
2141  * vim<600: noet sw=4 ts=4
2142  */
2143