added policy rejected message as input 50/207650/12
authorBaumann <a.baumann@samsung.com>
Thu, 30 May 2019 14:41:19 +0000 (16:41 +0200)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Wed, 26 Jun 2019 05:15:21 +0000 (05:15 +0000)
Change-Id: I15f921221f02d9d8d72097d93aa54f92f91895c0

src/dbuspolicy_finder.cpp

index 17e1516..c25f030 100644 (file)
 #include "internal/storage_backend_xml.hpp"
 #include "internal/uid_gid_helpers.hpp"
 #include "primary-conf-files.c"
+#include <algorithm>
+#include <boost/tokenizer.hpp>
 #include <cassert>
 #include <getopt.h>
 #include <iostream>
+#include <map>
+#include <sstream>
 #include <string>
 #include <vector>
 
@@ -188,6 +192,7 @@ int showHelp() {
                "dbuspolicy-filter {send|receive|access|own} [options]\n"
                "\n"
                "  -c, --configuration {file name} | --session | --system\n"
+               "  -e, --explain      \tread an error message from standard input and find relevant policy rules\n"
                "  -h, --help         \thelp\n"
                "\n"
                "Options for 'send':\n"
@@ -222,6 +227,52 @@ int bailOut(const std::string & error) {
        return EXIT_FAILURE;
 }
 
+void getToken(const std::string & long_name, std::string & interface, std::string & member, MessageType & type, std::string & serviceName,
+               gid_t & numberGroup, uid_t & numberUser, std::string & path)
+{
+       std::string short_name = long_name;
+
+       const auto semicolon = std::find(short_name.begin(), short_name.end(), ';');
+       if (semicolon == short_name.end())
+               throw std::invalid_argument("Error message should contain ';'");
+
+       short_name.erase(short_name.begin(), semicolon + 1);
+
+       std::map<std::string, std::string> elements;
+       typedef boost::char_separator <char> separator_t;
+       typedef boost::tokenizer <separator_t> tokenizer;
+       separator_t separator (" ");
+       tokenizer tokens(short_name, separator);
+
+       const std::map<std::string, const std::function<void(const std::string &)>> values {
+               {  "interface", [&](const std::string & val){ interface = val; }},
+               {     "member", [&](const std::string & val){ member    = val; }},
+               {       "path", [&](const std::string & val){ path      = val; }},
+               {     "sender", [&](const std::string & val){ if (long_name.find("Rejected send"   ) == 0) serviceName = val; }},
+               {"destination", [&](const std::string & val){ if (long_name.find("Rejected receive") == 0) serviceName = val; }},
+               {       "type", [&](const std::string & val){ type = stringToMessageType(val); }},
+               {        "gid", [&](const std::string & val){ numberGroup = std::stoi(val, nullptr, 10); }},
+               {        "uid", [&](const std::string & val){ numberUser  = std::stoi(val, nullptr, 10); }}
+       };
+
+       for (const auto & token : tokens) {
+               size_t pos = token.find("=");
+               if (pos == std::string::npos)
+                       continue;
+
+               const std::string key = token.substr(0, pos);
+               std::string value = token.substr(pos + 1);
+
+               value.erase(std::remove_if(value.begin(), value.end(),
+                       [](char c){ return (c == ' ' || c == '\'' || c == '\"' || c == ','); } ), value.end());
+
+               const auto iter = values.find(key);
+               if (iter != values.end()){
+                       iter->second(value);
+               }
+       }
+}
+
 int main(int argc, char *argv[]) {
        tslog::init();
 
@@ -237,7 +288,7 @@ int main(int argc, char *argv[]) {
        constexpr int SESSION = 1;
        constexpr int SYSTEM = 2;
 
-       const char * const short_opts = ":t:g:u:n:i:p:m:h:c:";
+       const char * const short_opts = ":t:g:u:n:i:p:m:h:c:e";
        const option long_opts[] = {
                {"type"         , required_argument, nullptr,     't'},
                {"group"        , required_argument, nullptr,     'g'},
@@ -250,6 +301,7 @@ int main(int argc, char *argv[]) {
                {"configuration", required_argument, nullptr,     'c'},
                {"session"      ,       no_argument, nullptr, SESSION},
                {"system"       ,       no_argument, nullptr,  SYSTEM},
+               {"explain"      ,       no_argument, nullptr,     'e'},
                {nullptr        ,                 0, nullptr,    '\0'}
        };
 
@@ -301,6 +353,17 @@ int main(int argc, char *argv[]) {
                                return bailOut("Choose only one configuration file!");
                        file_name = system_bus_conf_file_primary();
                        break;
+               case 'e': {
+                       std::string str((std::istreambuf_iterator<char>(std::cin)), std::istreambuf_iterator<char>());
+                       if (str.empty())
+                               return bailOut("There is no error message to read!");
+                       try {
+                               getToken(str, interface, member, type, serviceName, numberGroup, numberUser, path);
+                       } catch (std::invalid_argument & e) {
+                               return bailOut(e.what());
+                       }
+                       break;
+               }
                case '?':
                        return bailOut("Unknown parameter!");
                }