summaryrefslogtreecommitdiff
path: root/src/sp_ini.c
diff options
context:
space:
mode:
authorBen Fuhrmannek2021-08-07 15:56:57 +0200
committerBen Fuhrmannek2021-08-07 15:56:57 +0200
commitbd8b5bb241ca359b65c1a3717c9905d034b9703b (patch)
tree152cf1c0c91433ef7599097b4e9d12241c5dc628 /src/sp_ini.c
parente8bb162220ac17cb9b8cc229666356e88f081887 (diff)
more ini protection features
Diffstat (limited to 'src/sp_ini.c')
-rw-r--r--src/sp_ini.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/src/sp_ini.c b/src/sp_ini.c
index 05d7d99..5777ca3 100644
--- a/src/sp_ini.c
+++ b/src/sp_ini.c
@@ -3,6 +3,15 @@
3#define SP_INI_HAS_CHECKS_COND(entry) (entry->min || entry->max || entry->regexp) 3#define SP_INI_HAS_CHECKS_COND(entry) (entry->min || entry->max || entry->regexp)
4#define SP_INI_ACCESS_READONLY_COND(entry, cfg) (entry->access == SP_READONLY || (!entry->access && cfg->policy_readonly)) 4#define SP_INI_ACCESS_READONLY_COND(entry, cfg) (entry->access == SP_READONLY || (!entry->access && cfg->policy_readonly))
5 5
6#define sp_log_auto2(feature, is_simulation, drop, ...) \
7 sp_log_msgf(feature, ((is_simulation || !drop) ? SP_LOG_WARN : SP_LOG_ERROR), \
8 (is_simulation ? SP_TYPE_SIMULATION : (drop ? SP_TYPE_DROP : SP_TYPE_LOG)), \
9 __VA_ARGS__)
10#define sp_log_ini_check_violation(...) if (simulation || cfg->policy_drop || (entry && entry->drop) || !cfg->policy_silent_fail) { \
11 sp_log_auto2("ini_protection", simulation, (cfg->policy_drop || (entry && entry->drop)), __VA_ARGS__); \
12 }
13
14
6static bool /* success */ sp_ini_check(zend_string *varname, zend_string *new_value, sp_ini_entry **sp_entry_p) { 15static bool /* success */ sp_ini_check(zend_string *varname, zend_string *new_value, sp_ini_entry **sp_entry_p) {
7 if (!varname || ZSTR_LEN(varname) == 0) { 16 if (!varname || ZSTR_LEN(varname) == 0) {
8 return false; 17 return false;
@@ -17,40 +26,49 @@ static bool /* success */ sp_ini_check(zend_string *varname, zend_string *new_va
17 26
18 if (!entry) { 27 if (!entry) {
19 if (cfg->policy_readonly) { 28 if (cfg->policy_readonly) {
20 sp_log_auto("ini_protection", simulation, "INI setting is read-only"); 29 if (!cfg->policy_silent_ro) {
21 if (simulation) { return true; } 30 sp_log_ini_check_violation("INI setting is read-only");
22 return false; 31 }
32 return simulation;
23 } 33 }
24 return true; 34 return true;
25 } 35 }
26 36
37 // we have an entry.
38
27 if (SP_INI_ACCESS_READONLY_COND(entry, cfg)) { 39 if (SP_INI_ACCESS_READONLY_COND(entry, cfg)) {
28 sp_log_auto("ini_protection", simulation, "%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI setting is read-only")); 40 if (!cfg->policy_silent_ro) {
29 if (simulation) { return true; } 41 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI setting is read-only"));
30 return false; 42 }
43 return simulation;
31 } 44 }
32 45
33 if (!new_value && SP_INI_HAS_CHECKS_COND(entry)) { 46 if (!new_value || ZSTR_LEN(new_value) == 0) {
34 sp_log_auto("ini_protection", simulation, "new INI value must not be NULL"); 47 if (entry->allow_null) {
35 if (simulation) { return true; } 48 return true; // allow NULL value and skip other tests
36 return false; 49 }
50 if (SP_INI_HAS_CHECKS_COND(entry)) {
51 sp_log_ini_check_violation("new INI value must not be NULL or empty");
52 return simulation;
53 }
54 return true; // no new_value, but no checks to perform
37 } 55 }
38 56
57 // we have a new_value.
58
39 if (entry->min || entry->max) { 59 if (entry->min || entry->max) {
40 zend_long lvalue = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); 60 zend_long lvalue = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
41 if ((entry->min && zend_atol(ZSTR_VAL(entry->min), ZSTR_LEN(entry->min)) > lvalue) || 61 if ((entry->min && zend_atol(ZSTR_VAL(entry->min), ZSTR_LEN(entry->min)) > lvalue) ||
42 (entry->max && zend_atol(ZSTR_VAL(entry->max), ZSTR_LEN(entry->max)) < lvalue)) { 62 (entry->max && zend_atol(ZSTR_VAL(entry->max), ZSTR_LEN(entry->max)) < lvalue)) {
43 sp_log_auto("ini_protection", simulation, "%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value out of range")); 63 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value out of range"));
44 if (simulation) { return true; } 64 return simulation;
45 return false;
46 } 65 }
47 } 66 }
48 67
49 if (entry->regexp) { 68 if (entry->regexp) {
50 if (!sp_is_regexp_matching_len(entry->regexp, ZSTR_VAL(new_value), ZSTR_LEN(new_value))) { 69 if (!sp_is_regexp_matching_len(entry->regexp, ZSTR_VAL(new_value), ZSTR_LEN(new_value))) {
51 sp_log_auto("ini_protection", simulation, "%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value does not match regex")); 70 sp_log_ini_check_violation("%s", (entry->msg ? ZSTR_VAL(entry->msg) : "INI value does not match regex"));
52 if (simulation) { return true; } 71 return simulation;
53 return false;
54 } 72 }
55 } 73 }
56 74
@@ -83,7 +101,7 @@ void sp_hook_ini() {
83 sp_log_warn("ini_protection", "Cannot hook INI var `%s`. Maybe a typo or the PHP extension providing this var is not loaded yet.", ZSTR_VAL(sp_entry->key)); 101 sp_log_warn("ini_protection", "Cannot hook INI var `%s`. Maybe a typo or the PHP extension providing this var is not loaded yet.", ZSTR_VAL(sp_entry->key));
84 continue; 102 continue;
85 } 103 }
86 if (SP_INI_ACCESS_READONLY_COND(sp_entry, cfg)) { 104 if (SP_INI_ACCESS_READONLY_COND(sp_entry, cfg) && (cfg->policy_silent_ro || cfg->policy_silent_fail) && !sp_entry->drop && !(sp_entry->simulation || cfg->simulation)) {
87 ini_entry->modifiable = ini_entry->orig_modifiable = 0; 105 ini_entry->modifiable = ini_entry->orig_modifiable = 0;
88 } 106 }
89 PHP_INI_MH((*orig_onmodify)) = ini_entry->on_modify; 107 PHP_INI_MH((*orig_onmodify)) = ini_entry->on_modify;