#include <cstdlib>
#include <sys/types.h>
#include <grp.h>
+#include <map>
#include <pwd.h>
using namespace ldp_xml_parser;
+using boost::property_tree::ptree;
static const char* message_type[] = { "ANY", "METHOD_CALL", "METHOD_RETURN", "ERROR", "SIGNAL"};
static const char* message_dir[] = { "ANY", "SEND", "RECEIVE"};
return message_decision[static_cast<std::size_t>(dec)];
}
-DbAdapter::DbAdapter() : __attr(false), __tag_state(NONE) {
-}
-
static uid_t convertToUid(const char* user) {
long val = -1;
errno = 0;
return gg->gr_gid;
}
-static bool field_has(const boost::property_tree::ptree::value_type& v, const std::string& substr) {
+static bool field_has(const ptree::value_type& v, const std::string& substr) {
return (v.first.find(substr) != std::string::npos);
}
-void DbAdapter::updateDecision(const boost::property_tree::ptree::value_type& v,
- PolicyType& policy_type,
- PolicyTypeValue& policy_type_value,
- state& t,
- bool& attr) {
- const char* value = NULL;
- if (v.first == "allow" && t == POLICY) {
- __builder.reset();
- __builder.addDecision(Decision::ALLOW);
- t = ALLOW_DENY_CHECK;
- attr = false;
- } else if (v.first == "deny" && t == POLICY) {
- __builder.reset();
- __builder.addDecision(Decision::DENY);
- t = ALLOW_DENY_CHECK;
- attr = false;
- } else if (v.first == "check" && t == POLICY) {
- __builder.reset();
- __builder.addDecision(Decision::CHECK);
- t = ALLOW_DENY_CHECK;
- attr = false;
- } else if (v.first == "<xmlattr>") {
- attr = true;
- } else if (attr && t == POLICY) {
- if (v.second.data() != "*")
- value = v.second.data().c_str();
-
- if (value) {
- if (v.first == "context") {
- if (std::strcmp(value, "mandatory") == 0 ) {
- policy_type = PolicyType::CONTEXT;
- policy_type_value.context = ContextType::MANDATORY;
- } else if (std::strcmp(value, "default") == 0) {
- policy_type = PolicyType::CONTEXT;
- policy_type_value.context = ContextType::DEFAULT;
- }
- } else if (v.first == "user") {
- policy_type = PolicyType::USER;
- policy_type_value.user = convertToUid(value);
- } else if (v.first == "group") {
- policy_type = PolicyType::GROUP;
- policy_type_value.group = convertToGid(value);
- }
- }
- } else if (attr && t == ALLOW_DENY_CHECK) {
- if (v.second.data() != "*")
- value = v.second.data().c_str();
-
- if (field_has(v, "send_")) {
- __builder.addDirection(MessageDirection::SEND);
- } else if (field_has(v, "receive_")) {
- __builder.addDirection(MessageDirection::RECEIVE);
- } else if (v.first == "own") {
- __builder.addOwner(value);
- __builder.setPrefix(false);
- } else if (v.first == "own_prefix") {
- __builder.addOwner(value);
- __builder.setPrefix(true);
- } else if (v.first == "privilege") {
- __builder.addPrivilege(value);
+void DbAdapter::updateDb(bool bus, const ptree& pt, std::vector<std::string>& incl_dirs) {
+ const auto& busconfig = pt.get_child("busconfig");
+ for (const auto& x : busconfig) {
+ if (x.first == "policy") {
+ parsePolicy(bus, x.second);
+ } else if (x.first == "includedir") {
+ incl_dirs.push_back(x.second.data());
}
-
- if (field_has(v, "_destination"))
- __builder.addName(value);
- else if (field_has(v, "_sender"))
- __builder.addName(value);
- else if (field_has(v, "_path"))
- __builder.addPath(value);
- else if (field_has(v, "_interface"))
- __builder.addInterface(value);
- else if (field_has(v, "_member"))
- __builder.addMember(value);
- else if (field_has(v, "_type"))
- __builder.addMessageType(__str_to_message_type(value));
- } else {
- attr = false;
- t = NONE;
}
}
-void DbAdapter::xmlTraversal(bool bus,
- const boost::property_tree::ptree& pt,
- DbAdapter::state tag,
- PolicyType& policy_type,
- PolicyTypeValue& policy_type_value,
- bool attr,
- int level) {
- static const int Q_XML_MAX_LEVEL = 10;
- if (level < Q_XML_MAX_LEVEL) {
- for(const auto& v : pt) {
- if (v.first == "<xmlcomment>") { continue; }
- state t = tag;
- updateDecision(v, policy_type, policy_type_value, t, attr);
- xmlTraversal(bus, v.second, t, policy_type, policy_type_value, attr, level + 1);
+static const std::map<std::string, Decision> str2decision{
+ {"allow", Decision::ALLOW},
+ {"deny", Decision::DENY},
+ {"check", Decision::CHECK}};
+
+void DbAdapter::parsePolicy(bool bus, const ptree& pt)
+{
+ PolicyType policy_type = PolicyType::NONE;
+ PolicyTypeValue policy_type_value;
+
+ // we must read policy attrs before parsing rules, as ptree API
+ // doesn't guarantee that <xmlattr> will occur before other
+ // child elements
+ const auto xmlattr = pt.get_child_optional("<xmlattr>");
+ if (xmlattr) {
+ for (const auto& va : *xmlattr) {
+ parsePolicyAttribute(va, policy_type, policy_type_value);
}
- if (!pt.empty() && level > 1)
+ }
+ if (policy_type == PolicyType::NONE) {
+ return;
+ }
+ for (const auto& v : pt) {
+ if (str2decision.find(v.first) != str2decision.end()) {
+ parseRule(v);
__builder.generateItem(policy_checker().db(bus), policy_type, policy_type_value);
+ }
}
}
-void DbAdapter::updateDb(bool bus, boost::property_tree::ptree& xmlTree, std::vector<std::string>& incl_dirs) {
- const auto& children = xmlTree.get_child("busconfig");
- PolicyType policy_type;
- PolicyTypeValue policy_type_value;
- for (const auto& x : children) {
- if (x.first == "policy") {
- __tag_state = POLICY;
- __attr = false;
- xmlTraversal(bus, x.second, POLICY, policy_type, policy_type_value);
- } else if (x.first == "includedir") {
- incl_dirs.push_back(x.second.data());
+void DbAdapter::parsePolicyAttribute(const ptree::value_type& v, PolicyType& policy_type, PolicyTypeValue& policy_type_value)
+{
+ //possible values (from dbus-daemon man):
+ // context="(default|mandatory)"
+ // at_console="(true|false)" (deprecated and not used on targets, we ignore it)
+ // user="username or userid"
+ // group="group name or gid"
+ const char* value = v.second.data().c_str();
+ if (v.first == "context") {
+ if (std::strcmp(value, "mandatory") == 0 ) {
+ policy_type = PolicyType::CONTEXT;
+ policy_type_value.context = ContextType::MANDATORY;
+ } else if (std::strcmp(value, "default") == 0) {
+ policy_type = PolicyType::CONTEXT;
+ policy_type_value.context = ContextType::DEFAULT;
+ }
+ } else if (v.first == "user") {
+ policy_type = PolicyType::USER;
+ policy_type_value.user = convertToUid(value);
+ } else if (v.first == "group") {
+ policy_type = PolicyType::GROUP;
+ policy_type_value.group = convertToGid(value);
+ }
+}
+
+void DbAdapter::parseRule(const ptree::value_type& v)
+{
+ __builder.reset();
+ __builder.addDecision(str2decision.at(v.first));
+
+ const auto xmlattr = v.second.get_child_optional("<xmlattr>");
+ if (xmlattr) {
+ for (const auto& va : *xmlattr) {
+ parseRuleAttribute(va);
}
}
}
+void DbAdapter::parseRuleAttribute(const ptree::value_type& v)
+{
+ const char* value = nullptr;
+ if (v.second.data() != "*")
+ value = v.second.data().c_str();
+
+ if (field_has(v, "send_")) {
+ __builder.addDirection(MessageDirection::SEND);
+ } else if (field_has(v, "receive_")) {
+ __builder.addDirection(MessageDirection::RECEIVE);
+ } else if (v.first == "own") {
+ __builder.addOwner(value);
+ __builder.setPrefix(false);
+ } else if (v.first == "own_prefix") {
+ __builder.addOwner(value);
+ __builder.setPrefix(true);
+ } else if (v.first == "privilege") {
+ __builder.addPrivilege(value);
+ }
+
+ if (field_has(v, "_destination"))
+ __builder.addName(value);
+ else if (field_has(v, "_sender"))
+ __builder.addName(value);
+ else if (field_has(v, "_path"))
+ __builder.addPath(value);
+ else if (field_has(v, "_interface"))
+ __builder.addInterface(value);
+ else if (field_has(v, "_member"))
+ __builder.addMember(value);
+ else if (field_has(v, "_type"))
+ __builder.addMessageType(__str_to_message_type(value));
+}
+
void DbAdapter::updateGroupDb(bool bus)
{
policy_checker().db(bus).updateSupGroup();