From d87beebd524ad2592b44eac91efb4bf01a3a2377 Mon Sep 17 00:00:00 2001 From: =?utf8?q?T=C3=BAlio=20Cavalcanti?= Date: Tue, 18 Sep 2018 15:12:10 +0200 Subject: [PATCH] RedirectHash class created in restricted_html file class used to find all redirect urls in a html text and add a query parameter "urlauth" with a hash as value to them. --- CMakeLists.txt | 5 ++ src/CMakeLists.txt | 3 +- src/restricted_html.cpp | 83 +++++++++++++++++++++++++++++++++++++++++ src/restricted_html.hpp | 27 ++++++++++++- test/test_crypto.cpp | 4 +- test/test_restricted_html.cpp | 52 +++++++++++++++++++++++++ 6 files changed, 169 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d53b6..918945b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,11 @@ include(FindPkgConfig) # Find Boost find_package(Boost 1.44 COMPONENTS iostreams unit_test_framework thread REQUIRED) +# Find pcrecpp +pkg_check_modules(PCRECPP REQUIRED libpcrecpp) +INCLUDE_DIRECTORIES(${PCRECPP_INCLUDE_DIRS}) +LINK_DIRECTORIES(${PCRECPP_LIBRARY_DIRS}) + # Find libxml++ if (BUILD_XMLLIB) pkg_check_modules(XMLPP REQUIRED libxml++-2.6) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 605b81e..a1894cc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -66,7 +66,8 @@ target_link_libraries(i2ncommon ${Boost_IOSTREAMS_LIBRARIES} ${Boost_THREAD_LIBRARIES} ${ICONV_LIBRARIES} - ${OPENSSL_LIBRARIES}) + ${OPENSSL_LIBRARIES} + ${PCRECPP_LIBRARIES}) set_target_properties(i2ncommon PROPERTIES VERSION ${VERSION} SOVERSION 7) set_target_properties(i2ncommon PROPERTIES OUTPUT_NAME i2ncommon CLEAN_DIRECT_OUTPUT 1) diff --git a/src/restricted_html.cpp b/src/restricted_html.cpp index d59bcff..85424fa 100644 --- a/src/restricted_html.cpp +++ b/src/restricted_html.cpp @@ -30,6 +30,10 @@ on this file might be covered by the GNU General Public License. #include #include +#include +#include +#include "crypto.hxx" +#include "filefunc.hxx" using namespace std; @@ -164,4 +168,83 @@ string encode_url(string s) return out.str(); } + +/** +* @brief Change the attribute Filename from which the SecretId is going +* to be read. +* +* @param s custom_filename string new filename. +*/ +void RedirectHash::set_custom_filename(string custom_filename) +{ + Filename = custom_filename; +} + +/** +* @brief Reads the file Filename and loads the data into SecretId. +*/ +void RedirectHash::load_secret_id() +{ + SecretId = read_file(Filename); + + if (SecretId.empty()) + throw runtime_error("Inexistent file or empty"); +} + +/** +* @brief Hashes the given url with the SecretId and returns a base64 hash. +* +* @param s &url string. +* +* @return base64 raw hash +*/ +string RedirectHash::hash_url(const string &url) +{ + if (SecretId.empty()) + load_secret_id(); + + return base64_encode(hash_data_raw(url + SecretId, MD5)); +} + +/** +* @brief Reads a HTML file, removes all ##BEGIN_URL## and ##END_URL## tags and +* adds urlauth param to the url in between these tags. +* +* @param s &html string. +* +* @return new html with the urls signed +*/ +string RedirectHash::sign_urls(const string &html) +{ + string ret(html); + string url; + string re = "##BEGIN_URL##(.*?)##END_URL##"; + pcrecpp::RE re_match(re); + while (re_match.PartialMatch(ret, &url)) + { + string hashed_url = hash_url(url); + + replace_all(ret, + "##BEGIN_URL##" + url + "##END_URL##", + encode_url(url) + "&urlauth=" + encode_url(hashed_url)); + } + return ret; +} + +/** +* @brief Validates if the given url is the correspondent url to the given +* authtag hash. +* +* @param s &url string; +* &authtag string hash; +* +* @return bool true if the given url is the correspondent url to the +* authtag hash, else returns false +*/ +bool RedirectHash::validate_redirect_authtag(const string &url, + const string &authtag) +{ + return authtag == hash_url(url); +} + } // eo namespace I2n diff --git a/src/restricted_html.hpp b/src/restricted_html.hpp index 09b3d14..1d84c6d 100644 --- a/src/restricted_html.hpp +++ b/src/restricted_html.hpp @@ -33,9 +33,32 @@ namespace I2n { - std::string decode_url(std::string s); +std::string decode_url(std::string s); - std::string encode_url(std::string s); +std::string encode_url(std::string s); + + +class RedirectHash +{ + public: + RedirectHash() : Filename("/var/intranator/etc/redirect_secret_id"){} + + void set_custom_filename(std::string custom_filename); + + void load_secret_id(); + + std::string hash_url(const std::string &url); + + std::string sign_urls(const std::string &html); + + bool validate_redirect_authtag(const std::string &url, + const std::string &authtag); + + private: + std::string Filename; + + std::string SecretId; +}; } // eo namespace I2n diff --git a/test/test_crypto.cpp b/test/test_crypto.cpp index 6f3edff..ac83656 100644 --- a/test/test_crypto.cpp +++ b/test/test_crypto.cpp @@ -40,7 +40,7 @@ class TestCryptoFixture { protected: - char* Filename; + string Filename; tmpfstream Tempfile; @@ -51,7 +51,7 @@ protected: Tempfile << "Long Data and or Password"; Tempfile.close(); - Filename = (char*)Tempfile.get_tmp_filename().c_str(); + Filename = Tempfile.get_tmp_filename(); } public: diff --git a/test/test_restricted_html.cpp b/test/test_restricted_html.cpp index d744ed2..bc95180 100644 --- a/test/test_restricted_html.cpp +++ b/test/test_restricted_html.cpp @@ -25,6 +25,7 @@ on this file might be covered by the GNU General Public License. */ #define BOOST_TEST_DYN_LINK #include +#include #include @@ -61,4 +62,55 @@ BOOST_AUTO_TEST_CASE(EncodeStringURL2) output); } +BOOST_AUTO_TEST_CASE(RedirectHash1) +{ + tmpfstream TempFile; + string TempFilePattern = "/tmp/libi2ncommon_test_restricted_html_XXXXXX"; + TempFile.open(TempFilePattern); + TempFile << "ABCDEF"; + TempFile.close(); + + RedirectHash redirect_hash = RedirectHash(); + redirect_hash.set_custom_filename(TempFile.get_tmp_filename()); + + string url1 = "http://www.domain.com/params?param=p"; + string url2 = "http://www.google.com/search?q=test"; + + string url1_encoded = "http%3A%2F%2Fwww%2Edomain%2Ecom%2Fparams%3Fparam%3Dp"; + string url2_encoded = "http%3A%2F%2Fwww%2Egoogle%2Ecom%2Fsearch%3Fq%3Dtest"; + + string hash1 = "a2Dlksjt5kBrt6Or4nKdxQ=="; + string hash2 = "2BdwBA6vlqJS/3vWzUxa1w=="; + + string hash1_encoded = "a2Dlksjt5kBrt6Or4nKdxQ%3D%3D"; + string hash2_encoded = "2BdwBA6vlqJS%2F3vWzUxa1w%3D%3D"; + + BOOST_CHECK_EQUAL(encode_url(url1) , url1_encoded); + BOOST_CHECK_EQUAL(encode_url(url2) , url2_encoded); + + const string html = ("" + "Further information" + "Further information" + ""); + + const string result = ("" + "Further information" + "Further information" + ""); + + + string new_html = redirect_hash.sign_urls(html); + + BOOST_CHECK_EQUAL(result, new_html); + + BOOST_CHECK(redirect_hash.validate_redirect_authtag(url1, hash1)); + BOOST_CHECK(redirect_hash.validate_redirect_authtag(url2, hash2)); + + TempFile.unlink(); +} + BOOST_AUTO_TEST_SUITE_END() -- 1.7.1