summaryrefslogtreecommitdiff
path: root/src/internal/storage_backend_serialized.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/storage_backend_serialized.cpp')
-rw-r--r--src/internal/storage_backend_serialized.cpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/src/internal/storage_backend_serialized.cpp b/src/internal/storage_backend_serialized.cpp
index 8337ee0..ac3c5bc 100644
--- a/src/internal/storage_backend_serialized.cpp
+++ b/src/internal/storage_backend_serialized.cpp
@@ -21,9 +21,11 @@
* THE SOFTWARE. */
#include "print_content.hpp"
+#include "serialized_convert.hpp"
#include "storage_backend_serialized.hpp"
#include "transaction_guard.hpp"
#include "tslog.hpp"
+#include <boost/tokenizer.hpp>
#include <cassert>
#include <fcntl.h>
#include <sys/mman.h>
@@ -123,3 +125,239 @@ void StorageBackendSerialized::release() {
impl.release();
}
+
+template <> auto StorageBackendSerialized::getPolicySet<ldp_xml_parser::MatchItemOwn>() const {
+ return impl.fileGetOwnSet(impl.getFile());
+}
+
+template <> auto StorageBackendSerialized::getPolicySet<ldp_xml_parser::MatchItemSend>() const {
+ return impl.fileGetSendSet(impl.getFile());
+}
+
+template <> auto StorageBackendSerialized::getPolicySet<ldp_xml_parser::MatchItemReceive>() const {
+ return impl.fileGetReceiveSet(impl.getFile());
+}
+
+template <> auto StorageBackendSerialized::getPolicySet<ldp_xml_parser::MatchItemAccess>() const {
+ return impl.fileGetAccessSet(impl.getFile());
+}
+
+template <typename DI>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::makeDecisionItem(const DI &item) const {
+ return ldp_xml_parser::DecisionItem(makeDecision(impl.decisionItemGetDecision(item)),
+ impl.stringGetCStr(impl.decisionItemGetPrivilege(item)));
+}
+
+template <typename String>
+boost::string_ref StorageBackendSerialized::toStringRef(const String &str) const {
+ return boost::string_ref(impl.stringGetCStr(str), impl.stringGetSize(str));
+}
+
+template <typename T, typename I>
+bool StorageBackendSerialized::match(const T &match, const I &item) const {
+ return match.match(makeMessageType(impl.itemSrGetMessageType(item)),
+ toStringRef(impl.itemSrGetInterface(item)),
+ toStringRef(impl.itemSrGetPath(item)),
+ toStringRef(impl.itemSrGetMember(item)),
+ toStringRef(impl.itemSrGetName(item)),
+ impl.itemSrGetIsNamePrefix(item),
+ makeDecision(impl.decisionItemGetDecision(impl.itemGetDecisionItem(item))));
+}
+
+template <typename I>
+bool StorageBackendSerialized::match(const ldp_xml_parser::MatchItemAccess &match, const I &item) const {
+ return match.match(makeBusAccessType(impl.itemAccessGetType(item)), impl.itemAccessGetUid(item), impl.itemAccessGetGid(item));
+}
+
+template <typename T, typename P>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItem(const T &item, const P &policy, ldp_serialization::ItemsType) const {
+ auto v = impl.policyGetItems(policy);
+ auto rend = impl.containerGetReverseIteratorEnd(v);
+ for (auto rit = impl.containerGetReverseIterator(v); rit != rend; ++rit) {
+ if (match(item, *rit))
+ return makeDecisionItem(impl.itemGetDecisionItem(*rit));
+ }
+ return ldp_xml_parser::Decision::ANY;
+}
+
+template <typename P>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItem(const ldp_xml_parser::MatchItemSend &item, const P &policy) const {
+ if (!impl.policyHasIndex(policy))
+ return getDecisionItem(item, policy, ldp_serialization::ItemsType()); // make it old way for old databases
+
+ auto index = impl.policyGetIndex(policy);
+
+ uint32_t currentBest = 0;
+
+ auto updateCurrentBest = [&currentBest, &item, &policy, this](const auto &vec) {
+ // look from the back, the rule is the same as for the full database
+ // we now only check among less elements, because the database is indexed to small lists
+ // item_scores are in increasing order in the index, and they serve also as ids of the policy rules
+ for (auto item_score_it = impl.containerGetReverseIterator(vec);
+ item_score_it != impl.containerGetReverseIteratorEnd(vec);
+ item_score_it++) {
+ auto db_items = impl.policyGetItems(policy);
+ auto db_item = impl.containerLookupByIndex(db_items, *item_score_it - 1); // rules are indexed/scored from 1
+ if (*item_score_it > currentBest && match(item, db_item)) {
+ currentBest = *item_score_it;
+ return;
+ } else if (*item_score_it <= currentBest) {
+ // there is no need to look further as we can't improve the score anymore
+ return;
+ }
+ }
+ };
+
+ auto searchAndUpdateCurrentBest = [&currentBest, &index, &updateCurrentBest, this](boost::string_ref name_ref) {
+ // we need to create C-string for the lookups
+ // boost::string_ref gives us correct start, but possibly NUL-terminated in a wrong place, as it does not modify
+ // input string and keeps only the length
+ std::string name(name_ref.data(), name_ref.size());
+
+ if (impl.containerEmpty(index))
+ return;
+
+ // check if there are any rules for the name
+ auto fit = impl.containerLookupByKey(index, name.c_str());
+ if (!fit.first)
+ return;
+
+ // check if there's any chance to get better score
+ if (impl.policyIndexGetBestScore(fit.second) <= currentBest)
+ return;
+
+ // look for better score
+ updateCurrentBest(impl.policyIndexGetItemRefs(fit.second));
+ };
+
+ auto prefixIndex = impl.policyGetPrefixIndex(policy);
+
+ // iterate over names
+ for (const auto &name: item.getNames()) {
+ // find and check the no-prefix rules
+ searchAndUpdateCurrentBest(name);
+
+ // check the prefix rules
+ updateCurrentBest(prefixIndex);
+ }
+
+ // check no-name rules
+ searchAndUpdateCurrentBest("");
+
+ // if a matching rule was found, return the decision
+ if (currentBest > 0) {
+ auto db_item = impl.containerLookupByIndex(impl.policyGetItems(policy), currentBest - 1);
+ return makeDecisionItem(impl.itemGetDecisionItem(db_item));
+ }
+
+ // or if no matching rule was not found, return the default decision
+ return ldp_xml_parser::Decision::ANY;
+}
+
+template <typename OwnNode>
+auto StorageBackendSerialized::getDecisionItemFromTree(const OwnNode &node,
+ const tokenizer::iterator &tokens_end,
+ tokenizer::iterator &iterator) const {
+ if (iterator == tokens_end) {
+ if (makeDecision(impl.decisionItemGetDecision(impl.ownNodeGetDecisionItem(node))) != ldp_xml_parser::Decision::ANY)
+ return impl.ownNodeGetDecisionItem(node);
+ else
+ return impl.ownNodeGetPrefixDecisionItem(node);
+ }
+
+ auto children = impl.ownNodeGetChildren(node);
+
+ if (impl.containerEmpty(children))
+ return impl.ownNodeGetPrefixDecisionItem(node);
+
+ auto child = impl.containerLookupByKey(children, iterator->c_str());
+ if (!child.first)
+ return impl.ownNodeGetPrefixDecisionItem(node);
+
+ ++iterator;
+ auto child_decision = getDecisionItemFromTree(child.second, tokens_end, iterator);
+ if (makeDecision(impl.decisionItemGetDecision(child_decision)) == ldp_xml_parser::Decision::ANY)
+ return impl.ownNodeGetPrefixDecisionItem(node);
+
+ return child_decision;
+}
+
+template <typename T, typename P>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItem(const T &item, const P &policy, ldp_serialization::TreeType) const {
+ if (item.getName().length() == 0)
+ return ldp_xml_parser::Decision::DENY;
+
+ boost::char_separator<char> separator(".");
+ tokenizer tokens(item.getName(), separator);
+
+ auto iterator = tokens.begin();
+
+ return makeDecisionItem(getDecisionItemFromTree(impl.policyGetTree(policy), tokens.end(), iterator));
+}
+
+template <typename T, typename P>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItem(const T &item, const P &policy) const {
+ return getDecisionItem(item, policy, typename ldp_serialization::PolicyContentType<P>::result());
+}
+
+template <typename MatchItem>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMandatory(const MatchItem &item) const {
+ return getDecisionItem(item, impl.setGetContextMandatory(getPolicySet<MatchItem>()));
+}
+
+template <typename MatchItem>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const MatchItem &item) const {
+ return getDecisionItem(item, impl.setGetContextDefault(getPolicySet<MatchItem>()));
+}
+
+template <typename MatchItem, typename Map>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItem(const MatchItem &item, const Map &map, id_t id) const {
+ if (impl.containerEmpty(map))
+ return ldp_xml_parser::Decision::ANY;
+
+ auto elem = impl.containerLookupByKey(map, id);
+ if (!elem.first)
+ return ldp_xml_parser::Decision::ANY;
+ return getDecisionItem(item, impl.setUserGroupGetPolicy(elem.second));
+}
+
+template <typename MatchItem>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const MatchItem &item) const {
+ return getDecisionItem(item, impl.setGetUser(getPolicySet<MatchItem>()), uid);
+}
+template <typename MatchItem>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_t gid, const MatchItem &item) const {
+ return getDecisionItem(item, impl.setGetGroup(getPolicySet<MatchItem>()), gid);
+}
+
+template <typename MatchItem>
+bool StorageBackendSerialized::existsPolicyForGroup(gid_t gid) const {
+ auto map = impl.setGetGroup(getPolicySet<MatchItem>());
+
+ if (impl.containerEmpty(map))
+ return false;
+
+ return impl.containerLookupByKey(map, gid).first;
+}
+
+#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)
+
+#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 bool StorageBackendSerialized::existsPolicyForGroup<ldp_xml_parser::MatchItem##T>(gid_t) const;
+
+T_INSTANTIATION2(Own)
+T_INSTANTIATION2(Send)
+T_INSTANTIATION2(Receive)
+
+#undef T_INSTANTIATION2