From c24c5381587e376d39caf6a1ffa1193e7ce1d364 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Mon, 27 May 2024 17:15:28 +0200 Subject: [PATCH] MT#57764 permissions: add upstream patch Substitute internal sipwise patch introduced by dc673fead with the one taken from the upstream. Change-Id: Ie5a7de61e77c06deab2f28c5b9fd339d519587ff --- debian/patches/series | 2 +- ...s_add_register_allow_with_port_check.patch | 131 ------- ...s_add_register_allow_with_port_check.patch | 370 ++++++++++++++++++ 3 files changed, 371 insertions(+), 132 deletions(-) delete mode 100644 debian/patches/sipwise/permissions_add_register_allow_with_port_check.patch create mode 100644 debian/patches/upstream/permissions_add_register_allow_with_port_check.patch diff --git a/debian/patches/series b/debian/patches/series index b720a9c28..d15154ee4 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -37,6 +37,7 @@ sipwise/sca-add-pai_avp-parameter.patch upstream/rtpengine_rework_rtpp_flags.patch upstream/cfgutils-expose-optional-second-string-key-for-lock.patch upstream/cfgutils-initialize-the-optional-key.patch +upstream/permissions_add_register_allow_with_port_check.patch ### relevant for upstream sipwise/dialplan-don-t-stop-loading-rules-on-error.patch sipwise/kamctl-TMPDIR-config.patch @@ -48,7 +49,6 @@ sipwise/presence_vqr.patch sipwise/dialog-dlg_get_ttag.patch sipwise/app_lua_sr-support-second-str-for-cfgutils-lock.patch ### active development -sipwise/permissions_add_register_allow_with_port_check.patch # ### Don't just put stuff in any order ### use gbp pq import/export tooling to help maintain patches diff --git a/debian/patches/sipwise/permissions_add_register_allow_with_port_check.patch b/debian/patches/sipwise/permissions_add_register_allow_with_port_check.patch deleted file mode 100644 index c10a1c472..000000000 --- a/debian/patches/sipwise/permissions_add_register_allow_with_port_check.patch +++ /dev/null @@ -1,131 +0,0 @@ ---- a/src/modules/permissions/permissions.c -+++ b/src/modules/permissions/permissions.c -@@ -123,6 +123,9 @@ static int allow_routing_2( - static int allow_register_1(struct sip_msg *msg, char *basename, char *s); - static int allow_register_2( - struct sip_msg *msg, char *allow_file, char *deny_file); -+static int allow_register_include_port_1(struct sip_msg *msg, char *basename, char *s); -+static int allow_register_include_port_2( -+ struct sip_msg *msg, char *allow_file, char *deny_file); - static int allow_uri(struct sip_msg *msg, char *basename, char *uri); - - static int mod_init(void); -@@ -142,6 +145,10 @@ static cmd_export_t cmds[] = { - REQUEST_ROUTE | FAILURE_ROUTE}, - {"allow_register", (cmd_function)allow_register_2, 2, load_fixup, 0, - REQUEST_ROUTE | FAILURE_ROUTE}, -+ {"allow_register_include_port", (cmd_function)allow_register_include_port_1, 1, -+ single_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, -+ {"allow_register_include_port", (cmd_function)allow_register_include_port_2, 2, -+ load_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"allow_trusted", (cmd_function)allow_trusted_0, 0, 0, 0, ANY_ROUTE}, - {"allow_trusted", (cmd_function)allow_trusted_2, 2, fixup_spve_spve, - fixup_free_spve_spve, ANY_ROUTE}, -@@ -285,7 +292,7 @@ static int find_index(rule_file_t *array - * sip:username@domain, resulting buffer is statically allocated and - * zero terminated - */ --static char *get_plain_uri(const str *uri) -+static char *get_plain_uri(const str *uri, int check_port) - { - static char buffer[EXPRESSION_LENGTH + 1]; - struct sip_uri puri; -@@ -300,9 +307,14 @@ static char *get_plain_uri(const str *ur - } - - if(puri.user.len) { -- len = puri.user.len + puri.host.len + 5; -+ len = puri.user.len + puri.host.len + 5; /* +5 is 'sip:' and '@' */ - } else { -- len = puri.host.len + 4; -+ len = puri.host.len + 4; /* +4 is 'sip:' */ -+ } -+ -+ if(check_port && puri.port.len) { -+ LM_DBG("Port number will also be used to check the Contact value\n"); -+ len += (puri.port.len + 1); /* +1 is ':' */ - } - - if(len > EXPRESSION_LENGTH) { -@@ -312,11 +324,19 @@ static char *get_plain_uri(const str *ur - - strcpy(buffer, "sip:"); - if(puri.user.len) { -- memcpy(buffer + 4, puri.user.s, puri.user.len); -+ memcpy(buffer + 4, puri.user.s, puri.user.len); /* +4 is 'sip:' */ - buffer[puri.user.len + 4] = '@'; -- memcpy(buffer + puri.user.len + 5, puri.host.s, puri.host.len); -+ memcpy(buffer + puri.user.len + 5, puri.host.s, puri.host.len); /* +5 is 'sip:' and '@' */ -+ if (check_port && puri.port.len) { -+ buffer[puri.user.len + puri.host.len + 5] = ':'; -+ memcpy(buffer + puri.user.len + puri.host.len + 6, puri.port.s, puri.port.len); /* +6 is 'sip:', '@' and ':' */ -+ } - } else { - memcpy(buffer + 4, puri.host.s, puri.host.len); -+ if (check_port && puri.port.len) { -+ buffer[puri.host.len + 4] = ':'; -+ memcpy(buffer + puri.host.len + 5, puri.port.s, puri.port.len); /* +5 is 'sip:' and ':' */ -+ } - } - - buffer[len] = '\0'; -@@ -416,7 +436,7 @@ check_branches: - br_idx, &branch.len, &q, 0, 0, 0, 0, 0, 0, 0)) - != 0; - br_idx++) { -- uri_str = get_plain_uri(&branch); -+ uri_str = get_plain_uri(&branch, 0); - if(!uri_str) { - LM_ERR("failed to extract plain URI\n"); - return -1; -@@ -755,9 +775,11 @@ int allow_routing_2(struct sip_msg *msg, - * against rules in allow and deny files passed as parameters. The function - * iterates over all Contacts and creates a pair with To for each contact - * found. That allows to restrict what IPs may be used in registrations, for -- * example -+ * example. -+ * -+ * If check_port is 0, then port isn't taken into account. - */ --static int check_register(struct sip_msg *msg, int idx) -+static int check_register(struct sip_msg *msg, int idx, int check_port) - { - int len; - static char to_str[EXPRESSION_LENGTH + 1]; -@@ -821,7 +843,8 @@ static int check_register(struct sip_msg - } - - while(c) { -- contact_str = get_plain_uri(&c->uri); -+ /* if check_port = 1, then port is included into regex check */ -+ contact_str = get_plain_uri(&c->uri, check_port); - if(!contact_str) { - LM_ERR("can't extract plain Contact URI\n"); - return -1; -@@ -854,15 +877,23 @@ static int check_register(struct sip_msg - - int allow_register_1(struct sip_msg *msg, char *basename, char *s) - { -- return check_register(msg, (int)(long)basename); -+ return check_register(msg, (int)(long)basename, 0); - } - -- - int allow_register_2(struct sip_msg *msg, char *allow_file, char *deny_file) - { -- return check_register(msg, (int)(long)allow_file); -+ return check_register(msg, (int)(long)allow_file, 0); - } - -+int allow_register_include_port_1(struct sip_msg *msg, char *basename, char *s) -+{ -+ return check_register(msg, (int)(long)basename, 1); -+} -+ -+int allow_register_include_port_2(struct sip_msg *msg, char *allow_file, char *deny_file) -+{ -+ return check_register(msg, (int)(long)allow_file, 1); -+} - - /* - * determines the permission to an uri diff --git a/debian/patches/upstream/permissions_add_register_allow_with_port_check.patch b/debian/patches/upstream/permissions_add_register_allow_with_port_check.patch new file mode 100644 index 000000000..5c81a0665 --- /dev/null +++ b/debian/patches/upstream/permissions_add_register_allow_with_port_check.patch @@ -0,0 +1,370 @@ +From 534a35956b1a79598dcd2436248c5d7ce4e92da8 Mon Sep 17 00:00:00 2001 +From: Donat Zenichev +Date: Fri, 10 May 2024 09:43:28 +0200 +Subject: [PATCH] permissions: introduce func `allow_register_include_port()` + +Introduce new function: `allow_register_include_port()` +to be able to check the whole Contact header including port. + +Example, register.deny content is: + ALL : "^sip:.*192.168.0.101:5062" + +If the Contact is: "Contact: " +then this will check the Contact hf including port of it. + +Otherwise if usual `allow_register()` function is used, +then only the "testuser1004@192.168.0.101" will be taken into +account, which will lead the regex to be failing and letting +the check to pass through. + +The func `allow_register_include_port()` works similarly +as `allow_register()` except it checks Contact's port. + +Full backwards compatibility is kept in place, +no need for users of the module to change anything in +their configuration or kamailio script itself. +--- + src/modules/permissions/doc/permissions.xml | 7 + + .../permissions/doc/permissions_admin.xml | 142 ++++++++++++++++++ + src/modules/permissions/permissions.c | 63 ++++++-- + 3 files changed, 200 insertions(+), 12 deletions(-) + +diff --git a/src/modules/permissions/doc/permissions.xml b/src/modules/permissions/doc/permissions.xml +index 10b16ae1e9..a8adfdf944 100644 +--- a/src/modules/permissions/doc/permissions.xml ++++ b/src/modules/permissions/doc/permissions.xml +@@ -48,6 +48,13 @@ + eschmidbauer@voipxswitch.com + + ++ ++ Donat ++ Zenichev ++
++ dzenichev@sipwise.com ++
++
+ + + 2003 +diff --git a/src/modules/permissions/doc/permissions_admin.xml b/src/modules/permissions/doc/permissions_admin.xml +index 4ddde99d62..494a7ecc0f 100644 +--- a/src/modules/permissions/doc/permissions_admin.xml ++++ b/src/modules/permissions/doc/permissions_admin.xml +@@ -121,6 +121,8 @@ + similar to the algorithm described in + . The only difference is in the way + how pairs are created. ++ Additionally one can use allow_register_include_port ++ function in order to include the port value of the Contact into the check. + + + Instead of the From header field the function uses the To header field because +@@ -384,6 +386,7 @@ modparam("permissions", "check_all_branches", 0) + Suffix to be appended to basename to create filename of the allow + file when version with one parameter of either + allow_routing or ++ allow_register_include_port or + allow_register is used. + + +@@ -411,6 +414,7 @@ modparam("permissions", "allow_suffix", ".allow") + Suffix to be appended to basename to create filename of the deny file + when version with one parameter of either + allow_routing or ++ allow_register_include_port or + allow_register is used. + + +@@ -1094,6 +1098,98 @@ if (method=="REGISTER") { + }; + }; + ... ++ ++ ++ ++
++ ++ <function moreinfo="none">allow_register_include_port(basename)</function> ++ ++ ++ The function does exacty the same thing as allow_register(basename) ++ apart that it tells the module to include the port value of Contact into the check. ++ No additional function parameters required. ++ ++ Meaning of the parameters is as follows: ++ ++ ++ basename - Basename from which allow ++ and deny filenames will be created by appending contents of ++ allow_suffix and deny_suffix ++ parameters. ++ ++ ++ If the parameter doesn't contain full pathname then the function ++ expects the file to be located in the same directory as the main ++ configuration file of the server. ++ ++ ++ ++ ++ This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. ++ ++ ++ <function>allow_register_include_port(basename)</function> usage ++ ++... ++if (method=="REGISTER") { ++ if (allow_register_include_port("register")) { ++ save("location"); ++ exit; ++ } else { ++ sl_send_reply("403", "Forbidden"); ++ }; ++}; ++... ++ ++ ++
++
++ ++ <function moreinfo="none">allow_register_include_port(allow_file, deny_file)</function> ++ ++ ++ The function does exacty the same thing as allow_register(allow_file, deny_file) ++ apart that it tells the module to include the port value of Contact into the check. ++ No additional function parameters required. ++ ++ Meaning of the parameters is as follows: ++ ++ ++ allow_file - File containing allow rules. ++ ++ ++ If the parameter doesn't contain full pathname then the function ++ expects the file to be located in the same directory as the main ++ configuration file of the server. ++ ++ ++ ++ deny_file - File containing deny rules. ++ ++ ++ If the parameter doesn't contain full pathname then the function ++ expects the file to be located in the same directory as the main ++ configuration file of the server. ++ ++ ++ ++ ++ This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. ++ ++ ++ <function>allow_register_include_port(allow_file, deny_file)</function> usage ++ ++... ++if (method=="REGISTER") { ++ if (allow_register_include_port("register.allow", "register.deny")) { ++ save("location"); ++ exit; ++ } else { ++ sl_send_reply("403", "Forbidden"); ++ }; ++}; ++... + + +
+@@ -1492,4 +1588,50 @@ if (allow_trusted("$si", "any", "$ai")) { + + + ++
++ Register File Format ++ ++ It is a text file with one record per line. Lines starting with '#' are ++ considered comments and ignored. Comments can be also at the end of ++ records, by using '#' to start the comment part of the line. ++ ++ ++ Each record line has the format: ++ ++ ++... ++(from_list,str) (req_uri_list,str) ++... ++ ++ ++ The 'str' indicates that the value has to be a string compatible with ++ POSIX Extended Regular Expressions. ++ ++ ++ Register File Sample ++ ++... ++# Syntax: ++# from_list [EXCEPT from_list] : req_uri_list [EXCEPT req_uri_list] ++# ++# from_list and req_uri_list are comma separated expressions ++# Expressions are treated as case insensitive POSIX Extended Regular Expressions. ++# Keyword ALL matches any expression. ++# ++# Examples (requires a usage of allow_register() function): ++# ALL : "^sip:361[0-9]*@abc\.com$" EXCEPT "^sip:361[0-9]*3@abc\.com$", "^sip:361[0-9]*4@abc\.com$" ++# ++# "^sip:3677[0-9]*@abc\.com$" : "^sip:361[0-9]*@abc\.com$" ++# ++# All : ALL ++# ++# Examples including port check (requires a usage of allow_register_include_port() function): ++# ++# ALL : "^sip:.*@192.168.0.1:5062" ++... ++ ++ ++ ++
++ + +diff --git a/src/modules/permissions/permissions.c b/src/modules/permissions/permissions.c +index 2b860b81b2..f91f1a0f11 100644 +--- a/src/modules/permissions/permissions.c ++++ b/src/modules/permissions/permissions.c +@@ -123,6 +123,10 @@ static int allow_routing_2( + static int allow_register_1(struct sip_msg *msg, char *basename, char *s); + static int allow_register_2( + struct sip_msg *msg, char *allow_file, char *deny_file); ++static int allow_register_include_port_1( ++ struct sip_msg *msg, char *basename, char *s); ++static int allow_register_include_port_2( ++ struct sip_msg *msg, char *allow_file, char *deny_file); + static int allow_uri(struct sip_msg *msg, char *basename, char *uri); + + static int mod_init(void); +@@ -142,6 +146,12 @@ static cmd_export_t cmds[] = { + REQUEST_ROUTE | FAILURE_ROUTE}, + {"allow_register", (cmd_function)allow_register_2, 2, load_fixup, 0, + REQUEST_ROUTE | FAILURE_ROUTE}, ++ {"allow_register_include_port", ++ (cmd_function)allow_register_include_port_1, 1, single_fixup, 0, ++ REQUEST_ROUTE | FAILURE_ROUTE}, ++ {"allow_register_include_port", ++ (cmd_function)allow_register_include_port_2, 2, load_fixup, 0, ++ REQUEST_ROUTE | FAILURE_ROUTE}, + {"allow_trusted", (cmd_function)allow_trusted_0, 0, 0, 0, ANY_ROUTE}, + {"allow_trusted", (cmd_function)allow_trusted_2, 2, fixup_spve_spve, + fixup_free_spve_spve, ANY_ROUTE}, +@@ -285,7 +295,7 @@ static int find_index(rule_file_t *array, char *pathname) + * sip:username@domain, resulting buffer is statically allocated and + * zero terminated + */ +-static char *get_plain_uri(const str *uri) ++static char *get_plain_uri(const str *uri, int check_port) + { + static char buffer[EXPRESSION_LENGTH + 1]; + struct sip_uri puri; +@@ -300,9 +310,14 @@ static char *get_plain_uri(const str *uri) + } + + if(puri.user.len) { +- len = puri.user.len + puri.host.len + 5; ++ len = puri.user.len + puri.host.len + 5; /* +5 is 'sip:' and '@' */ + } else { +- len = puri.host.len + 4; ++ len = puri.host.len + 4; /* +4 is 'sip:' */ ++ } ++ ++ if(check_port && puri.port.len) { ++ LM_DBG("Port number will also be used to check the Contact value\n"); ++ len += (puri.port.len + 1); /* +1 is ':' */ + } + + if(len > EXPRESSION_LENGTH) { +@@ -312,11 +327,22 @@ static char *get_plain_uri(const str *uri) + + strcpy(buffer, "sip:"); + if(puri.user.len) { +- memcpy(buffer + 4, puri.user.s, puri.user.len); ++ memcpy(buffer + 4, puri.user.s, puri.user.len); /* +4 is 'sip:' */ + buffer[puri.user.len + 4] = '@'; +- memcpy(buffer + puri.user.len + 5, puri.host.s, puri.host.len); ++ memcpy(buffer + puri.user.len + 5, puri.host.s, ++ puri.host.len); /* +5 is 'sip:' and '@' */ ++ if(check_port && puri.port.len) { ++ buffer[puri.user.len + puri.host.len + 5] = ':'; ++ memcpy(buffer + puri.user.len + puri.host.len + 6, puri.port.s, ++ puri.port.len); /* +6 is 'sip:', '@' and ':' */ ++ } + } else { + memcpy(buffer + 4, puri.host.s, puri.host.len); ++ if(check_port && puri.port.len) { ++ buffer[puri.host.len + 4] = ':'; ++ memcpy(buffer + puri.host.len + 5, puri.port.s, ++ puri.port.len); /* +5 is 'sip:' and ':' */ ++ } + } + + buffer[len] = '\0'; +@@ -416,7 +442,7 @@ check_branches: + br_idx, &branch.len, &q, 0, 0, 0, 0, 0, 0, 0)) + != 0; + br_idx++) { +- uri_str = get_plain_uri(&branch); ++ uri_str = get_plain_uri(&branch, 0); + if(!uri_str) { + LM_ERR("failed to extract plain URI\n"); + return -1; +@@ -755,9 +781,11 @@ int allow_routing_2(struct sip_msg *msg, char *allow_file, char *deny_file) + * against rules in allow and deny files passed as parameters. The function + * iterates over all Contacts and creates a pair with To for each contact + * found. That allows to restrict what IPs may be used in registrations, for +- * example ++ * example. ++ * ++ * If check_port is 0, then port isn't taken into account. + */ +-static int check_register(struct sip_msg *msg, int idx) ++static int check_register(struct sip_msg *msg, int idx, int check_port) + { + int len; + static char to_str[EXPRESSION_LENGTH + 1]; +@@ -821,7 +849,8 @@ static int check_register(struct sip_msg *msg, int idx) + } + + while(c) { +- contact_str = get_plain_uri(&c->uri); ++ /* if check_port = 1, then port is included into regex check */ ++ contact_str = get_plain_uri(&c->uri, check_port); + if(!contact_str) { + LM_ERR("can't extract plain Contact URI\n"); + return -1; +@@ -854,13 +883,23 @@ static int check_register(struct sip_msg *msg, int idx) + + int allow_register_1(struct sip_msg *msg, char *basename, char *s) + { +- return check_register(msg, (int)(long)basename); ++ return check_register(msg, (int)(long)basename, 0); + } + +- + int allow_register_2(struct sip_msg *msg, char *allow_file, char *deny_file) + { +- return check_register(msg, (int)(long)allow_file); ++ return check_register(msg, (int)(long)allow_file, 0); ++} ++ ++int allow_register_include_port_1(struct sip_msg *msg, char *basename, char *s) ++{ ++ return check_register(msg, (int)(long)basename, 1); ++} ++ ++int allow_register_include_port_2( ++ struct sip_msg *msg, char *allow_file, char *deny_file) ++{ ++ return check_register(msg, (int)(long)allow_file, 1); + } + + +-- +2.34.1 +