示例#1
0
/**
 *  Compile the file
 *  @return bool
 */
bool File::compile()
{
    // never works if the path is invalid
    if (!_path) return false;
    
    // is the file already compiled?
    if (_opcodes) return _opcodes->valid();
    
    // we are going to open the file
    zend_file_handle fileHandle;

    // we need the tsrm_ls variable (@todo would it be better if this was a member?)
    TSRMLS_FETCH();

    // open the file
    if (zend_stream_open(_path, &fileHandle TSRMLS_CC) == FAILURE) return false;

    // make sure the path name is stored in the handle
    if (!fileHandle.opened_path) fileHandle.opened_path = estrdup(_path);
    
    // we need temporary compiler options
    CompilerOptions options(ZEND_COMPILE_DEFAULT TSRMLS_CC);
    
    // create the opcodes
    _opcodes = new Opcodes(zend_compile_file(&fileHandle, ZEND_INCLUDE TSRMLS_CC) TSRMLS_CC);

    // close the file handle
    zend_destroy_file_handle(&fileHandle TSRMLS_CC);
    
    // done
    return _opcodes->valid();
}
示例#2
0
static size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t len) /* {{{ */
{
	if (!zend_stream_is_mmap(file_handle) && file_handle->handle.stream.isatty) {
		int c = '*';
		size_t n;

#ifdef NETWARE
		/*
			c != 4 check is there as fread of a character in NetWare LibC gives 4 upon ^D character.
			Ascii value 4 is actually EOT character which is not defined anywhere in the LibC
			or else we can use instead of hardcoded 4.
		*/
		for (n = 0; n < len && (c = zend_stream_getc(file_handle)) != EOF && c != 4 && c != '\n'; ++n) {
#else
		for (n = 0; n < len && (c = zend_stream_getc(file_handle)) != EOF && c != '\n'; ++n)  {
#endif
			buf[n] = (char)c;
		}
		if (c == '\n') {
			buf[n++] = (char)c;
		}

		return n;
	}
	return file_handle->handle.stream.reader(file_handle->handle.stream.handle, buf, len);
} /* }}} */

ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len) /* {{{ */
{
	size_t size;
	zend_stream_type old_type;

	if (file_handle->type == ZEND_HANDLE_FILENAME) {
		if (zend_stream_open(file_handle->filename, file_handle) == FAILURE) {
			return FAILURE;
		}
	}

	switch (file_handle->type) {
		case ZEND_HANDLE_FD:
			file_handle->type = ZEND_HANDLE_FP;
			file_handle->handle.fp = fdopen(file_handle->handle.fd, "rb");
			/* no break; */
		case ZEND_HANDLE_FP:
			if (!file_handle->handle.fp) {
				return FAILURE;
			}
			memset(&file_handle->handle.stream.mmap, 0, sizeof(zend_mmap));
			file_handle->handle.stream.isatty     = isatty(fileno((FILE *)file_handle->handle.stream.handle)) ? 1 : 0;
			file_handle->handle.stream.reader     = (zend_stream_reader_t)zend_stream_stdio_reader;
			file_handle->handle.stream.closer     = (zend_stream_closer_t)zend_stream_stdio_closer;
			file_handle->handle.stream.fsizer     = (zend_stream_fsizer_t)zend_stream_stdio_fsizer;
			memset(&file_handle->handle.stream.mmap, 0, sizeof(file_handle->handle.stream.mmap));
			/* no break; */
		case ZEND_HANDLE_STREAM:
			/* nothing to do */
			break;

		case ZEND_HANDLE_MAPPED:
			file_handle->handle.stream.mmap.pos = 0;
			*buf = file_handle->handle.stream.mmap.buf;
			*len = file_handle->handle.stream.mmap.len;
			return SUCCESS;

		default:
			return FAILURE;
	}

	size = zend_stream_fsize(file_handle);
	if (size == (size_t)-1) {
		return FAILURE;
	}

	old_type = file_handle->type;
	file_handle->type = ZEND_HANDLE_STREAM;  /* we might still be _FP but we need fsize() work */

	if (old_type == ZEND_HANDLE_FP && !file_handle->handle.stream.isatty && size) {
#if HAVE_MMAP
		size_t page_size = REAL_PAGE_SIZE;

		if (file_handle->handle.fp &&
		    size != 0 &&
		    ((size - 1) % page_size) <= page_size - ZEND_MMAP_AHEAD) {
			/*  *buf[size] is zeroed automatically by the kernel */
			*buf = mmap(0, size + ZEND_MMAP_AHEAD, PROT_READ, MAP_PRIVATE, fileno(file_handle->handle.fp), 0);
			if (*buf != MAP_FAILED) {
				zend_long offset = ftell(file_handle->handle.fp);
				file_handle->handle.stream.mmap.map = *buf;

				if (offset != -1) {
					*buf += offset;
					size -= offset;
				}
				file_handle->handle.stream.mmap.buf = *buf;
				file_handle->handle.stream.mmap.len = size;

				goto return_mapped;
			}
		}
#endif
		file_handle->handle.stream.mmap.map = 0;
		file_handle->handle.stream.mmap.buf = *buf = safe_emalloc(1, size, ZEND_MMAP_AHEAD);
		file_handle->handle.stream.mmap.len = zend_stream_read(file_handle, *buf, size);
	} else {
		size_t read, remain = 4*1024;
		*buf = emalloc(remain);
		size = 0;

		while ((read = zend_stream_read(file_handle, *buf + size, remain)) > 0) {
			size   += read;
			remain -= read;

			if (remain == 0) {
				*buf   = safe_erealloc(*buf, size, 2, 0);
				remain = size;
			}
		}
		file_handle->handle.stream.mmap.map = 0;
		file_handle->handle.stream.mmap.len = size;
		if (size && remain < ZEND_MMAP_AHEAD) {
			*buf = safe_erealloc(*buf, size, 1, ZEND_MMAP_AHEAD);
		}
		file_handle->handle.stream.mmap.buf = *buf;
	}

	if (file_handle->handle.stream.mmap.len == 0) {
		*buf = erealloc(*buf, ZEND_MMAP_AHEAD);
		file_handle->handle.stream.mmap.buf = *buf;
	}

	if (ZEND_MMAP_AHEAD) {
		memset(file_handle->handle.stream.mmap.buf + file_handle->handle.stream.mmap.len, 0, ZEND_MMAP_AHEAD);
	}
#if HAVE_MMAP
return_mapped:
#endif
	file_handle->type = ZEND_HANDLE_MAPPED;
	file_handle->handle.stream.mmap.pos        = 0;
	file_handle->handle.stream.mmap.old_handle = file_handle->handle.stream.handle;
	file_handle->handle.stream.mmap.old_closer = file_handle->handle.stream.closer;
	file_handle->handle.stream.handle          = &file_handle->handle.stream;
	file_handle->handle.stream.closer          = (zend_stream_closer_t)zend_stream_mmap_closer;

	*buf = file_handle->handle.stream.mmap.buf;
	*len = file_handle->handle.stream.mmap.len;

	return SUCCESS;
} /* }}} */
示例#3
0
/* {{{ php_fopen_primary_script
 */
PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle)
{
	char *path_info;
	char *filename = NULL;
	zend_string *resolved_path = NULL;
	int length;
	zend_bool orig_display_errors;

	path_info = SG(request_info).request_uri;
#if HAVE_PWD_H
	if (PG(user_dir) && *PG(user_dir) && path_info && '/' == path_info[0] && '~' == path_info[1]) {
		char *s = strchr(path_info + 2, '/');

		if (s) {			/* if there is no path name after the file, do not bother */
			char user[32];			/* to try open the directory */
			struct passwd *pw;
#if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
			struct passwd pwstruc;
			long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
			char *pwbuf;

			if (pwbuflen < 1) {
				return FAILURE;
			}

			pwbuf = emalloc(pwbuflen);
#endif
			length = s - (path_info + 2);
			if (length > (int)sizeof(user) - 1) {
				length = sizeof(user) - 1;
			}
			memcpy(user, path_info + 2, length);
			user[length] = '\0';
#if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
			if (getpwnam_r(user, &pwstruc, pwbuf, pwbuflen, &pw)) {
				efree(pwbuf);
				return FAILURE;
			}
#else
			pw = getpwnam(user);
#endif
			if (pw && pw->pw_dir) {
				spprintf(&filename, 0, "%s%c%s%c%s", pw->pw_dir, PHP_DIR_SEPARATOR, PG(user_dir), PHP_DIR_SEPARATOR, s + 1); /* Safe */
			} else {
				filename = SG(request_info).path_translated;
			}
#if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
			efree(pwbuf);
#endif
		}
	} else
#endif
	if (PG(doc_root) && path_info && (length = (int)strlen(PG(doc_root))) &&
		IS_ABSOLUTE_PATH(PG(doc_root), length)) {
		int path_len = (int)strlen(path_info);
		filename = emalloc(length + path_len + 2);
		if (filename) {
			memcpy(filename, PG(doc_root), length);
			if (!IS_SLASH(filename[length - 1])) {	/* length is never 0 */
				filename[length++] = PHP_DIR_SEPARATOR;
			}
			if (IS_SLASH(path_info[0])) {
				length--;
			}
			strncpy(filename + length, path_info, path_len + 1);
		}
	} else {
		filename = SG(request_info).path_translated;
	}


	if (filename) {
		resolved_path = zend_resolve_path(filename, (int)strlen(filename));
	}

	if (!resolved_path) {
		if (SG(request_info).path_translated != filename) {
			if (filename) {
				efree(filename);
			}
		}
		/* we have to free SG(request_info).path_translated here because
		 * php_destroy_request_info assumes that it will get
		 * freed when the include_names hash is emptied, but
		 * we're not adding it in this case */
		if (SG(request_info).path_translated) {
			efree(SG(request_info).path_translated);
			SG(request_info).path_translated = NULL;
		}
		return FAILURE;
	}
	zend_string_release(resolved_path);

	orig_display_errors = PG(display_errors);
	PG(display_errors) = 0;
	if (zend_stream_open(filename, file_handle) == FAILURE) {
		PG(display_errors) = orig_display_errors;
		if (SG(request_info).path_translated != filename) {
			if (filename) {
				efree(filename);
			}
		}
		if (SG(request_info).path_translated) {
			efree(SG(request_info).path_translated);
			SG(request_info).path_translated = NULL;
		}
		return FAILURE;
	}
	PG(display_errors) = orig_display_errors;

	if (SG(request_info).path_translated != filename) {
		if (SG(request_info).path_translated) {
			efree(SG(request_info).path_translated);
		}
		SG(request_info).path_translated = filename;
	}

	return SUCCESS;
}
示例#4
0
文件: log.c 项目: SinSiXX/suhosin
PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...)
{
	int s, r, i=0, fd;
	long written, towrite;
	int getcaller=0;
	char *wbuf;
	struct timeval tv;
	time_t now;
	struct tm tm;
#if defined(AF_UNIX)
	struct sockaddr_un saun;
#endif
#ifdef PHP_WIN32
	LPTSTR strs[2];
	unsigned short etype;
	DWORD evid;
#endif
	char buf[5000];
	char error[5000];
	char *ip_address;
	char *fname;
	char *alertstring;
	int lineno;
	va_list ap;
	TSRMLS_FETCH();

#if PHP_VERSION_ID >= 50500
	getcaller = (loglevel & S_GETCALLER) == S_GETCALLER;
#endif
	/* remove the S_GETCALLER flag */
	loglevel = loglevel & ~S_GETCALLER;

	SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script));

	/* dump core if wanted */
	if (SUHOSIN_G(coredump) && loglevel == S_MEMORY) {
		volatile unsigned int *x = 0;
		volatile int y = *x;
	}
	
	if (SUHOSIN_G(log_use_x_forwarded_for)) {
		ip_address = suhosin_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
		if (ip_address == NULL) {
			ip_address = "X-FORWARDED-FOR not set";
		}
	} else {
		ip_address = suhosin_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
		if (ip_address == NULL) {
			ip_address = "REMOTE_ADDR not set";
		}
	}
	
	
	va_start(ap, fmt);
	ap_php_vsnprintf(error, sizeof(error), fmt, ap);
	va_end(ap);
	while (error[i]) {
		if (error[i] < 32) error[i] = '.';
		i++;
	}
	
	if (SUHOSIN_G(simulation)) {
		alertstring = "ALERT-SIMULATION";
	} else {
		alertstring = "ALERT";
	}
	
	if (zend_is_executing(TSRMLS_C)) {
		zend_execute_data *exdata = EG(current_execute_data);
		if (exdata) {
			if (getcaller && exdata->prev_execute_data) {
				lineno = exdata->prev_execute_data->opline->lineno;
				fname = (char *)exdata->prev_execute_data->op_array->filename;									
			} else {
				lineno = exdata->opline->lineno;
				fname = (char *)exdata->op_array->filename;				
			}
		} else {
			lineno = zend_get_executed_lineno(TSRMLS_C);
			fname = (char *)zend_get_executed_filename(TSRMLS_C);
		}
		ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno);
	} else {
		fname = suhosin_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
		if (fname==NULL) {
			fname = "unknown";
		}
		ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname);
	}
			
	/* Syslog-Logging disabled? */
	if (((SUHOSIN_G(log_syslog)|S_INTERNAL) & loglevel)==0) {
		goto log_file;
	}	
	
#if defined(AF_UNIX)
	ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SUHOSIN_G(log_syslog_facility)|SUHOSIN_G(log_syslog_priority)),getpid(),buf);

	s = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (s == -1) {
		goto log_file;
	}
	
	memset(&saun, 0, sizeof(saun));
	saun.sun_family = AF_UNIX;
	strcpy(saun.sun_path, SYSLOG_PATH);
	/*saun.sun_len = sizeof(saun);*/
	
	r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
	if (r) {
		close(s);
    		s = socket(AF_UNIX, SOCK_STREAM, 0);
		if (s == -1) {
			goto log_file;
		}
	
		memset(&saun, 0, sizeof(saun));
		saun.sun_family = AF_UNIX;
		strcpy(saun.sun_path, SYSLOG_PATH);
		/*saun.sun_len = sizeof(saun);*/

		r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
		if (r) { 
			close(s);
			goto log_file;
		}
	}
	send(s, error, strlen(error), 0);
	
	close(s);
#endif
#ifdef PHP_WIN32
	ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf);

	switch (SUHOSIN_G(log_syslog_priority)) {			/* translate UNIX type into NT type */
		case 1: /*LOG_ALERT:*/
			etype = EVENTLOG_ERROR_TYPE;
			break;
		case 6: /*LOG_INFO:*/
			etype = EVENTLOG_INFORMATION_TYPE;
			break;
		default:
			etype = EVENTLOG_WARNING_TYPE;
	}
	evid = loglevel;
	strs[0] = error;
	/* report the event */
	if (log_source == NULL) {
		log_source = RegisterEventSource(NULL, "Suhosin-" SUHOSIN_EXT_VERSION);
	}
	ReportEvent(log_source, etype, (unsigned short) SUHOSIN_G(log_syslog_priority), evid, NULL, 1, 0, strs, NULL);
	
#endif
log_file:
	/* File-Logging disabled? */
	if ((SUHOSIN_G(log_file) & loglevel)==0) {
		goto log_sapi;
	}
	
	if (!SUHOSIN_G(log_filename) || !SUHOSIN_G(log_filename)[0]) {
		goto log_sapi;
	}
	fd = open(SUHOSIN_G(log_filename), O_CREAT|O_APPEND|O_WRONLY, 0640);
	if (fd == -1) {
	    suhosin_log(S_INTERNAL, "Unable to open logfile: %s", SUHOSIN_G(log_filename));
	    return;
	}

	gettimeofday(&tv, NULL);
	now = tv.tv_sec;
	php_gmtime_r(&now, &tm);
	ap_php_snprintf(error, sizeof(error), "%s %2d %02d:%02d:%02d [%u] %s\n", month_names[tm.tm_mon], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, getpid(),buf);
	towrite = strlen(error);
	wbuf = error;
	php_flock(fd, LOCK_EX);
	while (towrite > 0) {
		written = write(fd, wbuf, towrite);
		if (written < 0) {
			break;
		}
		towrite -= written;
		wbuf += written;
	}
	php_flock(fd, LOCK_UN);
	close(fd);

log_sapi:
	/* SAPI Logging activated? */
	SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script), SUHOSIN_G(log_phpscript));
	if (((SUHOSIN_G(log_sapi)|S_INTERNAL) & loglevel)!=0) {
#if PHP_VERSION_ID < 50400
		sapi_module.log_message(buf);
#else
		sapi_module.log_message(buf TSRMLS_CC);
#endif
	}
	if ((SUHOSIN_G(log_stdout) & loglevel)!=0) {
		printf("%s\n", buf);
	}

/*log_script:*/
	/* script logging activaed? */
	if (((SUHOSIN_G(log_script) & loglevel)!=0) && SUHOSIN_G(log_scriptname)!=NULL) {
		char cmd[8192], *cmdpos, *bufpos;
		FILE *in;
		int space;
		struct stat st;
		
		char *sname = SUHOSIN_G(log_scriptname);
		while (isspace(*sname)) ++sname;
		if (*sname == 0) goto log_phpscript;
		
		if (VCWD_STAT(sname, &st) < 0) {
			suhosin_log(S_INTERNAL, "unable to find logging shell script %s - file dropped", sname);
			goto log_phpscript;
		}
		if (access(sname, X_OK|R_OK) < 0) {
			suhosin_log(S_INTERNAL, "logging shell script %s is not executable - file dropped", sname);
			goto log_phpscript;					
		}
		
		/* TODO: clean up this code to calculate size of output dynamically */
		ap_php_snprintf(cmd, sizeof(cmd) - 20, "%s %s \'", sname, loglevel2string(loglevel));
		space = sizeof(cmd) - strlen(cmd) - 20;
		cmdpos = cmd + strlen(cmd);
		bufpos = buf;
		if (space <= 1) return;
		while (space > 2 && *bufpos) {
			if (*bufpos == '\'') {
				if (space<=5) break;
				*cmdpos++ = '\'';
				*cmdpos++ = '\\';
				*cmdpos++ = '\'';
				*cmdpos++ = '\'';
				bufpos++;
				space-=4;
			} else {
				*cmdpos++ = *bufpos++;
				space--;
			}
		}
		*cmdpos++ = '\'';
		*cmdpos++ = ' ';
		*cmdpos++ = '2';
		*cmdpos++ = '>';
		*cmdpos++ = '&';
		*cmdpos++ = '1';
		*cmdpos = 0;
		
		if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
			suhosin_log(S_INTERNAL, "Unable to execute logging shell script: %s", sname);
			goto log_phpscript;
		}
		/* read and forget the result */
		while (1) {
			int readbytes = fread(cmd, 1, sizeof(cmd), in);
			if (readbytes<=0) {
				break;
			}
			if (strncmp(cmd, "sh: ", 4) == 0) {
				/* assume this is an error */
				suhosin_log(S_INTERNAL, "Error while executing logging shell script: %s", sname);
				pclose(in);
				goto log_phpscript;
			}
		}
		pclose(in);
	}
log_phpscript:
	if ((SUHOSIN_G(log_phpscript) & loglevel)!=0 && EG(in_execution) && SUHOSIN_G(log_phpscriptname) && SUHOSIN_G(log_phpscriptname)[0]) {
		zend_file_handle file_handle;
		zend_op_array *new_op_array;
		zval *result = NULL;
		
		long orig_execution_depth = SUHOSIN_G(execution_depth);
#if PHP_VERSION_ID < 50400
		zend_bool orig_safe_mode = PG(safe_mode);
#endif
		char *orig_basedir = PG(open_basedir);
		
		char *phpscript = SUHOSIN_G(log_phpscriptname);
SDEBUG("scriptname %s", SUHOSIN_G(log_phpscriptname));				
#ifdef ZEND_ENGINE_2
		if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) {
#else
		if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
			file_handle.filename = phpscript;
			file_handle.free_filename = 0;
#endif		
			if (!file_handle.opened_path) {
				file_handle.opened_path = estrndup(phpscript, strlen(phpscript));
			}
			new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
			zend_destroy_file_handle(&file_handle TSRMLS_CC);
			if (new_op_array) {
				HashTable *active_symbol_table = EG(active_symbol_table);
				zval *zerror, *zerror_class;
				
				if (active_symbol_table == NULL) {
					active_symbol_table = &EG(symbol_table);
				}
				EG(return_value_ptr_ptr) = &result;
				EG(active_op_array) = new_op_array;
				
				MAKE_STD_ZVAL(zerror);
				MAKE_STD_ZVAL(zerror_class);
				ZVAL_STRING(zerror, buf, 1);
				ZVAL_LONG(zerror_class, loglevel);

				zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL);
				zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL);
				
				SUHOSIN_G(execution_depth) = 0;
				if (SUHOSIN_G(log_phpscript_is_safe)) {
#if PHP_VERSION_ID < 50400
					PG(safe_mode) = 0;
#endif
					PG(open_basedir) = NULL;
				}
				
				zend_execute(new_op_array TSRMLS_CC);
				
				SUHOSIN_G(execution_depth) = orig_execution_depth;
#if PHP_VERSION_ID < 50400				
				PG(safe_mode) = orig_safe_mode;
#endif
				PG(open_basedir) = orig_basedir;
				
#ifdef ZEND_ENGINE_2
				destroy_op_array(new_op_array TSRMLS_CC);
#else
				destroy_op_array(new_op_array);
#endif
				efree(new_op_array);
#ifdef ZEND_ENGINE_2
				if (!EG(exception))
#endif			
				{
					if (EG(return_value_ptr_ptr)) {
						zval_ptr_dtor(EG(return_value_ptr_ptr));
						EG(return_value_ptr_ptr) = NULL;
					}
				}
			} else {
				suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
				return;
			}
		} else {
			suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
			return;
		}
	}

}