diff options
Diffstat (limited to 'src/internal/storage_backend_serialized.cpp')
-rw-r--r-- | src/internal/storage_backend_serialized.cpp | 238 |
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 = [¤tBest, &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 = [¤tBest, &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 |