From bdadca41424c434966701635c73d3de2b108a5a8 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Thu, 14 Feb 2019 08:04:05 +0100 Subject: [PATCH 01/16] serialization: add serialization class Change-Id: I8eb5d24012b24830c1f8e671805eb091b1d2c9a1 --- src/dbuspolicy_serializer.cpp | 77 ++++++++++++ src/internal/serializer.cpp | 279 ++++++++++++++++++++++++++++++++++++++++++ src/internal/serializer.hpp | 80 ++++++++++++ 3 files changed, 436 insertions(+) create mode 100644 src/dbuspolicy_serializer.cpp create mode 100644 src/internal/serializer.cpp create mode 100644 src/internal/serializer.hpp diff --git a/src/dbuspolicy_serializer.cpp b/src/dbuspolicy_serializer.cpp new file mode 100644 index 0000000..63b0e19 --- /dev/null +++ b/src/dbuspolicy_serializer.cpp @@ -0,0 +1,77 @@ +#include +#include + +#include +#include +#include "internal/internal.h" +#include "internal/serializer.hpp" +#include "internal/naive_policy_checker.hpp" +#include "dbuspolicy1/libdbuspolicy1.h" +#include "libdbuspolicy1-private.h" + +using namespace std; + +static const struct option options[] = { + {"system", no_argument, 0, 0 }, + {"session", no_argument, 0, 0} +}; + +static void print_help(const char *name) { + cout << endl; + cout << "usage: " << name << " [-o output_filename] " << endl; + cout << " " << name << " {--system|--session} [-o output_filename]" << endl; + cout << endl; +} + +int main(int argc, char *argv[]) +{ + BusType bus_type = BusType::SYSTEM_BUS; + bool need_input_filename = true; + std::string output_filename = "result.dat"; + std::string input_filename; + int c; + + while (1) { + int option_index; + c = getopt_long(argc, argv, "o:", options, &option_index); + if (c == -1) + break; + + switch(c) { + case 0: + if (option_index == 1) + bus_type = BusType::SESSION_BUS; + need_input_filename = false; + break; + case 'o': + output_filename = optarg; + break; + } + } + + if (need_input_filename) { + if (optind < argc) { + input_filename = argv[optind]; + } else { + print_help(argv[0]); + return 1; + } + } else { + switch (bus_type) { + case BusType::SYSTEM_BUS: + input_filename = system_bus_conf_file_primary(); + break; + case BusType::SESSION_BUS: + input_filename = session_bus_conf_file_primary(); + break; + } + } + + cout << "Read from: " << input_filename << " write to: " << output_filename << endl; + ldp_xml_parser::Serializer serializer; + ofstream output(output_filename, ofstream::binary); + + serializer.serialize(input_filename, output); + + return 0; +} diff --git a/src/internal/serializer.cpp b/src/internal/serializer.cpp new file mode 100644 index 0000000..c4beffb --- /dev/null +++ b/src/internal/serializer.cpp @@ -0,0 +1,279 @@ +#include +#include +#include + +#include "internal.h" +#include "naive_policy_checker.hpp" +#include "naive_policy_db.hpp" +#include "serializer.hpp" +#include "include/flatbuffers/flatbuffers.h" +#include "include/fb_generated.h" + +using namespace std; + +namespace ldp_xml_parser { + +map decisions_map { + { Decision::ANY, FB::Decision_ANY }, + { Decision::DENY, FB::Decision_DENY }, + { Decision::ALLOW, FB::Decision_ALLOW }, + { Decision::CHECK, FB::Decision_CHECK } +}; + +map bus_access_map { + { BusAccessType::USER, FB::BusAccessType_USER }, + { BusAccessType::GROUP, FB::BusAccessType_GROUP }, + { BusAccessType::ALL_USERS, FB::BusAccessType_ALL_USERS }, + { BusAccessType::ALL_GROUPS, FB::BusAccessType_ALL_GROUPS }, +}; + +map message_type_map { + { MessageType::ANY, FB::MessageType_ANY }, + { MessageType::METHOD_CALL, FB::MessageType_METHOD_CALL }, + { MessageType::METHOD_RETURN, FB::MessageType_METHOD_RETURN }, + { MessageType::ERROR, FB::MessageType_ERROR }, + { MessageType::SIGNAL, FB::MessageType_SIGNAL } +}; + +template <> +struct Serializer::type_helper { + typedef struct FB::OwnSet set; + typedef struct FB::OwnSetBuilder builder; + typedef struct FB::PolicyOwn policy; + typedef struct FB::PolicyOwnPair pair; + static constexpr auto create_set = &FB::CreateOwnSet; + static constexpr auto create_policy = &FB::CreatePolicyOwn; + static constexpr auto create_policy_pair = &FB::CreatePolicyOwnPair; +}; + +template <> +struct Serializer::type_helper { + typedef struct FB::SendSet set; + typedef struct FB::SendSetBuilder builder; + typedef struct FB::PolicySend policy; + typedef struct FB::PolicySendPair pair; + typedef struct FB::ItemSend item; + static constexpr auto create_set = &FB::CreateSendSet; + static constexpr auto create_policy = &FB::CreatePolicySend; + static constexpr auto create_policy_pair = &FB::CreatePolicySendPair; + static constexpr auto create_item = &FB::CreateItemSend; +}; + +template <> +struct Serializer::type_helper { + typedef struct FB::ReceiveSet set; + typedef struct FB::ReceiveSetBuilder builder; + typedef struct FB::PolicyReceive policy; + typedef struct FB::PolicyReceivePair pair; + typedef struct FB::ItemReceive item; + static constexpr auto create_set = &FB::CreateReceiveSet; + static constexpr auto create_policy = &FB::CreatePolicyReceive; + static constexpr auto create_policy_pair = &FB::CreatePolicyReceivePair; + static constexpr auto create_item = &FB::CreateItemReceive; +}; + +template <> +struct Serializer::type_helper { + typedef struct FB::AccessSet set; + typedef struct FB::AccessSetBuilder builder; + typedef struct FB::PolicyAccess policy; + typedef struct FB::ItemAccess item; + static constexpr auto create_set = &FB::CreateAccessSet; + static constexpr auto create_policy = &FB::CreatePolicyAccess; + static constexpr auto create_item = &FB::CreateItemAccess; +}; + +uint8_t* Serializer::serialize(const BusType bus_type, size_t &size) { + m_db = &policy_checker().getPolicyDb(bus_type); + + auto own_set = serialize_set(); + auto send_set = serialize_set(); + auto receive_set = serialize_set(); + auto access_set = serialize_set(); + + auto file = FB::CreateFile(m_builder, + own_set, + send_set, + receive_set, + access_set); + + m_builder.Finish(file); + uint8_t* buf = m_builder.GetBufferPointer(); + size = m_builder.GetSize(); + + return buf; +} + +uint8_t* Serializer::serialize(const std::string config_path, size_t &size) { + // SYSTEM_BUS here because something had to be choosen + if (__internal_init(BusType::SYSTEM_BUS, config_path.c_str()) != 0) + cout << "internal_init error" << endl; + + return serialize(BusType::SYSTEM_BUS, size); +} + +void Serializer::serialize(const std::string config_path, ostream &output) { + size_t size; + uint8_t *buf = serialize(config_path, size); + + output.write(reinterpret_cast(buf), size); +} + +template +auto Serializer::get_create_set() -> decltype(type_helper::create_set) { + return type_helper::create_set; +} + +template +auto Serializer::get_create_policy() -> decltype(type_helper::create_policy) { + return type_helper::create_policy; +} + +template +auto Serializer::get_create_policy_pair() -> decltype(type_helper::create_policy_pair) { + return type_helper::create_policy_pair; +} + +template +auto Serializer::get_create_item() -> decltype(type_helper::create_item) { + return type_helper::create_item; +} + +FbOff Serializer::serialize_tree(const OwnershipTree &tree) { + auto tree_item = serialize_tree(tree.getRoot()); + auto policy = FB::CreatePolicyOwn(m_builder, tree_item); + + return policy; +} + +FbOff Serializer::serialize_tree(const shared_ptr &node) { + auto prefix_decision_item = serialize_decision(node->getOwnPrefixDecisionItem()); + auto decision_item = serialize_decision(node->getOwnDecisionItem()); + + std::vector> children; + + for (const auto &subnode : node->getChildren()) { + auto child = serialize_tree(subnode.second); + children.push_back(child); + } + + auto policy_own = FB::CreatePolicyOwnNode(m_builder, + m_builder.CreateString(node->getToken()), + prefix_decision_item, + decision_item, + m_builder.CreateVectorOfSortedTables(&children)); + return policy_own; +} + +FbOff Serializer::serialize_decision(const DecisionItem &item) { + return FB::CreateDecisionItem(m_builder, + decisions_map[item.getDecision()], + m_builder.CreateString(item.getPrivilege())); +} + +template <> +auto Serializer::serialize_item(const ItemAccess &item) -> FbOff { + auto create_item = get_create_item(); + + return create_item(m_builder, + item.getUid(), + item.getGid(), + serialize_decision(item.getDecision()), + bus_access_map[item.getType()]); +} + +template +auto Serializer::serialize_item(const P &item) -> FbOff::item> { + auto create_item = get_create_item(); + return create_item(m_builder, + serialize_decision(item.getDecision()), + m_builder.CreateString(item.getName()), + m_builder.CreateString(item.getInterface()), + m_builder.CreateString(item.getMember()), + m_builder.CreateString(item.getPath()), + message_type_map[item.getType()], + item.isNamePrefix()); +} + +template +auto Serializer::serialize_policy(const T &policy, + const std::vector::item>> items) + -> FbOff::policy> { + (void)policy; + auto create_policy = get_create_policy(); + return create_policy(m_builder, m_builder.CreateVector(items)); +} + +template <> +auto Serializer::serialize_policy(const PolicyAccess &policy, + const std::vector> items) + -> FbOff { + (void)policy; + auto create_policy = get_create_policy(); + return create_policy(m_builder, + m_builder.CreateVector(items)); +} + +template <> +auto Serializer::serialize_policy(const PolicyOwn &policy) + -> FbOff { + return serialize_tree(policy.getTree()); +} + +template +auto Serializer::serialize_policy(const T &policy) -> FbOff::policy> { + std::vector::item>> items; + + for (const auto &item : policy.getItems()) { + items.push_back(serialize_item(item)); + } + + return serialize_policy(policy, items); +} + +template +auto Serializer::serialize_pair(const long int id, const P policy) + -> FbOff::pair> { + auto create_policy_pair = get_create_policy_pair(); + return create_policy_pair(m_builder, id, serialize_policy(policy)); +} + +template +auto Serializer::serialize_set() -> FbOff::set> { + auto context_default = serialize_policy(m_db->getPolicyContextDefault()); + auto context_mandatory = serialize_policy(m_db->getPolicyContextMandatory()); + + return serialize_set(context_default, context_mandatory); +} + +template <> +auto Serializer::serialize_set(FbOff context_default, + FbOff context_mandatory) + -> FbOff::set> +{ + return FB::CreateAccessSet(m_builder, context_default, context_mandatory); +} + +template +auto Serializer::serialize_set(FbOff context_default, + FbOff context_mandatory) + -> FbOff::set> +{ + std::vector::pair>> user; + std::vector::pair>> group; + std::vector uid; + std::vector gid; + + for (const auto &u : m_db->getPoliciesUser()) + user.push_back(serialize_pair(u.first, u.second)); + + for (const auto &g : m_db->getPoliciesGroup()) + group.push_back(serialize_pair(g.first, g.second)); + + auto func = get_create_set(); + return func(m_builder, context_default, context_mandatory, + m_builder.CreateVectorOfSortedTables(&user), + m_builder.CreateVectorOfSortedTables(&group)); +} + +} diff --git a/src/internal/serializer.hpp b/src/internal/serializer.hpp new file mode 100644 index 0000000..12be5b0 --- /dev/null +++ b/src/internal/serializer.hpp @@ -0,0 +1,80 @@ +#ifndef _SERIALIZER_HPP +#define _SERIALIZER_HPP + +#include +#include +#include + +#include "include/flatbuffers/flatbuffers.h" +#include "include/fb_generated.h" + +#include "naive_policy_db.hpp" +#include "policy_containers.hpp" + +using namespace std; + +namespace ldp_xml_parser +{ + enum class SetType : uint8_t { + OWN, + SEND, + RECEIVE, + ACCESS + }; + + template + using FbOff = flatbuffers::Offset; + + class Serializer { + private: + template + struct type_helper; + + const NaivePolicyDb *m_db; + flatbuffers::FlatBufferBuilder m_builder; + + template + auto get_create_set() -> decltype(type_helper::create_set); + template + auto get_create_policy() -> decltype(type_helper::create_policy); + template + auto get_create_policy_pair() -> decltype(type_helper::create_policy_pair); + template + auto get_create_item() -> decltype(type_helper::create_item); + + FbOff serialize_tree(const OwnershipTree &tree); + FbOff serialize_tree(const shared_ptr &node); + FbOff serialize_decision(const DecisionItem &item); + + template + auto serialize_item(const P &item) -> FbOff::item>; + + template + auto serialize_policy(const T &policy) -> FbOff::policy>; + + template + auto serialize_policy(const T &policy, + const std::vector::item>> items) + -> FbOff::policy>; + + template + auto serialize_pair(const long int id, const P policy) + -> FbOff::pair>; + + template + auto serialize_set() -> FbOff::set>; + + template + auto serialize_set(FbOff context_default, + FbOff context_mandatory) + -> FbOff::set>; + public: + uint8_t *serialize(const BusType bus_type, size_t &size); + uint8_t *serialize(const std::string config_path, size_t &size); + void serialize(const std::string config_path, ostream &output); + friend class SerializerTests; + }; +} + + +#endif -- 2.7.4 From 1c43aa46e9ac755b7bd36f4da992e92812dd94ab Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Fri, 8 Feb 2019 12:44:02 +0100 Subject: [PATCH 02/16] serialization: add dbuspolicyserializer to Makefile Change-Id: I9b75dcae61188665f01611f124459f0ec44196cb --- Makefile.am | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 249041b..32f6154 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,8 @@ AM_CPPFLAGS = \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ $(CYNARA_CFLAGS) \ $(DLOG_CFLAGS) \ - -I${top_srcdir}/src + -I${top_srcdir}/src \ + -Isrc/internal/include AM_CFLAGS = ${my_CFLAGS} \ -fvisibility=hidden \ @@ -59,7 +60,8 @@ COMMON_SRC =\ src/internal/policy_containers.cpp \ src/internal/own_tree.cpp \ src/internal/xml_parser.cpp \ - src/internal/tslog.cpp + src/internal/tslog.cpp \ + src/internal/serializer.cpp src_libdbuspolicy1_la_SOURCES =\ $(COMMON_SRC) \ @@ -76,6 +78,27 @@ src_libdbuspolicy1_la_LDFLAGS = $(AM_LDFLAGS) \ -Wl,--version-script=$(top_srcdir)/src/libdbuspolicy1.sym src_libdbuspolicy1_la_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym +dbuspolicyserializer_SOURCES =\ + src/dbuspolicy_serializer.cpp + +dbuspolicyserializer_CFLAGS="-Isrc/internal/include $(AM_CFLAGS)" + +# dbuspolicyserializer_LDFLAGS = $(AM_LDFLAGS) \ +# -version-info $(LIBDBUSPOLICY1_CURRENT):$(LIBDBUSPOLICY1_REVISION):$(LIBDBUSPOLICY1_AGE) \ +# $(CYNARA_LIBS) \ +# $(DLOG_LIBS) \ +# -Wl,--version-script=$(top_srcdir)/src/libdbuspolicy1.sym + +dbuspolicyserializer_LDADD = src/libinternal.a \ + $(CYNARA_LIBS) \ + $(DLOG_LIBS) \ + -lexpat + +dbuspolicyserializer_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym + +bin_PROGRAMS = dbuspolicyserializer +dbuspolicyserializerdir = /bin/ + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = src/libdbuspolicy1.pc EXTRA_DIST += src/libdbuspolicy1.pc.in -- 2.7.4 From 02df40bbea16cd240df0451b33634e3bd5ea08e6 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Fri, 8 Feb 2019 12:44:32 +0100 Subject: [PATCH 03/16] serializer: add dbuspolicyserializer do the spec file Change-Id: I25616008fd2d4bb43c084deaea79fae0adda0db4 --- packaging/libdbuspolicy.spec | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packaging/libdbuspolicy.spec b/packaging/libdbuspolicy.spec index 8e99a50..149f107 100644 --- a/packaging/libdbuspolicy.spec +++ b/packaging/libdbuspolicy.spec @@ -14,6 +14,9 @@ BuildRequires: pkgconfig(dlog) %package devel Summary: Helper library for fine-grained userspace policy handling-development package +%package serializer +Summary: Tool to serialize dbus policy + %package tests Summary: Helper library for fine-grained userspace policy handling-development package Requires: %{name} = %{version} @@ -27,6 +30,9 @@ libdbuspolicy is a helper library for fine-grained userspace policy handling (with SMACK support). This package contains development files. +%description serializer +dbuspolicyserializer is a tool to serialize dbus policy + %description tests This package contains contains integration tests for libdbuspolicy. @@ -100,6 +106,12 @@ libtool --mode=install install -m 0755 %{runnername} %{btestrunnerdir} %{_libdir}/pkgconfig/* %{_libdir}/libdbuspolicy1.so +%files serializer +%manifest %{name}.manifest +%license LICENSE.APACHE2.0 +%defattr(-,root,root) +%{_bindir}/dbuspolicyserializer + %if 0%{?enable_doxygen:1} %files doc %license LICENSE.APACHE2.0 -- 2.7.4 From f9f8b2c5b3f467430a274d6717de9daad7cc0f7d Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Wed, 20 Feb 2019 10:56:29 +0100 Subject: [PATCH 04/16] serialization: rework printing content We want to print content from both serialized and XML. This makes a common base for printing content in the similar way. Change-Id: If010b8adb1e39e6ada7b08b7949a0b446470160a --- Makefile.am | 3 +- src/internal/naive_policy_db.cpp | 11 +- src/internal/own_tree.cpp | 1 + src/internal/policy.cpp | 82 +------------ src/internal/policy.hpp | 27 ----- src/internal/policy_containers.cpp | 3 +- src/internal/policy_containers.hpp | 1 + src/internal/print_content.cpp | 231 ++++++++++++++++++++++++++++++++++++ src/internal/print_content.hpp | 24 ++++ src/internal/serialized_convert.hpp | 20 ++++ 10 files changed, 291 insertions(+), 112 deletions(-) create mode 100644 src/internal/print_content.cpp create mode 100644 src/internal/print_content.hpp create mode 100644 src/internal/serialized_convert.hpp diff --git a/Makefile.am b/Makefile.am index 32f6154..dbfdbb0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,7 +61,8 @@ COMMON_SRC =\ src/internal/own_tree.cpp \ src/internal/xml_parser.cpp \ src/internal/tslog.cpp \ - src/internal/serializer.cpp + src/internal/serializer.cpp \ + src/internal/print_content.cpp src_libdbuspolicy1_la_SOURCES =\ $(COMMON_SRC) \ diff --git a/src/internal/naive_policy_db.cpp b/src/internal/naive_policy_db.cpp index dc67e41..d9cfed0 100644 --- a/src/internal/naive_policy_db.cpp +++ b/src/internal/naive_policy_db.cpp @@ -2,6 +2,7 @@ #include "naive_policy_db.hpp" #include "cynara.hpp" #include "groups_proxy.hpp" +#include "print_content.hpp" #include "tslog.hpp" #include #include @@ -32,11 +33,15 @@ protected: void addItemGroup(gid_t gid, T &item) { group[gid].addItem(item); } void printContent() const { - for (const auto& i : user) + for (const auto& i : user) { + std::cerr << "user: " << i.first << std::endl; i.second.printContent(); + } - for (const auto& i : group) + for (const auto& i : group) { + std::cerr << "group: " << i.first << std::endl; i.second.printContent(); + } } size_t getSize() const { @@ -146,7 +151,9 @@ public: } void printSet() const { + std::cerr << "context default" << std::endl; contextDefault.printContent(); + std::cerr << "context mandatory" << std::endl; contextMandatory.printContent(); UG::printContent(); diff --git a/src/internal/own_tree.cpp b/src/internal/own_tree.cpp index 21ea4a9..c81d7a8 100644 --- a/src/internal/own_tree.cpp +++ b/src/internal/own_tree.cpp @@ -1,4 +1,5 @@ #include "own_tree.hpp" +#include "print_content.hpp" #include #include #include diff --git a/src/internal/policy.cpp b/src/internal/policy.cpp index 06f4322..9999869 100644 --- a/src/internal/policy.cpp +++ b/src/internal/policy.cpp @@ -7,6 +7,7 @@ #include "naive_policy_checker.hpp" #include "naive_policy_db.hpp" #include "tslog.hpp" + #include #include #include @@ -17,10 +18,6 @@ using namespace ldp_xml_parser; -static const char* message_type[] = { "ANY", "METHOD_CALL", "METHOD_RETURN", "ERROR", "SIGNAL"}; -static const char* message_decision[] = {"NO_DECISION", "ALLOW", "DENY", "CHECK"}; -static const char* message_access[] = {"USER", "GROUP", "ALL_USERS", "ALL_GROUPS"}; - size_t ldp_xml_parser::get_string_heap_allocated_memory(const std::string& x) { /* an empty string will have nothing allocated on the heap; * it can still have some capacity regardless due to short string optimisation, @@ -32,18 +29,6 @@ size_t ldp_xml_parser::get_string_heap_allocated_memory(const std::string& x) { return x.capacity(); } -static inline const char* __message_type_to_str(MessageType type) { - return message_type[static_cast(type)]; -} - -static inline const char* __decision_to_str(Decision dec) { - return message_decision[static_cast(dec)]; -} - -static inline const char* __access_type_to_str(BusAccessType type) { - return message_access[static_cast(type)]; -} - DecisionItem::DecisionItem(Decision decision, const char* privilege) : __decision(decision) { @@ -439,68 +424,3 @@ PolicyTypeValue::PolicyTypeValue(ContextType type) : context(type) { PolicyTypeValue::PolicyTypeValue(uid_t us) : user(us) { } - -namespace ldp_xml_parser { - -std::ostream &operator<<(std::ostream& stream, const DecisionItem &di) -{ - return stream << __decision_to_str(di.__decision) << (di.__privilege.empty() ? "" : ":") << di.__privilege; -} - -std::ostream &operator<<(std::ostream& stream, const ItemOwn &item) -{ - return stream << "ItemOwn: service(" << (item.__name.empty() ? "*" : item.__name) << - "), pref(" << item.__is_prefix << ")"; -} - -std::ostream &operator<<(std::ostream& stream, const MatchItemOwn &item) -{ - return stream << (item._name.empty() ? "NULL" : item._name); -} - -std::ostream &operator<<(std::ostream& stream, const MatchItemSR &item) -{ - stream << ": services("; - for (int i = 0; i < item.names_num; i++) { - stream << item.names[i]; - if (i != item.names_num -1) - stream << " "; - } - return stream << "), interface(" << item.interface << "), member(" << item.member << - "), path(" << item.path << "), type(" << __message_type_to_str(item.type) << ")"; -} - -std::ostream &operator<<(std::ostream& stream, const MatchItemSend &item) -{ - stream << "MatchItemSend"; - return stream << static_cast(item); -} - -std::ostream &operator<<(std::ostream& stream, const MatchItemReceive &item) -{ - stream << "MatchItemReceive"; - return stream << static_cast(item); -} - -std::ostream &operator<<(std::ostream& stream, const ItemSendReceive &item) -{ - return stream << ": name(" << item.__name << "), inter(" << item.__interface << - "), member(" << item.__member << "), path(" << item.__path << "), type(" << - __message_type_to_str(item.__type) << ")"; -} - -std::ostream &operator<<(std::ostream& stream, const ItemAccess &item) -{ - return stream << "ItemAccess: type(" << __access_type_to_str(item.__type) << "), uid(" << - item.__uid << "), gid(" << item.__gid << ")"; -} - -std::ostream &operator<<(std::ostream& stream, const MatchItemAccess &item) -{ - stream << "uid: " << item.getUid() << ", gid: "; - for (auto gid : item.getGids()) - stream << gid << ", "; - return stream << std::endl; -} - -} diff --git a/src/internal/policy.hpp b/src/internal/policy.hpp index 008151c..a3bf85c 100644 --- a/src/internal/policy.hpp +++ b/src/internal/policy.hpp @@ -116,10 +116,7 @@ namespace ldp_xml_parser Decision getDecision() const; const std::string &getPrivilege() const; size_t getSize() const; - - friend std::ostream &operator<<(std::ostream& stream, const DecisionItem &di); }; - std::ostream &operator<<(std::ostream& stream, const DecisionItem &di); class MatchItemOwn { private: @@ -127,10 +124,7 @@ namespace ldp_xml_parser public: MatchItemOwn(const char *name) : _name(name) {} const std::string &getName() const { return _name; } - - friend std::ostream &operator<<(std::ostream& stream, const MatchItemOwn &item); }; - std::ostream &operator<<(std::ostream& stream, const MatchItemOwn &item); /** Class contains info about ownership policy item */ class ItemOwn { @@ -151,10 +145,7 @@ namespace ldp_xml_parser const std::string &getName() const; bool isPrefix() const; bool isMatchAll() const; - - friend std::ostream &operator<<(std::ostream& stream, const ItemOwn &item); }; - std::ostream &operator<<(std::ostream& stream, const ItemOwn &item); /** Struct which allows to contain multiple connection names then compared in s/r policy checker */ struct MatchItemSR { @@ -167,21 +158,15 @@ namespace ldp_xml_parser MatchItemSR(const char* i, const char* me, const char* p, MessageType t); void addName(const char* name); bool addNames(const char* name); - - friend std::ostream &operator<<(std::ostream& stream, const MatchItemSR &item); }; class MatchItemSend : public MatchItemSR { using MatchItemSR::MatchItemSR; - friend std::ostream &operator<<(std::ostream& stream, const MatchItemSend &item); }; - std::ostream &operator<<(std::ostream& stream, const MatchItemSend &item); class MatchItemReceive : public MatchItemSR { using MatchItemSR::MatchItemSR; - friend std::ostream &operator<<(std::ostream& stream, const MatchItemReceive &item); }; - std::ostream &operator<<(std::ostream& stream, const MatchItemReceive &item); /** Class contains info about item send/receive */ class ItemSendReceive { @@ -205,9 +190,7 @@ namespace ldp_xml_parser MessageType getType() const; bool isNamePrefix() const; size_t getSize() const; - friend std::ostream &operator<<(std::ostream& stream, const ItemSendReceive &item); }; - std::ostream &operator<<(std::ostream& stream, const ItemSendReceive &item); template class ItemSR : public ItemSendReceive { @@ -217,11 +200,6 @@ namespace ldp_xml_parser bool match(const M &item) const { return ItemSendReceive::match(item); } - - friend std::ostream &operator<<(std::ostream& stream, const ItemSR &item) { - stream << typeid(item).name(); - return stream << static_cast(item); - } }; typedef ItemSR ItemSend; @@ -236,10 +214,7 @@ namespace ldp_xml_parser MatchItemAccess(const uid_t uid, const std::vector &gids); uid_t getUid() const; const std::vector& getGids() const; - - friend std::ostream &operator<<(std::ostream& stream, const MatchItemAccess &item); }; - std::ostream &operator<<(std::ostream& stream, const MatchItemAccess &item); /** DBus bus access constraint */ class ItemAccess { @@ -263,9 +238,7 @@ namespace ldp_xml_parser gid_t getGid() const; BusAccessType getType() const; size_t getSize() const; - friend std::ostream &operator<<(std::ostream& stream, const ItemAccess &item); }; - std::ostream &operator<<(std::ostream& stream, const ItemAccess &item); class NaivePolicyDb; diff --git a/src/internal/policy_containers.cpp b/src/internal/policy_containers.cpp index 92a4f64..613f82b 100644 --- a/src/internal/policy_containers.cpp +++ b/src/internal/policy_containers.cpp @@ -22,8 +22,9 @@ DecisionItem PolicyAccess::getDecisionItem(const MatchItemAccess& query) const { } void PolicyAccess::printContent() const { - for (const auto& i : m_items) + for (const auto& i : m_items) { std::cerr << i << std::endl; + } } size_t PolicyAccess::getSize() const { diff --git a/src/internal/policy_containers.hpp b/src/internal/policy_containers.hpp index 3f24431..114e181 100644 --- a/src/internal/policy_containers.hpp +++ b/src/internal/policy_containers.hpp @@ -3,6 +3,7 @@ #include "tslog.hpp" #include "policy.hpp" #include "own_tree.hpp" +#include "print_content.hpp" #include namespace ldp_xml_parser { diff --git a/src/internal/print_content.cpp b/src/internal/print_content.cpp new file mode 100644 index 0000000..6c636a0 --- /dev/null +++ b/src/internal/print_content.cpp @@ -0,0 +1,231 @@ +#include "print_content.hpp" +#include "serialized_convert.hpp" +#include "policy.hpp" + +#include +#include + +/************ PRINTING CONTENT ********************/ +std::ostream &print_content_item_own(std::ostream &stream, const std::string &name, bool is_prefix) { + return stream << "ItemOwn: service(" << (name.empty() ? "*" : name) << "), pref(" << is_prefix << ")"; +} + +namespace { +const char* message_access[] = {"USER", "GROUP", "ALL_USERS", "ALL_GROUPS"}; +inline const char* __access_type_to_str(ldp_xml_parser::BusAccessType type) { + return message_access[static_cast(type)]; +} +} + +template +std::ostream &print_val(std::ostream &stream, const boost::string_ref &name, const T &val) { + return stream << name << "(" << val << ")"; +} + +template +std::ostream &print_next_val(std::ostream &stream, const boost::string_ref &name, const T &val) { + stream << ", "; + return print_val(stream, name, val); +} + +std::ostream &print_content_item_access(std::ostream &stream, + ldp_xml_parser::BusAccessType type, + uid_t uid, + gid_t gid, + const ldp_xml_parser::DecisionItem &decisionItem) { + stream << "ItemAccess: "; + print_val(stream, "type", __access_type_to_str(type)); + print_next_val(stream, "uid", uid); + print_next_val(stream, "gid", gid); + return print_next_val(stream, "decision", decisionItem); +} + +namespace { +static const char* message_type[] = { "ANY", "METHOD_CALL", "METHOD_RETURN", "ERROR", "SIGNAL"}; +static inline const char* __message_type_to_str(ldp_xml_parser::MessageType type) { + return message_type[static_cast(type)]; +} +} + +std::ostream &print_content_item_sr(std::ostream &stream, + const boost::string_ref &item_type, + const boost::string_ref &name, + const boost::string_ref &interface, + const boost::string_ref &member, + const boost::string_ref &path, + ldp_xml_parser::MessageType type, + const ldp_xml_parser::DecisionItem &decisionItem) +{ + stream << item_type << ": "; + print_val(stream, "name", name); + print_next_val(stream, "inter", interface); + print_next_val(stream, "member", member); + print_next_val(stream, "path", path); + print_next_val(stream, "type", __message_type_to_str(type)); + return print_next_val(stream, "decision", decisionItem); +} + +namespace { +static const char* message_decision[] = {"NO_DECISION", "ALLOW", "DENY", "CHECK"}; +static inline const char* __decision_to_str(ldp_xml_parser::Decision dec) { + return message_decision[static_cast(dec)]; +} +} + +std::ostream &print_content_decision_item(std::ostream &stream, + ldp_xml_parser::Decision decision, + const boost::string_ref &privilege) { + stream << __decision_to_str(decision); + if (!privilege.empty()) + stream << ":" << privilege; + return stream; +} + +template +void printContentItem(std::ostream &stream, const T *item); + +template <> void printContentItem(std::ostream &stream, const FB::ItemAccess *item) { + print_content_item_access(stream, makeBusAccessType(item->type()), item->uid(), + item->gid(), makeDecisionItem(item->decision())); +} + +template +void printContentItemSR(std::ostream &stream, const boost::string_ref &item_type, const T *item) { + print_content_item_sr(stream, item_type, item->name()->c_str(), item->interface()->c_str(), + item->member()->c_str(), item->path()->c_str(), makeMessageType(item->type()), + makeDecisionItem(item->decision())); +} + +template <> void printContentItem(std::ostream &stream, const FB::ItemSend *item) { + printContentItemSR(stream, "ItemSend", item); +} + +template <> void printContentItem(std::ostream &stream, const FB::ItemReceive *item) { + printContentItemSR(stream, "ItemReceive", item); +} + +template +void printContentPolicy(std::ostream &stream, const T *policy) { + for (const auto *i: *policy->items()) { + printContentItem(stream, i); + stream << std::endl; + } +} + +void printDecisionItem(std::ostream &stream, const FB::DecisionItem *item) { + print_content_decision_item(stream, makeDecision(item->decision()), item->privilege()->c_str()); +} + +void printTreeLevel(std::ostream &stream, const FB::PolicyOwnNode *node, unsigned indent) { + for (decltype(indent) i = 0; i < indent; ++i) + stream << "\t"; + stream << "| " << node->token()->c_str() << " (" << node->children()->size() << ") | "; + printDecisionItem(stream, node->decision_item()); + stream << " "; + printDecisionItem(stream, node->prefix_decision_item()); + stream << std::endl; + + for (const auto &i: *node->children()) + printTreeLevel(stream, i, indent+1); +} + +template <> void printContentPolicy(std::ostream &stream, const FB::PolicyOwn *policy) { + printTreeLevel(stream, policy->tree(), 0); +} + +template +void printContentUserGroup(std::ostream &stream, const T *set) { + for (const auto *i: *set->user()) { + stream << "user: " << i->id() << std::endl; + printContentPolicy(stream, i->policy()); + } + + for (const auto *i: *set->group()) { + stream << "group: " << i->id() << std::endl; + printContentPolicy(stream, i->policy()); + } +} + +template <> void printContentUserGroup(std::ostream &, const FB::AccessSet *) {} + +template +void printContentSet(std::ostream &stream, const T *set) { + stream << "context default" << std::endl; + printContentPolicy(stream, set->context_default()); + stream << "context mandatory" << std::endl; + printContentPolicy(stream, set->context_mandatory()); + + printContentUserGroup(stream, set); +} + +namespace FB { +std::ostream &operator<<(std::ostream &stream, const FB::File &file) { + printContentSet(stream, file.m_own_set()); + printContentSet(stream, file.m_send_set()); + printContentSet(stream, file.m_receive_set()); + printContentSet(stream, file.m_access_set()); + return stream; +} +} + +/********* PRINTING ITEMS PARSED FROM XML *******************/ +namespace ldp_xml_parser { +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemOwn &item) { + return print_content_item_own(stream, item.getName(), item.isPrefix()); +} + +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemSend &item) { + return print_content_item_sr(stream, "ItemSend", item.getName(), item.getInterface(), item.getMember(), + item.getPath(), item.getType(), item.getDecision()); +} + +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemReceive &item) { + return print_content_item_sr(stream, "ItemReceive", item.getName(), item.getInterface(), item.getMember(), + item.getPath(), item.getType(), item.getDecision()); +} + +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemAccess &item) { + return print_content_item_access(stream, item.getType(), item.getUid(), item.getGid(), item.getDecision()); +} + +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::DecisionItem &item) { + return print_content_decision_item(stream, item.getDecision(), item.getPrivilege()); +} +std::ostream &operator<<(std::ostream& stream, const MatchItemOwn &item) +{ + return stream << (item.getName().empty() ? "NULL" : item.getName()); +} + +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemSR &item) +{ + stream << ": services("; + for (int i = 0; i < item.names_num; i++) { + stream << item.names[i]; + if (i != item.names_num -1) + stream << " "; + } + return stream << "), interface(" << item.interface << "), member(" << item.member << + "), path(" << item.path << "), type(" << __message_type_to_str(item.type) << ")"; +} + +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemSend &item) +{ + stream << "MatchItemSend"; + return stream << static_cast(item); +} + +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemReceive &item) +{ + stream << "MatchItemReceive"; + return stream << static_cast(item); +} + +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemAccess &item) +{ + stream << "uid: " << item.getUid() << ", gid: "; + for (auto gid : item.getGids()) + stream << gid << ", "; + return stream << std::endl; +} + +} diff --git a/src/internal/print_content.hpp b/src/internal/print_content.hpp new file mode 100644 index 0000000..2827362 --- /dev/null +++ b/src/internal/print_content.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "include/fb_generated.h" +#include "policy.hpp" + +#include + +namespace FB { +std::ostream &operator<<(std::ostream &stream, const FB::File &file); +} + +namespace ldp_xml_parser { +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::DecisionItem &item); + +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemOwn &item); +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemSend &item); +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemReceive &item); +std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemAccess &item); + +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemOwn &item); +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemSend &item); +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemReceive &item); +std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemAccess &item); +} diff --git a/src/internal/serialized_convert.hpp b/src/internal/serialized_convert.hpp new file mode 100644 index 0000000..3caae16 --- /dev/null +++ b/src/internal/serialized_convert.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "include/fb_generated.h" +#include "policy.hpp" + +inline ldp_xml_parser::Decision makeDecision(FB::Decision d) { + return static_cast(d); +} + +inline ldp_xml_parser::DecisionItem makeDecisionItem(const FB::DecisionItem *di) { + return ldp_xml_parser::DecisionItem(makeDecision(di->decision()), di->privilege()->c_str()); +} + +inline ldp_xml_parser::BusAccessType makeBusAccessType(FB::BusAccessType type) { + return static_cast(type); +} + +inline ldp_xml_parser::MessageType makeMessageType(FB::MessageType type) { + return static_cast(type); +} -- 2.7.4 From 62129bc298f6e41182a4dc2d0a8ce6d4e4d8d28f Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Wed, 20 Feb 2019 14:34:32 +0100 Subject: [PATCH 05/16] serialization: add storage backend Change-Id: I1830ff322a8c14557d46f8f353a7b3d34a43d187 --- Makefile.am | 3 +- src/internal/storage_backend_serialized.cpp | 240 ++++++++++++++++++++++++++++ src/internal/storage_backend_serialized.hpp | 34 ++++ 3 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 src/internal/storage_backend_serialized.cpp create mode 100644 src/internal/storage_backend_serialized.hpp diff --git a/Makefile.am b/Makefile.am index dbfdbb0..024f3e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,7 +62,8 @@ COMMON_SRC =\ src/internal/xml_parser.cpp \ src/internal/tslog.cpp \ src/internal/serializer.cpp \ - src/internal/print_content.cpp + src/internal/print_content.cpp \ + src/internal/storage_backend_serialized.cpp src_libdbuspolicy1_la_SOURCES =\ $(COMMON_SRC) \ diff --git a/src/internal/storage_backend_serialized.cpp b/src/internal/storage_backend_serialized.cpp new file mode 100644 index 0000000..3a6b207 --- /dev/null +++ b/src/internal/storage_backend_serialized.cpp @@ -0,0 +1,240 @@ +#include "storage_backend_serialized.hpp" +#include "print_content.hpp" +#include "serialized_convert.hpp" +#include "tslog.hpp" + +#include "include/fb_generated.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include + +using namespace FB; + +namespace ldp_serialized { + +class StorageBackendSerialized::StorageBackendSerializedImpl { + int fd{-1}; + uint8_t *mem{nullptr}; + size_t length{0}; + const FB::File *file; +public: + void init(const char *filename); + void release(); + + void printContent() const; + + template + T *getPolicySet(); +}; + +void StorageBackendSerialized::StorageBackendSerializedImpl::release() { + if (nullptr != mem) { + if (munmap(mem, length) != 0) + tslog::log("munmap(): ", strerror(errno), "\n"); + mem = nullptr; + length = 0; + } + + if (-1 != fd) { + if (close(fd) != 0) + tslog::log("close(): ", strerror(errno), "\n"); + fd = -1; + } + + file = nullptr; +} + +void StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *filename) { + auto err = [filename] (const char *what) { + tslog::log("Can't ", what, " ", filename, ": ", strerror(errno), "\n"); + }; + + fd = open(filename, O_RDONLY); + if (-1 == fd) { + err("open"); + return; + } + + struct stat buf; + + if (fstat(fd, &buf) == -1) { + err("stat"); + close(fd); + return; + } + + length = buf.st_size; + + mem = reinterpret_cast(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0)); + if (MAP_FAILED == mem) { + err("mmap"); + close(fd); + return; + } +// for verification: +// +// if (!VerifyFileBuffer(Verifier(mem, length))) +// bailout(); +// + file = GetFile(mem); +} + +void StorageBackendSerialized::StorageBackendSerializedImpl::printContent() const { + std::cerr << *file; +} + +/*************************************************/ +template +struct type_helper; + +#define TYPE_HELPER(T, t) \ + template <> \ + struct type_helper { \ + typedef FB::T##Set policy_set_type; \ + typedef FB::Policy##T policy_type; \ + }; \ + template <> \ + auto StorageBackendSerialized::StorageBackendSerializedImpl::getPolicySet() \ + -> const typename type_helper::policy_set_type * { \ + assert(file); \ + return file->m_##t##_set(); \ + } + +TYPE_HELPER(Own, own) +TYPE_HELPER(Send, send) +TYPE_HELPER(Receive, receive) +TYPE_HELPER(Access, access) + +void StorageBackendSerialized::init(const char *filename) { + pimpl->init(filename); +} + +void StorageBackendSerialized::release() { + pimpl->release(); +} + +void StorageBackendSerialized::printContent() const { + pimpl->printContent(); +} + +template +bool match(const T &t, const I *i) { + // TODO!!!! + return true; +} + +template ::policy_type> +ldp_xml_parser::DecisionItem getDecisionItem(const T &item, const P *policy) { + const auto *v = policy->items(); + for (auto it = v->rbegin(); it != v->rend(); ++it) { + if (match(item, *it)) + return makeDecisionItem((*it)->decision()); + } + return ldp_xml_parser::Decision::ANY; +} + +typedef boost::tokenizer> tokenizer; + +const DecisionItem *getDecisionItemFromTree(const FB::PolicyOwnNode *node, + tokenizer &tokens, + tokenizer::iterator &iterator) { + if (iterator == tokens.end()) { + if (node->decision_item()->decision() != Decision_ANY) + return node->decision_item(); + else + return node->prefix_decision_item(); + } + + auto child = node->children()->LookupByKey(iterator->c_str()); + if (nullptr == child) + return node->prefix_decision_item(); + + ++iterator; + const DecisionItem *child_decision = getDecisionItemFromTree(child, tokens, iterator); + if (child_decision->decision() == Decision_ANY) + return node->prefix_decision_item(); + + return child_decision; +} + +template <> ldp_xml_parser::DecisionItem getDecisionItem(const ldp_xml_parser::MatchItemOwn &item, + const PolicyOwn *policy) { + if (item.getName().length() == 0) + return ldp_xml_parser::Decision::DENY; + + boost::char_separator separator("."); + tokenizer tokens(item.getName(), separator); + + auto node = policy->tree(); + if (nullptr == node) + return ldp_xml_parser::Decision::ANY; + + auto iterator = tokens.begin(); + + return makeDecisionItem(getDecisionItemFromTree(node, tokens, iterator)); +} + +template ::policy_type> +ldp_xml_parser::DecisionItem getDecisionItemMaybeNull(const T &item, const P *policy) { + if (nullptr == policy) + return ldp_xml_parser::Decision::ANY; + return getDecisionItem(item, policy); +} + +template +ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMandatory(const T &item) const { + return getDecisionItem(item, pimpl->getPolicySet()->context_mandatory()); +} + +template +ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const T &item) const { + return getDecisionItem(item, pimpl->getPolicySet()->context_default()); +} + +template +ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const T &item) const { + return getDecisionItemMaybeNull(item, pimpl->getPolicySet()->user()->LookupByKey(uid)); +} + +template +ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_t gid, const T &item) const { + return getDecisionItemMaybeNull(item, pimpl->getPolicySet()->group()->LookupByKey(gid)); +} + +#define T_INSTANTIATION(T) \ + template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMandatory(const ldp_xml_parser::MatchItem##T &item) const; \ + template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const ldp_xml_parser::MatchItem##T &item) const; + +T_INSTANTIATION(Own) +T_INSTANTIATION(Send) +T_INSTANTIATION(Receive) +T_INSTANTIATION(Access) + +#define T_INSTANTIATION2(T) \ + template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const ldp_xml_parser::MatchItem##T &item) const; \ + template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_t gid, const ldp_xml_parser::MatchItem##T &item) const; + +T_INSTANTIATION2(Own) +T_INSTANTIATION2(Send) +T_INSTANTIATION2(Receive) + +#undef T_INSTANTIATION +#undef T_INSTANTIATION2 + +StorageBackendSerialized::StorageBackendSerialized() + : pimpl{new StorageBackendSerializedImpl} { +} + +StorageBackendSerialized::~StorageBackendSerialized() { + pimpl->release(); +} + +} diff --git a/src/internal/storage_backend_serialized.hpp b/src/internal/storage_backend_serialized.hpp new file mode 100644 index 0000000..159994a --- /dev/null +++ b/src/internal/storage_backend_serialized.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "policy.hpp" + +#include + +namespace ldp_serialized { + +class StorageBackendSerialized { + class StorageBackendSerializedImpl; + std::unique_ptr pimpl; +public: + StorageBackendSerialized(); + ~StorageBackendSerialized(); + + void init(const char *filename); + void release(); + + void printContent() const; + + // Supported template parameters are: + // MatchPolicyOwn, MatchPolicySend, MatchPolicyReceive + // and - only for Contexts - MatchPolicyAccess + template + ldp_xml_parser::DecisionItem getDecisionItemContextMandatory(const T &item) const; + template + ldp_xml_parser::DecisionItem getDecisionItemContextDefault(const T &item) const; + template + ldp_xml_parser::DecisionItem getDecisionItemUser(uid_t uid, const T &item) const; + template + ldp_xml_parser::DecisionItem getDecisionItemGroup(gid_t gid, const T &item) const; +}; + +} -- 2.7.4 From 541f4762e51a4d24a7bc1c3468ae6c5cdae87956 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Wed, 20 Feb 2019 14:35:07 +0100 Subject: [PATCH 06/16] serialization: add printing tool This adds dbuspolicyprinter, which takes serialized file as input and prints it in the same fashion as libdbuspolicy does with XML policy. Change-Id: I20c8d5af6c97975251cf48bcf94649ef668b9abf --- Makefile.am | 20 +++++++++++++++++--- packaging/libdbuspolicy.spec | 1 + src/dbuspolicy_printer.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 src/dbuspolicy_printer.cpp diff --git a/Makefile.am b/Makefile.am index 024f3e4..d29293c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,7 +78,7 @@ src_libdbuspolicy1_la_LDFLAGS = $(AM_LDFLAGS) \ $(CYNARA_LIBS) \ $(DLOG_LIBS) \ -Wl,--version-script=$(top_srcdir)/src/libdbuspolicy1.sym -src_libdbuspolicy1_la_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym +EXTRA_src_libdbuspolicy1_la_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym dbuspolicyserializer_SOURCES =\ src/dbuspolicy_serializer.cpp @@ -96,11 +96,25 @@ dbuspolicyserializer_LDADD = src/libinternal.a \ $(DLOG_LIBS) \ -lexpat -dbuspolicyserializer_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym +EXTRA_dbuspolicyserializer_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym -bin_PROGRAMS = dbuspolicyserializer dbuspolicyserializerdir = /bin/ +dbuspolicyprinter_SOURCES =\ + src/dbuspolicy_printer.cpp + +dbuspolicyprinter_CFLAGS="-Isrc/internal/include $(AM_CFLAGS)" + +dbuspolicyprinter_LDADD = src/libinternal.a \ + $(CYNARA_LIBS) \ + $(DLOG_LIBS) \ + -lexpat + +EXTRA_dbuspolicyprinter_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym + +bin_PROGRAMS = dbuspolicyserializer dbuspolicyprinter +dbuspolicyprinterdir = /bin/ + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = src/libdbuspolicy1.pc EXTRA_DIST += src/libdbuspolicy1.pc.in diff --git a/packaging/libdbuspolicy.spec b/packaging/libdbuspolicy.spec index 149f107..ba23170 100644 --- a/packaging/libdbuspolicy.spec +++ b/packaging/libdbuspolicy.spec @@ -111,6 +111,7 @@ libtool --mode=install install -m 0755 %{runnername} %{btestrunnerdir} %license LICENSE.APACHE2.0 %defattr(-,root,root) %{_bindir}/dbuspolicyserializer +%{_bindir}/dbuspolicyprinter %if 0%{?enable_doxygen:1} %files doc diff --git a/src/dbuspolicy_printer.cpp b/src/dbuspolicy_printer.cpp new file mode 100644 index 0000000..a95e18d --- /dev/null +++ b/src/dbuspolicy_printer.cpp @@ -0,0 +1,27 @@ +#include "internal/print_content.hpp" +#include "internal/storage_backend_serialized.hpp" +#include + +using namespace std; + +static void print_help(const char *name) { + cout << endl; + cout << "usage: " << name << " " << endl; + cout << endl; +} + +int main(int argc, const char **argv) { + + if (argc < 2) { + print_help(argv[0]); + return 1; + } + + ldp_serialized::StorageBackendSerialized storage; + + storage.init(argv[1]); + + storage.printContent(); + + return 0; +} -- 2.7.4 From c651ac5cd0bb32a74d10ceebca89c14b56213bc5 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Tue, 19 Feb 2019 10:42:36 +0100 Subject: [PATCH 07/16] serializer: add tests Change-Id: Ibd782e92c88f63caa290a33b13a890f54071619b --- Makefile.am | 5 +- src/test-serializer.cpp | 427 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 src/test-serializer.cpp diff --git a/Makefile.am b/Makefile.am index d29293c..beb20b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -125,7 +125,8 @@ TESTS = src/test-libdbuspolicy1-ownership \ src/test-libdbuspolicy1-signal \ src/test-libdbuspolicy1-method \ src/test-libdbuspolicy1-access-deny \ - src/test-libdbuspolicy1-send_destination_prefix-deny + src/test-libdbuspolicy1-send_destination_prefix-deny \ + src/test-serializer check_PROGRAMS = $(TESTS) @@ -135,6 +136,7 @@ src_test_libdbuspolicy1_signal_SOURCES = src/test-libdbuspolicy1-signal.cpp src_test_libdbuspolicy1_method_SOURCES = src/test-libdbuspolicy1-method.cpp src_test_libdbuspolicy1_access_deny_SOURCES = src/test-libdbuspolicy1-access-deny.cpp src_test_libdbuspolicy1_send_destination_prefix_deny_SOURCES = src/test-libdbuspolicy1-send_destination_prefix-deny.cpp +src_test_serializer_SOURCES = src/test-serializer.cpp noinst_LTLIBRARIES = src/libinternal.a src_libinternal_a_SOURCES =\ @@ -154,6 +156,7 @@ src_test_libdbuspolicy1_signal_LDADD = $(TESTS_LDADD) src_test_libdbuspolicy1_method_LDADD = $(TESTS_LDADD) src_test_libdbuspolicy1_access_deny_LDADD = $(TESTS_LDADD) src_test_libdbuspolicy1_send_destination_prefix_deny_LDADD = $(TESTS_LDADD) +src_test_serializer_LDADD = $(TESTS_LDADD) if ENABLE_STANDALONE_TESTS noinst_LTLIBRARIES += src/libinternalfortests.a diff --git a/src/test-serializer.cpp b/src/test-serializer.cpp new file mode 100644 index 0000000..95b33fe --- /dev/null +++ b/src/test-serializer.cpp @@ -0,0 +1,427 @@ +#include +#include +#include + +#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 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 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 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 + 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 + 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 + 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 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 context_mandatory_tests = {}; + +std::vector 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 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 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 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 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 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 &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 + bool checkPolicy(const T *policy, const std::vector &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; +} -- 2.7.4 From 060bdccc439b9f1a914b3d6df02eeeb1e8f1bae7 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Thu, 21 Feb 2019 11:56:44 +0100 Subject: [PATCH 08/16] refactoring: reworked matching This changes matching. Previously Items had match() function with MatchItems as params. Now, MatchItems have generic match() functions for use with both types of Items (XML-based and serialized). Therefore, the matching code is the same for both. Change-Id: I68a90bd3b787c66d72fa30d5fc25e16b0634daa2 --- src/internal/policy.cpp | 76 +++++++++++++++++++++----------------- src/internal/policy.hpp | 24 ++++++------ src/internal/policy_containers.cpp | 2 +- src/internal/policy_containers.hpp | 3 +- 4 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/internal/policy.cpp b/src/internal/policy.cpp index 9999869..15ef3c3 100644 --- a/src/internal/policy.cpp +++ b/src/internal/policy.cpp @@ -122,32 +122,36 @@ bool MatchItemSR::addNames(const char* name) { return true; } -ItemSendReceive::ItemSendReceive() - : __type(MessageType::ANY), - __is_name_prefix(false) { -} - -bool ItemSendReceive::match(const MatchItemSR& item) const { - if (__type != MessageType::ANY && __type != item.type) +bool MatchItemSR::match(MessageType _type, + const boost::string_ref &_interface, + const boost::string_ref &_path, + const boost::string_ref &_member, + const boost::string_ref &_name, + bool _is_name_prefix) const { + if (_type != MessageType::ANY && _type != type) return false; - if (!__interface.empty() && !item.interface.empty() && __interface != item.interface) + auto equal_or_empty = [] (const boost::string_ref &lhs, const boost::string_ref &rhs) { + return lhs.empty() || rhs.empty() || lhs == rhs; + }; + + if (!equal_or_empty(_interface, interface)) return false; - if (!__path.empty() && !item.path.empty() && __path != item.path) + if (!equal_or_empty(_path, path)) return false; - if (!__member.empty() && !item.member.empty() && __member != item.member) + if (!equal_or_empty(_member, member)) return false; - if (!__name.empty()) { - for (int i = 0; i < item.names_num; i++) { - if (!boost::algorithm::starts_with(item.names[i], __name)) + if (!_name.empty()) { + for (int i = 0; i < names_num; i++) { + if (!boost::algorithm::starts_with(names[i], _name)) continue; - if (item.names[i].length() == __name.length()) + if (names[i].length() == _name.length()) return true; - else if (__is_name_prefix && item.names[i][__name.length()] == '.') + else if (_is_name_prefix && names[i][_name.length()] == '.') return true; } return false; @@ -156,6 +160,11 @@ bool ItemSendReceive::match(const MatchItemSR& item) const { return true; } +ItemSendReceive::ItemSendReceive() + : __type(MessageType::ANY), + __is_name_prefix(false) { +} + const DecisionItem& ItemSendReceive::getDecision() const { return __decision; } @@ -212,25 +221,6 @@ void ItemAccess::setGroup(gid_t group) { __gid = group; } -bool ItemAccess::match(const MatchItemAccess& query) const -{ - switch(__type) { - case BusAccessType::ALL_GROUPS: - case BusAccessType::ALL_USERS: - return true; - case BusAccessType::GROUP: - for (const auto gid : query.getGids()) { - if (gid == __gid) { - return true; - } - } - return false; - case BusAccessType::USER: - return query.getUid() == __uid; - } - return false; -} - size_t ItemAccess::getSize() const { return __decision.getSize(); @@ -264,6 +254,24 @@ const std::vector& MatchItemAccess::getGids() const return __gids; } +bool MatchItemAccess::match(BusAccessType type, uid_t uid, gid_t gid) const { + switch(type) { + case BusAccessType::ALL_GROUPS: + case BusAccessType::ALL_USERS: + return true; + case BusAccessType::GROUP: + for (const auto _gid : __gids) { + if (gid == _gid) { + return true; + } + } + return false; + case BusAccessType::USER: + return uid == __uid; + } + return false; +} + void ItemBuilder::setOwnItem() { if (__current_item_type != ItemType::OWN) { __current_own = ItemOwn(); diff --git a/src/internal/policy.hpp b/src/internal/policy.hpp index a3bf85c..bc6d9a9 100644 --- a/src/internal/policy.hpp +++ b/src/internal/policy.hpp @@ -122,7 +122,7 @@ namespace ldp_xml_parser private: std::string _name; public: - MatchItemOwn(const char *name) : _name(name) {} + explicit MatchItemOwn(const char *name) : _name(name) {} const std::string &getName() const { return _name; } }; @@ -137,10 +137,9 @@ namespace ldp_xml_parser typedef MatchItemOwn match_type; friend class ItemBuilder; - ItemOwn(const char* name = NULL, - Decision decision = Decision::ANY, - const char* privilege = NULL); - bool match(const char* const name) const; + explicit ItemOwn(const char* name = NULL, + Decision decision = Decision::ANY, + const char* privilege = NULL); const DecisionItem& getDecision() const; const std::string &getName() const; bool isPrefix() const; @@ -158,6 +157,13 @@ namespace ldp_xml_parser MatchItemSR(const char* i, const char* me, const char* p, MessageType t); void addName(const char* name); bool addNames(const char* name); + + bool match(MessageType _type, + const boost::string_ref &_interface, + const boost::string_ref &_path, + const boost::string_ref &_member, + const boost::string_ref &_name, + bool _is_name_prefix) const; }; class MatchItemSend : public MatchItemSR { @@ -178,7 +184,6 @@ namespace ldp_xml_parser std::string __path; MessageType __type; bool __is_name_prefix; - bool match(const MatchItemSR& item) const; ItemSendReceive(); public: friend class ItemBuilder; @@ -196,10 +201,6 @@ namespace ldp_xml_parser class ItemSR : public ItemSendReceive { public: typedef M match_type; - - bool match(const M &item) const { - return ItemSendReceive::match(item); - } }; typedef ItemSR ItemSend; @@ -214,6 +215,8 @@ namespace ldp_xml_parser MatchItemAccess(const uid_t uid, const std::vector &gids); uid_t getUid() const; const std::vector& getGids() const; + + bool match(BusAccessType type, uid_t uid, gid_t gid) const; }; /** DBus bus access constraint */ @@ -233,7 +236,6 @@ namespace ldp_xml_parser friend class ItemBuilder; const DecisionItem& getDecision() const; - bool match(const MatchItemAccess& query) const; uid_t getUid() const; gid_t getGid() const; BusAccessType getType() const; diff --git a/src/internal/policy_containers.cpp b/src/internal/policy_containers.cpp index 613f82b..93db2d8 100644 --- a/src/internal/policy_containers.cpp +++ b/src/internal/policy_containers.cpp @@ -14,7 +14,7 @@ DecisionItem PolicyAccess::getDecisionItem(const MatchItemAccess& query) const { // (according to how dbus-daemon actually works, not stated clearly in documentation) DecisionItem ret = Decision::ANY; for (const auto& item : m_items) { - if (item.match(query)) { + if (query.match(item.getType(), item.getUid(), item.getGid())) { ret = item.getDecision(); } } diff --git a/src/internal/policy_containers.hpp b/src/internal/policy_containers.hpp index 114e181..a55a97b 100644 --- a/src/internal/policy_containers.hpp +++ b/src/internal/policy_containers.hpp @@ -28,7 +28,8 @@ public: for (auto i : *this) { tslog::log_verbose("-read: ", i.getDecision(), " ", i, "\n"); - if (i.match(item)) { + if (item.match(i.getType(), i.getInterface(), i.getPath(), + i.getMember(), i.getName(), i.isNamePrefix())) { tslog::log_verbose("-matched: ", i.getDecision(), " ", i, "\n"); return i.getDecision(); -- 2.7.4 From 1008e2957ca75b7dd5eda838c922a017458826fa Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Thu, 21 Feb 2019 12:00:33 +0100 Subject: [PATCH 09/16] serialization: implement matching Change-Id: I2d94b5475939e4ccea92def362fe6cc0b1ec98cf --- src/internal/storage_backend_serialized.cpp | 43 +++++++++++++++++------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/internal/storage_backend_serialized.cpp b/src/internal/storage_backend_serialized.cpp index 3a6b207..96b4532 100644 --- a/src/internal/storage_backend_serialized.cpp +++ b/src/internal/storage_backend_serialized.cpp @@ -20,6 +20,9 @@ using namespace FB; namespace ldp_serialized { +template +struct type_helper; + class StorageBackendSerialized::StorageBackendSerializedImpl { int fd{-1}; uint8_t *mem{nullptr}; @@ -31,8 +34,8 @@ public: void printContent() const; - template - T *getPolicySet(); + template ::policy_set_type> + const M *getPolicySet(); }; void StorageBackendSerialized::StorageBackendSerializedImpl::release() { @@ -79,6 +82,7 @@ void StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *fi close(fd); return; } +// TODO: decide - do we need verification? // for verification: // // if (!VerifyFileBuffer(Verifier(mem, length))) @@ -92,18 +96,16 @@ void StorageBackendSerialized::StorageBackendSerializedImpl::printContent() cons } /*************************************************/ -template -struct type_helper; #define TYPE_HELPER(T, t) \ template <> \ - struct type_helper { \ + struct type_helper { \ typedef FB::T##Set policy_set_type; \ typedef FB::Policy##T policy_type; \ }; \ template <> \ - auto StorageBackendSerialized::StorageBackendSerializedImpl::getPolicySet() \ - -> const typename type_helper::policy_set_type * { \ + auto StorageBackendSerialized::StorageBackendSerializedImpl::getPolicySet() \ + -> const typename type_helper::policy_set_type * { \ assert(file); \ return file->m_##t##_set(); \ } @@ -126,9 +128,13 @@ void StorageBackendSerialized::printContent() const { } template -bool match(const T &t, const I *i) { - // TODO!!!! - return true; +bool match(const T &match, const I *i) { + return match.match(makeMessageType(i->type()), i->interface()->c_str(), i->path()->c_str(), + i->member()->c_str(), i->name()->c_str(), i->is_name_prefix()); +} + +template <> bool match(const ldp_xml_parser::MatchItemAccess &match, const FB::ItemAccess *item) { + return match.match(makeBusAccessType(item->type()), item->uid(), item->gid()); } template ::policy_type> @@ -183,10 +189,10 @@ template <> ldp_xml_parser::DecisionItem getDecisionItem(const ldp_xml_parser::M } template ::policy_type> -ldp_xml_parser::DecisionItem getDecisionItemMaybeNull(const T &item, const P *policy) { - if (nullptr == policy) +ldp_xml_parser::DecisionItem getDecisionItemMaybeNull(const T &item, const P *policyPair) { + if (nullptr == policyPair) return ldp_xml_parser::Decision::ANY; - return getDecisionItem(item, policy); + return getDecisionItem(item, policyPair->policy()); } template @@ -210,23 +216,24 @@ ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_ } #define T_INSTANTIATION(T) \ - template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMandatory(const ldp_xml_parser::MatchItem##T &item) const; \ - template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const ldp_xml_parser::MatchItem##T &item) const; + template ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMandatory(const ldp_xml_parser::MatchItem##T &item) const; \ + template ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const ldp_xml_parser::MatchItem##T &item) const; T_INSTANTIATION(Own) T_INSTANTIATION(Send) T_INSTANTIATION(Receive) T_INSTANTIATION(Access) +#undef T_INSTANTIATION + #define T_INSTANTIATION2(T) \ - template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const ldp_xml_parser::MatchItem##T &item) const; \ - template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_t gid, const ldp_xml_parser::MatchItem##T &item) const; + template ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const ldp_xml_parser::MatchItem##T &item) const; \ + template ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_t gid, const ldp_xml_parser::MatchItem##T &item) const; T_INSTANTIATION2(Own) T_INSTANTIATION2(Send) T_INSTANTIATION2(Receive) -#undef T_INSTANTIATION #undef T_INSTANTIATION2 StorageBackendSerialized::StorageBackendSerialized() -- 2.7.4 From ccc210535a56bbc0ebafa1d3fae97935ba62aa94 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Thu, 21 Feb 2019 16:03:35 +0100 Subject: [PATCH 10/16] serialization: reworked init for serialized backend Change-Id: Ie72cf3444dfc7bf446bb6035df6a57d04ae0c180 --- src/internal/storage_backend_serialized.cpp | 107 ++++++++++++++++++---------- src/internal/storage_backend_serialized.hpp | 4 +- src/internal/transaction_guard.hpp | 37 ++++++++++ 3 files changed, 111 insertions(+), 37 deletions(-) create mode 100644 src/internal/transaction_guard.hpp diff --git a/src/internal/storage_backend_serialized.cpp b/src/internal/storage_backend_serialized.cpp index 96b4532..fb5ccda 100644 --- a/src/internal/storage_backend_serialized.cpp +++ b/src/internal/storage_backend_serialized.cpp @@ -2,6 +2,7 @@ #include "print_content.hpp" #include "serialized_convert.hpp" #include "tslog.hpp" +#include "transaction_guard.hpp" #include "include/fb_generated.h" @@ -25,11 +26,16 @@ struct type_helper; class StorageBackendSerialized::StorageBackendSerializedImpl { int fd{-1}; - uint8_t *mem{nullptr}; + uint8_t *mem{static_cast(MAP_FAILED)}; size_t length{0}; - const FB::File *file; + const FB::File *file{nullptr}; + + void releaseMMap(); + void releaseFD(); + public: - void init(const char *filename); + bool init(const char *filename, bool verify); + bool init(const FB::File *f); void release(); void printContent() const; @@ -38,57 +44,82 @@ public: const M *getPolicySet(); }; -void StorageBackendSerialized::StorageBackendSerializedImpl::release() { - if (nullptr != mem) { - if (munmap(mem, length) != 0) - tslog::log("munmap(): ", strerror(errno), "\n"); - mem = nullptr; - length = 0; - } +void StorageBackendSerialized::StorageBackendSerializedImpl::releaseMMap() { + assert(MAP_FAILED != mem); + assert(0 != length); + + if (munmap(mem, length) != 0) + tslog::log("munmap(): ", strerror(errno), "\n"); + + mem = static_cast(MAP_FAILED); + length = 0; +} - if (-1 != fd) { - if (close(fd) != 0) - tslog::log("close(): ", strerror(errno), "\n"); - fd = -1; +void StorageBackendSerialized::StorageBackendSerializedImpl::releaseFD() { + assert(-1 != fd); + + if (close(fd) != 0) + tslog::log("close(): ", strerror(errno), "\n"); + + fd = -1; +} + +void StorageBackendSerialized::StorageBackendSerializedImpl::release() { + if (-1 != fd) { // we need to check it, because we may have initialized the storage directly from File * + releaseMMap(); + releaseFD(); } file = nullptr; } -void StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *filename) { +bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *filename, bool verify) { + assert(nullptr == file); + auto err = [filename] (const char *what) { tslog::log("Can't ", what, " ", filename, ": ", strerror(errno), "\n"); + return false; }; fd = open(filename, O_RDONLY); - if (-1 == fd) { - err("open"); - return; - } + if (-1 == fd) + return err("open"); + + auto openGuard = transaction_guard::makeGuard([&] () { releaseFD(); }); struct stat buf; - if (fstat(fd, &buf) == -1) { - err("stat"); - close(fd); - return; - } + if (fstat(fd, &buf) == -1) + return err("stat"); length = buf.st_size; mem = reinterpret_cast(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0)); - if (MAP_FAILED == mem) { - err("mmap"); - close(fd); - return; + if (MAP_FAILED == mem) + return err("mmap"); + + auto mmapGuard = transaction_guard::makeGuard([&] () { releaseMMap(); }); + + if (verify) { + auto verifier = flatbuffers::Verifier(mem, length); + if (!FB::VerifyFileBuffer(verifier)) { + tslog::log("verification of serialized data: failed\n"); + return false; + } } -// TODO: decide - do we need verification? -// for verification: -// -// if (!VerifyFileBuffer(Verifier(mem, length))) -// bailout(); -// + + openGuard.dismiss(); + mmapGuard.dismiss(); + file = GetFile(mem); + return true; +} + +bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const FB::File *f) { + assert(nullptr == file); + + file = f; + return true; } void StorageBackendSerialized::StorageBackendSerializedImpl::printContent() const { @@ -115,8 +146,12 @@ TYPE_HELPER(Send, send) TYPE_HELPER(Receive, receive) TYPE_HELPER(Access, access) -void StorageBackendSerialized::init(const char *filename) { - pimpl->init(filename); +bool StorageBackendSerialized::init(const char *filename, bool verify) { + return pimpl->init(filename, verify); +} + +bool StorageBackendSerialized::init(const FB::File *f) { + return pimpl->init(f); } void StorageBackendSerialized::release() { diff --git a/src/internal/storage_backend_serialized.hpp b/src/internal/storage_backend_serialized.hpp index 159994a..bf48dd7 100644 --- a/src/internal/storage_backend_serialized.hpp +++ b/src/internal/storage_backend_serialized.hpp @@ -1,6 +1,7 @@ #pragma once #include "policy.hpp" +#include "fb_generated.h" #include @@ -13,7 +14,8 @@ public: StorageBackendSerialized(); ~StorageBackendSerialized(); - void init(const char *filename); + bool init(const char *filename, bool verify = false); + bool init(const FB::File *file); void release(); void printContent() const; diff --git a/src/internal/transaction_guard.hpp b/src/internal/transaction_guard.hpp new file mode 100644 index 0000000..5fc20da --- /dev/null +++ b/src/internal/transaction_guard.hpp @@ -0,0 +1,37 @@ +#pragma once + +namespace transaction_guard { + +/* Helping class for automatically releasing acquired resources when transaction + * during initialization failed at some point. + */ +template +class Guard { + FunRelease fun; + bool active; +public: + Guard(FunRelease f) : fun(f), active(true) {} + Guard() = delete; + Guard(const Guard &) = delete; + Guard &operator=(const Guard &) = delete; + + ~Guard() { + if (active) + fun(); + } + + void dismiss() { + active = false; + } + + Guard(Guard &&g) : fun(std::move(g.fun)), active(g.active) { + dismiss(); + } +}; + +template +Guard makeGuard(FunRelease f) { + return Guard(std::move(f)); +} + +} // namespace transaction_guard -- 2.7.4 From f5d6337acbd3c53f17106ce3b46c174f4bf27a00 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Fri, 22 Feb 2019 10:51:06 +0100 Subject: [PATCH 11/16] refactoring: PolicyAccess uses common policy base PolicyAccess works in a very similar way to PolicySend and PolicyReceive, but it has its own class. This commit makes common base for all three classes. Change-Id: I63c89f23a6f65b6e5107c9a17a950b99a6664111 --- src/internal/policy_containers.cpp | 29 -------------- src/internal/policy_containers.hpp | 80 ++++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 67 deletions(-) diff --git a/src/internal/policy_containers.cpp b/src/internal/policy_containers.cpp index 93db2d8..9683e13 100644 --- a/src/internal/policy_containers.cpp +++ b/src/internal/policy_containers.cpp @@ -5,33 +5,4 @@ constexpr const char *PolicySend::name; constexpr const char *PolicyReceive::name; constexpr const char *PolicyOwn::name; constexpr const char *PolicyAccess::name; - -/****************** PolicyAccess ************************/ -DecisionItem PolicyAccess::getDecisionItem(const MatchItemAccess& query) const { - // All group and user rules are applied in the order in which they appear in config, so: - // - a subsequent matching group rule overrides all previous matched user and group rules, - // - a subsequent matching user rule overrides all previous matched user and group rules. - // (according to how dbus-daemon actually works, not stated clearly in documentation) - DecisionItem ret = Decision::ANY; - for (const auto& item : m_items) { - if (query.match(item.getType(), item.getUid(), item.getGid())) { - ret = item.getDecision(); - } - } - return ret; -} - -void PolicyAccess::printContent() const { - for (const auto& i : m_items) { - std::cerr << i << std::endl; - } -} - -size_t PolicyAccess::getSize() const { - size_t size = m_items.capacity() * sizeof(decltype(m_items)::value_type); - for (const auto & i : m_items) - size += i.getSize(); - return size; -} - } diff --git a/src/internal/policy_containers.hpp b/src/internal/policy_containers.hpp index a55a97b..5b0ddca 100644 --- a/src/internal/policy_containers.hpp +++ b/src/internal/policy_containers.hpp @@ -7,37 +7,23 @@ #include namespace ldp_xml_parser { -/****************** PolicySR: a base for PolicySend and PolicyReceive ************************/ -/** Class containing policy with send/receive rules */ +/****************** PolicyBase: a base for policies ************************/ template -class PolicySR { -private: +class PolicyBase { +protected: /** Vector with policy items */ std::vector m_items; typedef typename decltype(m_items)::const_reverse_iterator PolicyConstIterator; PolicyConstIterator begin() const { return m_items.rbegin(); } PolicyConstIterator end() const { return m_items.rend(); } -public: +public: + typedef TI item_type; /** Adds given item to policy. * \param[in] item Item to add to policy */ void addItem(TI &item) { m_items.push_back(std::move(item)); } - DecisionItem getDecisionItem(const typename TI::match_type &item) const { - for (auto i : *this) { - tslog::log_verbose("-read: ", i.getDecision(), " ", i, "\n"); - - if (item.match(i.getType(), i.getInterface(), i.getPath(), - i.getMember(), i.getName(), i.isNamePrefix())) { - tslog::log_verbose("-matched: ", i.getDecision(), " ", i, "\n"); - - return i.getDecision(); - } - } - return Decision::ANY; - } - void printContent() const { for (const auto& i : m_items) std::cerr << i << std::endl; @@ -53,20 +39,55 @@ public: const std::vector &getItems() const { return m_items; } }; +/****************** PolicySRBase: a base for send/receive policies ************************/ +/** Class containing policy with send/receive rules */ +template +class PolicySRBase : public PolicyBase { +public: + DecisionItem getDecisionItem(const typename TI::match_type &item) const { + for (auto i : *this) { + tslog::log_verbose("-read: ", i.getDecision(), " ", i, "\n"); + + if (item.match(i.getType(), i.getInterface(), i.getPath(), + i.getMember(), i.getName(), i.isNamePrefix())) { + tslog::log_verbose("-matched: ", i.getDecision(), " ", i, "\n"); + + return i.getDecision(); + } + } + return Decision::ANY; + } +}; + /****************** PolicySend ************************/ -class PolicySend : public PolicySR { +class PolicySend : public PolicySRBase { public: static constexpr const char *name = "send"; }; /****************** PolicyReceive ************************/ -class PolicyReceive : public PolicySR { +class PolicyReceive : public PolicySRBase { public: static constexpr const char *name = "receive"; }; +/****************** PolicyAccess ************************/ +class PolicyAccess : public PolicyBase { +public: + static constexpr const char *name = "access"; + DecisionItem getDecisionItem(const typename item_type::match_type &item) const { + for (auto i : *this) { + if (item.match(i.getType(), i.getUid(), i.getGid())) { + return i.getDecision(); + } + } + return Decision::ANY; + } +}; + /****************** PolicyOwn ************************/ /** Class containing policy with ownership rules */ +/* PolicyOwn is different than other policies, so it has its own class */ class PolicyOwn { private: class OwnershipTree ownership_tree; @@ -89,21 +110,4 @@ public: static constexpr const char *name = "own"; }; -/****************** PolicyAccess ************************/ -/** Class containing policy with access rules */ -class PolicyAccess { -private: - std::vector m_items; - -public: - void addItem(const ItemAccess &item) { m_items.push_back(std::move(item)); } - - DecisionItem getDecisionItem(const MatchItemAccess& query) const; - - void printContent() const; - size_t getSize() const; - - static constexpr const char *name = "access"; - const std::vector &getItems() const { return m_items; } -}; } -- 2.7.4 From 30d9b4264cb99459ea705f41d953eb22368fa4a4 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Fri, 22 Feb 2019 16:49:18 +0100 Subject: [PATCH 12/16] serialization: extract mapGroups from pimpl of DB Previously, mapGroups were incorporated into PolicySets in pimpl NaivePolicyDbImpl. But they are in fact not a part of policies. They are gathered from the system and only filtered through policy data. This commit extracts mapGroups from pimpl back to NaivePolicyDb, with some required changes to work with current interfaces, and also with some not required, but fun changes. The extraction will allow switching pimpl in the future, keeping the same groups logic for any pimpl. Change-Id: I3e1dace93bebb7e19c94cacd7fbf7ceb426d315e --- src/internal/naive_policy_db.cpp | 166 ++++++++++++++++++--------------------- src/internal/naive_policy_db.hpp | 12 ++- src/internal/policy.hpp | 4 + src/internal/type_list.h | 58 ++++++++++++++ 4 files changed, 150 insertions(+), 90 deletions(-) create mode 100644 src/internal/type_list.h diff --git a/src/internal/naive_policy_db.cpp b/src/internal/naive_policy_db.cpp index d9cfed0..377d4da 100644 --- a/src/internal/naive_policy_db.cpp +++ b/src/internal/naive_policy_db.cpp @@ -4,6 +4,8 @@ #include "groups_proxy.hpp" #include "print_content.hpp" #include "tslog.hpp" +#include "type_list.h" + #include #include @@ -109,7 +111,6 @@ class PolicySet : public UG { return contextDefault; } - mutable std::map mapGroup; public: typedef P policy_type; /** Adds given item to policy @@ -161,21 +162,6 @@ public: std::cerr << "Memory consumption: " << getSetSize() << " B" << std::endl; } - void printMap() const { - int size = sizeof(mapGroup); - size += mapGroup.size() * sizeof(typename std::remove_reference::type::value_type); - - for (const auto& i : mapGroup) { - size += i.second.capacity() * sizeof(gid_t); - std:: cerr << "gid: " << i.first << " |"; - for (auto j : i.second) - std::cerr << " " << j << ","; - std::cerr << std::endl; - } - - std::cerr << "Memory consumption: " << size << " B" << std::endl; - } - size_t getSetSize() const { size_t size = sizeof(*this); @@ -185,9 +171,6 @@ public: size += UG::getSize(); return size; } - - NaivePolicyDb::VGid &getMapGroup(uid_t uid) const { return mapGroup[uid]; } - void clearMapGroup() { mapGroup.clear(); } }; /****************** NaivePolicyDbImpl ************************/ @@ -202,9 +185,6 @@ public: /** Set of bus access policies */ PolicySet m_access_set; - /* A mutex for mapGroups within sets */ - mutable pthread_mutex_t mutexGroup = PTHREAD_MUTEX_INITIALIZER; - template struct MatchPolicy; // provide policy_type in specializations @@ -220,45 +200,6 @@ public: DecisionItem getDecisionItem(const T &item, const P *(PS::*f)(Args ... args) const, Args ...args) const; - - void updateSupplementaryGroups(const NaivePolicyDb::VGid &groups, uid_t uid, gid_t gid) const { - auto &vsend = m_send_set.getMapGroup(uid); - auto &vrecv = m_receive_set.getMapGroup(uid); - auto &vaccess = m_access_set.getMapGroup(uid); - - if (groups.empty()) { - vsend.push_back(gid); - vrecv.push_back(gid); - vaccess.push_back(gid); - return; - } - - /* insert supplementary group */ - for (const auto group : groups) { - if (m_send_set.getPolicyGroup(group) != nullptr) - vsend.push_back(group); - if (m_receive_set.getPolicyGroup(group) != nullptr) - vrecv.push_back(group); - vaccess.push_back(group); // no filtering, it will be used once - } - - if (vsend.empty()) - vsend.push_back(-1); - if (vrecv.empty()) - vrecv.push_back(-1); - } - - void updateSupplementaryGroupsOwn(const NaivePolicyDb::VGid &groups, uid_t uid, gid_t gid) const { - auto &vown = m_own_set.getMapGroup(uid); - if (groups.empty()) { - vown.push_back(gid); - } else { - for (const auto group : groups) { - if (m_own_set.getPolicyGroup(group) != nullptr) - vown.push_back(group); - } - } - } }; /* Tie MatchItems with proper policy sets. @@ -329,6 +270,45 @@ DecisionItem NaivePolicyDb::NaivePolicyDbImpl::getDecisionItem(const T &item, return policy->getDecisionItem(item); } +void NaivePolicyDb::updateSupplementaryGroups(const VGid &groups, uid_t uid, gid_t gid) const { + auto &vsend = getMapGroup(uid); + auto &vrecv = getMapGroup(uid); + auto &vaccess = getMapGroup(uid); + + if (groups.empty()) { + vsend.push_back(gid); + vrecv.push_back(gid); + vaccess.push_back(gid); + return; + } + + /* insert supplementary group */ + for (const auto group : groups) { + if (pimpl->getPolicySet().getPolicyGroup(group) != nullptr) + vsend.push_back(group); + if (pimpl->getPolicySet().getPolicyGroup(group) != nullptr) + vrecv.push_back(group); + vaccess.push_back(group); // no filtering, it will be used once + } + + if (vsend.empty()) + vsend.push_back(-1); + if (vrecv.empty()) + vrecv.push_back(-1); +} + +void NaivePolicyDb::updateSupplementaryGroupsOwn(const VGid &groups, uid_t uid, gid_t gid) const { + auto &vown = getMapGroup(uid); + if (groups.empty()) { + vown.push_back(gid); + } else { + for (const auto group : groups) { + if (pimpl->getPolicySet().getPolicyGroup(group) != nullptr) + vown.push_back(group); + } + } +} + /********************* NaivePolicyDb **********************/ template void NaivePolicyDb::addItem(const PolicyType policy_type, @@ -351,16 +331,20 @@ void NaivePolicyDb::printContent() const #undef PRINT_SET - #define PRINT_MAP(x) \ - std::cerr << std::endl << "----" #x "----" << std::endl; \ - (x).printMap(); - - PRINT_MAP(pimpl->m_own_set); - PRINT_MAP(pimpl->m_send_set); - PRINT_MAP(pimpl->m_receive_set); - PRINT_MAP(pimpl->m_access_set); + for (const auto &mapGroup : mapGroups) { + std::cerr << std::endl << "---- mapGroup ----" << std::endl; + int size = sizeof(mapGroup); + size += mapGroup.size() * sizeof(typename std::remove_reference::type::value_type); - #undef PRINT_MAP + for (const auto& i : mapGroup) { + size += i.second.capacity() * sizeof(gid_t); + std:: cerr << "gid: " << i.first << " |"; + for (auto j : i.second) + std::cerr << " " << j << ","; + std::cerr << std::endl; + } + std::cerr << "Memory consumption: " << size << " B" << std::endl; + } } template @@ -388,29 +372,29 @@ DecisionItem NaivePolicyDb::getDecisionItemGroup(gid_t gid, const T &item) const } template <> -const NaivePolicyDb::VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t) const +const VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t) const { - return &pimpl->m_own_set.getMapGroup(uid); + return &getMapGroup(uid); } template <> -const NaivePolicyDb::VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t) const +const VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t) const { - return &pimpl->m_access_set.getMapGroup(uid); + return &getMapGroup(uid); } template -const NaivePolicyDb::VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t gid) const +const VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t gid) const { if (uid == getuid() && gid == getgid()) - return &pimpl->getPolicySet().getMapGroup(uid); + return &getMapGroup(uid); - pthread_mutex_lock(&pimpl->mutexGroup); - auto &vgid = pimpl->getPolicySet().getMapGroup(uid); + pthread_mutex_lock(&mutexGroup); + auto &vgid = getMapGroup(uid); if (vgid.empty()) - pimpl->updateSupplementaryGroups(get_groups(uid, gid), uid, gid); - pthread_mutex_unlock(&pimpl->mutexGroup); + updateSupplementaryGroups(get_groups(uid, gid), uid, gid); + pthread_mutex_unlock(&mutexGroup); if (vgid[0] == (gid_t)-1) return nullptr; @@ -420,18 +404,22 @@ const NaivePolicyDb::VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t gid) const void NaivePolicyDb::initializeGroups(uid_t uid, gid_t gid) { - pthread_mutex_lock(&pimpl->mutexGroup); + pthread_mutex_lock(&mutexGroup); - pimpl->m_send_set.clearMapGroup(); - pimpl->m_receive_set.clearMapGroup(); - pimpl->m_own_set.clearMapGroup(); - pimpl->m_access_set.clearMapGroup(); + for (auto &mapGroup : mapGroups) + mapGroup.clear(); auto groups = get_groups(uid, gid); - pimpl->updateSupplementaryGroups(groups, uid, gid); - pimpl->updateSupplementaryGroupsOwn(groups, uid, gid); + updateSupplementaryGroups(groups, uid, gid); + updateSupplementaryGroupsOwn(groups, uid, gid); - pthread_mutex_unlock(&pimpl->mutexGroup); + pthread_mutex_unlock(&mutexGroup); +} + +template +VGid &NaivePolicyDb::getMapGroup(uid_t uid) const +{ + return mapGroups[type_list::IDX::idx][uid]; } void NaivePolicyDb::clear() { @@ -468,7 +456,7 @@ NaivePolicyDb::~NaivePolicyDb() = default; #define T_INSTANTIATION(T) \ template DecisionItem NaivePolicyDb::getDecisionItemContextMandatory(const T &) const; \ template DecisionItem NaivePolicyDb::getDecisionItemContextDefault(const T &) const; \ - template const NaivePolicyDb::VGid *NaivePolicyDb::getGroups(uid_t, gid_t) const; + template const VGid *NaivePolicyDb::getGroups(uid_t, gid_t) const; T_INSTANTIATION(MatchItemOwn) T_INSTANTIATION(MatchItemSend) diff --git a/src/internal/naive_policy_db.hpp b/src/internal/naive_policy_db.hpp index fe5f95f..877d4d3 100644 --- a/src/internal/naive_policy_db.hpp +++ b/src/internal/naive_policy_db.hpp @@ -29,6 +29,8 @@ namespace ldp_xml_parser { + typedef std::vector VGid; + /** Database class, contains policies for ownership and send/receive */ class NaivePolicyDb { private: @@ -36,8 +38,16 @@ namespace ldp_xml_parser std::unique_ptr pimpl; + mutable std::map mapGroups[MatchItemTypes::count]; + /* A mutex for mapGroups */ + mutable pthread_mutex_t mutexGroup = PTHREAD_MUTEX_INITIALIZER; + + template + VGid &getMapGroup(uid_t uid) const; + + void updateSupplementaryGroups(const VGid &groups, uid_t uid, gid_t gid) const; + void updateSupplementaryGroupsOwn(const VGid &groups, uid_t uid, gid_t gid) const; public: - typedef std::vector VGid; NaivePolicyDb(); ~NaivePolicyDb(); diff --git a/src/internal/policy.hpp b/src/internal/policy.hpp index bc6d9a9..c0d1d9b 100644 --- a/src/internal/policy.hpp +++ b/src/internal/policy.hpp @@ -23,6 +23,8 @@ #ifndef _POLICY_H #define _POLICY_H +#include "type_list.h" + #include #include #include @@ -242,6 +244,8 @@ namespace ldp_xml_parser size_t getSize() const; }; + using MatchItemTypes = type_list::type_list; + class NaivePolicyDb; /** Allows to create items from given name, decision etc. */ diff --git a/src/internal/type_list.h b/src/internal/type_list.h new file mode 100644 index 0000000..817bf9b --- /dev/null +++ b/src/internal/type_list.h @@ -0,0 +1,58 @@ +#pragma once + +namespace type_list { +// this is a list of types. +// It is parameterized by types contained in the list, and provides count field +// which gives number of elements in the list +template +struct type_list { constexpr static int count = sizeof...(Types); }; + +/******************* Helpers for dealing with lists of types ************/ +/* Compile-time computing of an index of a type in the type list + + Usage: + Declare your type list, e.g. + using my_type_list = type_list; + + IDX::idx gives 0 + IDX::idx gives 1 + IDX::idx gives 2 + IDX::idx gives 3 + + In some functional language it could be expressed as: + + idx_impl(elem, head::tail, n) = + if elem == head then + n + else + idx_impl(elem, tail, n+1) + + idx(elem, head::tail) = idx_impl(elem, head::tail, 0) + + Below is IDX and IDX_IMPL which express the same thing in C++. + */ + +// idx: look for Elem in TypeList. By default it is a list of MatchItems +template +struct IDX { }; + +namespace _type_list_detail { +// idx_impl: look for Elem in Types, counting how deep we went in n +template +struct IDX_IMPL { }; + +// idx_impl specialization for some type list where head is not the same type as elem +template +struct IDX_IMPL { constexpr static int idx = IDX_IMPL::idx; }; + +// idx_impl specialization for some type list where head is the same type as elem +template +struct IDX_IMPL { constexpr static int idx = n; }; +} + +// idx specialization for running idx_impl with all the things extracted +template typename TypeList, typename ... Types> +struct IDX> { + constexpr static int idx = _type_list_detail::IDX_IMPL<0, Elem, Types...>::idx; +}; +} // namespace type_list -- 2.7.4 From 17be74d4b21a77f6c0e49b9ceda48c68ea579f13 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Mon, 25 Feb 2019 14:04:45 +0100 Subject: [PATCH 13/16] fix uid/gid wording mapGroups are maps that tie uid with vector of gids. This fixes misleading wording. Change-Id: I982e8b474a25da189e16b8871f023e9110787b64 --- src/internal/naive_policy_db.cpp | 2 +- src/internal/naive_policy_db.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/naive_policy_db.cpp b/src/internal/naive_policy_db.cpp index 377d4da..7ce3b4e 100644 --- a/src/internal/naive_policy_db.cpp +++ b/src/internal/naive_policy_db.cpp @@ -338,7 +338,7 @@ void NaivePolicyDb::printContent() const for (const auto& i : mapGroup) { size += i.second.capacity() * sizeof(gid_t); - std:: cerr << "gid: " << i.first << " |"; + std::cerr << "uid: " << i.first << " | gids: "; for (auto j : i.second) std::cerr << " " << j << ","; std::cerr << std::endl; diff --git a/src/internal/naive_policy_db.hpp b/src/internal/naive_policy_db.hpp index 877d4d3..7db549e 100644 --- a/src/internal/naive_policy_db.hpp +++ b/src/internal/naive_policy_db.hpp @@ -38,7 +38,7 @@ namespace ldp_xml_parser std::unique_ptr pimpl; - mutable std::map mapGroups[MatchItemTypes::count]; + mutable std::map mapGroups[MatchItemTypes::count]; /* A mutex for mapGroups */ mutable pthread_mutex_t mutexGroup = PTHREAD_MUTEX_INITIALIZER; -- 2.7.4 From 63e315708801da6d159297b1e841286b8f6cdb2a Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Mon, 25 Feb 2019 14:42:33 +0100 Subject: [PATCH 14/16] serialization: extract xml-based db implementation Change-Id: I84ef422a5451192fe18762c16bc14aa7ed4b9d02 --- Makefile.am | 3 +- src/internal/naive_policy_db.cpp | 369 +++-------------------------------- src/internal/naive_policy_db.hpp | 30 +-- src/internal/storage_backend_xml.cpp | 366 ++++++++++++++++++++++++++++++++++ src/internal/storage_backend_xml.hpp | 56 ++++++ 5 files changed, 469 insertions(+), 355 deletions(-) create mode 100644 src/internal/storage_backend_xml.cpp create mode 100644 src/internal/storage_backend_xml.hpp diff --git a/Makefile.am b/Makefile.am index beb20b7..28d274e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,8 @@ COMMON_SRC =\ src/internal/tslog.cpp \ src/internal/serializer.cpp \ src/internal/print_content.cpp \ - src/internal/storage_backend_serialized.cpp + src/internal/storage_backend_serialized.cpp \ + src/internal/storage_backend_xml.cpp src_libdbuspolicy1_la_SOURCES =\ $(COMMON_SRC) \ diff --git a/src/internal/naive_policy_db.cpp b/src/internal/naive_policy_db.cpp index 7ce3b4e..cf53c10 100644 --- a/src/internal/naive_policy_db.cpp +++ b/src/internal/naive_policy_db.cpp @@ -5,6 +5,7 @@ #include "print_content.hpp" #include "tslog.hpp" #include "type_list.h" +#include "storage_backend_xml.hpp" #include #include @@ -16,260 +17,6 @@ namespace ldp_xml_parser { -/* The following two are building blocks for PolicySet class. - * They specify if a given PolicySet class supports user and group policies. - */ -/****************** UserAndGroupContext ************************/ -template -class UserAndGroupContext { -protected: - /** Map with policies for different users */ - std::map user; - /** Map with policies for different groups */ - std::map group; - - template - void addItemUser(uid_t uid, T &item) { user[uid].addItem(item); } - - template - void addItemGroup(gid_t gid, T &item) { group[gid].addItem(item); } - - void printContent() const { - for (const auto& i : user) { - std::cerr << "user: " << i.first << std::endl; - i.second.printContent(); - } - - for (const auto& i : group) { - std::cerr << "group: " << i.first << std::endl; - i.second.printContent(); - } - } - - size_t getSize() const { - size_t size = user.size() * sizeof(typename decltype(user)::value_type); - for (const auto& i : user) - size += i.second.getSize(); - - size += group.size() * sizeof(typename decltype(group)::value_type); - for (const auto& i : group) - size += i.second.getSize(); - return size; - } - -public: - const P *getPolicyUser(uid_t uid) const { - tslog::log("---policy_type = USER =", uid, "\n"); - - auto it = user.find(uid); - if (it == user.end()) { - tslog::log_verbose("GetPolicy: Out of Range exception\n"); - return nullptr; - } - return &(it->second); - } - - const P *getPolicyGroup(gid_t gid) const { - tslog::log("---policy_type = GROUP = ", gid, "\n"); - - auto it = group.find(gid); - if (it == group.end()) { - tslog::log_verbose("GetPolicy: Out of Range exception\n"); - return nullptr; - } - return &(it->second); - } - - const std::map &getPoliciesUser() const { return user; } - const std::map &getPoliciesGroup() const { return group; } -}; - -/****************** NoUserAndGroupContext ************************/ -class NoUserAndGroupContext { -protected: - template - void addItemUser(uid_t, T &) { assert(false); } - - template - void addItemGroup(gid_t, T &) { assert(false); } - - void printContent() const {} - size_t getSize() const { return 0; } -}; - -template> -class PolicySet : public UG { - /** Policies for all contexts */ - P contextMandatory; - P contextDefault; - - P &getPolicyContext(ContextType type) { - if (ContextType::MANDATORY == type) - return contextMandatory; - - assert(ContextType::DEFAULT == type); - return contextDefault; - } - -public: - typedef P policy_type; - /** Adds given item to policy - * \param[in] policy_type Policy type - * \param[in] policy_type_value Policy type value - * \param[in] item Item to add - */ - template - void addItem(const PolicyType policy_type, - const PolicyTypeValue policy_type_value, - T &item) { - switch (policy_type) { - case PolicyType::CONTEXT: - getPolicyContext(policy_type_value.context).addItem(item); - break; - case PolicyType::USER: - UG::addItemUser(policy_type_value.user, item); - break; - case PolicyType::GROUP: - UG::addItemGroup(policy_type_value.group, item); - break; - case PolicyType::NONE: - assert(false); - break; - } - } - - const P &getRefPolicyContextMandatory() const { return contextMandatory; } - const P &getRefPolicyContextDefault() const { return contextDefault; } - - const P *getPolicyContextMandatory() const { - tslog::log("---policy_type = CONTEXT = MANDATORY\n"); - return &contextMandatory; - } - - const P *getPolicyContextDefault() const { - tslog::log("---policy_type = CONTEXT = DEFAULT\n"); - return &contextDefault; - } - - void printSet() const { - std::cerr << "context default" << std::endl; - contextDefault.printContent(); - std::cerr << "context mandatory" << std::endl; - contextMandatory.printContent(); - - UG::printContent(); - - std::cerr << "Memory consumption: " << getSetSize() << " B" << std::endl; - } - - size_t getSetSize() const { - size_t size = sizeof(*this); - - size += contextMandatory.getSize(); - size += contextDefault.getSize(); - - size += UG::getSize(); - return size; - } -}; - -/****************** NaivePolicyDbImpl ************************/ -class NaivePolicyDb::NaivePolicyDbImpl { -public: - /** Set of ownership policies */ - PolicySet m_own_set; - /** Set of send policies */ - PolicySet m_send_set; - /** Set of receive policies */ - PolicySet m_receive_set; - /** Set of bus access policies */ - PolicySet m_access_set; - - template - struct MatchPolicy; // provide policy_type in specializations - - template - const typename MatchPolicy::policy_set_type &getPolicySet() const; - template - typename MatchPolicy::policy_set_type &getPolicySet(); - - template ::policy_type, - typename PS = typename MatchPolicy::policy_set_type, - typename ...Args> - DecisionItem getDecisionItem(const T &item, - const P *(PS::*f)(Args ... args) const, - Args ...args) const; -}; - -/* Tie MatchItems with proper policy sets. - * Parameters: T - MatchItem* type - * field - one of m_*_set fields from NaivePolicyDb - * - * The below DEF_GET_POLICY_SET defines specialization for MatchPolicy template, - * and a specialization of NaivePolicyDb::getPolicySet template function - * - * Specialization for MatchPolicy provides field 'policy_type' which specifies - * a type of policy used within 'field' parameter, and field 'policy_set_type' - * which specifies a type of the 'field' parameter. - * Specialization of NaivePolicyDb::getPolicySet returns the 'field'. - * - * For example: DEF_GET_POLICY_SET(MatchItemOwn, m_own_set) defines equivalent to - * MatchPolicy { - * typedef PolicyOwn policy_type; - * typedef PolicySet policy_set_type; - * } - * PolicySet &getPolicySet const; - * - * Thanks to this construction we do not need to manually specify PolicyOwn in functions that - * know MatchItemOwn - it is inferred. - * - */ -#define DEF_GET_POLICY_SET(T, field) \ - template <> struct NaivePolicyDb::NaivePolicyDbImpl::MatchPolicy { \ - typedef decltype(field)::policy_type policy_type; \ - typedef decltype(field) policy_set_type; \ - }; \ - template <> struct NaivePolicyDb::NaivePolicyDbImpl::MatchPolicy { \ - typedef decltype(field) policy_set_type; \ - }; \ - template <> \ - auto NaivePolicyDb::NaivePolicyDbImpl::getPolicySet() const -> decltype((field)) { \ - return field; \ - } \ - template <> \ - auto NaivePolicyDb::NaivePolicyDbImpl::getPolicySet() -> decltype((field)) { \ - return field; \ - } \ - template <> \ - auto NaivePolicyDb::NaivePolicyDbImpl::getPolicySet() -> decltype((field)) { \ - return field; \ - } - -DEF_GET_POLICY_SET(MatchItemOwn, m_own_set) -DEF_GET_POLICY_SET(MatchItemSend, m_send_set) -DEF_GET_POLICY_SET(MatchItemReceive, m_receive_set) -DEF_GET_POLICY_SET(MatchItemAccess, m_access_set) - -#undef DEF_GET_POLICY_SET - -template -DecisionItem NaivePolicyDb::NaivePolicyDbImpl::getDecisionItem(const T &item, - const P *(PS::*f)(Args ... args) const, - Args ...args) const -{ - const auto &policySet = getPolicySet(); - typedef typename std::remove_reference::type PolicySetType; - - auto policy = (policySet.*f)(args...); - if (nullptr == policy) - return Decision::ANY; - - tslog::log_verbose("Checking ", PolicySetType::policy_type::name, " policy for: ", item, "\n"); - - return policy->getDecisionItem(item); -} - void NaivePolicyDb::updateSupplementaryGroups(const VGid &groups, uid_t uid, gid_t gid) const { auto &vsend = getMapGroup(uid); auto &vrecv = getMapGroup(uid); @@ -284,9 +31,9 @@ void NaivePolicyDb::updateSupplementaryGroups(const VGid &groups, uid_t uid, gid /* insert supplementary group */ for (const auto group : groups) { - if (pimpl->getPolicySet().getPolicyGroup(group) != nullptr) + if (backend.existsPolicyForGroup(group)) vsend.push_back(group); - if (pimpl->getPolicySet().getPolicyGroup(group) != nullptr) + if (backend.existsPolicyForGroup(group)) vrecv.push_back(group); vaccess.push_back(group); // no filtering, it will be used once } @@ -303,7 +50,7 @@ void NaivePolicyDb::updateSupplementaryGroupsOwn(const VGid &groups, uid_t uid, vown.push_back(gid); } else { for (const auto group : groups) { - if (pimpl->getPolicySet().getPolicyGroup(group) != nullptr) + if (backend.existsPolicyForGroup(group)) vown.push_back(group); } } @@ -315,21 +62,12 @@ void NaivePolicyDb::addItem(const PolicyType policy_type, const PolicyTypeValue policy_type_value, T &item) { tslog::log("Add item: ", item, ", decision: ", item.getDecision(), "\n"); - pimpl->getPolicySet().addItem(policy_type, policy_type_value, item); + backend.addItem(policy_type, policy_type_value, item); } void NaivePolicyDb::printContent() const { - #define PRINT_SET(x) \ - std::cerr << std::endl << "----" #x "----" << std::endl; \ - (x).printSet(); - - PRINT_SET(pimpl->m_own_set) - PRINT_SET(pimpl->m_send_set) - PRINT_SET(pimpl->m_receive_set) - PRINT_SET(pimpl->m_access_set) - - #undef PRINT_SET + backend.printContent(); for (const auto &mapGroup : mapGroups) { std::cerr << std::endl << "---- mapGroup ----" << std::endl; @@ -347,30 +85,6 @@ void NaivePolicyDb::printContent() const } } -template -DecisionItem NaivePolicyDb::getDecisionItemContextMandatory(const T &item) const -{ - return pimpl->getDecisionItem(item, &NaivePolicyDbImpl::MatchPolicy::policy_set_type::getPolicyContextMandatory); -} - -template -DecisionItem NaivePolicyDb::getDecisionItemContextDefault(const T &item) const -{ - return pimpl->getDecisionItem(item, &NaivePolicyDbImpl::MatchPolicy::policy_set_type::getPolicyContextDefault); -} - -template -DecisionItem NaivePolicyDb::getDecisionItemUser(uid_t uid, const T &item) const -{ - return pimpl->getDecisionItem(item, &NaivePolicyDbImpl::MatchPolicy::policy_set_type::getPolicyUser, uid); -} - -template -DecisionItem NaivePolicyDb::getDecisionItemGroup(gid_t gid, const T &item) const -{ - return pimpl->getDecisionItem(item, &NaivePolicyDbImpl::MatchPolicy::policy_set_type::getPolicyGroup, gid); -} - template <> const VGid *NaivePolicyDb::getGroups(uid_t uid, gid_t) const { @@ -423,83 +137,52 @@ VGid &NaivePolicyDb::getMapGroup(uid_t uid) const } void NaivePolicyDb::clear() { - pimpl = std::unique_ptr{new NaivePolicyDbImpl}; + backend.clear(); } template const T &NaivePolicyDb::getPolicyContextMandatory() const { - return pimpl->getPolicySet().getRefPolicyContextMandatory(); + return backend.getPolicyContextMandatory(); } template const T &NaivePolicyDb::getPolicyContextDefault() const { - return pimpl->getPolicySet().getRefPolicyContextDefault(); + return backend.getPolicyContextDefault(); } template const std::map &NaivePolicyDb::getPoliciesUser() const { - return pimpl->getPolicySet().getPoliciesUser(); + return backend.getPoliciesUser(); } template const std::map &NaivePolicyDb::getPoliciesGroup() const { - return pimpl->getPolicySet().getPoliciesGroup(); + return backend.getPoliciesGroup(); } -NaivePolicyDb::NaivePolicyDb() : pimpl{new NaivePolicyDbImpl} { -} - -NaivePolicyDb::~NaivePolicyDb() = default; - /* Explicit instantiation is needed for used public template methods defined in this file. */ #define T_INSTANTIATION(T) \ - template DecisionItem NaivePolicyDb::getDecisionItemContextMandatory(const T &) const; \ - template DecisionItem NaivePolicyDb::getDecisionItemContextDefault(const T &) const; \ - template const VGid *NaivePolicyDb::getGroups(uid_t, gid_t) const; - -T_INSTANTIATION(MatchItemOwn) -T_INSTANTIATION(MatchItemSend) -T_INSTANTIATION(MatchItemReceive) -T_INSTANTIATION(MatchItemAccess) - -#define T_INSTANTIATION2(T) \ - template DecisionItem NaivePolicyDb::getDecisionItemUser(uid_t, const T &) const; \ - template DecisionItem NaivePolicyDb::getDecisionItemGroup(gid_t, const T &) const; - -T_INSTANTIATION2(MatchItemOwn) -T_INSTANTIATION2(MatchItemSend) -T_INSTANTIATION2(MatchItemReceive) + template const VGid *NaivePolicyDb::getGroups(uid_t, gid_t) const; \ + template void NaivePolicyDb::addItem(const PolicyType policy_type, const PolicyTypeValue policy_type_value, Item##T &item); \ + template const Policy##T &NaivePolicyDb::getPolicyContextMandatory() const; \ + template const Policy##T &NaivePolicyDb::getPolicyContextDefault() const; -#define T_INSTANTIATION3(T) \ - template void NaivePolicyDb::addItem(const PolicyType policy_type, const PolicyTypeValue policy_type_value, T &item); +T_INSTANTIATION(Own) +T_INSTANTIATION(Send) +T_INSTANTIATION(Receive) +T_INSTANTIATION(Access) -T_INSTANTIATION3(ItemOwn) -T_INSTANTIATION3(ItemSend) -T_INSTANTIATION3(ItemReceive) -T_INSTANTIATION3(ItemAccess) - -#define T_INSTANTIATION4(T) \ - template const T &NaivePolicyDb::getPolicyContextMandatory() const; \ - template const T &NaivePolicyDb::getPolicyContextDefault() const; - -T_INSTANTIATION4(PolicyOwn) -T_INSTANTIATION4(PolicySend) -T_INSTANTIATION4(PolicyReceive) -T_INSTANTIATION4(PolicyAccess) +#undef T_INSTANTIATION -#define T_INSTANTIATION5(T) \ - template const std::map &NaivePolicyDb::getPoliciesGroup() const; \ - template const std::map &NaivePolicyDb::getPoliciesUser() const; +#define T_INSTANTIATION(T) \ + template const std::map &NaivePolicyDb::getPoliciesGroup() const; \ + template const std::map &NaivePolicyDb::getPoliciesUser() const; -T_INSTANTIATION5(PolicyOwn) -T_INSTANTIATION5(PolicySend) -T_INSTANTIATION5(PolicyReceive) +T_INSTANTIATION(Own) +T_INSTANTIATION(Send) +T_INSTANTIATION(Receive) #undef T_INSTANTIATION -#undef T_INSTANTIATION2 -#undef T_INSTANTIATION3 -#undef T_INSTANTIATION4 -#undef T_INSTANTIATION5 } // namespace ldp_xml_parser diff --git a/src/internal/naive_policy_db.hpp b/src/internal/naive_policy_db.hpp index 7db549e..9137dfc 100644 --- a/src/internal/naive_policy_db.hpp +++ b/src/internal/naive_policy_db.hpp @@ -16,6 +16,7 @@ #ifndef _NAIVE_DB_H #define _NAIVE_DB_H +#include "storage_backend_xml.hpp" #include #include #include @@ -34,9 +35,7 @@ namespace ldp_xml_parser /** Database class, contains policies for ownership and send/receive */ class NaivePolicyDb { private: - class NaivePolicyDbImpl; - - std::unique_ptr pimpl; + ldp_xml::StorageBackendXML backend; mutable std::map mapGroups[MatchItemTypes::count]; /* A mutex for mapGroups */ @@ -47,27 +46,36 @@ namespace ldp_xml_parser void updateSupplementaryGroups(const VGid &groups, uid_t uid, gid_t gid) const; void updateSupplementaryGroupsOwn(const VGid &groups, uid_t uid, gid_t gid) const; - public: - - NaivePolicyDb(); - ~NaivePolicyDb(); + public: + /***** Common interface for all backends ******/ void printContent() const; template - DecisionItem getDecisionItemContextMandatory(const T &item) const; + DecisionItem getDecisionItemContextMandatory(const T &item) const + { return backend.getDecisionItemContextMandatory(item); } + template - DecisionItem getDecisionItemContextDefault(const T &item) const; + DecisionItem getDecisionItemContextDefault(const T &item) const + { return backend.getDecisionItemContextDefault(item); } + template - DecisionItem getDecisionItemUser(uid_t uid, const T &item) const; + DecisionItem getDecisionItemUser(uid_t uid, const T &item) const + { return backend.getDecisionItemUser(uid, item); } + template - DecisionItem getDecisionItemGroup(gid_t gid, const T &item) const; + DecisionItem getDecisionItemGroup(gid_t gid, const T &item) const + { return backend.getDecisionItemGroup(gid, item); } + /******* Common interface for group maps management **********/ template const VGid *getGroups(uid_t uid, gid_t gid) const; void initializeGroups(uid_t uid, gid_t gid); + /******* Interface for read-write backends (e.g. XML-based) */ + /* This will be probably moved from here */ + /** Adds item to a policy * \param[in] policy_type Policy type * \param[in] policy_type_value Policy type value diff --git a/src/internal/storage_backend_xml.cpp b/src/internal/storage_backend_xml.cpp new file mode 100644 index 0000000..5cfb9cb --- /dev/null +++ b/src/internal/storage_backend_xml.cpp @@ -0,0 +1,366 @@ +#include "storage_backend_xml.hpp" +#include "policy_containers.hpp" + +using namespace ldp_xml_parser; + +namespace ldp_xml { + +/* The following two are building blocks for PolicySet class. + * They specify if a given PolicySet class supports user and group policies. + */ +/****************** UserAndGroupContext ************************/ +template +class UserAndGroupContext { +protected: + /** Map with policies for different users */ + std::map user; + /** Map with policies for different groups */ + std::map group; + + template + void addItemUser(uid_t uid, T &item) { user[uid].addItem(item); } + + template + void addItemGroup(gid_t gid, T &item) { group[gid].addItem(item); } + + void printContent() const { + for (const auto& i : user) { + std::cerr << "user: " << i.first << std::endl; + i.second.printContent(); + } + + for (const auto& i : group) { + std::cerr << "group: " << i.first << std::endl; + i.second.printContent(); + } + } + + size_t getSize() const { + size_t size = user.size() * sizeof(typename decltype(user)::value_type); + for (const auto& i : user) + size += i.second.getSize(); + + size += group.size() * sizeof(typename decltype(group)::value_type); + for (const auto& i : group) + size += i.second.getSize(); + return size; + } + +public: + const P *getPolicyUser(uid_t uid) const { + tslog::log("---policy_type = USER =", uid, "\n"); + + auto it = user.find(uid); + if (it == user.end()) { + tslog::log_verbose("GetPolicy: Out of Range exception\n"); + return nullptr; + } + return &(it->second); + } + + const P *getPolicyGroup(gid_t gid) const { + tslog::log("---policy_type = GROUP = ", gid, "\n"); + + auto it = group.find(gid); + if (it == group.end()) { + tslog::log_verbose("GetPolicy: Out of Range exception\n"); + return nullptr; + } + return &(it->second); + } + + const std::map &getPoliciesUser() const { return user; } + const std::map &getPoliciesGroup() const { return group; } +}; + +/****************** NoUserAndGroupContext ************************/ +class NoUserAndGroupContext { +protected: + template + void addItemUser(uid_t, T &) { assert(false); } + + template + void addItemGroup(gid_t, T &) { assert(false); } + + void printContent() const {} + size_t getSize() const { return 0; } +}; + +/****************** PolicySet ************************/ +template> +class PolicySet : public UG { + /** Policies for all contexts */ + P contextMandatory; + P contextDefault; + + P &getPolicyContext(ContextType type) { + if (ContextType::MANDATORY == type) + return contextMandatory; + + assert(ContextType::DEFAULT == type); + return contextDefault; + } + +public: + typedef P policy_type; + /** Adds given item to policy + * \param[in] policy_type Policy type + * \param[in] policy_type_value Policy type value + * \param[in] item Item to add + */ + template + void addItem(const PolicyType policy_type, + const PolicyTypeValue policy_type_value, + T &item) { + switch (policy_type) { + case PolicyType::CONTEXT: + getPolicyContext(policy_type_value.context).addItem(item); + break; + case PolicyType::USER: + UG::addItemUser(policy_type_value.user, item); + break; + case PolicyType::GROUP: + UG::addItemGroup(policy_type_value.group, item); + break; + case PolicyType::NONE: + assert(false); + break; + } + } + + const P &getRefPolicyContextMandatory() const { return contextMandatory; } + const P &getRefPolicyContextDefault() const { return contextDefault; } + + const P *getPolicyContextMandatory() const { + tslog::log("---policy_type = CONTEXT = MANDATORY\n"); + return &contextMandatory; + } + + const P *getPolicyContextDefault() const { + tslog::log("---policy_type = CONTEXT = DEFAULT\n"); + return &contextDefault; + } + + void printSet() const { + std::cerr << "context default" << std::endl; + contextDefault.printContent(); + std::cerr << "context mandatory" << std::endl; + contextMandatory.printContent(); + + UG::printContent(); + + std::cerr << "Memory consumption: " << getSetSize() << " B" << std::endl; + } + + size_t getSetSize() const { + size_t size = sizeof(*this); + + size += contextMandatory.getSize(); + size += contextDefault.getSize(); + + size += UG::getSize(); + return size; + } +}; + +/****************** StorageBackendXML ************************/ +class StorageBackendXML::StorageBackendXMLImpl { +public: + /** Set of ownership policies */ + PolicySet m_own_set; + /** Set of send policies */ + PolicySet m_send_set; + /** Set of receive policies */ + PolicySet m_receive_set; + /** Set of bus access policies */ + PolicySet m_access_set; + + template + struct MatchPolicy; // provide policy_type in specializations + + template + const typename MatchPolicy::policy_set_type &getPolicySet() const; + template + typename MatchPolicy::policy_set_type &getPolicySet(); + + template ::policy_type, + typename PS = typename MatchPolicy::policy_set_type, + typename ...Args> + DecisionItem getDecisionItem(const T &item, + const P *(PS::*f)(Args ... args) const, + Args ...args) const; +}; + +/* Tie MatchItems with proper policy sets. + * Parameters: T - MatchItem* type + * field - one of m_*_set fields from StorageBackendXMLImpl + * + * The below DEF_GET_POLICY_SET defines specialization for MatchPolicy template, + * and a specialization of StorageBackendXMLImpl::getPolicySet template function + * + * Specialization for MatchPolicy provides field 'policy_type' which specifies + * a type of policy used within 'field' parameter, and field 'policy_set_type' + * which specifies a type of the 'field' parameter. + * Specialization of StorageBackendXMLImpl::getPolicySet returns the 'field'. + * + * For example: DEF_GET_POLICY_SET(MatchItemOwn, m_own_set) defines equivalent to + * MatchPolicy { + * typedef PolicyOwn policy_type; + * typedef PolicySet policy_set_type; + * } + * PolicySet &getPolicySet const; + * + * Thanks to this construction we do not need to manually specify PolicyOwn in functions that + * know MatchItemOwn - it is inferred. + * + */ +#define DEF_GET_POLICY_SET(T, field) \ + template <> struct StorageBackendXML::StorageBackendXMLImpl::MatchPolicy { \ + typedef decltype(field)::policy_type policy_type; \ + typedef decltype(field) policy_set_type; \ + }; \ + template <> struct StorageBackendXML::StorageBackendXMLImpl::MatchPolicy { \ + typedef decltype(field) policy_set_type; \ + }; \ + template <> \ + auto StorageBackendXML::StorageBackendXMLImpl::getPolicySet() const -> decltype((field)) { \ + return field; \ + } \ + template <> \ + auto StorageBackendXML::StorageBackendXMLImpl::getPolicySet() -> decltype((field)) { \ + return field; \ + } \ + template <> \ + auto StorageBackendXML::StorageBackendXMLImpl::getPolicySet() -> decltype((field)) { \ + return field; \ + } + +DEF_GET_POLICY_SET(MatchItemOwn, m_own_set) +DEF_GET_POLICY_SET(MatchItemSend, m_send_set) +DEF_GET_POLICY_SET(MatchItemReceive, m_receive_set) +DEF_GET_POLICY_SET(MatchItemAccess, m_access_set) + +#undef DEF_GET_POLICY_SET + +template +DecisionItem StorageBackendXML::StorageBackendXMLImpl::getDecisionItem(const T &item, + const P *(PS::*f)(Args ... args) const, + Args ...args) const +{ + const auto &policySet = getPolicySet(); + typedef typename std::remove_reference::type PolicySetType; + + auto policy = (policySet.*f)(args...); + if (nullptr == policy) + return Decision::ANY; + + tslog::log_verbose("Checking ", PolicySetType::policy_type::name, " policy for: ", item, "\n"); + + return policy->getDecisionItem(item); +} + +template +void StorageBackendXML::addItem(const ldp_xml_parser::PolicyType policy_type, + const ldp_xml_parser::PolicyTypeValue policy_type_value, + T &item) { + pimpl->getPolicySet().addItem(policy_type, policy_type_value, item); +} + +void StorageBackendXML::clear() { + pimpl.reset(new StorageBackendXMLImpl); +} + +void StorageBackendXML::printContent() const { + #define PRINT_SET(x) \ + std::cerr << std::endl << "----" #x "----" << std::endl; \ + (x).printSet(); + + PRINT_SET(pimpl->m_own_set) + PRINT_SET(pimpl->m_send_set) + PRINT_SET(pimpl->m_receive_set) + PRINT_SET(pimpl->m_access_set) + + #undef PRINT_SET +} + +template +const T &StorageBackendXML::getPolicyContextMandatory() const { + return pimpl->getPolicySet().getRefPolicyContextMandatory(); +} + +template +const T &StorageBackendXML::getPolicyContextDefault() const { + return pimpl->getPolicySet().getRefPolicyContextDefault(); +} + +template +const std::map &StorageBackendXML::getPoliciesUser() const { + return pimpl->getPolicySet().getPoliciesUser(); +} + +template +const std::map &StorageBackendXML::getPoliciesGroup() const { + return pimpl->getPolicySet().getPoliciesGroup(); +} + +template +bool StorageBackendXML::existsPolicyForGroup(gid_t gid) const { + return pimpl->getPolicySet().getPolicyGroup(gid) != nullptr; +} + +template +ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemContextMandatory(const T &item) const { + return pimpl->getDecisionItem(item, &StorageBackendXMLImpl::MatchPolicy::policy_set_type::getPolicyContextMandatory); +} + +template +ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemContextDefault(const T &item) const { + return pimpl->getDecisionItem(item, &StorageBackendXMLImpl::MatchPolicy::policy_set_type::getPolicyContextDefault); +} + +template +ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemUser(uid_t uid, const T &item) const { + return pimpl->getDecisionItem(item, &StorageBackendXMLImpl::MatchPolicy::policy_set_type::getPolicyUser, uid); +} + +template +ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemGroup(gid_t gid, const T &item) const { + return pimpl->getDecisionItem(item, &StorageBackendXMLImpl::MatchPolicy::policy_set_type::getPolicyGroup, gid); +} + +StorageBackendXML::StorageBackendXML() : pimpl{new StorageBackendXMLImpl} { +} + +StorageBackendXML::~StorageBackendXML() = default; + +/* Explicit instantiation is needed for used public template methods defined in this file. + */ +#define T_INSTANTIATION(T) \ + template ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemContextMandatory(const MatchItem##T &item) const; \ + template ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemContextDefault(const MatchItem##T &item) const; \ + template void StorageBackendXML::addItem(const PolicyType policy_type, const PolicyTypeValue policy_type_value, Item##T &item); \ + template const Policy##T &StorageBackendXML::getPolicyContextMandatory() const; \ + template const Policy##T &StorageBackendXML::getPolicyContextDefault() const; + +T_INSTANTIATION(Own) +T_INSTANTIATION(Send) +T_INSTANTIATION(Receive) +T_INSTANTIATION(Access) + +#undef T_INSTANTIATION + +#define T_INSTANTIATION(T) \ + template bool StorageBackendXML::existsPolicyForGroup(gid_t gid) const; \ + template ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemUser(uid_t uid, const MatchItem##T &item) const; \ + template ldp_xml_parser::DecisionItem StorageBackendXML::getDecisionItemGroup(gid_t gid, const MatchItem##T &item) const; \ + template const std::map &StorageBackendXML::getPoliciesGroup() const; \ + template const std::map &StorageBackendXML::getPoliciesUser() const; + +T_INSTANTIATION(Own) +T_INSTANTIATION(Send) +T_INSTANTIATION(Receive) + +#undef T_INSTANTIATION + +} // namespace ldp_xml diff --git a/src/internal/storage_backend_xml.hpp b/src/internal/storage_backend_xml.hpp new file mode 100644 index 0000000..dd4cffc --- /dev/null +++ b/src/internal/storage_backend_xml.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "policy.hpp" +#include +#include +#include + +namespace ldp_xml { + +class StorageBackendXML { + class StorageBackendXMLImpl; + std::unique_ptr pimpl; +public: + StorageBackendXML(); + ~StorageBackendXML(); + + // This works with T set to MatchItemOwn, MatchItemSend, MatchItemReceive or MatchItemAccess + template + void addItem(const ldp_xml_parser::PolicyType policy_type, + const ldp_xml_parser::PolicyTypeValue policy_type_value, + T &item); + + void clear(); + + void printContent() const; + + // The getPolicy*() methods are intended for Serializers to get + // access to policy structures. + // Supported template parameters are: PolicyOwn, PolicySend, PolicyReceive + // and for PolicyAccess only getPolicyContext*() + template + const T &getPolicyContextMandatory() const; + template + const T &getPolicyContextDefault() const; + template + const std::map &getPoliciesUser() const; + template + const std::map &getPoliciesGroup() const; + + // This works with T set to MatchItemOwn, MatchItemSend or MatchItemReceive + // This is needed for filtering mapGroups. Check NaivePolicyDb. + template + bool existsPolicyForGroup(gid_t gid) const; + + // These work with T set to MatchItemOwn, MatchItemSend, MatchItemReceive or MatchItemAccess + template + ldp_xml_parser::DecisionItem getDecisionItemContextMandatory(const T &item) const; + template + ldp_xml_parser::DecisionItem getDecisionItemContextDefault(const T &item) const; + template + ldp_xml_parser::DecisionItem getDecisionItemUser(uid_t uid, const T &item) const; + template + ldp_xml_parser::DecisionItem getDecisionItemGroup(gid_t gid, const T &item) const; +}; + +} -- 2.7.4 From 15ad9b47847ebec8bee4dba860c720eec6e75228 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Fri, 1 Mar 2019 13:14:25 +0100 Subject: [PATCH 15/16] refactoring: make assert more informative Function parseAssert() showed only that an error occurred. A macro instead shows also the error condition and line number. Change-Id: Ibd686286c58b657fd578f92bd4328072aa892933 --- src/internal/xml_parser.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/internal/xml_parser.cpp b/src/internal/xml_parser.cpp index c3bc869..d5815e5 100644 --- a/src/internal/xml_parser.cpp +++ b/src/internal/xml_parser.cpp @@ -42,11 +42,12 @@ public: bool ignore_always{false}; }; -void parseAssert(bool condition) { - assert(condition); - if (!condition) { - throw std::runtime_error("Parsing error"); - } +#define parseAssert(cond) \ +{ \ + assert(cond); \ + if (!(cond)) { \ + throw std::runtime_error("Parsing error"); \ + } \ } void start_element_handler(void *data, const char *el, const char **attr) { -- 2.7.4 From ef347bb169dec1c3f5baf2295d3ca84ae4a84351 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Fri, 1 Mar 2019 13:32:30 +0100 Subject: [PATCH 16/16] refactoring: simplify strings management in XmlParser File name is passed from external API by const char *. This (at least partially) eliminates construction of std::string where it is not needed. Change-Id: I05375820fe2996cb4f95af5be8bbbab5ecd87fc4 --- src/internal/xml_parser.cpp | 28 ++++++++++++---------------- src/internal/xml_parser.hpp | 8 ++++---- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/internal/xml_parser.cpp b/src/internal/xml_parser.cpp index d5815e5..2433e03 100644 --- a/src/internal/xml_parser.cpp +++ b/src/internal/xml_parser.cpp @@ -26,13 +26,9 @@ std::string expandPath(const std::string& parent_dir, const std::string& path) { return parent_dir + "/" + path; } -std::string getDir(std::string path) { - // dirname may modify path, so we must pass a modifiable char* to it - char* modifiable_path = new char[path.size() + 1]; - strncpy(modifiable_path, path.c_str(), path.size() + 1); - std::string ret = dirname(modifiable_path); - delete[] modifiable_path; - return ret; +std::string getDir(const char *path) { + std::string p(path); + return dirname(&p.front()); } class XmlParser::IncludeItem { @@ -83,12 +79,12 @@ void text_handler(void *data, const char *text, int len) { } } -bool XmlParser::isMainConfFile(const std::string& filename) { +bool XmlParser::isMainConfFile(const char *filename) { switch (curr_bus) { case SYSTEM_BUS: - return (filename == SYSTEM_BUS_CONF_FILE_PRIMARY || filename == SYSTEM_BUS_CONF_FILE_SECONDARY); + return strcmp(filename, SYSTEM_BUS_CONF_FILE_PRIMARY) == 0 || strcmp(filename, SYSTEM_BUS_CONF_FILE_SECONDARY) == 0; case SESSION_BUS: - return (filename == SESSION_BUS_CONF_FILE_PRIMARY || filename == SESSION_BUS_CONF_FILE_SECONDARY); + return strcmp(filename, SESSION_BUS_CONF_FILE_PRIMARY) == 0 || strcmp(filename, SESSION_BUS_CONF_FILE_SECONDARY) == 0; } return false; } @@ -180,14 +176,14 @@ void XmlParser::elementEnd(const char *el) { } } -int XmlParser::parsePolicyConfigFile(BusType bus, const std::string& fname) { +int XmlParser::parsePolicyConfigFile(BusType bus, const char *fname) { tslog::log("XmlParser::parsePolicyConfigFile called with filename: ", fname, "\n"); curr_bus = bus; parsePolicyConfigFileInternal(fname); return ret_code; } -void XmlParser::parsePolicyConfigFileInternal(const std::string& filename) { +void XmlParser::parsePolicyConfigFileInternal(const char *filename) { ret_code = 0; try { parseXmlFile(filename); @@ -208,13 +204,13 @@ void XmlParser::parsePolicyConfigFileInternal(const std::string& filename) { } std::vector curr_included_files = included_files; // deep copy for (const auto& included_file : curr_included_files) { - parsePolicyConfigFileInternal(included_file); + parsePolicyConfigFileInternal(included_file.c_str()); } } -std::unique_ptr file2str(const std::string& filename) { +std::unique_ptr file2str(const char *filename) { - FILE *fp = fopen(filename.c_str(), "rb"); + FILE *fp = fopen(filename, "rb"); if (fp == nullptr) { throw std::runtime_error(std::string("Failed to open file: ").append(filename).c_str()); } @@ -240,7 +236,7 @@ std::unique_ptr file2str(const std::string& filename) { return str; } -void XmlParser::parseXmlFile(const std::string& filename) { +void XmlParser::parseXmlFile(const char *filename) { included_files.clear(); tslog::log("Processing: ", filename, " ...\n"); diff --git a/src/internal/xml_parser.hpp b/src/internal/xml_parser.hpp index 8ede445..a47b963 100644 --- a/src/internal/xml_parser.hpp +++ b/src/internal/xml_parser.hpp @@ -33,7 +33,7 @@ namespace ldp_xml_parser { public: /** Parses given config file for declared bus type */ - int parsePolicyConfigFile(BusType bus_type, const std::string& fname); + int parsePolicyConfigFile(BusType bus_type, const char *fname); void elementStart(const char *el, const char **attr); @@ -47,13 +47,13 @@ namespace ldp_xml_parser class IncludeItem; /** Decides whether a filename describes one of main system.conf/session.conf files */ - bool isMainConfFile(const std::string& filename); + bool isMainConfFile(const char *filename); /** Parses config file and all files included in it (recursively) */ - void parsePolicyConfigFileInternal(const std::string& filename); + void parsePolicyConfigFileInternal(const char *filename); /** Parses config file and returns all files included in it */ - void parseXmlFile(const std::string& filename); + void parseXmlFile(const char *filename); /** Parses element */ IncludeItem parseIncludeItem(); -- 2.7.4