--- /dev/null
+#include <iostream>
+#include <cstdarg>
+#include <ostream>
+
+#include "internal/include/flatbuffers/flatbuffers.h"
+#include "internal/include/fb_generated.h"
+#include "internal/naive_policy_db.hpp"
+#include "internal/policy_containers.hpp"
+#include "internal/serializer.hpp"
+
+namespace ldp_xml_parser {
+
+static void print_error(const char *fmt...) {
+ va_list args;
+ va_start(args, fmt);
+ printf("[ERROR]: ");
+ vprintf(fmt, args);
+ printf("\n");
+ va_end(args);
+}
+
+std::map<FB::MessageType, const char *> messageTypeMap = {
+ { FB::MessageType_ANY, "ANY" },
+ { FB::MessageType_MIN, "MIN" },
+ { FB::MessageType_MAX, "MAX" },
+ { FB::MessageType_METHOD_RETURN, "METHOD_RETURN" },
+ { FB::MessageType_ERROR, "ERROR" },
+ { FB::MessageType_SIGNAL, "SIGNAL" },
+ { FB::MessageType_METHOD_CALL, "METHOD_CALL" }
+};
+
+std::map<FB::Decision, const char *> decisionTypeMap = {
+ { FB::Decision_ANY, "ANY" },
+ { FB::Decision_MIN, "MIN" },
+ { FB::Decision_MAX, "MAX" },
+ { FB::Decision_CHECK, "CHECK" },
+ { FB::Decision_DENY, "DENY" },
+ { FB::Decision_ALLOW, "ALLOW" }
+};
+
+std::map<FB::BusAccessType, const char *> busTypeMap = {
+ { FB::BusAccessType_MIN, "MIN" },
+ { FB::BusAccessType_MAX, "MAX" },
+ { FB::BusAccessType_USER, "USER" },
+ { FB::BusAccessType_GROUP, "GROUP" },
+ { FB::BusAccessType_ALL_USERS, "ALL_USERS" },
+ { FB::BusAccessType_ALL_GROUPS, "ALL_GROUPS" },
+};
+
+struct TestsHelper {
+ static const char *to_str(const bool value) {
+ return value ? "true" : "false";
+ }
+
+ static const char *to_str(const char *value) {
+ return value;
+ }
+
+ static const char *to_str(const std::string value) {
+ return value.c_str();
+ }
+
+ static const char *to_str(const FB::MessageType value) {
+ return messageTypeMap[value];
+ }
+
+ static const char *to_str(const FB::Decision value) {
+ return decisionTypeMap[value];
+ }
+
+ static const char *to_str(const FB::BusAccessType value) {
+ return busTypeMap[value];
+ }
+
+ template <typename T>
+ static bool compare(const T current, const T expected) {
+ if (current != expected) {
+ // print_error("Current: \"%s\" expected: \"%s\"", to_str(current), to_str(expected));
+ return false;
+ }
+ return true;
+ }
+
+ template <typename T>
+ static void print_property(const char *name, const T value) {
+ std::cout << name << ": " << to_str(value) << std::endl;
+ }
+};
+
+using TH = TestsHelper;
+
+struct NodeTest {
+ const std::string name;
+ const std::string privilege;
+ const FB::Decision decision;
+ const std::string prefix_privilege;
+ const FB::Decision prefix_decision;
+
+ void printContent() const {
+ TH::print_property("name", name);
+ TH::print_property("privilege", privilege);
+ TH::print_property("decision", decision);
+ TH::print_property("prefix_privilege", prefix_privilege);
+ TH::print_property("prefix_decision", prefix_decision);
+ }
+
+ bool isMatch(const FB::PolicyOwnNode *node, const std::string &token) const {
+ return (TH::compare(node->token()->str(), token) &&
+ TH::compare(node->decision_item()->privilege()->str(), privilege) &&
+ TH::compare(node->decision_item()->decision(), decision) &&
+ TH::compare(node->prefix_decision_item()->privilege()->str(), prefix_privilege) &&
+ TH::compare(node->prefix_decision_item()->decision(), prefix_decision));
+ }
+};
+
+struct ItemSRTest {
+ const std::string name;
+ const std::string interface;
+ const std::string member;
+ const std::string path;
+ const FB::MessageType type;
+ const bool is_name_prefix;
+ const FB::Decision decision;
+
+ void printContent() const {
+ TH::print_property("name", name);
+ TH::print_property("interface", interface);
+ TH::print_property("member", member);
+ TH::print_property("path", path);
+ TH::print_property("type", type);
+ TH::print_property("is_name_prefix", is_name_prefix);
+ TH::print_property("decision", decision);
+ }
+
+ template <typename T>
+ bool isMatch(const T *item) const {
+ return TH::compare(item->name()->str(), name) &&
+ TH::compare(item->interface()->str(), interface) &&
+ TH::compare(item->member()->str(), member) &&
+ TH::compare(item->path()->str(), path) &&
+ TH::compare(item->type(), type) &&
+ TH::compare(item->is_name_prefix(), is_name_prefix) &&
+ TH::compare(item->decision()->decision(), decision);
+ }
+};
+
+struct ItemAccessTest {
+ const uid_t uid;
+ const gid_t gid;
+ const FB::Decision decision;
+ const std::string privilege;
+ const FB::BusAccessType type;
+
+ void printContent() const {
+ TH::print_property("uid", uid);
+ TH::print_property("gid", gid);
+ TH::print_property("decision", decision);
+ TH::print_property("privilege", privilege);
+ TH::print_property("type", type);
+ }
+
+ bool isMatch(const FB::ItemAccess *item) const {
+ return TH::compare(item->uid(), uid) &&
+ TH::compare(item->gid(), gid) &&
+ TH::compare(item->decision()->decision(), decision) &&
+ TH::compare(item->decision()->privilege()->str(), privilege) &&
+ TH::compare(item->type(), type);
+ }
+};
+
+
+std::vector<NodeTest> context_default_tests = {
+ { "org", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen.pok2", "", FB::Decision_ANY, "privilege1", FB::Decision_CHECK },
+ { "org.tizen.pok2.a", "", FB::Decision_ANY, "", FB::Decision_DENY },
+ { "org.tizen.pok2.a.b", "", FB::Decision_ANY, "privilege2", FB::Decision_CHECK },
+ { "org.tizen.pnope", "http://tizen.org/privilege/packagemanager.nope", FB::Decision_CHECK, "", FB::Decision_ANY },
+ { "org.tizen.pok1.a1", "http://tizen.org/privilege/packagemanager.nope", FB::Decision_CHECK, "http://tizen.org/privilege/packagemanager.admin", FB::Decision_CHECK },
+ { "org.tizen.pok1.a", "", FB::Decision_ANY, "", FB::Decision_DENY },
+ { "org.tizen.pok1.a.b4", "http://tizen.org/privilege/packagemanager.nope", FB::Decision_CHECK, "", FB::Decision_ANY },
+ { "org.tizen.pok1.a.b3", "", FB::Decision_ANY, "http://tizen.org/privilege/packagemanager.nope", FB::Decision_CHECK },
+ { "org.tizen.pok1.a.b2", "http://tizen.org/privilege/packagemanager.admin", FB::Decision_CHECK, "", FB::Decision_ANY },
+ { "org.tizen.pok1.a.b1", "", FB::Decision_ANY, "http://tizen.org/privilege/packagemanager.admin", FB::Decision_CHECK },
+ { "org.tizen.pok", "http://tizen.org/privilege/packagemanager.admin", FB::Decision_CHECK, "", FB::Decision_ANY },
+};
+
+std::vector<NodeTest> context_mandatory_tests = {};
+
+std::vector<NodeTest> user_root_tests = {
+ { "org", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen.a1", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a1.b", "", FB::Decision_DENY, "", FB::Decision_ANY },
+ { "org.tizen.b", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen.b.z", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.b.c", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.d", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.c", "", FB::Decision_DENY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.b", "", FB::Decision_ANY, "", FB::Decision_DENY },
+ { "org.tizen.a.b.c2", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.b.c1", "", FB::Decision_ANY, "", FB::Decision_DENY },
+ { "org.tizen.a.b.c1.d", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c1.d.e", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c1.d.e.f", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c1.d.e.f.g", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c3", "", FB::Decision_DENY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.b.c3.d", "", FB::Decision_ANY, "", FB::Decision_DENY },
+ { "org.tizen.a.b.c3.d.esth", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c3.d.e", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.b.c3.d.e.f", "", FB::Decision_DENY, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c3.d.e.f.g", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.b.c.d", "", FB::Decision_ANY, "", FB::Decision_DENY },
+ { "org.tizen.a.b.c.d.esth", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.a.b.c.d.e", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.a.b.c.d.e.f", "", FB::Decision_DENY, "", FB::Decision_ANY },
+ { "org.tizen.a.bsth", "", FB::Decision_DENY, "", FB::Decision_ANY },
+ { "org.tizen.ldposd", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.ldposa", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.test", "", FB::Decision_ANY, "", FB::Decision_ANY },
+ { "org.tizen.test.dest_prefix", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.ldpoga", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+ { "org.tizen.ldpo", "", FB::Decision_ANY, "", FB::Decision_ALLOW },
+ { "org.tizen.ldpogd", "", FB::Decision_ALLOW, "", FB::Decision_ANY },
+};
+
+std::vector<ItemSRTest> item_send_context_default_tests {
+ { "", "", "", "", FB::MessageType_METHOD_CALL, false, FB::Decision_DENY },
+ { "org.freedesktop.DBus", "org.freedesktop.DBus", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+ { "org.freedesktop.DBus", "org.freedesktop.DBus.Introspectable", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+ { "org.freedesktop.DBus", "org.freedesktop.DBus", "UpdateActivationEnvironment", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+ { "org.freedesktop.DBus", "org.freedesktop.DBus.Debug.Stats", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+ { "org.freedesktop.DBus", "org.freedesktop.systemd1.Activator", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+};
+
+std::vector<ItemSRTest> item_receive_context_default_test {
+ { "", "", "", "", FB::MessageType_METHOD_CALL, false, FB::Decision_ALLOW },
+ { "", "", "", "", FB::MessageType_METHOD_RETURN, false, FB::Decision_ALLOW },
+ { "", "", "", "", FB::MessageType_ERROR, false, FB::Decision_ALLOW },
+ { "", "", "", "", FB::MessageType_SIGNAL, false, FB::Decision_ALLOW },
+};
+
+std::vector<ItemSRTest> item_send_root_tests {
+ { "org.tizen.test.dest_prefix.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ao", "", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.1.d", "", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.ap.1.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.ap.1.d.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.1.dp.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.1.dp.a", "", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+
+ { "org.tizen.test.dest_prefix.ap.2.apxdp", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.2.apxdp.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.ap.2.apxdp.dp.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.2.apxdp.dp.ap.d", "", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+
+ { "org.tizen.test.dest_prefix.ap.3.dpxap", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.ap.3.dpxap.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.3.dpxap.ap.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.ap.3.dpxap.ap.dp.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.3.dpxap.ap.dp.a", "", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.ap.3.dpxap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+
+ { "org.tizen.test.dest_prefix.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+
+ { "org.tizen.test.dest_prefix.do", "", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.ao.ao", "", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+
+ { "org.tizen.test.dest_prefix.dp.1.a", "", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.dp.1.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+
+ { "org.tizen.test.dest_prefix.dp.1.a.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.1.ap.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.1.ap.d", "", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+
+ { "org.tizen.test.dest_prefix.dp.2.dpxap", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.2.dpxap.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.dp.2.dpxap.ap.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.2.dpxap.ap.dp.a", "", "", "", FB::MessageType_ANY, false, FB::Decision_ALLOW },
+
+ { "org.tizen.test.dest_prefix.dp.2.dpxap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.dp.2.dpxap.ap.d", "", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.2.dpxap.ap.dp.f.d", "", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.2.dpxap.f.f.f.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+
+ { "org.tizen.test.dest_prefix.dp.3.apxdp", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.dp.3.apxdp.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.3.apxdp.dp.ap", "", "", "", FB::MessageType_ANY, true, FB::Decision_ALLOW },
+ { "org.tizen.test.dest_prefix.dp.3.apxdp.dp.ap.dp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.3.apxdp.dp.ap.d", "", "", "", FB::MessageType_ANY, false, FB::Decision_DENY },
+ { "org.tizen.test.dest_prefix.dp.3.apxdp", "", "", "", FB::MessageType_ANY, true, FB::Decision_DENY },
+
+};
+
+std::vector<ItemAccessTest> item_access_context_default_test {
+ { 0, 0, FB::Decision_ALLOW, "", FB::BusAccessType_ALL_USERS },
+ { 1, 0, FB::Decision_DENY, "", FB::BusAccessType_USER },
+ { 2, 0, FB::Decision_DENY, "", FB::BusAccessType_USER },
+ { 0, 20, FB::Decision_ALLOW, "", FB::BusAccessType_GROUP },
+ { 0, 30, FB::Decision_DENY, "", FB::BusAccessType_GROUP },
+ { 3, 0, FB::Decision_ALLOW, "", FB::BusAccessType_USER },
+ { 7, 0, FB::Decision_ALLOW, "", FB::BusAccessType_USER },
+ { 8, 0, FB::Decision_DENY, "", FB::BusAccessType_USER },
+ { 9991, 0, FB::Decision_CHECK, "privilege1", FB::BusAccessType_USER },
+ { 9992, 0, FB::Decision_CHECK, "privilege2", FB::BusAccessType_USER },
+ { 9993, 0, FB::Decision_CHECK, "privilege1", FB::BusAccessType_USER },
+ { 888, 0, FB::Decision_CHECK, "privilege1", FB::BusAccessType_USER },
+};
+
+
+std::vector<ItemAccessTest> item_access_context_mandatory_test {
+ { 6, 0, FB::Decision_DENY, "", FB::BusAccessType_USER },
+ { 7, 0, FB::Decision_DENY, "", FB::BusAccessType_USER },
+ { 8, 0, FB::Decision_ALLOW, "", FB::BusAccessType_USER },
+ { 0, 9992, FB::Decision_CHECK, "privilege1", FB::BusAccessType_GROUP },
+ { 9993, 0, FB::Decision_CHECK, "privilege2", FB::BusAccessType_USER },
+};
+
+class SerializerTests {
+ Serializer serializer;
+ const FB::File *file;
+
+ void serialize_xml(const std::string &file_name) {
+ uint8_t *buff;
+ size_t size;
+ buff = serializer.serialize(file_name, size);
+
+ file = FB::GetFile(buff);
+ }
+
+ bool check_tree(const std::string &token, const FB::PolicyOwnNode *nnode, const NodeTest &test) {
+ size_t dot = token.find('.');
+ if (dot == std::string::npos) {
+ auto node = nnode->children()->LookupByKey(token.c_str());
+ if (node == nullptr) {
+ print_error("node %s not found for:", TH::to_str(token));
+ test.printContent();
+ return false;
+ }
+
+ if (!test.isMatch(node, token)) {
+ print_error("No matching child found for test:");
+ test.printContent();
+ return false;
+ }
+
+ return true;
+ } else {
+ std::string part = token.substr(0, dot);
+ std::string rest = token.substr(dot + 1);
+
+ auto new_node = nnode->children()->LookupByKey(part.c_str());
+ if (new_node == nullptr) {
+ print_error("node %s not found", TH::to_str(part));
+ return false;
+ }
+ return check_tree(rest, new_node, test);
+ }
+ }
+
+ bool check_tree(const FB::PolicyOwnNode *tree, const std::vector<NodeTest> &tree_tests) {
+ for (const auto &test : tree_tests) {
+ if (!check_tree(test.name, tree, test))
+ return false;
+ }
+ return true;
+ }
+
+ bool check_own_set() {
+ return check_tree(file->m_own_set()->context_default()->tree(), context_default_tests) &&
+ check_tree(file->m_own_set()->context_mandatory()->tree(), context_mandatory_tests) &&
+ check_tree(file->m_own_set()->user()->LookupByKey(0)->policy()->tree(), user_root_tests);
+ }
+
+ template <typename T, typename U>
+ bool checkPolicy(const T *policy, const std::vector<U> &tests) {
+ for (const auto &test : tests) {
+ bool found = false;
+ for (const auto &item : *policy->items()) {
+ if (test.isMatch(item)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ print_error("No matching item found for test:");
+ test.printContent();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool check_send_set() {
+ return checkPolicy(file->m_send_set()->context_default(), item_send_context_default_tests) &&
+ checkPolicy(file->m_send_set()->user()->LookupByKey(0)->policy(), item_send_root_tests);
+ }
+
+ bool check_receive_set() {
+ return checkPolicy(file->m_receive_set()->context_default(), item_receive_context_default_test);
+ }
+
+ bool check_access_set() {
+ return checkPolicy(file->m_access_set()->context_default(), item_access_context_default_test) &&
+ checkPolicy(file->m_access_set()->context_mandatory(), item_access_context_mandatory_test);
+ }
+
+ public:
+ bool run_all_tests(const std::string &config) {
+ serialize_xml(config);
+
+ return check_own_set() &&
+ check_send_set() &&
+ check_receive_set() &&
+ check_access_set();
+ }
+};
+}
+
+int main() {
+ auto st = ldp_xml_parser::SerializerTests();
+ if (st.run_all_tests("tests/default_deny/system.conf"))
+ return 0;
+ return -1;
+}