new implementation of own/own_prefix rules handling 57/173457/4
authorAleksy Barcz <a.barcz@partner.samsung.com>
Mon, 19 Mar 2018 09:30:02 +0000 (10:30 +0100)
committerAleksy Barcz <a.barcz@partner.samsung.com>
Tue, 3 Apr 2018 10:07:06 +0000 (12:07 +0200)
Bugfix/rewrite. Previous implementation was based on the incorrect assumption
that "ab" is a prefix of "abc", while according to the dbus specification
"ab" is a prefix of "ab.c" but not "abc" (elements/tokens must be dot-separated).
Added multiple regression tests, covering both simple and exotic cases
(like allowing a prefix "a.b.c", but denying "a.b.c").
All expected test results verified against dbus-daemon (except cynara checks).
All new tests use default-deny-own policy, changed tests directory structure.
Fixed fragile DecisionItem class which assumed ownership of __privilege,
but didn't hide it's copy-constructor, which could result in freeing freed memory.

Change-Id: I98924ccf475ddd5e49e2eac99c9f1b586f982b90

22 files changed:
Makefile.am
packaging/libdbuspolicy.spec
src/internal/cynara_mockup.cpp
src/internal/naive_policy_checker.cpp
src/internal/naive_policy_checker.hpp
src/internal/naive_policy_db.cpp
src/internal/naive_policy_db.hpp
src/internal/own_tree.cpp [new file with mode: 0644]
src/internal/own_tree.hpp [new file with mode: 0644]
src/internal/policy.cpp
src/internal/policy.hpp
src/test-libdbuspolicy1-method.cpp
src/test-libdbuspolicy1-ownership-deny.cpp [new file with mode: 0644]
src/test-libdbuspolicy1-ownership.cpp
src/test-libdbuspolicy1-signal.cpp
tests/default_allow/system.conf [moved from tests/system.conf with 99% similarity]
tests/default_allow/system.d/cynara.test.conf [moved from tests/system.d/cynara.test.conf with 100% similarity]
tests/default_allow/system.d/methods.test.conf [moved from tests/system.d/methods.test.conf with 100% similarity]
tests/default_allow/system.d/ownerships.test.conf [moved from tests/system.d/ownerships.test.conf with 100% similarity]
tests/default_allow/system.d/signals.test.conf [moved from tests/system.d/signals.test.conf with 100% similarity]
tests/default_deny/system.conf [new file with mode: 0644]
tests/default_deny/system.d/ownerships.test.conf [new file with mode: 0644]

index e134086..b4a9012 100644 (file)
@@ -51,6 +51,7 @@ COMMON_SRC =\
        src/internal/naive_policy_checker.cpp \
        src/internal/naive_policy_db.cpp \
        src/internal/policy.cpp \
+       src/internal/own_tree.cpp \
        src/internal/xml_parser.cpp \
        src/internal/tslog.cpp
 
@@ -72,14 +73,17 @@ EXTRA_DIST += src/libdbuspolicy1.pc.in
 CLEANFILES += src/libdbuspolicy1.pc
 
 TESTS = src/test-libdbuspolicy1-ownership \
+       src/test-libdbuspolicy1-ownership-deny \
        src/test-libdbuspolicy1-signal \
        src/test-libdbuspolicy1-method
 
 check_PROGRAMS = src/test-libdbuspolicy1-ownership \
+       src/test-libdbuspolicy1-ownership-deny \
     src/test-libdbuspolicy1-signal \
     src/test-libdbuspolicy1-method
 
 src_test_libdbuspolicy1_ownership_SOURCES = src/test-libdbuspolicy1-ownership.cpp
+src_test_libdbuspolicy1_ownership_deny_SOURCES = src/test-libdbuspolicy1-ownership-deny.cpp
 src_test_libdbuspolicy1_signal_SOURCES = src/test-libdbuspolicy1-signal.cpp
 src_test_libdbuspolicy1_method_SOURCES = src/test-libdbuspolicy1-method.cpp
 
@@ -91,6 +95,9 @@ src_libinternal_a_SOURCES =\
 src_test_libdbuspolicy1_ownership_LDADD = $(CYNARA_LIBS) \
        src/libinternal.a
 
+src_test_libdbuspolicy1_ownership_deny_LDADD = $(CYNARA_LIBS) \
+       src/libinternal.a
+
 src_test_libdbuspolicy1_signal_LDADD = $(CYNARA_LIBS) \
        src/libinternal.a
 
index 0ec26d2..725c1b8 100644 (file)
@@ -64,15 +64,15 @@ rm %{buildroot}%{_libdir}/libdbuspolicy1.la
 %define testconfigsdir %{dbustestsdir}/configs/%{testsdirname}
 %define btestconfigsdir %{buildroot}%{testconfigsdir}
 mkdir -p %{btestconfigsdir}
-libtool --mode=install install -m 0644 tests/system.conf %{btestconfigsdir}
+libtool --mode=install install -m 0644 tests/default_allow/system.conf %{btestconfigsdir}
 
 %define testconfigsystemddir %{testconfigsdir}/system.d
 %define btestconfigsystemddir %{buildroot}%{testconfigsystemddir}
 mkdir -p %{btestconfigsystemddir}
-libtool --mode=install install -m 0644 tests/system.d/ownerships.test.conf %{btestconfigsystemddir}
-libtool --mode=install install -m 0644 tests/system.d/signals.test.conf %{btestconfigsystemddir}
-libtool --mode=install install -m 0644 tests/system.d/methods.test.conf %{btestconfigsystemddir}
-libtool --mode=install install -m 0644 tests/system.d/cynara.test.conf %{btestconfigsystemddir}
+libtool --mode=install install -m 0644 tests/default_allow/system.d/ownerships.test.conf %{btestconfigsystemddir}
+libtool --mode=install install -m 0644 tests/default_allow/system.d/signals.test.conf %{btestconfigsystemddir}
+libtool --mode=install install -m 0644 tests/default_allow/system.d/methods.test.conf %{btestconfigsystemddir}
+libtool --mode=install install -m 0644 tests/default_allow/system.d/cynara.test.conf %{btestconfigsystemddir}
 
 %define testsuitedir %{dbustestsdir}/test-suites/%{testsdirname}
 %define btestsuitedir %{buildroot}%{testsuitedir}
index d472cdb..a95d160 100644 (file)
@@ -3,12 +3,32 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdexcept>
+#include <string.h>
 
 using namespace ldp_cynara;
 
 CynaraResult Cynara::check(const char* label, const char* privilege, const char* uid) {
        (void)label;
-       (void)privilege;
-       (void)uid;
+       if (privilege == nullptr) {
+               return CynaraResult::ALLOW;
+       }
+       if (strcmp(uid, "9999") == 0) {
+               if (strcmp(privilege, "http://tizen.org/privilege/packagemanager.admin") == 0) {
+                       return CynaraResult::ALLOW;
+               }
+               return CynaraResult::DENY;
+       }
+       if (strcmp(privilege, "privilege1") == 0) {
+               if (strcmp(uid, "9991") == 0 || strcmp(uid, "9993") == 0) {
+                       return CynaraResult::ALLOW;
+               }
+               return CynaraResult::DENY;
+       }
+       if (strcmp(privilege, "privilege2") == 0) {
+               if (strcmp(uid, "9992") == 0 || strcmp(uid, "9993") == 0) {
+                       return CynaraResult::ALLOW;
+               }
+               return CynaraResult::DENY;
+       }
        return CynaraResult::ALLOW;
 }
index e743147..dac8eb9 100755 (executable)
@@ -107,80 +107,46 @@ Decision NaivePolicyChecker::checkPolicySR(const NaivePolicyDb::PolicySR& policy
        return Decision::ANY;
 }
 
-Decision NaivePolicyChecker::checkPolicyOwn(const NaivePolicyDb::PolicyOwn& policy, const ItemOwn& item, const char*& privilege)
+DecisionItem NaivePolicyChecker::checkPolicyOwn(const NaivePolicyDb::PolicyOwn& policy, const ItemOwn& item)
 {
        if (tslog::verbose()) {
                std::cout << "Checking policy for name: " << std::string(!(item.getName()) ?  item.getName() : "NULL") << std::endl;
        }
 
-       const char *name = item.getName();
-       const struct TreeNode *node = policy.getTreeRoot();
-       int childIndex = 0;
-       assert(node);
-       Decision ret = Decision::ANY;
-       while ((name != NULL) && (*name != '\0')) {
-               childIndex = char_map[static_cast<unsigned>(*name)];
-               if (childIndex > 64) {
-                       /* name contains forbidden char */
-                       if (tslog::verbose()) {
-                               std::cout << "Name: " << std::string(!(item.getName()) ? (item.getName()) : "NULL") << " contains forbidden character!" << std::endl;
-                       }
-                       privilege = NULL;
-                       return Decision::DENY;
-               }
-               /* Current node is prefix, remember decision */
-               if (node->__is_prefix) {
-                       ret = node->__decisionItem.getDecision();
-                       privilege = node->__decisionItem.getPrivilege();
-               }
-               /* Node for this letter don't exist */
-               if (node->children[childIndex] == NULL) {
-                       if(ret != Decision::ANY)
-                               return ret;
-                       else if (policy.getTreeRoot()->__is_prefix)
-                               return policy.getTreeRoot()->__decisionItem.getDecision();
-                       else
-                               return Decision::ANY;
-               } else { /* if it exists check for next letter in its child */
-                       node = node->children[childIndex];
-               }
-               name++;
-       }
-
-       return node->__decisionItem.getDecision();
+       DecisionItem decision_item = policy.getDecisionItem(item);
+       return decision_item;
 }
 
 DecisionResult NaivePolicyChecker::checkItemOwn(bool bus_type, uid_t uid, gid_t gid, const char* label, const ItemOwn& item) {
        NaivePolicyDb& policy_db = getPolicyDb(bus_type);
-       Decision ret = Decision::ANY;
-       const char* privilege;
+       DecisionItem ret = Decision::ANY;
        const NaivePolicyDb::PolicyOwn* curr_policy = NULL;
-       if (ret == Decision::ANY) {
+       if (ret.getDecision() == Decision::ANY) {
                if (policy_db.getPolicy(PolicyType::CONTEXT, PolicyTypeValue(ContextType::MANDATORY), curr_policy))
-                       ret = checkPolicyOwn(*curr_policy, item, privilege);
+                       ret = checkPolicyOwn(*curr_policy, item);
        }
-       if (ret == Decision::ANY) {
+       if (ret.getDecision() == Decision::ANY) {
                if (policy_db.getPolicy(PolicyType::USER, PolicyTypeValue(uid), curr_policy))
-                       ret = checkPolicyOwn(*curr_policy, item, privilege);
+                       ret = checkPolicyOwn(*curr_policy, item);
        }
-       if (ret == Decision::ANY) {
+       if (ret.getDecision() == Decision::ANY) {
                auto sgroups = policy_db.getGroups(uid, gid);
                if (sgroups != nullptr) {
                        for (auto sgid : *sgroups) {
                                if (policy_db.getPolicy(PolicyType::GROUP, PolicyTypeValue(sgid), curr_policy)) {
-                                       ret = checkPolicyOwn(*curr_policy, item, privilege);
-                                       if (ret != Decision::ANY)
+                                       ret = checkPolicyOwn(*curr_policy, item);
+                                       if (ret.getDecision() != Decision::ANY)
                                                break;
                                }
                        }
                }
        }
-       if (ret == Decision::ANY) {
+       if (ret.getDecision() == Decision::ANY) {
                if (policy_db.getPolicy(PolicyType::CONTEXT, PolicyTypeValue(ContextType::DEFAULT), curr_policy))
-                       ret = checkPolicyOwn(*curr_policy, item, privilege);
+                       ret = checkPolicyOwn(*curr_policy, item);
        }
-       if (ret != Decision::ANY) {
-               return parseDecision(ret, uid, label, privilege);
+       if (ret.getDecision() != Decision::ANY) {
+               return parseDecision(ret.getDecision(), uid, label, ret.getPrivilege());
        } else {
                return DecisionResult::DENY;
        }
index 2e330ee..70b6a69 100644 (file)
@@ -47,7 +47,6 @@ namespace ldp_xml_parser
                /** Checks send/receive policy for given item
                 * \param[in] policy Policy to check
                 * \param[in] item Item to check
-                * \param[in] privilege Privilege string
                 * \return Returns decision retrieved from policy
                 * \ingroup Implementation
                 * \callgraph
@@ -59,13 +58,11 @@ namespace ldp_xml_parser
                /** Checks ownership policy for given item
                 * \param[in] policy Policy to check
                 * \param[in] item Item to check
-                * \param[in] privilege Privilege string
                 * \return Returns decision retrieved from policy
                 * \ingroup Implementation
                 */
-               Decision checkPolicyOwn(const NaivePolicyDb::PolicyOwn& policy,
-                                                        const ItemOwn& item,
-                                                        const char*& privilege);
+               DecisionItem checkPolicyOwn(const NaivePolicyDb::PolicyOwn& policy,
+                                                        const ItemOwn& item);
 
                /** Parses delivered decision. In case of Decision::CHECK calls cynara.
                 * \param[in] decision Decision from checkers
index f1b3d2b..be88fa0 100755 (executable)
 using namespace ldp_xml_parser;
 
 
-
-NaivePolicyDb::PolicyOwn::PolicyOwn(){
-       treeRootPtr = new struct TreeNode;
-       assert(treeRootPtr);
-       treeRootPtr->__decisionItem = {Decision::ANY, NULL};
-       treeRootPtr->__nameChar = '\0';
-       treeRootPtr->__is_prefix = false;
-       for (int i = 0; i < MAX_CHILDREN; i++) {
-               treeRootPtr->children[i] = NULL;
-       }
-}
-
-void NaivePolicyDb::PolicyOwn::nodeRemove(TreeNode **node){
-       if (!*node) {
-               return;
-       }
-       for (int i = 0 ; i < MAX_CHILDREN; i++) {
-               if ((*node)->children[i] != NULL) {
-                       nodeRemove(&(*node)->children[i]);
-               }
-       }
-       delete *node;
-       *node = NULL;
-}
-
 void NaivePolicyDb::addItem(const PolicyType policy_type,
                                                        const PolicyTypeValue policy_type_value,
                                                        ItemSendReceive* const item) {
@@ -127,12 +102,6 @@ void NaivePolicyDb::PolicySR::addItem(ItemSendReceive* item) {
        m_items.push_back(item);
 }
 
-
-const struct TreeNode* NaivePolicyDb::PolicyOwn::getTreeRoot() const{
-       assert(treeRootPtr);
-       return treeRootPtr;
-}
-
 void NaivePolicyDb::PolicyOwn::addItem(ItemOwn* item) {
        const char *name = item->getName();
        if (tslog::enabled()){
@@ -141,52 +110,12 @@ void NaivePolicyDb::PolicyOwn::addItem(ItemOwn* item) {
                else
                        std::cout << "Adding item: NULL with decision: " << (int) item->getDecision().getDecision() << std::endl;
        }
-       if (!name) {
-               /* For '*' name*/
-               if(item->getDecision().getDecision() != Decision::ANY){
-                       treeRootPtr->__decisionItem = item->getDecision();
-                       treeRootPtr->__is_prefix = true;
-               }
-               return;
-       }
-
-       struct TreeNode *node = treeRootPtr;
-       assert(node);
+       ownership_tree.addItem(item);
+}
 
-       const char *tmp = name;
-       while (tmp && *tmp != '\0') {
-               if (char_map[static_cast<unsigned>(*tmp)] > 64) {
-                       /* Forbidden char */
-                       return;
-               }
-               tmp++;
-       }
-       int childIndex = 0;
-       while (name && *name != '\0') {
-               childIndex = char_map[static_cast<unsigned>(*name)];
-               if (node->children[childIndex] == NULL) {
-                       node->children[childIndex] = new struct TreeNode;
-                       assert(node->children[childIndex]);
-                       node->children[childIndex]->__decisionItem = {Decision::ANY, NULL};
-                       node->children[childIndex]->__nameChar = *name;
-                       node->children[childIndex]->__is_prefix = false;
-                       for (int k = 0; k < MAX_CHILDREN; k++) {
-                               node->children[childIndex]->children[k] = NULL;
-                       }
-
-                       node = node->children[childIndex];
-               } else {
-                       node = node->children[childIndex];
-               }
-               name++;
-       }
-       /*If item is prefix, delete children*/
-       if(item->isPrefix()){
-               for(int i = 0; i < MAX_CHILDREN; i++)
-                       nodeRemove(&(node->children[i]));
-       }
-       node->__decisionItem = item->getDecision();
-       node->__is_prefix = item->isPrefix();
+DecisionItem NaivePolicyDb::PolicyOwn::getDecisionItem(const ItemOwn& item) const
+{
+       return ownership_tree.getDecisionItem(item);
 }
 
 bool NaivePolicyDb::getPolicySR(const NaivePolicyDb::PolicyTypeSetSR& set,
@@ -410,4 +339,4 @@ void NaivePolicyDb::updateSupGroup()
        pthread_mutex_lock(&mutexGroup);
        updateSupplementaryGroups(getuid(), getgid(), ItemType::GENERIC);
        pthread_mutex_unlock(&mutexGroup);
-}
\ No newline at end of file
+}
index 571c31c..f6b5e31 100755 (executable)
@@ -19,6 +19,7 @@
 #include <map>
 #include <vector>
 #include "policy.hpp"
+#include "own_tree.hpp"
 
 
 /**
@@ -74,24 +75,14 @@ namespace ldp_xml_parser
                /** Class containing policy with ownership rules */
                class PolicyOwn {
                        private:
-                               /** Pointer to policy tree root */
-                               struct TreeNode *treeRootPtr = NULL;
+                               class OwnershipTree ownership_tree;
 
-                               /** Removes given node and its descendants
-                                * \param[in] node Node to remove from tree
-                                */
-                               void nodeRemove(TreeNode **node);
                        public:
-                               PolicyOwn();
                                /** Adds given item to tree by retrieving its name, decision and checking is it prefix.
                                 * \param[in] item Item to add to policy
                                 */
                                void addItem(ItemOwn* item);
-
-                               /** Retrieves policy tree root
-                                * \return Pointer to tree root
-                                */
-                               const TreeNode* getTreeRoot() const;
+                               DecisionItem getDecisionItem(const ItemOwn& item) const;
                };
 
                /** Gets policy with ownership rules from DB
diff --git a/src/internal/own_tree.cpp b/src/internal/own_tree.cpp
new file mode 100644 (file)
index 0000000..9eb4b17
--- /dev/null
@@ -0,0 +1,132 @@
+#include "own_tree.hpp"
+#include <boost/tokenizer.hpp>
+#include <unordered_map>
+#include <deque>
+
+/**
+ * \file
+ * \ingroup Implementation
+ */
+
+using namespace ldp_xml_parser;
+
+
+class OwnershipTree::TreeNode{
+public:
+       TreeNode(std::string token);
+       void add(std::deque<std::string>& tokens, const DecisionItem& decision, const bool is_prefix);
+       void setDecisionItem(const DecisionItem& decision, const bool is_prefix);
+       DecisionItem getDecisionItem(std::deque<std::string>& tokens) const;
+
+private:
+       DecisionItem prefixBasedDecision() const;
+
+       std::string __token;    // element of dot-separated name
+       DecisionItem __own_prefix_decision_item;
+       DecisionItem __own_decision_item;
+       std::unordered_map<std::string, std::shared_ptr<TreeNode>> __children;
+};
+
+
+OwnershipTree::OwnershipTree() {
+       __root = std::make_shared<TreeNode>("");
+}
+
+std::deque<std::string> tokenize(const std::string& item_name)
+{
+       std::deque<std::string> elements;
+       typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
+       boost::char_separator<char> separator(".");
+       tokenizer tokens(item_name, separator);
+       for (auto token: tokens) {
+               elements.push_back(token);
+       }
+       return elements;
+}
+
+void OwnershipTree::addItem(ItemOwn* item) {
+       if (item->isMatchAll()) {
+               if (item->getDecision().getDecision() != Decision::ANY){
+                       __root->setDecisionItem(item->getDecision(), true);
+               }
+               return;
+       }
+       assert(item->getName() != nullptr);
+       std::string name = item->getName();
+
+       auto tokens = tokenize(name);
+       __root->add(tokens, item->getDecision(), item->isPrefix());
+}
+
+DecisionItem OwnershipTree::getDecisionItem(const ItemOwn& item) const
+{
+       if (item.getName() == nullptr) {
+               return Decision::DENY;
+       }
+       std::string name = item.getName();
+
+       auto tokens = tokenize(name);
+       return __root->getDecisionItem(tokens);
+}
+
+OwnershipTree::TreeNode::TreeNode(std::string token)
+:__token(token), __own_prefix_decision_item(Decision::ANY), __own_decision_item(Decision::ANY)
+{}
+
+void OwnershipTree::TreeNode::add(std::deque<std::string>& tokens, const DecisionItem& decision, const bool is_prefix)
+{
+       if (tokens.empty()) {
+               setDecisionItem(decision, is_prefix);
+
+               if (is_prefix) {
+                       __children.clear();
+               }
+               return;
+       }
+
+       const auto& token = tokens.front();
+       auto it = __children.find(token);
+       if (it == __children.end()) {
+               it = __children.insert({token, std::make_shared<TreeNode>(token)}).first;
+       }
+       assert(it != __children.end());
+       tokens.pop_front();
+
+       it->second->add(tokens, decision, is_prefix);
+}
+
+void OwnershipTree::TreeNode::setDecisionItem(const DecisionItem& decision, const bool is_prefix)
+{
+       if (is_prefix) {
+               __own_prefix_decision_item = decision;
+               __own_decision_item = Decision::ANY;
+       } else {
+               __own_decision_item = decision;
+               // we don't clear own_prefix decision, it still applies to children
+       }
+}
+
+DecisionItem OwnershipTree::TreeNode::getDecisionItem(std::deque<std::string>& tokens) const
+{
+       if (tokens.empty()) {
+               if (__own_decision_item.getDecision() != Decision::ANY) {
+                       return __own_decision_item;
+               } else {
+                       return __own_prefix_decision_item;
+               }
+       }
+
+       const auto& token = tokens.front();
+       auto it = __children.find(token);
+       if (it == __children.end()) {
+               return __own_prefix_decision_item;
+       }
+       assert(it != __children.end());
+       tokens.pop_front();
+
+       DecisionItem child_decision = it->second->getDecisionItem(tokens);
+       if (child_decision.getDecision() == Decision::ANY) {
+               return __own_prefix_decision_item;
+       }
+       return child_decision;
+}
diff --git a/src/internal/own_tree.hpp b/src/internal/own_tree.hpp
new file mode 100644 (file)
index 0000000..710b1ea
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+
+/**
+ * \file
+ * \ingroup Implementation
+ */
+
+#ifndef _OWN_TREE_H
+#define _OWN_TREE_H
+
+#include "policy.hpp"
+#include <memory>
+
+namespace ldp_xml_parser
+{
+       class OwnershipTree{
+       public:
+               OwnershipTree();
+               void addItem(ItemOwn* item);
+               DecisionItem getDecisionItem(const ItemOwn& item) const;
+
+       private:
+               class TreeNode;
+               std::shared_ptr<TreeNode> __root;
+       };
+}
+#endif
index 5286cd8..eb3b461 100755 (executable)
@@ -210,14 +210,19 @@ void DbAdapter::updateGroupDb(bool bus)
 }
 
 DecisionItem::DecisionItem(Decision decision, const char* privilege)
-       : __decision(decision), __privilege(privilege)
+       : __decision(decision)
 {
+       setPrivilege(privilege);
 }
 
-DecisionItem::~DecisionItem()
+void DecisionItem::setPrivilege(const char* privilege)
 {
-       if (__privilege)
-               delete[] __privilege;
+       if (privilege == nullptr) {
+               __privilege = "";
+       } else {
+               __privilege = privilege;
+       }
+
 }
 
 Decision DecisionItem::getDecision() const {
@@ -225,7 +230,10 @@ Decision DecisionItem::getDecision() const {
 }
 
 const char* DecisionItem::getPrivilege() const {
-       return __privilege;
+       if (__privilege == "") {
+               return nullptr;
+       }
+       return __privilege.c_str();
 }
 
 ItemType DecisionItem::getType() const {
@@ -233,7 +241,7 @@ ItemType DecisionItem::getType() const {
 }
 
 const char* DecisionItem::toString(char* str) const {
-       snprintf(str, MAX_LOG_LINE, "Item: dec(%s) priv(%s)", __decision_to_str(__decision), __privilege);
+       snprintf(str, MAX_LOG_LINE, "Item: dec(%s) priv(%s)", __decision_to_str(__decision), __privilege.c_str());
        return str;
 }
 
@@ -260,6 +268,10 @@ bool ItemOwn::isPrefix() const {
        return __is_prefix;
 }
 
+bool ItemOwn::isMatchAll() const {
+       return __name == nullptr;
+}
+
 const DecisionItem& ItemOwn::getDecision() const {
        return __decision;
 }
@@ -407,9 +419,9 @@ ItemBuilder::~ItemBuilder(){
 
 void ItemBuilder::reset() {
        __decision.__decision = Decision::ANY;
-       __decision.__privilege = NULL;
-       __current_sr = NULL;
-       __current_own = NULL;
+       __decision.setPrivilege(nullptr);
+       __current_sr = nullptr;
+       __current_own = nullptr;
 }
 
 char* ItemBuilder::duplicate(const char* str) {
@@ -498,7 +510,7 @@ void ItemBuilder::addDirection(MessageDirection direction) {
 }
 
 void ItemBuilder::addPrivilege(const char* privilege) {
-       __decision.__privilege = duplicate(privilege);
+       __decision.setPrivilege(privilege);
 }
 
 void ItemBuilder::addDecision(Decision decision) {
index 4dd7a6c..abcc0c9 100755 (executable)
 
 namespace ldp_xml_parser
 {
-       /** Char map used in ownership policy. Single character from given name is mapped to index of tree node child*/
-       const char char_map[256] {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 10, 12, 65,
-                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 65, 65, 65, 65, 65, 65,
-                               65, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-                               54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 65, 65, 65, 11,
-                               65, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
-                               28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 65, 65, 65, 65, 65,
-
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-                               65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65};
        /** Type of sent message*/
        enum class MessageType : uint8_t {
                ANY = 0,
@@ -121,11 +103,11 @@ namespace ldp_xml_parser
        class DecisionItem {
        private:
                Decision __decision;
-               const char* __privilege;
+               std::string __privilege;
+               void setPrivilege(const char* privilege);
        public:
                friend class ItemBuilder;
                DecisionItem(Decision decision = Decision::ANY, const char* privilege = NULL);
-               ~DecisionItem();
                Decision getDecision() const;
                const char*  getPrivilege() const;
                ItemType getType() const;
@@ -149,14 +131,7 @@ namespace ldp_xml_parser
                const DecisionItem& getDecision() const;
                const char* getName() const;
                bool isPrefix() const;
-       };
-
-       /** Node of tree used in ownership policy. */
-       struct TreeNode{
-               DecisionItem __decisionItem;
-               char __nameChar;
-               bool __is_prefix;
-               struct TreeNode *children[MAX_CHILDREN];
+               bool isMatchAll() const;
        };
 
        /** Name structure for send/receive policy */
index 9240590..615183d 100644 (file)
@@ -8,8 +8,6 @@
 
 using namespace ldp_xml_parser;
 
-const char* system_path =  "tests/system.conf";
-
 struct MethodTest {
        bool expected_result;
        uid_t user;
@@ -61,7 +59,7 @@ bool method_test() {
        unsigned  i = 0;
        bool flag = true;
        bool ret = true;
-       __internal_init(false, "tests/system.conf");
+       __internal_init(false, "tests/default_allow/system.conf");
        for (i = 0; i < sizeof(method_tests)/sizeof(struct MethodTest); i++) {
                if (method_tests[i].recv_send == MessageDirection::SEND)
                {
diff --git a/src/test-libdbuspolicy1-ownership-deny.cpp b/src/test-libdbuspolicy1-ownership-deny.cpp
new file mode 100644 (file)
index 0000000..872161e
--- /dev/null
@@ -0,0 +1,151 @@
+#include <string>
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "internal/internal.h"
+
+struct OwnershipTest {
+       bool expected_result;
+       uid_t user;
+       gid_t group;
+       const char* label;
+       const char* service;
+};
+
+const int ROOT = 0;
+const int GUEST = 9999;
+const int GUEST1 = 9991;
+const int GUEST2 = 9992;
+const int GUEST12 = 9993;
+
+/**
+ * This test set tests ability to parse xml db
+ * and check ownership privilege in many use cases
+ * including prefix feature
+ */
+struct OwnershipTest ownership_tests[]={
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.ldpo.a"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.ldpoga"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.ldpogd"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.ldposa"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.ldpo.any_suffix"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.ldpnotexistent"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.ldponotexistent"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.zz"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.aa"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.aaa"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a1"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a1.b"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a1.b1"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a1.c"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.b"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.b.c"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.b.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.c"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.c.c"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.c.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.zz"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.bsth"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.bsthelse"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.z.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d.e"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d.esth"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d.ee"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d.e.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d.e.z.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c.d.e.f"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.z.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.e"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.esth"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.ee"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.e.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.e.z.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.e.f"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c1.d.e.f.g"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2.d"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2.d.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2.dd"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2.d.e"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2.d.e.f"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2.d.e.f.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c2.d.e.fsth"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.z.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.e"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.esth"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.ee"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.e.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.e.z.z"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.e.f"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.b.c3.d.e.f.g"},
+       {false, ROOT, ROOT, "User::Shell", "org.tizen.a.c"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.c.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.d"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.a.d.z"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.pok"},
+       {true, ROOT, ROOT, "User::Shell", "org.tizen.pnope"},
+       {true, GUEST, GUEST, "User::Shell", "org.tizen.pok"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pnope"},
+       {true, GUEST, GUEST, "User::Shell", "org.tizen.pok1"},
+       {true, GUEST, GUEST, "User::Shell", "org.tizen.pok1.z"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a"},
+       {true, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b1"},
+       {true, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b1.z"},
+       {true, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b2"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b2.z"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b3"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b3.z"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b4"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a.b4.z"},
+       {false, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a1"},
+       {true, GUEST, GUEST, "User::Shell", "org.tizen.pok1.a1.z"},
+       {true, GUEST1, GUEST1, "User::Shell", "org.tizen.pok2"},
+       {false, GUEST2, GUEST2, "User::Shell", "org.tizen.pok2"},
+       {true, GUEST12, GUEST12, "User::Shell", "org.tizen.pok2"},
+       {false, GUEST1, GUEST1, "User::Shell", "org.tizen.pok2.a"},
+       {false, GUEST2, GUEST2, "User::Shell", "org.tizen.pok2.a"},
+       {false, GUEST12, GUEST12, "User::Shell", "org.tizen.pok2.a"},
+       {false, GUEST1, GUEST1, "User::Shell", "org.tizen.pok2.a.b"},
+       {true, GUEST2, GUEST2, "User::Shell", "org.tizen.pok2.a.b"},
+       {true, GUEST12, GUEST12, "User::Shell", "org.tizen.pok2.a.b"}
+};
+
+void ownershipTest_print(struct OwnershipTest* t, bool result) {
+       printf("uid = %lu, gid = %lu, label = %s, service = %s, expected = %d, result = %d",
+                  (unsigned long)t->user, (unsigned long)t->group, t->label, t->service, ((int)t->expected_result), (int)result);
+}
+
+bool ownership_test() {
+       unsigned  i = 0;
+       bool flag = true;
+       bool ret = true;
+       __internal_init(false, "tests/default_deny/system.conf");
+       for (i = 0; i < sizeof(ownership_tests)/sizeof(struct OwnershipTest); i++) {
+               ret = __internal_can_own(false, ownership_tests[i].user,  ownership_tests[i].group,  ownership_tests[i].label,  ownership_tests[i].service);
+               if ( (int)((ownership_tests[i].expected_result)) != ret) {
+                       printf("[ERROR][%d] ownership test failed: %d %d ", i, (int)((ownership_tests[i].expected_result)), ret);
+                       ownershipTest_print(&ownership_tests[i], ret);
+                       printf("\n");
+                       flag = false;
+               }
+       }
+       return flag;
+}
+
+int main() {
+       __internal_init_once();
+       if (!ownership_test())
+               return -1;
+return 0;
+}
index 12685ea..ae8d238 100644 (file)
@@ -5,8 +5,6 @@
 #include <dbuspolicy1/libdbuspolicy1.h>
 #include "internal/internal.h"
 
-const char* system_path =  "tests/system.conf";
-
 struct OwnershipTest {
        bool expected_result;
        uid_t user;
@@ -57,7 +55,7 @@ bool ownership_test() {
        unsigned  i = 0;
        bool flag = true;
        bool ret = true;
-       __internal_init(false, "tests/system.conf");
+       __internal_init(false, "tests/default_allow/system.conf");
        for (i = 0; i < sizeof(ownership_tests)/sizeof(struct OwnershipTest); i++) {
                ret = __internal_can_own(false, ownership_tests[i].user,  ownership_tests[i].group,  ownership_tests[i].label,  ownership_tests[i].service);
                if ( (int)((ownership_tests[i].expected_result)) != ret) {
index 5eeb840..e0c11cc 100644 (file)
@@ -5,8 +5,6 @@
 #include <dbuspolicy1/libdbuspolicy1.h>
 #include "internal/internal.h"
 
-const char* system_path =  "tests/system.conf";
-
 struct SignalTest {
        bool expected_result;
        uid_t user;
@@ -33,7 +31,7 @@ bool signal_test() {
        unsigned  i = 0;
        bool flag = true;
        bool ret = true;
-       __internal_init(false, "tests/system.conf");
+       __internal_init(false, "tests/default_allow/system.conf");
        for (i = 0; i < sizeof(signal_tests)/sizeof(struct SignalTest); i++) {
                ret = __internal_can_send(false, signal_tests[i].user, signal_tests[i].group, signal_tests[i].label, signal_tests[i].dest, NULL, signal_tests[i].interface, NULL, DBUSPOLICY_MESSAGE_TYPE_SIGNAL);
                if ( (int)((signal_tests[i].expected_result)) != ret) {
similarity index 99%
rename from tests/system.conf
rename to tests/default_allow/system.conf
index 0ba5b64..0ff249b 100644 (file)
@@ -81,3 +81,4 @@
   <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
 
 </busconfig>
+<!-- vim: set ft=xml: -->
diff --git a/tests/default_deny/system.conf b/tests/default_deny/system.conf
new file mode 100644 (file)
index 0000000..56a6eda
--- /dev/null
@@ -0,0 +1,106 @@
+<!-- This configuration file controls the systemwide message bus.
+     Add a system-local.conf and edit that rather than changing this
+     file directly. -->
+
+<!-- Note that there are any number of ways you can hose yourself
+     security-wise by screwing up this file; in particular, you
+     probably don't want to listen on any more addresses, add any more
+     auth mechanisms, run as a different user, etc. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <!-- Our well-known bus type, do not change this -->
+  <type>system</type>
+
+  <!-- Run as special user -->
+  <user>dbus</user>
+
+  <!-- Fork into daemon mode -->
+  <fork/>
+
+  <!-- We use system service launching using a helper -->
+  <standard_system_servicedirs/>
+
+  <!-- This is a setuid helper that is used to launch system services -->
+  <servicehelper>/usr/lib/dbus/dbus-daemon-launch-helper</servicehelper>
+
+  <!-- Write a pid file -->
+  <pidfile>/tmp/dbus_launch</pidfile>
+
+  <!-- Enable logging to syslog -->
+  <syslog/>
+
+  <!-- Only allow socket-credentials-based authentication -->
+  <auth>EXTERNAL</auth>
+
+  <!-- Only listen on a local socket. (abstract=/path/to/socket
+       means use abstract namespace, don't really create filesystem
+       file; only Linux supports this. Use path=/whatever on other
+       systems.) -->
+  <listen>unix:path=/var/run/dbus/system_bus_socket</listen>
+
+  <policy context="default">
+    <!-- All users can connect to system bus -->
+    <allow user="*"/>
+
+    <!-- Holes must be punched in service configuration files for
+         name ownership and sending method calls -->
+    <deny own="*"/>
+    <deny send_type="method_call"/>
+
+    <!-- Signals and reply messages (method returns, errors) are allowed
+         by default -->
+    <allow send_type="signal"/>
+    <allow send_requested_reply="true" send_type="method_return"/>
+    <allow send_requested_reply="true" send_type="error"/>
+
+    <!-- All messages may be received by default -->
+    <allow receive_type="method_call"/>
+    <allow receive_type="method_return"/>
+    <allow receive_type="error"/>
+    <allow receive_type="signal"/>
+
+    <!-- Allow anyone to talk to the message bus -->
+    <allow send_destination="org.freedesktop.DBus"
+           send_interface="org.freedesktop.DBus" />
+    <allow send_destination="org.freedesktop.DBus"
+           send_interface="org.freedesktop.DBus.Introspectable"/>
+
+    <!-- But disallow some specific bus services -->
+    <deny send_destination="org.freedesktop.DBus"
+          send_interface="org.freedesktop.DBus"
+          send_member="UpdateActivationEnvironment"/>
+    <deny send_destination="org.freedesktop.DBus"
+          send_interface="org.freedesktop.DBus.Debug.Stats"/>
+    <deny send_destination="org.freedesktop.DBus"
+          send_interface="org.freedesktop.systemd1.Activator"/>
+  </policy>
+
+  <!-- Only systemd, which runs as root, may report activation failures. -->
+  <policy user="root">
+    <allow send_destination="org.freedesktop.DBus"
+           send_interface="org.freedesktop.systemd1.Activator"/>
+  </policy>
+
+  <!-- root may monitor the system bus. -->
+  <policy user="root">
+    <allow send_destination="org.freedesktop.DBus"
+           send_interface="org.freedesktop.DBus.Monitoring"/>
+  </policy>
+
+  <!-- If the Stats interface was enabled at compile-time, root may use it.
+       Copy this into system.local.conf or system.d/*.conf if you want to
+       enable other privileged users to view statistics and debug info -->
+  <policy user="root">
+    <allow send_destination="org.freedesktop.DBus"
+           send_interface="org.freedesktop.DBus.Debug.Stats"/>
+  </policy>
+
+  <!-- Config files are placed here that among other things, punch
+       holes in the above policy for specific services. -->
+  <includedir>system.d</includedir>
+
+</busconfig>
+<!-- vim: set ft=xml: -->
diff --git a/tests/default_deny/system.d/ownerships.test.conf b/tests/default_deny/system.d/ownerships.test.conf
new file mode 100644 (file)
index 0000000..8ebd47f
--- /dev/null
@@ -0,0 +1,80 @@
+<!DOCTYPE busconfig PUBLIC
+          "-//tizen//DTD D-BUS Bus Configuration 1.0//EN"
+          "http://www.tizen.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <policy user="root">
+    <allow own_prefix="org.tizen.ldpo"/>
+    <allow own="org.tizen.ldpoga"/>
+    <allow own="org.tizen.ldpogd"/>
+    <allow own="org.tizen.ldposa"/>
+    <allow own="org.tizen.ldposd"/>
+
+       <allow own_prefix="org.tizen.b.c"/>
+       <allow own="org.tizen.b.z"/>
+
+       <allow own_prefix="org.tizen.a"/>
+       <deny own="org.tizen.a.bsth"/>
+       <deny own_prefix="org.tizen.a.b"/>
+
+       <allow own_prefix="org.tizen.a1"/>
+       <deny own="org.tizen.a1.b"/>
+
+       <allow own_prefix="org.tizen.a.b.c"/>
+       <deny own_prefix="org.tizen.a.b.c.d"/>
+       <allow own_prefix="org.tizen.a.b.c.d.e"/>
+       <allow own="org.tizen.a.b.c.d.esth"/>
+       <deny own="org.tizen.a.b.c.d.e.f"/>
+
+       <!--order matters -->
+       <allow own_prefix="org.tizen.a.b.c1"/>
+       <deny own_prefix="org.tizen.a.b.c1.d"/>
+       <allow own_prefix="org.tizen.a.b.c1.d.e"/>
+       <deny own="org.tizen.a.b.c1.d.e.f"/>
+       <deny own_prefix="org.tizen.a.b.c1"/>
+       <allow own="org.tizen.a.b.c1.d.esth"/>
+       <allow own="org.tizen.a.b.c1.d.e.f.g"/>
+
+       <deny own_prefix="org.tizen.a.b.c2"/>
+       <allow own_prefix="org.tizen.a.b.c2.d"/>
+       <deny own_prefix="org.tizen.a.b.c2.d.e"/>
+       <allow own_prefix="org.tizen.a.b.c2.d.e.f"/>
+       <allow own="org.tizen.a.b.c2.d.e.fsth"/>
+       <allow own_prefix="org.tizen.a.b.c2"/>
+
+       <allow own_prefix="org.tizen.a.b.c3"/>
+       <deny own_prefix="org.tizen.a.b.c3.d"/>
+       <allow own_prefix="org.tizen.a.b.c3.d.e"/>
+       <deny own="org.tizen.a.b.c3.d.e.f"/>
+       <deny own="org.tizen.a.b.c3"/>
+       <allow own="org.tizen.a.b.c3.d.esth"/>
+       <allow own="org.tizen.a.b.c3.d.e.f.g"/>
+
+       <!-- order matters, a.c will be denied -->
+       <allow own_prefix="org.tizen.a.c"/>
+       <deny own="org.tizen.a.c"/>
+
+       <deny own="org.tizen.a.d"/>
+       <allow own_prefix="org.tizen.a.d"/>
+  </policy>
+
+  <policy context="default">
+       <check own="org.tizen.pok" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+       <check own="org.tizen.pnope" privilege="http://tizen.org/privilege/packagemanager.nope"/>
+
+    <allow own_prefix="org.tizen.pok1" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+    <deny own_prefix="org.tizen.pok1.a"/>
+    <check own_prefix="org.tizen.pok1.a.b1" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+    <check own="org.tizen.pok1.a.b2" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+    <check own_prefix="org.tizen.pok1.a.b3" privilege="http://tizen.org/privilege/packagemanager.nope"/>
+    <check own="org.tizen.pok1.a.b4" privilege="http://tizen.org/privilege/packagemanager.nope"/>
+    <check own_prefix="org.tizen.pok1.a1" privilege="http://tizen.org/privilege/packagemanager.admin"/>
+    <check own="org.tizen.pok1.a1" privilege="http://tizen.org/privilege/packagemanager.nope"/>
+
+    <!-- tests not meant for integration, only for unit tests with cynara mockup -->
+    <check own_prefix="org.tizen.pok2" privilege="privilege1"/>
+    <deny own_prefix="org.tizen.pok2.a"/>
+    <check own_prefix="org.tizen.pok2.a.b" privilege="privilege2"/>
+  </policy>
+</busconfig>
+<!-- vim: set ft=xml: -->