#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>
"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"
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();
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'},
{"configuration", required_argument, nullptr, 'c'},
{"session" , no_argument, nullptr, SESSION},
{"system" , no_argument, nullptr, SYSTEM},
+ {"explain" , no_argument, nullptr, 'e'},
{nullptr , 0, nullptr, '\0'}
};
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!");
}