summaryrefslogtreecommitdiff
path: root/src/sp_ini.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp_ini.c')
-rw-r--r--src/sp_ini.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/src/sp_ini.c b/src/sp_ini.c
index 7b22012..8860a92 100644
--- a/src/sp_ini.c
+++ b/src/sp_ini.c
@@ -11,6 +11,29 @@
11 sp_log_auto2("ini_protection", simulation, (cfg->policy_drop || (entry && entry->drop)), __VA_ARGS__); \ 11 sp_log_auto2("ini_protection", simulation, (cfg->policy_drop || (entry && entry->drop)), __VA_ARGS__); \
12 } 12 }
13 13
14static const char* check_safe_key(const char* string) {
15 for (const char* p = string; *p != '\0'; p++) {
16 if (!isalnum((unsigned char)*p) && *p != '_' && *p != '.') {
17 return NULL;
18 }
19 }
20
21 return string;
22}
23
24static const char* check_safe_value(const char* string) {
25 for (const char* p = string; *p != '\0'; p++) {
26 if (*p == '\'' || *p == '"') {
27 return NULL;
28 }
29
30 if (!isgraph((unsigned char)*p)) {
31 return NULL;
32 }
33 }
34
35 return string;
36}
14 37
15static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend_string const *const restrict new_value, sp_ini_entry **sp_entry_p) { 38static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend_string const *const restrict new_value, sp_ini_entry **sp_entry_p) {
16 if (!varname || ZSTR_LEN(varname) == 0) { 39 if (!varname || ZSTR_LEN(varname) == 0) {
@@ -27,7 +50,8 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
27 if (!entry) { 50 if (!entry) {
28 if (cfg->policy_readonly) { 51 if (cfg->policy_readonly) {
29 if (!cfg->policy_silent_ro) { 52 if (!cfg->policy_silent_ro) {
30 sp_log_ini_check_violation("INI setting is read-only"); 53 sp_log_ini_check_violation("INI setting `%s` is read-only",
54 check_safe_key(ZSTR_VAL(varname)) ? ZSTR_VAL(varname) : "<invalid>");
31 } 55 }
32 return simulation; 56 return simulation;
33 } 57 }
@@ -38,7 +62,11 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
38 62
39 if (SP_INI_ACCESS_READONLY_COND(entry, cfg)) { 63 if (SP_INI_ACCESS_READONLY_COND(entry, cfg)) {
40 if (!cfg->policy_silent_ro) { 64 if (!cfg->policy_silent_ro) {
41 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI setting is read-only")); 65 if (entry->msg) {
66 sp_log_ini_check_violation("%s", ZSTR_VAL(entry->msg));
67 } else {
68 sp_log_ini_check_violation("INI setting `%s` is read-only", ZSTR_VAL(entry->key));
69 }
42 } 70 }
43 return simulation; 71 return simulation;
44 } 72 }
@@ -48,7 +76,7 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
48 return true; // allow NULL value and skip other tests 76 return true; // allow NULL value and skip other tests
49 } 77 }
50 if (SP_INI_HAS_CHECKS_COND(entry)) { 78 if (SP_INI_HAS_CHECKS_COND(entry)) {
51 sp_log_ini_check_violation("new INI value must not be NULL or empty"); 79 sp_log_ini_check_violation("new INI value for `%s` must not be NULL or empty", ZSTR_VAL(entry->key));
52 return simulation; 80 return simulation;
53 } 81 }
54 return true; // no new_value, but no checks to perform 82 return true; // no new_value, but no checks to perform
@@ -66,14 +94,36 @@ static bool /* success */ sp_ini_check(zend_string *const restrict varname, zend
66 if ((entry->min && zend_atol(ZSTR_VAL(entry->min), ZSTR_LEN(entry->min)) > lvalue) || 94 if ((entry->min && zend_atol(ZSTR_VAL(entry->min), ZSTR_LEN(entry->min)) > lvalue) ||
67 (entry->max && zend_atol(ZSTR_VAL(entry->max), ZSTR_LEN(entry->max)) < lvalue)) { 95 (entry->max && zend_atol(ZSTR_VAL(entry->max), ZSTR_LEN(entry->max)) < lvalue)) {
68#endif 96#endif
69 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value out of range")); 97 if (entry->msg) {
98 sp_log_ini_check_violation("%s", ZSTR_VAL(entry->msg));
99 } else {
100 sp_log_ini_check_violation("INI value %lld for `%s` out of range", lvalue, ZSTR_VAL(entry->key));
101 }
70 return simulation; 102 return simulation;
71 } 103 }
72 } 104 }
73 105
74 if (entry->regexp) { 106 if (entry->regexp) {
75 if (!sp_is_regexp_matching_zstr(entry->regexp, new_value)) { 107 if (!sp_is_regexp_matching_zstr(entry->regexp, new_value)) {
76 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value does not match regex")); 108 if (entry->msg) {
109 sp_log_ini_check_violation("%s", ZSTR_VAL(entry->msg));
110 } else {
111 zend_string *base64_new_val = NULL;
112 const char *safe_new_val = check_safe_value(ZSTR_VAL(new_value));
113 if (!safe_new_val) {
114 base64_new_val = php_base64_encode((const unsigned char*)(ZSTR_VAL(new_value)), ZSTR_LEN(new_value));
115 safe_new_val = base64_new_val ? ZSTR_VAL(base64_new_val) : "<invalid>";
116 }
117
118 sp_log_ini_check_violation("INI value `%s`%s for `%s` does not match regex",
119 safe_new_val,
120 base64_new_val ? "(base64)" : "",
121 ZSTR_VAL(entry->key));
122
123 if (base64_new_val) {
124 zend_string_release(base64_new_val);
125 }
126 }
77 return simulation; 127 return simulation;
78 } 128 }
79 } 129 }