summaryrefslogtreecommitdiff
path: root/src/sp_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp_utils.c')
-rw-r--r--src/sp_utils.c107
1 files changed, 66 insertions, 41 deletions
diff --git a/src/sp_utils.c b/src/sp_utils.c
index 6161859..42f7871 100644
--- a/src/sp_utils.c
+++ b/src/sp_utils.c
@@ -1,6 +1,6 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2 2
3static const char* default_ipaddr = "0.0.0.0"; 3static char const* const default_ipaddr = "0.0.0.0";
4const char* get_ipaddr() { 4const char* get_ipaddr() {
5 const char* client_ip = getenv("REMOTE_ADDR"); 5 const char* client_ip = getenv("REMOTE_ADDR");
6 if (client_ip) { 6 if (client_ip) {
@@ -15,8 +15,8 @@ const char* get_ipaddr() {
15 return default_ipaddr; 15 return default_ipaddr;
16} 16}
17 17
18void sp_log_msgf(char const* restrict feature, int level, int type, 18void sp_log_msgf(char const* const restrict feature, int level, int type,
19 const char* restrict fmt, ...) { 19 char const* const restrict fmt, ...) {
20 char* msg; 20 char* msg;
21 va_list args; 21 va_list args;
22 22
@@ -63,7 +63,7 @@ void sp_log_msgf(char const* restrict feature, int level, int type,
63 } 63 }
64} 64}
65 65
66int compute_hash(const char* const restrict filename, 66int compute_hash(char const* const restrict filename,
67 char* restrict file_hash) { 67 char* restrict file_hash) {
68 unsigned char buf[1024] = {0}; 68 unsigned char buf[1024] = {0};
69 unsigned char digest[SHA256_SIZE] = {0}; 69 unsigned char digest[SHA256_SIZE] = {0};
@@ -90,9 +90,18 @@ int compute_hash(const char* const restrict filename,
90 return SUCCESS; 90 return SUCCESS;
91} 91}
92 92
93static int construct_filename(char* filename, 93int sp_log_request(zend_string const* const restrict folder, zend_string const* const restrict text_repr) {
94 const zend_string* restrict folder, 94 FILE* file;
95 const zend_string* restrict textual) { 95 char const* const current_filename = zend_get_executed_filename(TSRMLS_C);
96 const int current_line = zend_get_executed_lineno(TSRMLS_C);
97 char filename[PATH_MAX] = {0};
98 static const struct {
99 char const* const str;
100 const int key;
101 } zones[] = {{"GET", TRACK_VARS_GET}, {"POST", TRACK_VARS_POST},
102 {"COOKIE", TRACK_VARS_COOKIE}, {"SERVER", TRACK_VARS_SERVER},
103 {"ENV", TRACK_VARS_ENV}, {NULL, 0}};
104
96 PHP_SHA256_CTX context; 105 PHP_SHA256_CTX context;
97 unsigned char digest[SHA256_SIZE] = {0}; 106 unsigned char digest[SHA256_SIZE] = {0};
98 char strhash[65] = {0}; 107 char strhash[65] = {0};
@@ -103,52 +112,54 @@ static int construct_filename(char* filename,
103 return -1; 112 return -1;
104 } 113 }
105 114
106 /* We're using the sha256 sum of the rule's textual representation 115 /* We're using the sha256 sum of the rule's textual representation, as well
107 * as filename, in order to only have one dump per rule, to mitigate 116 * as the stacktrace as filename, in order to only have one dump per rule, to
108 * DoS attacks. */ 117 * mitigate DoS attacks. We're doing the walk-the-execution-context dance
118 * twice because it's easier than to cache it in a linked-list. It doesn't
119 * really matter, since this is a super-cold path anyway.
120 */
109 PHP_SHA256Init(&context); 121 PHP_SHA256Init(&context);
110 PHP_SHA256Update(&context, (const unsigned char*)ZSTR_VAL(textual), 122 PHP_SHA256Update(&context, (const unsigned char*)ZSTR_VAL(text_repr), ZSTR_LEN(text_repr));
111 ZSTR_LEN(textual)); 123 zend_execute_data* orig_execute_data = EG(current_execute_data);
124 zend_execute_data* current = EG(current_execute_data);
125 while (current) {
126 EG(current_execute_data) = current;
127 char* const complete_path_function = get_complete_function_path(current);
128 if (complete_path_function) {
129 PHP_SHA256Update(&context, (const unsigned char*)complete_path_function, strlen(complete_path_function));
130 efree(complete_path_function);
131 }
132 current = current->prev_execute_data;
133 }
134 EG(current_execute_data) = orig_execute_data;
112 PHP_SHA256Final(digest, &context); 135 PHP_SHA256Final(digest, &context);
113 make_digest_ex(strhash, digest, SHA256_SIZE); 136 make_digest_ex(strhash, digest, SHA256_SIZE);
114 snprintf(filename, PATH_MAX - 1, "%s/sp_dump.%s", ZSTR_VAL(folder), strhash); 137 snprintf(filename, PATH_MAX - 1, "%s/sp_dump.%s", ZSTR_VAL(folder), strhash);
115 138
116 return 0;
117}
118
119int sp_log_request(const zend_string* restrict folder, const zend_string* restrict text_repr) {
120 FILE* file;
121 const char* current_filename = zend_get_executed_filename(TSRMLS_C);
122 const int current_line = zend_get_executed_lineno(TSRMLS_C);
123 char filename[PATH_MAX] = {0};
124 const struct {
125 char const* const str;
126 const int key;
127 } zones[] = {{"GET", TRACK_VARS_GET}, {"POST", TRACK_VARS_POST},
128 {"COOKIE", TRACK_VARS_COOKIE}, {"SERVER", TRACK_VARS_SERVER},
129 {"ENV", TRACK_VARS_ENV}, {NULL, 0}};
130
131 if (0 != construct_filename(filename, folder, text_repr)) {
132 return -1;
133 }
134 if (NULL == (file = fopen(filename, "w+"))) { 139 if (NULL == (file = fopen(filename, "w+"))) {
135 sp_log_warn("request_logging", "Unable to open %s: %s", filename, 140 sp_log_warn("request_logging", "Unable to open %s: %s", filename,
136 strerror(errno)); 141 strerror(errno));
137 return -1; 142 return -1;
138 } 143 }
139 144
140 fprintf(file, "RULE: %s\n", ZSTR_VAL(text_repr)); 145 fputs("RULE: ", file);
146 fputs(ZSTR_VAL(text_repr), file);
147 fputc('\n', file);
141 148
142 fprintf(file, "FILE: %s:%d\n", current_filename, current_line); 149 fputs("FILE: ", file);
150 fputs(current_filename, file);
151 fprintf(file, ":%d\n", current_line);
143 152
144 zend_execute_data* orig_execute_data = EG(current_execute_data); 153 orig_execute_data = EG(current_execute_data);
145 zend_execute_data* current = EG(current_execute_data); 154 current = EG(current_execute_data);
146 while (current) { 155 while (current) {
147 EG(current_execute_data) = current; 156 EG(current_execute_data) = current;
148 char* const complete_path_function = get_complete_function_path(current); 157 char* const complete_path_function = get_complete_function_path(current);
149 if (complete_path_function) { 158 if (complete_path_function) {
150 const int current_line = zend_get_executed_lineno(TSRMLS_C); 159 const int current_line = zend_get_executed_lineno(TSRMLS_C);
151 fprintf(file, "STACKTRACE: %s:%d\n", complete_path_function, current_line); 160 fputs("STACKTRACE: ", file);
161 fputs(complete_path_function, file);
162 fprintf(file, ":%d\n", current_line);
152 efree(complete_path_function); 163 efree(complete_path_function);
153 } 164 }
154 current = current->prev_execute_data; 165 current = current->prev_execute_data;
@@ -164,19 +175,32 @@ int sp_log_request(const zend_string* restrict folder, const zend_string* restri
164 } 175 }
165 176
166 HashTable* ht = Z_ARRVAL(PG(http_globals)[zones[i].key]); 177 HashTable* ht = Z_ARRVAL(PG(http_globals)[zones[i].key]);
167 fprintf(file, "%s:", zones[i].str); 178 fputs(zones[i].str, file);
179 fputc(':', file);
168 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, variable_key, variable_value) { 180 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, variable_key, variable_value) {
169 smart_str a; 181 smart_str a = {0};
170
171 memset(&a, 0, sizeof(a));
172 php_var_export_ex(variable_value, 1, &a); 182 php_var_export_ex(variable_value, 1, &a);
173 ZSTR_VAL(a.s)[ZSTR_LEN(a.s)] = '\0'; 183 ZSTR_VAL(a.s)[ZSTR_LEN(a.s)] = '\0';
174 fprintf(file, "%s=%s ", ZSTR_VAL(variable_key), ZSTR_VAL(a.s)); 184 fputs(ZSTR_VAL(variable_key), file);
185 fputc('=', file);
186 fputs(ZSTR_VAL(a.s), file);
187 fputc(' ', file);
175 zend_string_release(a.s); 188 zend_string_release(a.s);
176 } 189 }
177 ZEND_HASH_FOREACH_END(); 190 ZEND_HASH_FOREACH_END();
178 fputs("\n", file); 191 fputc('\n', file);
179 } 192 }
193
194 if (UNEXPECTED(0 != SPG(in_eval))) {
195 fputs("EVAL_CODE: ", file);
196#if PHP_VERSION_ID >= 80000
197 fputs(ZSTR_VAL(SPG(eval_source_string)), file);
198#else
199 fputs(Z_STRVAL_P(SPG(eval_source_string)), file);
200#endif
201 fputc('\n', file);
202 }
203
180 fclose(file); 204 fclose(file);
181 205
182 return 0; 206 return 0;
@@ -448,6 +472,7 @@ void unhook_functions(HashTable *ht) {
448 if (func && func->type == ZEND_INTERNAL_FUNCTION && orig_handler) { 472 if (func && func->type == ZEND_INTERNAL_FUNCTION && orig_handler) {
449 func->internal_function.handler = orig_handler; 473 func->internal_function.handler = orig_handler;
450 } 474 }
475 (void)idx;//silence a -Wunused-but-set-variable
451 ZEND_HASH_FOREACH_END_DEL(); 476 ZEND_HASH_FOREACH_END_DEL();
452} 477}
453 478