summaryrefslogtreecommitdiff
path: root/log.c
diff options
context:
space:
mode:
authorStefan Esser2010-02-21 11:44:54 +0100
committerStefan Esser2010-02-21 11:44:54 +0100
commit36dbfacbe64697d959f524e537b15b73c090d898 (patch)
treef1c7ce1409b0e7765fc72d550546967fcf0f9717 /log.c
Inital commit
Diffstat (limited to 'log.c')
-rw-r--r--log.c404
1 files changed, 404 insertions, 0 deletions
diff --git a/log.c b/log.c
new file mode 100644
index 0000000..d5e3b50
--- /dev/null
+++ b/log.c
@@ -0,0 +1,404 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007 SektionEins GmbH |
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 | Author: Stefan Esser <sesser@sektioneins.de> |
17 +----------------------------------------------------------------------+
18*/
19/*
20 $Id: log.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "php.h"
28#include "php_ini.h"
29#include "php_suhosin.h"
30#include <fcntl.h>
31#include "SAPI.h"
32#include "ext/standard/datetime.h"
33#include "ext/standard/flock_compat.h"
34
35#ifdef HAVE_SYS_SOCKET_H
36#include <sys/socket.h>
37#endif
38
39#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
40#undef AF_UNIX
41#endif
42
43#if defined(AF_UNIX)
44#include <sys/un.h>
45#endif
46
47#define SYSLOG_PATH "/dev/log"
48
49#include "snprintf.h"
50
51#ifdef PHP_WIN32
52static HANDLE log_source = 0;
53#endif
54
55
56static char *loglevel2string(int loglevel)
57{
58 switch (loglevel) {
59 case S_FILES:
60 return "FILES";
61 case S_INCLUDE:
62 return "INCLUDE";
63 case S_MEMORY:
64 return "MEMORY";
65 case S_MISC:
66 return "MISC";
67 case S_MAIL:
68 return "MAIL";
69 case S_SESSION:
70 return "SESSION";
71 case S_SQL:
72 return "SQL";
73 case S_EXECUTOR:
74 return "EXECUTOR";
75 case S_VARS:
76 return "VARS";
77 default:
78 return "UNKNOWN";
79 }
80}
81
82static char *month_names[] = {
83 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
84 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
85};
86
87PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...)
88{
89 int s, r, i=0, fd;
90 long written, towrite;
91 char *wbuf;
92 struct timeval tv;
93 time_t now;
94 struct tm tm;
95#if defined(AF_UNIX)
96 struct sockaddr_un saun;
97#endif
98#ifdef PHP_WIN32
99 LPTSTR strs[2];
100 unsigned short etype;
101 DWORD evid;
102#endif
103 char buf[4096+64];
104 char error[4096+100];
105 char *ip_address;
106 char *fname;
107 char *alertstring;
108 int lineno;
109 va_list ap;
110 TSRMLS_FETCH();
111
112 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));
113
114 /* dump core if wanted */
115 if (SUHOSIN_G(coredump) && loglevel == S_MEMORY) {
116 volatile unsigned int *x = 0;
117 volatile int y = *x;
118 }
119
120 if (SUHOSIN_G(log_use_x_forwarded_for)) {
121 ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
122 if (ip_address == NULL) {
123 ip_address = "X-FORWARDED-FOR not set";
124 }
125 } else {
126 ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
127 if (ip_address == NULL) {
128 ip_address = "REMOTE_ADDR not set";
129 }
130 }
131
132
133 va_start(ap, fmt);
134 ap_php_vsnprintf(error, sizeof(error), fmt, ap);
135 va_end(ap);
136 while (error[i]) {
137 if (error[i] < 32) error[i] = '.';
138 i++;
139 }
140
141 if (SUHOSIN_G(simulation)) {
142 alertstring = "ALERT-SIMULATION";
143 } else {
144 alertstring = "ALERT";
145 }
146
147 if (zend_is_executing(TSRMLS_C)) {
148 if (EG(current_execute_data)) {
149 lineno = EG(current_execute_data)->opline->lineno;
150 fname = EG(current_execute_data)->op_array->filename;
151 } else {
152 lineno = zend_get_executed_lineno(TSRMLS_C);
153 fname = zend_get_executed_filename(TSRMLS_C);
154 }
155 ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno);
156 } else {
157 fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
158 if (fname==NULL) {
159 fname = "unknown";
160 }
161 ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname);
162 }
163
164 /* Syslog-Logging disabled? */
165 if (((SUHOSIN_G(log_syslog)|S_INTERNAL) & loglevel)==0) {
166 goto log_file;
167 }
168
169#if defined(AF_UNIX)
170 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);
171
172 s = socket(AF_UNIX, SOCK_DGRAM, 0);
173 if (s == -1) {
174 goto log_file;
175 }
176
177 memset(&saun, 0, sizeof(saun));
178 saun.sun_family = AF_UNIX;
179 strcpy(saun.sun_path, SYSLOG_PATH);
180 /*saun.sun_len = sizeof(saun);*/
181
182 r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
183 if (r) {
184 close(s);
185 s = socket(AF_UNIX, SOCK_STREAM, 0);
186 if (s == -1) {
187 goto log_file;
188 }
189
190 memset(&saun, 0, sizeof(saun));
191 saun.sun_family = AF_UNIX;
192 strcpy(saun.sun_path, SYSLOG_PATH);
193 /*saun.sun_len = sizeof(saun);*/
194
195 r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
196 if (r) {
197 close(s);
198 goto log_file;
199 }
200 }
201 send(s, error, strlen(error), 0);
202
203 close(s);
204#endif
205#ifdef PHP_WIN32
206 ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf);
207
208 switch (SUHOSIN_G(log_syslog_priority)) { /* translate UNIX type into NT type */
209 case 1: /*LOG_ALERT:*/
210 etype = EVENTLOG_ERROR_TYPE;
211 break;
212 case 6: /*LOG_INFO:*/
213 etype = EVENTLOG_INFORMATION_TYPE;
214 break;
215 default:
216 etype = EVENTLOG_WARNING_TYPE;
217 }
218 evid = loglevel;
219 strs[0] = error;
220 /* report the event */
221 if (log_source == NULL) {
222 log_source = RegisterEventSource(NULL, "Suhosin-" SUHOSIN_EXT_VERSION);
223 }
224 ReportEvent(log_source, etype, (unsigned short) SUHOSIN_G(log_syslog_priority), evid, NULL, 1, 0, strs, NULL);
225
226#endif
227log_file:
228 /* File-Logging disabled? */
229 if ((SUHOSIN_G(log_file) & loglevel)==0) {
230 goto log_sapi;
231 }
232
233 if (!SUHOSIN_G(log_filename) || !SUHOSIN_G(log_filename)[0]) {
234 goto log_sapi;
235 }
236 fd = open(SUHOSIN_G(log_filename), O_CREAT|O_APPEND|O_WRONLY, 0640);
237 if (fd == -1) {
238 suhosin_log(S_INTERNAL, "Unable to open logfile: %s", SUHOSIN_G(log_filename));
239 return;
240 }
241
242 gettimeofday(&tv, NULL);
243 now = tv.tv_sec;
244 php_gmtime_r(&now, &tm);
245 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);
246 towrite = strlen(error);
247 wbuf = error;
248 php_flock(fd, LOCK_EX);
249 while (towrite > 0) {
250 written = write(fd, wbuf, towrite);
251 if (written < 0) {
252 break;
253 }
254 towrite -= written;
255 wbuf += written;
256 }
257 php_flock(fd, LOCK_UN);
258 close(fd);
259
260log_sapi:
261 /* SAPI Logging activated? */
262 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));
263 if (((SUHOSIN_G(log_sapi)|S_INTERNAL) & loglevel)!=0) {
264 sapi_module.log_message(buf);
265 }
266
267/*log_script:*/
268 /* script logging activaed? */
269 if (((SUHOSIN_G(log_script) & loglevel)!=0) && SUHOSIN_G(log_scriptname)!=NULL) {
270 char cmd[8192], *cmdpos, *bufpos;
271 FILE *in;
272 int space;
273
274 char *sname = SUHOSIN_G(log_scriptname);
275 while (isspace(*sname)) ++sname;
276 if (*sname == 0) goto log_phpscript;
277
278 ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", sname, loglevel2string(loglevel));
279 space = sizeof(cmd) - strlen(cmd);
280 cmdpos = cmd + strlen(cmd);
281 bufpos = buf;
282 if (space <= 1) return;
283 while (space > 2 && *bufpos) {
284 if (*bufpos == '\'') {
285 if (space<=5) break;
286 *cmdpos++ = '\'';
287 *cmdpos++ = '\\';
288 *cmdpos++ = '\'';
289 *cmdpos++ = '\'';
290 bufpos++;
291 space-=4;
292 } else {
293 *cmdpos++ = *bufpos++;
294 space--;
295 }
296 }
297 *cmdpos++ = '\'';
298 *cmdpos = 0;
299
300 if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
301 suhosin_log(S_INTERNAL, "Unable to execute logging shell script: %s", sname);
302 return;
303 }
304 /* read and forget the result */
305 while (1) {
306 int readbytes = fread(cmd, 1, sizeof(cmd), in);
307 if (readbytes<=0) {
308 break;
309 }
310 }
311 pclose(in);
312 }
313log_phpscript:
314 if ((SUHOSIN_G(log_phpscript) & loglevel)!=0 && EG(in_execution) && SUHOSIN_G(log_phpscriptname) && SUHOSIN_G(log_phpscriptname)[0]) {
315 zend_file_handle file_handle;
316 zend_op_array *new_op_array;
317 zval *result = NULL;
318
319 long orig_execution_depth = SUHOSIN_G(execution_depth);
320 zend_bool orig_safe_mode = PG(safe_mode);
321 char *orig_basedir = PG(open_basedir);
322
323 char *phpscript = SUHOSIN_G(log_phpscriptname);
324SDEBUG("scriptname %s", SUHOSIN_G(log_phpscriptname));
325#ifdef ZEND_ENGINE_2
326 if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) {
327#else
328 if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
329 file_handle.filename = phpscript;
330 file_handle.free_filename = 0;
331#endif
332 if (!file_handle.opened_path) {
333 file_handle.opened_path = estrndup(phpscript, strlen(phpscript));
334 }
335 new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
336 zend_destroy_file_handle(&file_handle TSRMLS_CC);
337 if (new_op_array) {
338 HashTable *active_symbol_table = EG(active_symbol_table);
339 zval *zerror, *zerror_class;
340
341 if (active_symbol_table == NULL) {
342 active_symbol_table = &EG(symbol_table);
343 }
344 EG(return_value_ptr_ptr) = &result;
345 EG(active_op_array) = new_op_array;
346
347 MAKE_STD_ZVAL(zerror);
348 MAKE_STD_ZVAL(zerror_class);
349 ZVAL_STRING(zerror, buf, 1);
350 ZVAL_LONG(zerror_class, loglevel);
351
352 zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL);
353 zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL);
354
355 SUHOSIN_G(execution_depth) = 0;
356 if (SUHOSIN_G(log_phpscript_is_safe)) {
357 PG(safe_mode) = 0;
358 PG(open_basedir) = NULL;
359 }
360
361 zend_execute(new_op_array TSRMLS_CC);
362
363 SUHOSIN_G(execution_depth) = orig_execution_depth;
364 PG(safe_mode) = orig_safe_mode;
365 PG(open_basedir) = orig_basedir;
366
367#ifdef ZEND_ENGINE_2
368 destroy_op_array(new_op_array TSRMLS_CC);
369#else
370 destroy_op_array(new_op_array);
371#endif
372 efree(new_op_array);
373#ifdef ZEND_ENGINE_2
374 if (!EG(exception))
375#endif
376 {
377 if (EG(return_value_ptr_ptr)) {
378 zval_ptr_dtor(EG(return_value_ptr_ptr));
379 EG(return_value_ptr_ptr) = NULL;
380 }
381 }
382 } else {
383 suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
384 return;
385 }
386 } else {
387 suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname));
388 return;
389 }
390 }
391
392}
393
394
395/*
396 * Local variables:
397 * tab-width: 4
398 * c-basic-offset: 4
399 * End:
400 * vim600: noet sw=4 ts=4 fdm=marker
401 * vim<600: noet sw=4 ts=4
402 */
403
404