diff --git a/userspace/engine/falco_utils.cpp b/userspace/engine/falco_utils.cpp index a52cf591..25cf4ceb 100644 --- a/userspace/engine/falco_utils.cpp +++ b/userspace/engine/falco_utils.cpp @@ -20,6 +20,7 @@ limitations under the License. #include #include +#include "falco_common.h" #include "falco_utils.h" #include "utils.h" @@ -159,6 +160,81 @@ void readfile(const std::string& filename, std::string& data) return; } + +// URI-decodes the given string by replacing percent-encoded +// characters with the actual character. Returns the decoded string. +// +// When plus_as_space is true, non-encoded plus signs in the query are decoded as spaces. +// (http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1) +std::string decode_uri(const std::string& str, bool plus_as_space) +{ + std::string decoded_str; + bool in_query = false; + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + while(it != end) + { + char c = *it++; + if(c == '?') + { + in_query = true; + } + // spaces may be encoded as plus signs in the query + if(in_query && plus_as_space && c == '+') + { + c = ' '; + } + else if(c == '%') + { + if (it == end) + { + throw falco_exception("URI encoding: no hex digit following percent sign in " + str); + } + char hi = *it++; + if (it == end) + { + throw falco_exception("URI encoding: two hex digits must follow percent sign in " + str); + } + char lo = *it++; + if (hi >= '0' && hi <= '9') + { + c = hi - '0'; + } + else if (hi >= 'A' && hi <= 'F') + { + c = hi - 'A' + 10; + } + else if (hi >= 'a' && hi <= 'f') + { + c = hi - 'a' + 10; + } + else + { + throw falco_exception("URI encoding: not a hex digit found in " + str); + } + c *= 16; + if (lo >= '0' && lo <= '9') + { + c += lo - '0'; + } + else if (lo >= 'A' && lo <= 'F') + { + c += lo - 'A' + 10; + } + else if (lo >= 'a' && lo <= 'f') + { + c += lo - 'a' + 10; + } + else + { + throw falco_exception("URI encoding: not a hex digit"); + } + } + decoded_str += c; + } + return decoded_str; +} + namespace network { bool is_unix_scheme(const std::string& url) diff --git a/userspace/engine/falco_utils.h b/userspace/engine/falco_utils.h index 38bc5c9f..81873077 100644 --- a/userspace/engine/falco_utils.h +++ b/userspace/engine/falco_utils.h @@ -52,6 +52,8 @@ void readfile(const std::string& filename, std::string& data); uint32_t hardware_concurrency(); +std::string decode_uri(const std::string& str, bool plus_as_space); + namespace network { static const std::string UNIX_SCHEME("unix://"); diff --git a/userspace/engine/json_evt.cpp b/userspace/engine/json_evt.cpp index 4a48b80c..5ba6e80d 100644 --- a/userspace/engine/json_evt.cpp +++ b/userspace/engine/json_evt.cpp @@ -17,11 +17,11 @@ limitations under the License. #include -#include "uri.h" #include "utils.h" #include "falco_common.h" #include "json_evt.h" +#include "falco_utils.h" using json = nlohmann::json; using namespace std; @@ -1006,7 +1006,7 @@ bool k8s_audit_filter_check::extract_query_param(const nlohmann::json &j, { std::vector param_parts = sinsp_split(part, '='); - if(param_parts.size() == 2 && uri::decode(param_parts[0], true) == jchk.idx()) + if(param_parts.size() == 2 && falco::utils::decode_uri(param_parts[0], true) == jchk.idx()) { jchk.add_extracted_value(param_parts[1]); return true;