--- /dev/null
+EXTRA_DIST =
+CLEANFILES =
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+AM_MAKEFLAGS = --no-print-directory
+
+AM_CXXFLAGS = ${my_CXXFLAGS}
+
+AM_CPPFLAGS = \
+ -include $(top_builddir)/config.h \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ $(CYNARA_CFLAGS) \
+ -I${top_srcdir}/src
+
+AM_CFLAGS = ${my_CFLAGS} \
+ -fvisibility=hidden \
+ -ffunction-sections \
+ $(CYNARA_CFLAGS) \
+ -fdata-sections
+
+AM_LDFLAGS = \
+ -Wl,--gc-sections \
+ -Wl,--as-needed \
+ $(CYNARA_CFLAGS) \
+$(CYNARA_LIBS)\
+ -pthread
+
+SED_PROCESS = \
+ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(SED) \
+ -e 's,@VERSION\@,$(VERSION),g' \
+ -e 's,@prefix\@,$(prefix),g' \
+ -e 's,@exec_prefix\@,$(exec_prefix),g' \
+ -e 's,@libdir\@,$(libdir),g' \
+ -e 's,@includedir\@,$(includedir),g' \
+ < $< > $@ || rm $@
+
+%.pc: %.pc.in Makefile
+ $(SED_PROCESS)
+
+LIBDBUSPOLICY1_CURRENT=1
+LIBDBUSPOLICY1_REVISION=0
+LIBDBUSPOLICY1_AGE=0
+
+pkginclude_HEADERS = src/dbuspolicy1/libdbuspolicy1.h
+lib_LTLIBRARIES = src/libdbuspolicy1.la
+
+src_libdbuspolicy1_la_SOURCES =\
+ src/libdbuspolicy1-private.h \
+ src/libdbuspolicy1.c \
+ src/internal/internal.cpp
+
+EXTRA_DIST += src/libdbuspolicy1.sym
+
+src_libdbuspolicy1_la_LDFLAGS = $(AM_LDFLAGS) \
+ -version-info $(LIBDBUSPOLICY1_CURRENT):$(LIBDBUSPOLICY1_REVISION):$(LIBDBUSPOLICY1_AGE) \
+ $(CYNARA_LIBS) \
+ -Wl,--version-script=$(top_srcdir)/src/libdbuspolicy1.sym
+src_libdbuspolicy1_la_DEPENDENCIES = ${top_srcdir}/src/libdbuspolicy1.sym
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = src/libdbuspolicy1.pc
+EXTRA_DIST += src/libdbuspolicy1.pc.in
+CLEANFILES += src/libdbuspolicy1.pc
+
+TESTS = src/test-libdbuspolicy1
+
+check_PROGRAMS = src/test-libdbuspolicy1
+src_test_libdbuspolicy1_SOURCES = src/test-libdbuspolicy1.c
+src_test_libdbuspolicy1_LDADD = src/libdbuspolicy1.la $(CYNARA_LIBS)
--- /dev/null
+Authors:
+ Kazimierz Krosman <k.krosman@samsung.com>
+ Arek Antoniak <a.antoniak2@samsung.com>
+
+Library libdbuspolicy adds functionality of DBUS policy utilization in KDBUS, it complies with DBUS policy specification and supports Cynara check directive.
+
+Usage:
+ ./autogen.sh
+ ./configure
+ make
+ make install
+
+The library delivers following API:
+
+ /*!
+ libdbuspolicy init
+ \param bus_type bus type (SYSTEM or SESSION)
+ */
+ void* dbuspolicy1_init(unsigned int bus_type);
+
+ /*!
+ libdbuspolicy free
+ \param configuration pointer with policy configuration acquired using dbuspolicy1_init
+ */
+ void dbuspolicy1_free(void* configuration);
+
+ /*!
+ Check policy for outgoing message
+ \param configuration pointer with policy configuration
+ \param destination list of message destinations
+ \param sender list of message sender names
+ \param path path
+ \param interface interface name
+ \param member member name
+ \param message_type message type
+ \param error_name (future implementation)
+ \param reply_serial (future implementation)
+ \param requested_reply (future implementation)
+ */
+ int dbuspolicy1_check_out(void* configuration,
+ const char *destination,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member,
+ int message_type,
+ const char *error_name,
+ int reply_serial,
+ int requested_reply);
+
+ /*!
+ Check policy for incoming message
+ \param configuration pointer with policy configuration
+ \param destination list of message destinations
+ \param sender list of message sender names
+ \param sender_label sender label (should be manually extracted from incomming message)
+ \param sender_uid sender uid (should be manually extracted from incomming message)
+ \param sender_gid sender gid (should be manually extracted from incomming message)
+ \param path path
+ \param interface interface name
+ \param member member name
+ \param message_type message type
+ \param error_name (future implementation)
+ \param reply_serial (future implementation)
+ \param requested_reply (future implementation)
+ */
+ int dbuspolicy1_check_in(void* configuration,
+ const char *destination,
+ const char *sender,
+ const char *sender_label,
+ uid_t sender_uid,
+ gid_t sender_gid,
+ const char *path,
+ const char *interface,
+ const char *member,
+ int message_type,
+ const char *error_name,
+ int reply_serial,
+ int requested_reply);
+
+ /*!
+ Check policy for service ownership
+ \param configuration pointer with policy configuration
+ \param service service name
+ */
+ int dbuspolicy1_can_own(void* configuration, const char* const service);
--- /dev/null
+#!/bin/sh
+
+set -e
+
+if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
+ cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \
+ chmod +x .git/hooks/pre-commit && \
+ echo "Activated pre-commit hook."
+fi
+
+autoreconf --install --symlink
+
+libdir() {
+ echo $(cd $1/$(gcc -print-multi-os-directory); pwd)
+}
+
+args="--prefix=/usr \
+--sysconfdir=/etc \
+--libdir=$(libdir /usr/lib)"
+
+echo
+echo "----------------------------------------------------------------"
+echo "Initialized build system. For a common configuration please run:"
+echo "----------------------------------------------------------------"
+echo
+echo "./configure CFLAGS='-g -O0' $args"
+echo
--- /dev/null
+AC_PREREQ(2.60)
+AC_INIT([dbuspolicy],
+ [1],
+ [dev@lists.tizen.org],
+ [dbuspolicy],
+ [http://review.tizen.org])
+AC_CONFIG_SRCDIR([src/libdbuspolicy1.c])
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([
+ check-news
+ foreign
+ 1.11
+ -Wall
+ -Wno-portability
+ silent-rules
+ tar-pax
+ no-dist-gzip
+ dist-xz
+ subdir-objects
+])
+AC_PROG_CC_STDC
+AC_PROG_CXX
+AC_USE_SYSTEM_EXTENSIONS
+AC_SYS_LARGEFILE
+AC_CONFIG_MACRO_DIR([m4])
+AM_SILENT_RULES([yes])
+LT_INIT([
+ disable-static
+ pic-only
+])
+AC_PREFIX_DEFAULT([/usr])
+
+AC_PROG_SED
+AC_PROG_MKDIR_P
+
+AC_ARG_ENABLE([logging],
+ AS_HELP_STRING([--disable-logging], [disable system logging @<:@default=enabled@:>@]),
+ [], enable_logging=yes)
+AS_IF([test "x$enable_logging" = "xyes"], [
+ AC_DEFINE(ENABLE_LOGGING, [1], [System logging.])
+])
+
+AC_ARG_ENABLE([debug],
+ AS_HELP_STRING([--enable-debug], [enable debug messages @<:@default=disabled@:>@]),
+ [], [enable_debug=no])
+AS_IF([test "x$enable_debug" = "xyes"], [
+ AC_DEFINE(ENABLE_DEBUG, [1], [Debug messages.])
+])
+
+AC_CHECK_FUNCS([ \
+ __secure_getenv \
+ secure_getenv\
+])
+
+my_CFLAGS="\
+-Wall \
+-Wchar-subscripts \
+-Wformat-security \
+-Wmissing-declarations \
+-Wmissing-prototypes \
+-Wnested-externs \
+-Wpointer-arith \
+-Wshadow \
+-Wsign-compare \
+-Wstrict-prototypes \
+-Wtype-limits \
+"
+AC_SUBST([my_CFLAGS])
+
+my_CXXFLAGS="\
+-Wall \
+-std=c++11 \
+"
+
+AC_SUBST([my_CXXFLAGS])
+PKG_CHECK_MODULES([CYNARA], [cynara-client >= 0.4.2 cynara-session >= 0.4.2],
+ [AC_DEFINE([ENABLE_CYNARA], [1], [Define to enable Cynara privilege checks in libdbuspolicy])],
+ [AC_MSG_ERROR([libcynara-client-async and cynara-session are required to enable Cynara integration])])
+
+AC_SUBST([CYNARA_CFLAGS])
+AC_SUBST([CYNARA_LIBS])
+
+AC_CONFIG_HEADERS(config.h)
+AC_CONFIG_FILES([
+ Makefile
+])
+
+AC_OUTPUT
+AC_MSG_RESULT([
+ $PACKAGE $VERSION
+ =====
+
+ prefix: ${prefix}
+ sysconfdir: ${sysconfdir}
+ libdir: ${libdir}
+ includedir: ${includedir}
+
+ compiler: ${CC}
+ cflags: ${CFLAGS} ${CYNARA_CFLAGS}
+ ldflags: ${LDFLAGS} ${CYMARA_LIBS}
+
+ logging: ${enable_logging}
+ debug: ${enable_debug}
+])
--- /dev/null
+libtool.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+lt~obsolete.m4
--- /dev/null
+Name: libdbuspolicy
+Summary: Helper library for fine-grained userspace policy handling
+License: Apache-2.0
+Group: Base/IPC
+Version: 1.0.0
+Release: 0
+
+Source: %{name}-%{version}.tar.gz
+BuildRequires: boost-devel
+BuildRequires: pkgconfig(cynara-client)
+
+
+%description
+libdbuspolicy is a helper library for fine-grained userspace
+policy handling (with SMACK support)
+
+%prep
+%setup -q
+
+%build
+./autogen.sh
+./configure \
+ --libdir=%{_libdir} \
+ --prefix=/usr
+
+make
+
+%install
+make DESTDIR=%{buildroot} install-strip
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root)
+%{_includedir}/*
+
+%{_libdir}/pkgconfig/*
+%{_libdir}/libdbuspolicy1.so.*
+%{_libdir}/libdbuspolicy1.la
+%{_libdir}/libdbuspolicy1.so
+
+%changelog
--- /dev/null
+.dirstamp
+.deps/
+.libs/
+*.la
+*.lo
+libdbuspolicy1.pc
+test-libdbuspolicy1
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _LIBDBUSPOLICY1_H_
+#define _LIBDBUSPOLICY1_H_
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SYSTEM_BUS_CONF_FILE "/etc/dbus-1/system.conf"
+#define SESSION_BUS_CONF_FILE "/etc/dbus-1/session.conf"
+
+#define SYSTEM_BUS 1
+#define SESSION_BUS 2
+
+/** used when check policy for message prepared to send */
+#define DBUSPOLICY_DIRECTION_SENDING 0
+
+ /** used when check policy for message read from bus */
+#define DBUSPOLICY_DIRECTION_RECEIVING 1
+
+#define DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL 1
+#define DBUSPOLICY_MESSAGE_TYPE_METHOD_RETURN 2
+#define DBUSPOLICY_MESSAGE_TYPE_ERROR 3
+#define DBUSPOLICY_MESSAGE_TYPE_SIGNAL 4
+
+struct udesc;
+
+/*!
+ libdbuspolicy init
+ \param bus_type bus type (SYSTEM or SESSION)
+ */
+void* dbuspolicy1_init(unsigned int bus_type);
+
+/*!
+ libdbuspolicy free
+ \param configuration pointer with policy configuration acquired using dbuspolicy1_init
+ */
+void dbuspolicy1_free(void* configuration);
+
+/*!
+ Check policy for outgoing message
+ \param configuration pointer with policy configuration
+ \param destination list of message destinations
+ \param sender list of message sender names
+ \param path path
+ \param interface interface name
+ \param member member name
+ \param message_type message type
+ \param error_name (future implementation)
+ \param reply_serial (future implementation)
+ \param requested_reply (future implementation)
+ */
+int dbuspolicy1_check_out(void* configuration,
+ const char *destination,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member,
+ int message_type,
+ const char *error_name,
+ int reply_serial,
+ int requested_reply);
+
+/*!
+ Check policy for incoming message
+ \param configuration pointer with policy configuration
+ \param destination list of message destinations
+ \param sender list of message sender names
+ \param sender_label sender label (should be manually extracted from incomming message)
+ \param sender_uid sender uid (should be manually extracted from incomming message)
+ \param sender_gid sender gid (should be manually extracted from incomming message)
+ \param path path
+ \param interface interface name
+ \param member member name
+ \param message_type message type
+ \param error_name (future implementation)
+ \param reply_serial (future implementation)
+ \param requested_reply (future implementation)
+ */
+int dbuspolicy1_check_in(void* configuration,
+ const char *destination,
+ const char *sender,
+ const char *sender_label,
+ uid_t sender_uid,
+ gid_t sender_gid,
+ const char *path,
+ const char *interface,
+ const char *member,
+ int message_type,
+ const char *error_name,
+ int reply_serial,
+ int requested_reply);
+
+/*!
+ Check policy for service ownership
+ \param configuration pointer with policy configuration
+ \param service service name
+ */
+int dbuspolicy1_can_own(void* configuration, const char* const service);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _CYNARA_HPP
+#define _CYNARA_HPP
+
+#include <cynara-client.h>
+#include <cynara-session.h>
+
+namespace _ldp_cynara {
+ class Cynara {
+ private:
+ cynara* __cynara;
+ std::string __session;
+
+ Cynara() {
+ int r = cynara_initialize(&__cynara, NULL);
+ if (r != CYNARA_API_SUCCESS)
+ throw std::runtime_error("Cynara initialization failed");
+
+ __session = cynara_session_from_pid(getpid());
+ }
+
+ ~Cynara() {
+ int r = cynara_finish(__cynara);
+ if (r != CYNARA_API_SUCCESS) {
+ //TODO: reaction
+ }
+ }
+
+ static Cynara& get_instance() {
+ static Cynara __self;
+ return __self;
+ }
+
+ public:
+ static std::string get_session() {
+ Cynara& c = Cynara::get_instance();
+ c.__session = cynara_session_from_pid(getpid());
+ return c.__session;
+ }
+
+ static bool check(std::string label, std::string privilege, std::string uid, std::string session = "") {
+ Cynara& c = Cynara::get_instance();
+ const char* _label="";
+ const char* _session="";
+ const char* _uid="";
+ const char* _privilege="";
+
+ /**
+ workaround. C-str() returns wrong pointer to str
+ when std::string == ""
+ */
+ if (!label.empty())
+ _label=label.c_str();
+
+ if (session == "")
+ session = c.__session;
+ if (!session.empty())
+ _session=session.c_str();
+
+ if (!privilege.empty())
+ _privilege=privilege.c_str();
+
+ if (!uid.empty())
+ _uid=uid.c_str();
+
+ int r = cynara_check (c.__cynara, _label, _session, _uid, _privilege);
+ if (r == CYNARA_API_ACCESS_ALLOWED)
+ return true;
+ else if (r == CYNARA_API_ACCESS_DENIED)
+ return false;
+ else
+ throw std::runtime_error("Cynara check failed");
+ }
+ };
+} //namespace
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#include <iostream>
+#include <string>
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "xml_parser.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const char* get_bus(int bus_type) {
+ return (bus_type == SYSTEM_BUS) ? "SYSTEM" : "SESSION";
+}
+
+static const char* get_str(const char* const szstr) {
+ return (szstr != NULL) ? szstr : "";
+}
+
+static const char* get_message_type(int type) {
+ const char* sztype;
+ switch(type) {
+ case DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL: sztype = "method_call"; break;
+ case DBUSPOLICY_MESSAGE_TYPE_METHOD_RETURN: sztype = "method_return"; break;
+ case DBUSPOLICY_MESSAGE_TYPE_ERROR: sztype = "error"; break;
+ case DBUSPOLICY_MESSAGE_TYPE_SIGNAL: sztype = "signal"; break;
+ default: sztype = ""; break;
+ }
+ return sztype;
+}
+
+int __internal_init(unsigned int bus_type, const char* const config_name)
+{
+ _ldp_xml_parser::XmlAsyncParser p;
+ auto err = p.parse_policy(get_bus(bus_type), get_str(config_name), std::chrono::milliseconds(10000));
+ return err.get();
+}
+
+int __internal_can_send(unsigned int bus_type,
+ const char* const user,
+ const char* const group,
+ const char* const label,
+ const char* const destination,
+ const char* const path,
+ const char* const interface,
+ const char* const member,
+ int type)
+{
+ _ldp_xml_parser::XmlAsyncParser p;
+ auto err = p.can_send(get_bus(bus_type), get_str(user), get_str(group), get_str(label), get_str(destination), get_str(path), get_str(interface), get_str(member), get_message_type(type));
+ return err.get();
+}
+
+int __internal_can_recv(unsigned int bus_type,
+ const char* const user,
+ const char* const group,
+ const char* const label,
+ const char* const sender,
+ const char* const path,
+ const char* const interface,
+ const char* const member,
+ int type)
+{
+ _ldp_xml_parser::XmlAsyncParser p;
+ auto err = p.can_recv(get_bus(bus_type), get_str(user), get_str(group), get_str(label), get_str(sender), get_str(path), get_str(interface), get_str(member), get_message_type(type));
+ return err.get();
+}
+
+int __internal_can_own(unsigned int bus_type,
+ const char* const user,
+ const char* const group,
+ const char* const service)
+{
+ _ldp_xml_parser::XmlAsyncParser p;
+ auto err = p.can_own(get_bus(bus_type), get_str(user), get_str(group), get_str(service));
+ return err.get();
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _LIBDBUSPOLICY1_INTERNAL_H_
+#define _LIBDBUSPOLICY1_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __internal_init(unsigned int bus_type, const char* const config_name);
+
+int __internal_can_send(unsigned int bus_type,
+ const char* const user,
+ const char* const group,
+ const char* const label,
+ const char* const destination,
+ const char* const path,
+ const char* const interface,
+ const char* const member,
+ int type);
+
+int __internal_can_recv(unsigned int bus_type,
+ const char* const user,
+ const char* const group,
+ const char* const label,
+ const char* const sender,
+ const char* const path,
+ const char* const interface,
+ const char* const member,
+ int type);
+
+int __internal_can_own(unsigned int bus_type,
+ const char* const user,
+ const char* const group,
+ const char* const service);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _LIBDBUSPOLICY1_PRIVATE_HPP
+#define _LIBDBUSPOLICY1_PRIVATE_HPP
+
+#include <string>
+
+namespace {
+ class ErrCode {
+ int m_err;
+ std::string m_err_str;
+ ErrCode(int e, const std::string& s) : m_err(e), m_err_str(s) {}
+ public:
+ ErrCode() : m_err(0), m_err_str("") {}
+ virtual ~ErrCode() {}
+
+ static ErrCode ok() {
+ return ErrCode(0, "OK");
+ }
+
+ template<typename T>
+ static ErrCode ok(T e) {
+ return ErrCode((e > 0) ? e : 0, "OK");
+ }
+
+ static ErrCode error(const std::string& what) {
+ return ErrCode(-1, what);
+ }
+
+ static ErrCode timeout(const std::string& what) {
+ return ErrCode(-99, std::string("Timeout: ") + what);
+ }
+
+ int get() const {
+ return m_err;
+ }
+
+ const std::string& get_str() const {
+ return m_err_str;
+ }
+
+ bool is_ok() const {
+ return (m_err >= 0);
+ }
+
+ bool is_true() const {
+ return (m_err > 0);
+ }
+
+ bool is_false() const {
+ return (m_err == 0);
+ }
+
+ bool is_error() const {
+ return (m_err < 0);
+ }
+
+ };
+} //namespace
+
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _TIMER_HPP
+#define _TIMER_HPP
+
+namespace _ldp_timer
+{
+ template<typename BaseTimeUnit = std::chrono::nanoseconds>
+ class Duration : public BaseTimeUnit {
+ public:
+ void setNanoTime(std::chrono::nanoseconds nano) {
+ BaseTimeUnit d = std::chrono::duration_cast<BaseTimeUnit>(nano);
+ BaseTimeUnit::operator =(d);
+ }
+
+ double getSeconds() {
+ typename BaseTimeUnit::period p;
+ return 1.0 * BaseTimeUnit::count() * p.num/p.den;
+ }
+
+ uint64_t getNativeTime() {
+ return BaseTimeUnit::count();
+ }
+
+ friend std::ostream& operator<< (std::ostream& os,
+ const Duration<BaseTimeUnit>& d) {
+ typename BaseTimeUnit::period p;
+ std::string unit;
+ switch(p.den/p.num) {
+ case 1000000000: unit = "ns"; break;
+ case 1000000: unit = "us"; break;
+ case 1000: unit = "ms"; break;
+ case 1: unit = "s"; break;
+ }
+
+ os << d.count() << " " << unit;
+ return os;
+ }
+ };
+
+ typedef Duration<std::chrono::nanoseconds> nanosec;
+ typedef Duration<std::chrono::microseconds> microsec;
+ typedef Duration<std::chrono::milliseconds> millisec;
+ typedef Duration<std::chrono::seconds> sec;
+
+ template<typename _T = nanosec>
+ class Timer {
+ typedef std::chrono::steady_clock CLK;
+ CLK::time_point tbegin;
+ _T* const pOT;
+ public:
+ Timer(_T* const pTP)
+ : tbegin(CLK::now()), pOT(pTP) {}
+
+ virtual ~Timer() {
+ if(pOT)
+ pOT->setNanoTime(CLK::now() - tbegin);
+ }
+ };
+}
+
+#endif // _TIMER_HPP
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _TSLOG_HPP
+#define _TSLOG_HPP
+
+#include <iostream>
+#include <thread>
+#include <mutex>
+
+namespace _ldp_tslog
+{
+ typedef std::ostream& (*t_ManFun)(std::ostream&);
+
+ namespace {
+ static constexpr bool LOG_ENABLE = false;
+ static constexpr bool LOG_VERBOSE = false;
+ }
+
+ const bool get_verbose() {
+ return LOG_VERBOSE;
+ }
+
+ const bool get_enable() {
+ return LOG_ENABLE;
+ }
+
+ class TsLog
+ {
+ private:
+ static bool m_verbose;
+ static std::mutex m_mtx;
+ std::ostream& m_os;
+ bool m_enable;
+
+ template<typename T>
+ TsLog& lckLog(const T& t) {
+ if(m_enable) {
+ std::unique_lock<std::mutex> lck(m_mtx);
+ m_os << t;
+ }
+ return *this;
+ }
+
+ public:
+ TsLog() = delete;
+
+ explicit TsLog(std::ostream& os, bool enable = true)
+ : m_os(os), m_enable(enable) {}
+
+ virtual ~TsLog() {}
+
+ template<typename T>
+ TsLog& operator<< (const T& t) {
+ return lckLog<T>(t);
+ }
+
+ TsLog& operator<< (t_ManFun f) {
+ return lckLog<t_ManFun>(f);
+ }
+
+ };
+ std::mutex TsLog::m_mtx;
+}
+
+namespace {
+ //Thread-safe loggers
+ _ldp_tslog::TsLog tout(std::cout, _ldp_tslog::get_enable());
+ _ldp_tslog::TsLog terr(std::cerr, _ldp_tslog::get_enable());
+
+ namespace verbose {
+ _ldp_tslog::TsLog tout(std::cout, _ldp_tslog::get_enable() && _ldp_tslog::get_verbose());
+ _ldp_tslog::TsLog terr(std::cerr, _ldp_tslog::get_enable() && _ldp_tslog::get_verbose());
+ }
+} //namespace
+
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _XML_PARSER_HPP
+#define _XML_PARSER_HPP
+
+#include <map>
+#include <thread>
+#include <future>
+#include <boost/noncopyable.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/functional/hash.hpp>
+#include <dirent.h>
+#include <libgen.h>
+#include "timer.hpp"
+#include "xml_policy.hpp"
+
+namespace _ldp_xml_parser
+{
+ class XmlAsyncParser : boost::noncopyable
+ {
+ public:
+ XmlAsyncParser() {
+ }
+
+ virtual ~XmlAsyncParser() {
+ }
+
+ ErrCode parse_policy(const std::string bus, const std::string fname, const std::chrono::milliseconds timeout) {
+ set_policy_bus_filename(bus, fname);
+ m_xml_policy.init();
+ ErrCode err = parse(timeout);
+ return err;
+ }
+
+ ErrCode can_send(const std::string bus,
+ const std::string user,
+ const std::string group,
+ const std::string label,
+ const std::string destination,
+ const std::string path,
+ const std::string interface,
+ const std::string member,
+ const std::string type) {
+ std::vector<std::string> idx_v = { user, group, destination, path, interface, member, type };
+ return m_xml_policy.can_send_to(bus, idx_v, label);
+ }
+
+ ErrCode can_recv(const std::string bus,
+ const std::string user,
+ const std::string group,
+ const std::string label,
+ const std::string sender,
+ const std::string path,
+ const std::string interface,
+ const std::string member,
+ const std::string type) {
+ std::vector<std::string> idx_v = { user, group, sender, path, interface, member, type };
+ return m_xml_policy.can_recv_from(bus, idx_v, label);
+ }
+
+ ErrCode can_own(const std::string bus,
+ const std::string user,
+ const std::string group,
+ const std::string service) {
+ std::vector<std::string> idx_v = { user, group, service };
+ return m_xml_policy.can_own_what(bus, idx_v);
+ }
+
+
+ private:
+ //IO operation
+ std::string m_bus;
+ std::string m_filename;
+ static std::map<std::string, std::size_t> m_hashes;
+ static std::mutex m_io_xml_mtx;
+
+ //Data obtained from XML
+ static XmlPolicy m_xml_policy;
+
+ //Called by calling user thread
+ void set_policy_bus_filename(const std::string& bus, const std::string& fname) {
+ m_filename = fname;
+ m_bus = bus;
+ }
+
+ const std::string& get_policy_bus() const {
+ return m_bus;
+ }
+
+ const std::string& get_policy_filename() const {
+ return m_filename;
+ }
+
+ ErrCode parse(const std::chrono::milliseconds timeout) {
+ ErrCode err;
+ std::vector<std::string> incl_files;
+
+ err = parse(get_policy_filename(), incl_files, timeout);
+ if(err.is_ok()) {
+ for(const auto& x : incl_files) {
+ err = parse(x, incl_files, timeout);
+ if(err.is_error()) { break; }
+ }
+ }
+
+ if(err.is_ok()) {
+ m_xml_policy.print_decision_trees();
+ }
+
+ return err;
+ }
+
+ ErrCode parse(const std::string& filename, std::vector<std::string>& included_files, const std::chrono::milliseconds timeout) {
+ std::pair<ErrCode, std::string> errparam;
+
+ verbose::tout << "=== XML PARSING BEGIN === : " << filename << std::endl;
+
+ auto fut = std::async(std::launch::async, &XmlAsyncParser::async_xml_parse, this, filename);
+
+ auto r = fut.wait_for(timeout);
+ if(r == std::future_status::ready) {
+ errparam = fut.get();
+ if(errparam.first.get() >= 0) {
+ get_included_files(filename, errparam.second, included_files);
+ }
+ } else if(r == std::future_status::timeout) {
+ errparam.first = ErrCode::timeout("XML parsing timeout");
+ }
+
+ verbose::tout << "=== XML PARSING END ===" << std::endl << std::endl;
+ tout << "Processing of " << filename << " -> [" << errparam.first.get() << ", " << errparam.first.get_str() << "]" << std::endl;
+ return errparam.first;
+ }
+
+ //Get all the .conf files within included subdirectory, POSIX style as boost::filesystem is not header-only
+ void get_included_files(const std::string& filename, const std::string& incldir, std::vector<std::string>& files) {
+ if(get_policy_filename() == filename && incldir != "") {
+ DIR *dir;
+ struct dirent *ent;
+ std::string fname;
+ std::copy(filename.begin(), filename.end(), fname.begin());
+ std::string dname = dirname(const_cast<char*>(fname.c_str()));
+ dname += (std::string("/") + incldir);
+ files.clear();
+ if((dir = opendir(dname.c_str())) != NULL) {
+ while((ent = readdir(dir)) != NULL) {
+ std::string s(ent->d_name);
+ if(s.find(".conf") != std::string::npos) {
+ files.push_back(dname + std::string("/") + s);
+ }
+ }
+ closedir(dir);
+
+ tout << std::endl << "includedir for " << filename << " is " << incldir << ", " << files.size() << " included files found:" << std::endl;
+ if(_ldp_tslog::get_enable()) { std::copy(files.begin(), files.end(), std::ostream_iterator<std::string>(std::cout, "\n")); }
+ tout << std::endl;
+ } else {
+ terr << "could not open directory " << dname << std::endl;
+ }
+ }
+ }
+
+ //All 'async_*' methods are executed in library's internal worker threads
+ std::pair<ErrCode, std::string> async_xml_parse(const std::string& filename) {
+ std::pair<ErrCode, std::string> ret;
+ _ldp_timer::microsec latency;
+
+ try {
+ boost::property_tree::ptree pt;
+
+ //XML file IO critical section
+ {
+ std::unique_lock<std::mutex> lck(m_io_xml_mtx);
+ _ldp_timer::Timer<_ldp_timer::microsec> t(&latency);
+
+ std::size_t hash;
+ if(async_xml_parsing_needed(filename, hash)) {
+ read_xml(filename, pt);
+ async_xml_hash_update(filename, hash);
+ }
+ }
+
+ m_xml_policy.update(get_policy_bus(), pt);
+
+ ret.second = pt.get("busconfig.includedir", "");
+
+ ret.first = ErrCode::ok();
+ } catch(const boost::property_tree::xml_parser::xml_parser_error& ex) {
+ ret.first = ErrCode::error(ex.what());
+ } catch(const boost::property_tree::ptree_error& ex) {
+ ret.first = ErrCode::error(ex.what());
+ } catch(...) {
+ ret.first = ErrCode::error(filename + std::string(": unknown error while parsing XML"));
+ }
+
+ tout << "XML processing latency: " << latency << std::endl;
+ return ret;
+ }
+
+ std::size_t async_xml_hash(const std::string& filename) {
+ std::size_t seed = 0;
+ std::ifstream ifs(filename);
+ for(std::string line; getline(ifs, line); ) {
+ boost::hash_combine(seed, line);
+ }
+ ifs.close();
+
+ return seed;
+ }
+
+ void async_xml_hash_update(const std::string& filename, const std::size_t hash) {
+ auto r = m_hashes.insert(std::pair<std::string, std::size_t>(filename, hash));
+ if(r.second == false) {
+ auto it = r.first;
+ it->second = hash;
+ }
+ }
+
+ bool async_xml_parsing_needed(const std::string& filename, std::size_t& hash) {
+ bool ret = false;
+ hash = async_xml_hash(filename);
+ auto it = m_hashes.find(filename);
+ if(it != m_hashes.end()) {
+ if(hash == it->second) {
+ ret = false;
+ } else {
+ ret = true;
+ }
+ } else {
+ ret = true;
+ }
+ return ret;
+ }
+
+ };
+ std::map<std::string, std::size_t> XmlAsyncParser::m_hashes;
+ std::mutex XmlAsyncParser::m_io_xml_mtx;
+ XmlPolicy XmlAsyncParser::m_xml_policy;
+} //namespace
+
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _XML_POLICY_HPP
+#define _XML_POLICY_HPP
+
+#include <boost/noncopyable.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include "libdbuspolicy1-private.hpp"
+#include "timer.hpp"
+#include "tslog.hpp"
+#include "cynara.hpp"
+
+namespace _ldp_xml_parser
+{
+ namespace {
+ static const std::string ROOT_FIELD = "busconfig";
+ static const std::string ROOT_POLICY = "policy";
+ } //namespace
+
+ class XmlPolicy : boost::noncopyable
+ {
+ enum class CtxType { DEFAULT, SPECIFIC, MANDATORY };
+
+ class Key {
+ public:
+ static constexpr const char* ANY = "__";
+ static constexpr const char* MRY = "!!";
+ static constexpr const char* DEF = "??";
+ static constexpr const char DELIM = '\\';
+ static const size_t IDX_USER = 0;
+ static const size_t IDX_GROUP = 1;
+ static const size_t IDX_DEST = 2;
+ static const size_t IDX_SENDER = IDX_DEST;
+ static const size_t IDX_SERVICE = IDX_DEST;
+ static const size_t IDX_PATH = 3;
+ static const size_t IDX_IFACE = 4;
+ static const size_t IDX_MEMBER = 5;
+ static const size_t IDX_TYPE = 6;
+
+ static const size_t IDX_TOTAL_LENGTH = IDX_TYPE + 1;
+ static const size_t IDX_OWN_LENGTH = IDX_SERVICE + 1;
+ static const size_t IDX_DEFAULT = IDX_GROUP + 1;
+
+ std::string m_bus;
+ std::vector<std::string> m_path_content;
+ std::string m_privilege;
+ bool m_bsend;
+ bool m_brecv;
+ bool m_bown;
+ bool m_bcheck;
+ bool m_ballow;
+ static size_t m_weight;
+
+ Key(const std::string& bus)
+ : m_bus(bus),
+ m_path_content(std::vector<std::string>(IDX_TOTAL_LENGTH, ANY)),
+ m_bsend(false),
+ m_brecv(false),
+ m_bown(false),
+ m_bcheck(false),
+ m_ballow(false) {}
+
+ ~Key() {}
+
+ void reset_attributes() {
+ m_bsend = m_brecv = m_bown = m_bcheck = m_ballow = false;
+ std::fill(m_path_content.begin() + IDX_DEFAULT, m_path_content.end(), ANY);
+ }
+
+ const std::string get_path() const {
+ std::string path = "R";
+ auto it_cend = m_bown ? m_path_content.cbegin() + IDX_OWN_LENGTH : m_path_content.cend();
+ for(auto it = m_path_content.cbegin(); it != it_cend; ++it) {
+ path += (std::string(1, Key::DELIM) + *it);
+ }
+ return path;
+ }
+ };
+
+ class Leaf {
+ bool m_decision;
+ bool m_check;
+ std::string m_privilege;
+ size_t m_weight;
+
+ public:
+ Leaf() : m_decision(false), m_check(false), m_privilege(""), m_weight(0) {};
+
+ Leaf(bool decision, bool check, const std::string& privilege, size_t weight)
+ : m_decision(decision), m_check(check), m_privilege(privilege), m_weight(weight) {}
+
+ bool get_decision() const {
+ return m_decision;
+ }
+
+ bool get_check() const {
+ return m_check;
+ }
+
+ const std::string& get_privilege() const {
+ return m_privilege;
+ }
+
+ size_t get_weight() const {
+ return m_weight;
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const Leaf& lf) {
+ if(lf.m_check) {
+ os << "check," << lf.m_privilege << "," << lf.m_weight;
+ } else {
+ os << (lf.m_decision ? "true" : "false") << "," << lf.m_weight;
+ }
+ return os;
+ }
+
+ friend std::istream& operator>>(std::istream& is, Leaf& lf) {
+ std::string s;
+ is >> s;
+ boost::char_separator<char> sep(",");
+ boost::tokenizer<boost::char_separator<char>> tokens(s, sep);
+ const auto size = std::distance(tokens.begin(), tokens.end());
+ for(auto it = tokens.begin(); it != tokens.end(); ++it) {
+ const auto it_last = std::next(tokens.begin(), size - 1);
+ if(it == tokens.begin()) {
+ if(size > 2) {
+ lf.m_check = (*it == "check") ? true : false;
+ } else {
+ lf.m_decision = (*it == "true") ? true : false;
+ }
+ } else if(it == it_last) {
+ lf.m_weight = std::stoul(*it);
+ } else {
+ if(size > 2) {
+ lf.m_privilege = *it;
+ }
+ }
+ }
+ return is;
+ }
+ };
+
+ static const std::string get_context_str(const CtxType& ctx_type) {
+ switch(ctx_type) {
+ case CtxType::DEFAULT: return "(default)"; break;
+ case CtxType::SPECIFIC: return "(specific)"; break;
+ case CtxType::MANDATORY: return "(mandatory)"; break;
+ default: return ""; break;
+ }
+ }
+
+ static const std::string get_field_str(const std::string& field) {
+ return (field == "") ? Key::ANY : field;
+ }
+
+ //Data obtained from XML parsing - decision trees
+ typedef std::map<std::string, boost::property_tree::ptree> Trees_t;
+ std::map<std::string, Trees_t> m_dec_trees;
+ std::mutex m_xml_policy_mtx;
+
+ boost::property_tree::ptree* get_decision_tree(const std::string& bus, const std::string& tree_type) {
+ boost::property_tree::ptree* p_tree = NULL;
+
+ auto it1 = m_dec_trees.find(bus);
+ if(it1 != m_dec_trees.end()) {
+ auto it2 = it1->second.find(tree_type);
+ if(it2 != it1->second.end()) {
+ p_tree = &it2->second;
+ }
+ }
+ return p_tree;
+ }
+
+ boost::property_tree::ptree* get_decision_tree(const Key& key) {
+ std::string tree_type;
+ if(key.m_bsend) { tree_type = "SEND"; }
+ else if(key.m_brecv) { tree_type = "RECV"; }
+ else if(key.m_bown) { tree_type = "OWN"; }
+
+ return get_decision_tree(key.m_bus, tree_type);
+ }
+
+ void print_decision_tree(const boost::property_tree::ptree& pt, int level = 0) {
+ for(const auto& v : pt) {
+ print_field(v, level);
+ print_decision_tree(v.second, level + 1);
+ }
+ }
+
+ void print_decision_key(const Key& key) {
+ if(_ldp_tslog::get_verbose()) {
+ std::string s = key.m_bus + " ";
+ if(key.m_bsend && !key.m_brecv) { s += "--> #"; }
+ if(!key.m_bsend && key.m_brecv) { s += "<-- #"; }
+ if(!key.m_bsend && !key.m_brecv && key.m_bown) { s += "OWN #"; }
+ std::string prv = key.m_bcheck ? key.m_privilege : "";
+ verbose::tout << s
+ << (key.m_bcheck ? "check " : std::to_string(key.m_ballow))
+ << prv
+ << " : "
+ << key.get_path()
+ << " (weight: "
+ << key.m_weight
+ << ")"
+ << std::endl;
+ }
+ }
+
+ void update_decision_tree(const Key& key) {
+ if(!key.get_path().empty()) {
+ print_decision_key(key);
+
+ //update
+ boost::property_tree::ptree* const p_tree = get_decision_tree(key);
+ if(p_tree) {
+ boost::property_tree::ptree::path_type tpath(key.get_path(), Key::DELIM);
+ p_tree->put(tpath, Leaf(key.m_ballow, key.m_bcheck, key.m_privilege, key.m_weight));
+ }
+ }
+ }
+
+ void update_decision_path(const boost::property_tree::ptree::value_type& v,
+ Key& key,
+ CtxType& current_ctx,
+ bool& allden,
+ bool& bcheck,
+ bool& attr) {
+ if(v.first == "allow") {
+ allden = true;
+ bcheck = false;
+ attr = false;
+ key.reset_attributes();
+ } else if(v.first == "deny") {
+ allden = false;
+ bcheck = false;
+ attr = false;
+ key.reset_attributes();
+ } else if(v.first == "check") {
+ allden = false;
+ bcheck = true;
+ attr = false;
+ key.reset_attributes();
+ } else if(v.first == "<xmlattr>") {
+ attr = true;
+ ++key.m_weight;
+ } else {
+ if(attr) {
+ std::string data_str = (v.second.data() == "*") ? Key::ANY : v.second.data();
+ if(v.first == "context") {
+ if(data_str == "mandatory") {
+ key.m_path_content[Key::IDX_USER] = Key::MRY;
+ key.m_path_content[Key::IDX_GROUP] = Key::MRY;
+ current_ctx = CtxType::MANDATORY;
+ } else if(data_str == "default") {
+ key.m_path_content[Key::IDX_USER] = Key::DEF;
+ key.m_path_content[Key::IDX_GROUP] = Key::DEF;
+ current_ctx = CtxType::DEFAULT;
+ }
+ } else if(v.first == "user") {
+ if(current_ctx == CtxType::SPECIFIC) {
+ key.m_path_content[Key::IDX_USER] = data_str;
+ }
+ } else if(v.first == "group") {
+ if(current_ctx == CtxType::SPECIFIC) {
+ key.m_path_content[Key::IDX_GROUP] = data_str;
+ }
+ } else {
+ if(field_has(v, "send_")) {
+ key.m_bsend = true;
+ }
+ if(field_has(v, "receive_")) {
+ key.m_brecv = true;
+ }
+ if(v.first == "own") {
+ key.m_bown = true;
+ key.m_path_content[Key::IDX_SERVICE] = data_str;
+ }
+ if(field_has(v, "_destination")) {
+ key.m_path_content[Key::IDX_DEST] = data_str;
+ }
+ if(field_has(v, "_sender")) {
+ key.m_path_content[Key::IDX_SENDER] = data_str;
+ }
+ if(field_has(v, "_path")) {
+ key.m_path_content[Key::IDX_PATH] = data_str;
+ }
+ if(field_has(v, "_interface")) {
+ key.m_path_content[Key::IDX_IFACE] = data_str;
+ }
+ if(field_has(v, "_member")) {
+ key.m_path_content[Key::IDX_MEMBER] = data_str;
+ }
+ if(field_has(v, "_type")) {
+ key.m_path_content[Key::IDX_TYPE] = data_str;
+ }
+ if(v.first == "privilege") {
+ key.m_privilege = data_str;
+ }
+
+ key.m_bcheck = bcheck;
+ key.m_ballow = allden;
+ }
+ }
+ }
+ }
+
+ bool field_has(const boost::property_tree::ptree::value_type& v, const std::string& substr) {
+ return (v.first.find(substr) != std::string::npos);
+ }
+
+ void print_field(const boost::property_tree::ptree::value_type& v, int level) {
+ verbose::tout << ((level > 0) ? std::string((level - 1) * 8, ' ') + std::string(8, '.') : "")
+ << v.first
+ << " : "
+ << v.second.data()
+ << std::endl;
+ }
+
+ void xml_traversal(const boost::property_tree::ptree& pt,
+ Key& key,
+ CtxType& current_ctx,
+ bool allden = false,
+ bool bcheck = false,
+ bool attr = false,
+ int level = 0) {
+ static const int Q_XML_MAX_LEVEL = 10;
+
+ if(level < Q_XML_MAX_LEVEL) {
+ for(const auto& v : pt) {
+ if(v.first == "<xmlcomment>") { continue; }
+
+ update_decision_path(v, key, current_ctx, allden, bcheck, attr);
+ //print_field(v, level);
+ xml_traversal(v.second, key, current_ctx, allden, bcheck, attr, level + 1);
+ }
+
+ if(!pt.empty() && attr && level > 1) {
+ update_decision_tree(key);
+ }
+ } else {
+ terr << "XML traversal max level reached: " << level << std::endl;
+ }
+ }
+
+ void print_indexing_path(size_t idx, const std::string& path, const Leaf& leaf = Leaf(), bool empty = true) {
+ if(_ldp_tslog::get_verbose()) {
+ std::string s;
+ if(!empty) {
+ s = " : <";
+ s += (leaf.get_check()
+ ? std::string("check: ") + std::to_string(leaf.get_check()) + ", privilege: " + leaf.get_privilege()
+ : std::string("decision: ") + std::to_string(leaf.get_decision()));
+ s += (std::string(", weight: ") + std::to_string(leaf.get_weight()));
+ s += std::string(">");
+ }
+
+ verbose::tout << "path #"
+ << idx
+ << " : "
+ << path
+ << s
+ << std::endl;
+ }
+ }
+
+ void prepare_indexing_path(const std::vector<std::string>& idx_v,
+ const size_t pattern,
+ const size_t obfuscate_order,
+ const CtxType& ctx_type,
+ std::string& path) {
+
+ const size_t offset = Key::IDX_DEFAULT;
+ path = "R";
+
+ if(ctx_type == CtxType::SPECIFIC) {
+ switch(obfuscate_order) {
+ case 0:
+ path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_USER]));
+ path += (std::string(1, Key::DELIM) + Key::ANY);
+ break;
+ case 1:
+ path += (std::string(1, Key::DELIM) + Key::ANY);
+ path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_GROUP]));
+ break;
+ case 2:
+ path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_USER]));
+ path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_GROUP]));
+ break;
+ case 3:
+ default:
+ path += (std::string(1, Key::DELIM) + Key::ANY);
+ path += (std::string(1, Key::DELIM) + Key::ANY);
+ break;
+ }
+ } else {
+ for(size_t i = 0; i < offset; ++i) {
+ const std::string as = (ctx_type == CtxType::MANDATORY) ? Key::MRY : Key::DEF;
+ path += (std::string(1, Key::DELIM) + as);
+ }
+ }
+
+ const size_t m = 1;
+ const size_t n = idx_v.size() - offset;
+ for(size_t i = 0; i < n; ++i) {
+ std::string s = get_field_str(idx_v[i + offset]);
+ path += Key::DELIM;
+ if(pattern & (m << i)) {
+ path += Key::ANY;
+ } else {
+ path += s;
+ }
+ }
+ }
+
+ ErrCode index_decision_tree(const boost::property_tree::ptree& pt,
+ const std::vector<std::string>& idx_v,
+ const std::string& label,
+ const CtxType& ctx_type) {
+ ErrCode err;
+ bool found = false;
+ size_t weight = 0;
+ const size_t offset = Key::IDX_DEFAULT;
+ const size_t m = (ctx_type == CtxType::SPECIFIC) ? (1 << offset) : 1;
+ for(size_t ob_or = 0; ob_or < m; ++ob_or) {
+ Leaf leaf_found;
+ const size_t n = 1 << (idx_v.size() - offset);
+ for(size_t p = 0; p < n; ++p) {
+ std::string path;
+ try {
+ prepare_indexing_path(idx_v, p, ob_or, ctx_type, path);
+ boost::property_tree::ptree::path_type tpath(path, Key::DELIM);
+
+ auto dec = pt.get<Leaf>(tpath);
+
+ print_indexing_path(p, path, dec, false);
+ found = true;
+ if(dec.get_weight() >= weight) {
+ weight = dec.get_weight();
+ leaf_found = dec;
+ }
+ } catch(const boost::property_tree::ptree_error& ex) {
+ //Path doesn't exist, continue
+ print_indexing_path(p, path);
+ if(!found) { err = ErrCode::error("No path"); }
+ } catch(...) {
+ print_indexing_path(p, path);
+ verbose::tout << "Unknown exception while indexing decision tree!" << std::endl;
+ if(!found) { err = ErrCode::error("Unknown err, no path"); }
+ }
+ }
+
+ if(found) {
+ if(leaf_found.get_check()) {
+ verbose::tout << __func__
+ << ": cynara check needed for privilege " << leaf_found.get_privilege()
+ << ", weight " << leaf_found.get_weight()
+ << std::endl;
+
+ //cynara check
+ try {
+ bool br = _ldp_cynara::Cynara::check(label, leaf_found.get_privilege(), idx_v[Key::IDX_USER]);
+ err = ErrCode::ok(br);
+ } catch(const std::runtime_error& ex) {
+ err = ErrCode::error(ex.what());
+ }
+ } else {
+ err = ErrCode::ok(leaf_found.get_decision());
+ }
+
+ verbose::tout << __func__ << ": returning decision #" << err.get() << " " << err.get_str() << ", weight " << leaf_found.get_weight() << std::endl;
+ break;
+ }
+ }
+
+ return err;
+ }
+
+ ErrCode index_decision_tree_lat(const boost::property_tree::ptree& pt,
+ const std::vector<std::string>& idx_v,
+ const std::string& label,
+ const CtxType& ctx_type) {
+ ErrCode err;
+
+ tout << "context: " << get_context_str(ctx_type) << ", indexing arguments: ";
+ if(_ldp_tslog::get_enable()) { std::copy(idx_v.begin(), idx_v.end(), std::ostream_iterator<std::string>(std::cout, ", ")); }
+ tout << std::endl;
+
+ //Examine policy data and make decision
+ _ldp_timer::microsec latency;
+ {
+ _ldp_timer::Timer<_ldp_timer::microsec> t(&latency);
+ err = index_decision_tree(pt, idx_v, label, ctx_type);
+ }
+
+ tout << __func__ << ": #" << err.get() << " " << err.get_str() << " " << get_context_str(ctx_type) << std::endl;
+ tout << "tree indexing latency: " << latency << std::endl;
+ return err;
+ }
+
+ ErrCode can_do_action(const std::string& bus, const std::string& tree_type, const std::vector<std::string>& idx_v, const std::string& label = "") {
+ std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
+ ErrCode err;
+ boost::property_tree::ptree* const p_tree = get_decision_tree(bus, tree_type);
+ if(p_tree) {
+ err = index_decision_tree_lat(*p_tree, idx_v, label, CtxType::MANDATORY);
+ if(!err.is_ok()) {
+ err = index_decision_tree_lat(*p_tree, idx_v, label, CtxType::SPECIFIC);
+ if(!err.is_ok()) {
+ err = index_decision_tree_lat(*p_tree, idx_v, label, CtxType::DEFAULT);
+ }
+ }
+ } else {
+ err = ErrCode::error("Get decision tree returned NULL ptr");
+ }
+ tout << __func__ << ": #" << err.get() << " " << err.get_str() << std::endl;
+ return err;
+ }
+
+ public:
+ XmlPolicy() {
+ Trees_t t;
+ t.emplace("SEND", typename Trees_t::mapped_type());
+ t.emplace("RECV", typename Trees_t::mapped_type());
+ t.emplace("OWN", typename Trees_t::mapped_type());
+ m_dec_trees.emplace("SYSTEM", t);
+ m_dec_trees.emplace("SESSION", t);
+ }
+
+ virtual ~XmlPolicy() {}
+
+ void init() {
+ std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
+ Key::m_weight = 0;
+ }
+
+ void update(const std::string& bus, const boost::property_tree::ptree& pt) {
+ if(!pt.empty()) {
+ std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
+ const auto& children = pt.get_child(ROOT_FIELD);
+ for(const auto& x : children) {
+ if(x.first == ROOT_POLICY) {
+ Key key(bus);
+ CtxType current_ctx = CtxType::SPECIFIC;
+ xml_traversal(x.second, key, current_ctx);
+ }
+ }
+ }
+ }
+
+ ErrCode can_send_to(const std::string bus, const std::vector<std::string>& idx_v, const std::string label) {
+ return can_do_action(bus, "SEND", idx_v, label);
+ }
+
+ ErrCode can_recv_from(const std::string bus, const std::vector<std::string>& idx_v, const std::string label) {
+ return can_do_action(bus, "RECV", idx_v, label);
+ }
+
+ ErrCode can_own_what(const std::string bus, const std::vector<std::string>& idx_v) {
+ return can_do_action(bus, "OWN", idx_v);
+ }
+
+ void print_decision_trees() {
+ if(_ldp_tslog::get_verbose()) {
+ std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
+
+ for(const auto& x : m_dec_trees) {
+ for(const auto& y : x.second) {
+ verbose::tout << x.first << " " << y.first << " " << (y.second.empty() ? "(empty)" : "") << std::endl;
+ print_decision_tree(y.second);
+ }
+ }
+ }
+ }
+
+ }; //XmlPolicy
+ size_t XmlPolicy::Key::m_weight = 0;
+} //namespace
+
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#ifndef _LIBDBUSPOLICY1_PRIVATE_H_
+#define _LIBDBUSPOLICY1_PRIVATE_H_
+
+#include <stdbool.h>
+#include <syslog.h>
+
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "kdbus.h"
+
+
+#define DBUSPOLICY1_EXPORT __attribute__ ((visibility("default")))
+
+#endif
--- /dev/null
+/*
+ * 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.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "libdbuspolicy1-private.h"
+#include "internal/internal.h"
+
+#define KDBUS_SYSTEM_BUS_PATH "/sys/fs/kdbus/0-system/bus"
+#define KDBUS_POOL_SIZE (16 * 1024UL * 1024UL)
+
+#define ALIGN8(l) (((l) + 7) & ~7)
+#define UID_INVALID ((uid_t) -1)
+#define GID_INVALID ((gid_t) -1)
+
+#define FOREACH_STRV(i,l, s, os)\
+for(\
+({\
+i=0;\
+l = strlen(s);\
+name = malloc(sizeof(char*)*(l+1));\
+strcpy(os, s);\
+});\
+i < l;\
+i++)
+
+#define GET_NEXT_STR(i,s,os)\
+ os = s+i;\
+ for(;s[i] && s[i] != ' ';i++);\
+ s[i] = 0;
+
+
+
+/** A process ID */
+typedef unsigned long dbus_pid_t;
+/** A user ID */
+typedef unsigned long dbus_uid_t;
+/** A group ID */
+typedef unsigned long dbus_gid_t;
+
+struct kcreds {
+ uid_t uid;
+ gid_t gid;
+ char* label;
+ char** names;
+};
+
+struct kconn {
+ int fd;
+ uint64_t id;
+ char *pool;
+};
+struct udesc {
+ unsigned int bus_type;
+ char user[256];
+ dbus_uid_t uid;
+ char group[256];
+ dbus_gid_t gid;
+ char label[256];
+ struct kconn* conn;
+};
+
+static void print_udesc(const char* const entry, const struct udesc* const p_udesc) {
+}
+
+static int kdbus_open_system_bus(void)
+{
+ return open(KDBUS_SYSTEM_BUS_PATH, O_RDWR|O_NOCTTY|O_LARGEFILE|O_CLOEXEC );
+}
+
+static int kdbus_hello(struct kconn *kc, uint64_t hello_flags, uint64_t attach_flags_send, uint64_t attach_flags_recv)
+{
+ struct kdbus_cmd_hello kcmd_hello;
+ int r;
+
+ memset(&kcmd_hello, 0, sizeof(kcmd_hello));
+ kcmd_hello.flags = hello_flags;
+ kcmd_hello.attach_flags_send = attach_flags_send;
+ kcmd_hello.attach_flags_recv = attach_flags_recv;
+ kcmd_hello.size = sizeof(kcmd_hello);
+ kcmd_hello.pool_size = KDBUS_POOL_SIZE;
+
+ r = ioctl(kc->fd, KDBUS_CMD_HELLO, &kcmd_hello);
+ if (r < 0)
+ return -errno;
+
+ kc->id = (uint64_t)kcmd_hello.id;
+ kc->pool = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, kc->fd, 0);
+ if (kc->pool == MAP_FAILED)
+ return -errno;
+
+ return 0;
+}
+
+static int kdbus_get_creds_from_name(struct kconn* kc, struct kcreds* kcr, const char* name)
+{
+ struct kdbus_cmd_info* cmd;
+ struct kdbus_info* conn_info;
+ struct kdbus_item *item;
+ char** tmp_names;
+ int j,size,r,l,counter;
+
+ counter = 0;
+ kcr->names = calloc(counter+1, sizeof(char *));
+
+ kcr->uid = UID_INVALID;
+ kcr->gid = GID_INVALID;
+ kcr->label = NULL;
+
+
+ l = strlen(name) + 1;
+
+ size = offsetof(struct kdbus_cmd_info, items) + ALIGN8((l) + offsetof(struct kdbus_item, data));//ietms+aligned(l+ITEM_HEADER_SIZE)
+ cmd = aligned_alloc(8, size);
+ memset(cmd, 0, sizeof(struct kdbus_cmd_info));
+ cmd->items[0].size = l + offsetof(struct kdbus_item, data) ;
+ cmd->items[0].type = KDBUS_ITEM_NAME;
+ memcpy(cmd->items[0].str, name, l);
+ cmd->size = size;
+ cmd->attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_SECLABEL | KDBUS_ATTACH_NAMES ;
+
+ r = ioctl(kc->fd, KDBUS_CMD_CONN_INFO, cmd);
+ if (r < 0)
+ return -errno;
+
+ conn_info = (struct kdbus_info *) ((uint8_t *) kc->pool + cmd->offset);
+
+ for(item = conn_info->items;
+ ((uint8_t *)(item) < (uint8_t *)(conn_info) + (conn_info)->size) &&
+ ((uint8_t *) item >= (uint8_t *) conn_info);
+ item = ((typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))) )
+ {
+ switch (item->type)
+ {
+ case KDBUS_ITEM_CREDS:
+ if (item->creds.euid != UID_INVALID)
+ {
+ kcr->uid = (uid_t) item->creds.euid;
+ }
+ if (item->creds.egid != GID_INVALID)
+ {
+ kcr->gid = (gid_t) item->creds.egid;
+ }
+ break;
+ case KDBUS_ITEM_SECLABEL:
+ kcr->label = strdup(item->str);
+ break;
+ case KDBUS_ITEM_OWNED_NAME:
+ counter++;
+ tmp_names = calloc(counter+1, sizeof(char*));
+ for (j = 0;kcr->names[j]; j++)
+ {
+ tmp_names[j] = kcr->names[j];
+ }
+ tmp_names[j] = strdup(item->name.name);
+ free(kcr->names);
+ kcr->names = tmp_names;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void kcreds_free(struct kcreds* kcr)
+{
+ int i = 0;
+ if (kcr == NULL)
+ return;
+
+ free(kcr->label);
+ for (i=0; kcr->names[i];i++)
+ free(kcr->names[i]);
+ free(kcr->names[i]);
+ free(kcr->names);
+ free(kcr);
+}
+/**
+ * dbuspolicy1_init
+ * @config_name: name of the XML configuration file
+ *
+ * Set the configuration file used by the calling application
+ **/
+DBUSPOLICY1_EXPORT void* dbuspolicy1_init(unsigned int bus_type)
+{
+ struct kconn* kc;
+ uint64_t hello_flags = 0;
+ uint64_t attach_flags_send = _KDBUS_ATTACH_ANY;
+ uint64_t attach_flags_recv = _KDBUS_ATTACH_ALL;
+ int r,fdl;
+ struct udesc* p_udesc;
+
+ kc = (struct kconn*) calloc(1, sizeof(struct kconn));
+ if (!kc)
+ return NULL;
+
+ kc->fd = kdbus_open_system_bus();
+ r = kdbus_hello(kc, hello_flags, attach_flags_send, attach_flags_recv);
+ if (r < 0) {
+ free(kc);
+ return NULL;
+ }
+
+ r = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE : SESSION_BUS_CONF_FILE);
+ if(r >= 0) {
+ p_udesc = (struct udesc*)malloc(sizeof(struct udesc));
+ if(p_udesc) {
+ p_udesc->bus_type = bus_type;
+ p_udesc->uid = getuid();
+ p_udesc->gid = getgid();
+ struct passwd* pwd = getpwuid(p_udesc->uid);
+ strcpy(p_udesc->user, pwd->pw_name);
+ struct group* gg = getgrgid(p_udesc->gid);
+ strcpy(p_udesc->group, gg->gr_name);
+ p_udesc->conn = kc;
+
+ fdl = open("/proc/self/attr/current", 0, S_IRUSR);
+ if (fdl < 0)
+ {
+ fprintf(stderr,"Cannot open /proc/self/attr/current\n");
+ dbuspolicy1_free(p_udesc);
+ return NULL;
+ }
+
+ r = read(fdl, p_udesc->label, 256);
+ if (r < 0)
+ {
+ fprintf(stderr, "Cannot read from /proc/self/attr/current\n");
+ close(fdl);
+ dbuspolicy1_free(p_udesc);
+ return NULL;
+ }
+ close(fdl);
+
+
+ print_udesc("New configuration", p_udesc);
+ }
+ } else {
+ p_udesc = NULL;
+ }
+ return p_udesc;
+}
+
+DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration)
+{
+ struct udesc* p_udesc = (struct udesc*)configuration;
+ if(p_udesc) {
+ print_udesc("Freeing configuration", p_udesc);
+ free(p_udesc->conn);
+ free(p_udesc);
+ p_udesc = NULL;
+ }
+}
+
+/**
+ * dbuspolicy1_can_send
+ * @param: <>
+ * @return: <>
+ *
+ * Description.
+ **/
+DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
+ const char *destination,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member,
+ int message_type,
+ const char *error_name,
+ int reply_serial,
+ int requested_reply)
+{
+ struct udesc* const p_udesc = (struct udesc*)configuration;
+ int i, rs, rr, l, r = 0;
+ struct kcreds* p_creds = NULL;
+ char gid[25], uid[25];
+ char* name = NULL;
+ char empty_names = 1;
+
+ rs = 0;
+ rr = 1;
+
+ if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL || (destination != NULL && *destination != '\0') ) {
+ p_creds = calloc(1, sizeof(struct kcreds));
+ r = kdbus_get_creds_from_name(p_udesc->conn, p_creds, destination);
+ if(r < 0) {
+ kcreds_free(p_creds);
+ return 0;
+ }
+
+ snprintf(uid, 24, "%lu", (unsigned long int)p_creds->uid);
+ snprintf(gid, 24, "%lu", (unsigned long int)p_creds->gid);
+ if (!p_creds->names[0])
+ empty_names = 0;
+
+ for (i=0;p_creds->names[i];i++)
+ {
+ rs = __internal_can_send(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, p_creds->names[i], path, interface, member, message_type);
+ if (rs > 0)
+ break;
+ }
+ }
+
+ if (empty_names)
+ rs = __internal_can_send(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, destination, path, interface, member, message_type);
+
+ if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) {
+ rr = 0;
+
+ if (!sender)
+ rr = __internal_can_recv(p_udesc->bus_type, uid, gid, p_creds->label, sender, path, interface, member, message_type);
+ else
+ FOREACH_STRV(i, l, sender, name) {
+ char* source;
+ GET_NEXT_STR(i, name, source);
+ rr = __internal_can_recv(p_udesc->bus_type, uid, gid, p_creds->label, source, path, interface, member, message_type);
+ if (rr > 0)
+ break;
+ }
+ }
+
+ free(name);
+ kcreds_free(p_creds);
+
+ if(rs > 0 && rr > 0) { r = 1; }
+ if(rs < 0 || rr < 0) { r = -1; }
+ return r;
+}
+/**
+ * dbuspolicy1_can_send
+ * @param: <>
+ * @return: <>
+ *
+ * Description.
+ **/
+DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration,
+ const char *destination,
+ const char *sender,
+ const char *sender_label,
+ uid_t sender_uid,
+ gid_t sender_gid,
+ const char *path,
+ const char *interface,
+ const char *member,
+ int message_type,
+ const char *error_name,
+ int reply_serial,
+ int requested_reply)
+{
+ struct udesc* const p_udesc = (struct udesc*)configuration;
+ int i, rs, rr, l, r = 0;
+ struct kcreds* p_creds = NULL;
+ char gid[25], uid[25];
+ char* name = NULL;
+
+ rs = 0;
+ rr = 1;
+
+ snprintf(uid, 24, "%lu", (unsigned long int)sender_uid);
+ snprintf(gid, 24, "%lu", (unsigned long int)sender_gid);
+
+ if (!destination)
+ rs = __internal_can_send(p_udesc->bus_type, uid, gid, sender_label, destination, path, interface, member, message_type);
+ else
+ FOREACH_STRV(i, l, destination, name) {
+ char* dest;
+ GET_NEXT_STR(i, name, dest);
+
+ rs = __internal_can_send(p_udesc->bus_type, uid, gid, sender_label, dest, path, interface, member, message_type);
+ if (rs > 0)
+ break;
+ }
+ free(name);
+
+ if(message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) {
+ rr = 0;
+
+ if (!sender)
+ rr = __internal_can_recv(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, sender, path, interface, member, message_type);
+ else
+ FOREACH_STRV(i, l, sender, name) {
+ char* source;
+ GET_NEXT_STR(i, name, source);
+ rr = __internal_can_recv(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, source, path, interface, member, message_type);
+ if(rr > 0)
+ break;
+ }
+ free(name);
+ }
+ kcreds_free(p_creds);
+
+ if(rs > 0 && rr > 0) { r = 1; }
+ if(rs < 0 || rr < 0) { r = -1; }
+ return r;
+}
+
+
+/**
+ * dbuspolicy1_can_send
+ * @param: <>
+ * @return: <>
+ *
+ * Description.
+ **/
+DBUSPOLICY1_EXPORT int dbuspolicy1_can_own(void* configuration, const char* const service)
+{
+ struct udesc* const p_udesc = (struct udesc*)configuration;
+ return __internal_can_own(p_udesc->bus_type, p_udesc->user, p_udesc->group, service);
+}
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libdbuspolicy1
+Description: Library for something with dbuspolicy1
+Version: @VERSION@
+Libs: -L${libdir} -ldbuspolicy1
+Libs.private:
+Cflags: -I${includedir}
--- /dev/null
+LIBDBUSPOLICY1_1 {
+global:
+ dbuspolicy1_init;
+ dbuspolicy1_free;
+ dbuspolicy1_check_in;
+ dbuspolicy1_check_out;
+ dbuspolicy1_can_own;
+local:
+ *;
+};
+
+LIBDBUSPOLICY1_3 {
+global:
+ dbuspolicy1_thing_ref;
+ dbuspolicy1_thing_unref;
+ dbuspolicy1_thing_get_ctx;
+ dbuspolicy1_thing_new_from_string;
+ dbuspolicy1_thing_get_some_list_entry;
+} LIBDBUSPOLICY1_1;