--- /dev/null
+/*
+ * Copyright (c) 2019 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.
+*/
+#pragma once
+
+#include <array>
+
+template <typename T, size_t MAX_SIZE>
+class ArrayWithSize : public std::array<T, MAX_SIZE> {
+ size_t num{0};
+
+public:
+ size_t size() const { return num; }
+ bool empty() const { return size() == 0; }
+
+ void push_back(const T &elem) {
+ if (num < MAX_SIZE)
+ (*this)[num++] = elem;
+ }
+ void clear() { num = 0; }
+ const T *begin() const { return &(*this)[0]; }
+ const T *end() const { return &(*this)[num]; }
+};
--- /dev/null
+/*
+ * Copyright (c) 2019 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.
+*/
+#pragma once
+
+#include "array_with_size.hpp"
+#include "tslog.hpp"
+
+#include <boost/utility/string_ref.hpp>
+#include <cstdlib>
+
+/* kdbus driver hard limit for names per connection - as in kernel's kdbus/limits.h. */
+#define KDBUS_CONN_MAX_NAMES 256
+
+class KdbusBusNames : public ArrayWithSize<boost::string_ref, KDBUS_CONN_MAX_NAMES>
+{
+public:
+ KdbusBusNames &addSpaceSeparatedNames(const char *names) noexcept {
+ if (names) {
+ boost::string_ref current(names);
+ while (!current.empty()) {
+
+ if (!(isalnum(current[0]) || current[0] == ' '))
+ tslog::log_verbose("Wrong name(", current, "): ", names, "\n");
+
+ auto space = current.find_first_of(" ");
+ push_back(current.substr(0, space));
+
+ if (space != current.npos) // skip the space
+ current = current.substr(space+1);
+ else
+ current.clear();
+ }
+ }
+ return *this;
+ }
+};
const uid_t user,
const gid_t group,
const char* const label,
- const char* const destination,
- const char** const destination_names,
- uint16_t destination_names_size,
+ const KdbusBusNames &destination_names,
const char* const path,
const char* const interface,
const char* const member,
int type)
{
- MatchItemSend matcher(interface, member, path, static_cast<MessageType>(type));
- if (destination_names_size == 0) {
- if (!matcher.addNames(destination)) {
- tslog::log_verbose("Destination too long: ", destination, "\n");
- return false;
- }
- } else {
- assert(destination_names);
- for (size_t i = 0; i < destination_names_size; i++)
- matcher.addName(destination_names[i]);
- }
+ MatchItemSend matcher(interface, member, path, static_cast<MessageType>(type), destination_names);
return static_cast<int>(policy_checker(bus_type).check(user, group, label, matcher));
}
const uid_t user,
const gid_t group,
const char* const label,
- const char* const sender,
- const char** const sender_names,
- uint16_t sender_names_size,
+ const KdbusBusNames &sender_names,
const char* const path,
const char* const interface,
const char* const member,
int type)
{
- MatchItemReceive matcher(interface, member, path, static_cast<MessageType>(type));
- if (0 == sender_names_size) {
- if (!matcher.addNames(sender)) {
- tslog::log_verbose("Sender too long: ", sender, "\n");
- return false;
- }
- } else {
- assert(sender_names);
- for (size_t i = 0; i < sender_names_size; i++)
- matcher.addName(sender_names[i]);
- }
+ MatchItemReceive matcher(interface, member, path, static_cast<MessageType>(type), sender_names);
return static_cast<int>(policy_checker(bus_type).check(user, group, label, matcher));
}
#ifndef _LIBDBUSPOLICY1_INTERNAL_H_
#define _LIBDBUSPOLICY1_INTERNAL_H_
+#include "bus_names_array.hpp"
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
const uid_t user,
const gid_t group,
const char* const label,
- const char* const destination,
- const char** const destination_names,
- uint16_t destination_names_size,
+ const KdbusBusNames &destination_names,
const char* const path,
const char* const interface,
const char* const member,
uid_t user,
gid_t group,
const char* const label,
- const char* const sender,
- const char** const sender_names,
- uint16_t sender_names_size,
+ const KdbusBusNames &sender_names,
const char* const path,
const char* const interface,
const char* const member,
return __decision;
}
-MatchItemSR::MatchItemSR(const char* i, const char* me, const char* p, MessageType t)
- : type(t) {
+MatchItemSR::MatchItemSR(const char* i,
+ const char* me,
+ const char* p,
+ MessageType t,
+ const KdbusBusNames &n_array)
+ : names{n_array}
+ , type{t}
+{
if (i) interface = i;
if (me) member = me;
if (p) path = p;
}
-void MatchItemSR::addName(const char* name) {
- names.push_back(name);
-}
-
-bool MatchItemSR::addNames(const char* name) noexcept {
-
- if (name) {
- boost::string_ref current(name);
- while (!current.empty()) {
-
- if (!(isalnum(current[0]) || current[0] == ' '))
- tslog::log_verbose("Wrong name(", current, "): ", name, "\n");
-
- auto space = current.find_first_of(" ");
- names.push_back(current.substr(0, space));
-
- if (space != current.npos) // skip the space
- current = current.substr(space+1);
- else
- current.clear();
- }
- }
- return true;
-}
-
bool MatchItemSR::match(MessageType _type,
const boost::string_ref &_interface,
const boost::string_ref &_path,
#define _POLICY_H
#include "type_list.h"
+#include "bus_names_array.hpp"
+#include "internal.h"
#include <boost/utility/string_ref.hpp>
-#include <internal/internal.h>
#include <string>
#include <vector>
-#include <typeinfo>
-
-/** Maximum tree node children. It is connected with proper characters which can be used in name.*/
-#define MAX_CHILDREN 65
namespace ldp_xml {
class StorageBackendXML;
};
/** Struct which allows to contain multiple connection names then compared in s/r policy checker */
- struct MatchItemSR {
- std::vector<boost::string_ref> names;
+ class MatchItemSR {
+ const KdbusBusNames &names;
boost::string_ref interface;
boost::string_ref member;
boost::string_ref path;
MessageType type;
- MatchItemSR(const char* i, const char* me, const char* p, MessageType t);
- void addName(const char* name);
- bool addNames(const char* name) noexcept;
+
+ friend std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemSR &item);
+ public:
+ MatchItemSR(const char* i, const char* me, const char* p, MessageType t, const KdbusBusNames &n_array);
bool match(MessageType _type,
const boost::string_ref &_interface,
*/
#include "kdbus.h"
+#include "internal/tslog.hpp"
+#include <boost/utility/string_ref.hpp>
#include <cassert>
#include <cerrno>
#include <cstddef>
#include <fcntl.h>
#include <linux/kdbus.h>
#include <memory>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
set_item_str(cmd->items, bus_name, l+1, KDBUS_ITEM_NAME);
}
if (ioctl(fd, KDBUS_CMD_CONN_INFO, cmd) < 0) {
+ LOGE("Failed KDBUS_CMD_CONN_INFO: %m\n");
if (errno == ENXIO || errno == ESRCH)
return DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE;
free_offset = offset;
set = true;
- names_num = 0;
+ k_names.clear();
_label = nullptr;
uid_n = UID_INVALID;
gid_n = GID_INVALID;
#pragma once
-#include <linux/kdbus.h>
-#include <stdint.h>
#include <pwd.h>
#include <grp.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-
-#define KDBUS_CONN_MAX_NAMES 256
+#include <array>
+#include "internal/bus_names_array.hpp"
+#include <boost/utility/string_ref.hpp>
class KdbusConnectionInfo;
static const gid_t GID_INVALID = -1;
char const *_label{nullptr};
- const char *k_names[KDBUS_CONN_MAX_NAMES]{};
+
+ KdbusBusNames k_names;
uint64_t free_offset{0};
uid_t uid_n{UID_INVALID};
gid_t gid_n{GID_INVALID};
- uint16_t names_num{0};
bool set{false};
KdbusConnection &my_connection;
void release_info();
void setNewData(uint64_t offset);
- void addName(const char *name) { k_names[names_num++] = name; }
+ void addName(const char *name) { k_names.push_back(name); }
void setCreds(uid_t uid, gid_t gid) { uid_n = uid; gid_n = gid; }
int get(const char *destination, KdbusConnection::conn_info_type conn_info_type) {
return my_connection.get_conn_info(destination, conn_info_type, this);
}
- const char **names() { return k_names; }
- uint16_t numberOfNames() const { return names_num; }
+ const KdbusBusNames &names() const { return k_names; }
+ KdbusBusNames &names() { return k_names; }
uid_t uid() const { return uid_n; }
gid_t gid() const { return gid_n; }
const char *label() const { return _label; }
delete KCONN(configuration);
}
+static int getNames(const char *name, KdbusConnectionInfo &info,
+ KdbusConnection::conn_info_type info_type) {
+ if (name && *name) {
+ int r = info.get(name, info_type);
+ if (r < 0)
+ return r;
+
+ if (info.names().empty())
+ info.names().addSpaceSeparatedNames(name);
+ }
+ return 0;
+}
+
DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
const char *destination,
const char *sender,
int r;
/* check can send */
/* if broadcasting, then pass - null destination */
- if (destination && *destination) {
- r = destinationInfo.get(destination, KdbusConnection::POLICY_CONN_INFO_ALL);
- if (r < 0)
- return r;
- }
+ r = getNames(destination, destinationInfo, KdbusConnection::POLICY_CONN_INFO_ALL);
+ if (r < 0)
+ return r;
r = __internal_can_send(kconn->bus_type,
g_udesc.uid, g_udesc.gid, g_udesc.label,
- destination, destinationInfo.names(), destinationInfo.numberOfNames(),
- path, interface, member, message_type);
+ destinationInfo.names(), path, interface, member, message_type);
if (r <= 0)
return r;
KdbusConnectionInfo senderInfo(kconn->conn);
/* check can recv */
/* get sender information from kdbus */
- r = senderInfo.get(sender, KdbusConnection::POLICY_CONN_INFO_NAME);
- if (r < 0) {
- fprintf(stderr, "failed to kdbus conn info:%d\n", r);
+ r = getNames(sender, senderInfo, KdbusConnection::POLICY_CONN_INFO_NAME);
+ if (r < 0)
return r;
- }
return __internal_can_recv(kconn->bus_type,
destinationInfo.uid(), destinationInfo.gid(), destinationInfo.label(),
- sender, senderInfo.names(), senderInfo.numberOfNames(),
- path, interface, member, message_type);
+ senderInfo.names(), path, interface, member, message_type);
}
DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration,
auto kconn = KCONN(configuration);
KdbusConnectionInfo info(kconn->conn);
int r;
- if (destination && *destination) {
- r = info.get(destination, KdbusConnection::POLICY_CONN_INFO_NAME);
- if (r < 0)
- return r;
- }
+ r = getNames(destination, info, KdbusConnection::POLICY_CONN_INFO_NAME);
+ if (r < 0)
+ return r;
r = __internal_can_send(kconn->bus_type,
sender_uid, sender_gid, sender_label,
- destination, info.names(), info.numberOfNames(),
- path, interface, member, message_type);
+ info.names(), path, interface, member, message_type);
if (r <= 0)
return r;
sender = ":";
/* libdbus, gdbus pass multiple sender as parameter : eg. "name_A name_B name_C". */
+ KdbusBusNames names;
r = __internal_can_recv(kconn->bus_type,
g_udesc.uid, g_udesc.gid, g_udesc.label,
- sender, nullptr, 0,
+ names.addSpaceSeparatedNames(sender),
path, interface, member, message_type);
if (r <= 0)
void send_prefix_test(const DB &db)
{
for (const auto &test : tests) {
- MatchItemSend m_item(test.interface, test.member, test.path, test.type);
- m_item.addNames(test.destination);
+ KdbusBusNames names;
+ MatchItemSend m_item(test.interface, test.member, test.path, test.type,
+ names.addSpaceSeparatedNames(test.destination));
auto ret = db.getDecisionItemContextMandatory(m_item);
Decision get_decision(DB &db, const MethodTest &test) {
DecisionItem ret;
- T m_item = T(test.interface, test.member, test.path, test.type);
- m_item.addNames(test.name);
+ KdbusBusNames names;
+ T m_item = T(test.interface, test.member, test.path, test.type,
+ names.addSpaceSeparatedNames(test.name));
ret = db.getDecisionItemContextMandatory(m_item);
if (ret.getDecision() == Decision::ANY) {
bool ret = true;
__internal_init(SYSTEM_BUS, "tests/default_allow/system.conf");
for (i = 0; i < sizeof(method_tests)/sizeof(struct MethodTest); i++) {
+ KdbusBusNames bus_names;
+ bus_names.addSpaceSeparatedNames(method_tests[i].name);
if (method_tests[i].recv_send == MessageDirection::SEND)
{
ret = __internal_can_send(SYSTEM_BUS,
method_tests[i].user, method_tests[i].group, method_tests[i].label,
- method_tests[i].name, nullptr, 0,
+ bus_names,
method_tests[i].path, method_tests[i].interface, method_tests[i].member,
static_cast<int>(method_tests[i].type));
} else if (method_tests[i].recv_send == MessageDirection::RECEIVE) {
ret = __internal_can_recv(SYSTEM_BUS,
method_tests[i].user, method_tests[i].group, method_tests[i].label,
- method_tests[i].name, nullptr, 0,
+ bus_names,
method_tests[i].path, method_tests[i].interface, method_tests[i].member,
static_cast<int>(method_tests[i].type));
}
bool flag = true;
for (const auto &test : tests) {
- MatchItemSend m_item(test.interface, test.member, test.path, test.type);
- m_item.addNames(test.destination);
+ KdbusBusNames names;
+ MatchItemSend m_item(test.interface, test.member, test.path, test.type,
+ names.addSpaceSeparatedNames(test.destination));
auto ret = db.getDecisionItemContextMandatory(m_item);
__internal_init(SYSTEM_BUS, "tests/default_deny/system.conf");
for (i = 0; i < sizeof(tests)/sizeof(struct Test); i++) {
+ KdbusBusNames names;
ret = __internal_can_send(SYSTEM_BUS, tests[i].user,
- tests[i].group, tests[i].label, tests[i].destination, nullptr, 0,
+ tests[i].group, tests[i].label,
+ names.addSpaceSeparatedNames(tests[i].destination),
tests[i].path, tests[i].interface, tests[i].member,
(int)tests[i].type);
unsigned i = 0;
bool flag = true;
for (const auto &test : signal_tests) {
- MatchItemSend m_item(test.interface, NULL, NULL, ldp_xml_parser::MessageType::SIGNAL);
- m_item.addNames(test.dest);
+ KdbusBusNames names;
+ MatchItemSend m_item(test.interface, NULL, NULL, ldp_xml_parser::MessageType::SIGNAL,
+ names.addSpaceSeparatedNames(test.dest));
auto ret = db.getDecisionItemContextMandatory(m_item);
bool ret = true;
__internal_init(SYSTEM_BUS, "tests/default_allow/system.conf");
for (i = 0; i < sizeof(signal_tests)/sizeof(struct SignalTest); i++) {
+ KdbusBusNames names;
ret = __internal_can_send(SYSTEM_BUS,
signal_tests[i].user, signal_tests[i].group, signal_tests[i].label,
- signal_tests[i].dest, nullptr, 0,
+ names.addSpaceSeparatedNames(signal_tests[i].dest),
NULL, signal_tests[i].interface, NULL, DBUSPOLICY_MESSAGE_TYPE_SIGNAL);
if ( (int)((signal_tests[i].expected_result)) != ret) {
printf("[ERROR][%d] signal test failed: %d %d ", i, (int)((signal_tests[i].expected_result)), ret);