1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include "php_snuffleupagus.h"
int (*sp_rfc1867_orig_callback)(unsigned int event, void *event_data,
void **extra);
int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra);
#define EFREE_3(env) \
for (size_t i = 0; i < 4; i++) { \
efree(env[i]); \
}
#ifdef PHP_WIN32
int sp_rfc1867_callback_win(unsigned int event, void *event_data,
void **extra) {
sp_log_simulation("upload_validation",
"The upload validation doesn't work for now on Windows yet, "
"see https://github.com/jvoisin/snuffleupagus/issues/248 for "
"details.");
return SUCCESS;
}
#else
int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) {
int retval = SUCCESS;
if (sp_rfc1867_orig_callback) {
retval = sp_rfc1867_orig_callback(event, event_data, extra);
}
if (event == MULTIPART_EVENT_END) {
zend_string *file_key __attribute__((unused)) = NULL;
const sp_config_upload_validation *config_upload =
SNUFFLEUPAGUS_G(config).config_upload_validation;
zval *file;
pid_t pid;
sp_log_debug(
"Got %d files",
zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES])));
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES]),
file_key, file) { // for each uploaded file
char *filename = Z_STRVAL_P(
zend_hash_str_find(Z_ARRVAL_P(file), "name", sizeof("name") - 1));
char *tmp_name = Z_STRVAL_P(zend_hash_str_find(
Z_ARRVAL_P(file), "tmp_name", sizeof("tmp_name") - 1));
size_t filesize = Z_LVAL_P(
zend_hash_str_find(Z_ARRVAL_P(file), "size", sizeof("size") - 1));
char *cmd[3] = {0};
char *env[5] = {0};
sp_log_debug("Filename: %s\nTmpname: %s\nSize: %d\nError: %d\nScript: %s",
filename, tmp_name, filesize,
Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "error", 5)),
ZSTR_VAL(config_upload->script));
cmd[0] = ZSTR_VAL(config_upload->script);
cmd[1] = tmp_name;
cmd[2] = NULL;
spprintf(&env[0], 0, "SP_FILENAME=%s", filename);
spprintf(&env[1], 0, "SP_REMOTE_ADDR=%s", getenv("REMOTE_ADDR"));
spprintf(&env[2], 0, "SP_CURRENT_FILE=%s",
zend_get_executed_filename(TSRMLS_C));
spprintf(&env[3], 0, "SP_FILESIZE=%zu", filesize);
env[4] = NULL;
if ((pid = fork()) == 0) {
if (execve(ZSTR_VAL(config_upload->script), cmd, env) == -1) {
sp_log_warn("upload_validation", "Could not call '%s' : %s",
ZSTR_VAL(config_upload->script), strerror(errno));
EFREE_3(env);
exit(1);
}
} else if (pid == -1) {
// LCOV_EXCL_START
sp_log_err("upload_validation", "Could not fork process : %s\n",
strerror(errno));
EFREE_3(env);
continue;
// LCOV_EXCL_STOP
}
EFREE_3(env);
int waitstatus;
wait(&waitstatus);
if (WEXITSTATUS(waitstatus) != 0) { // Nope
char *uri = getenv("REQUEST_URI");
int sim = config_upload->simulation;
sp_log_auto("upload_validation", sim,
"The upload of %s on %s was rejected.",
filename, uri ? uri : "?");
}
}
ZEND_HASH_FOREACH_END();
}
return retval;
}
#endif
void hook_upload() {
if (NULL == sp_rfc1867_orig_callback) {
sp_rfc1867_orig_callback = php_rfc1867_callback;
php_rfc1867_callback = sp_rfc1867_callback;
}
}
|