From 869f3003cee80192ffb02c9e0e8d72c3958a0bf0 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 6 Apr 2016 16:29:47 +0200 Subject: [PATCH 01/16] Fix: close file descriptior leak in dbuspolicy_init error path Refactor initialization to be able to provide error handling easily. Change-Id: Ibe69e8894b93590e21b3c37b6d08cb394bce6b1b --- src/libdbuspolicy1.c | 142 +++++++++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 8c4580a..8be9445 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -218,6 +218,50 @@ static void kcreds_free(struct kcreds* kcr) free(kcr->names); free(kcr); } + +static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct udesc* p_udesc) +{ + struct passwd pwent; + struct passwd *pwd; + struct group grent; + struct group *gg; + char buf[1024]; + int attr_fd; + int r; + int len; + + attr_fd = open("/proc/self/attr/current", O_RDONLY); + if (attr_fd < 0) + return -1; + r = read(attr_fd, p_udesc->label, 256); + + close(attr_fd); + + if (r < 0) /* read */ + return -1; + + if (getpwuid_r(p_udesc->uid, &pwent, buf, sizeof(buf), &pwd)) + return -1; + + if (getgrgid_r(p_udesc->gid, &grent, buf, sizeof(buf), &gg)) + return -1; + + len = sizeof(p_udesc->user) - 1; + strncpy(p_udesc->user, pwd->pw_name, len); + p_udesc->group[len] = 0; + + len = sizeof(p_udesc->group) - 1; + strncpy(p_udesc->group, gg->gr_name, len); + p_udesc->group[len] = 0; + + p_udesc->bus_type = bus_type; + p_udesc->uid = getuid(); + p_udesc->gid = getgid(); + p_udesc->conn = kc; + + return 0; +} + /** * dbuspolicy1_init * @config_name: name of the XML configuration file @@ -226,84 +270,40 @@ static void kcreds_free(struct kcreds* kcr) **/ 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) { - close(kc->fd); - free(kc); - return NULL; - } + uint64_t hello_flags = 0; + uint64_t attach_flags_send = _KDBUS_ATTACH_ANY; + uint64_t attach_flags_recv = _KDBUS_ATTACH_ALL; + struct kconn* kc = NULL; + struct udesc* p_udesc = NULL; - r = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY); - if(r < 0) { - r = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY); - } - if(r >= 0) { - p_udesc = (struct udesc*)malloc(sizeof(struct udesc)); - if(p_udesc) { - struct passwd pwent; - struct passwd *pwd; - struct group grent; - struct group* gg; - char buf[1024]; - - p_udesc->bus_type = bus_type; - p_udesc->uid = getuid(); - p_udesc->gid = getgid(); - - if (getpwuid_r(p_udesc->uid, &pwent, buf, sizeof(buf), &pwd) ) { - p_udesc = NULL; - close(kc->fd); - free(kc); - return p_udesc; - } + kc = (struct kconn*) calloc(1, sizeof(struct kconn)); + p_udesc = (struct udesc*)malloc(sizeof(struct udesc)); + if (!kc || !p_udesc) + goto err; - if (getgrgid_r(p_udesc->gid, &grent, buf, sizeof(buf), &gg) ) { - p_udesc = NULL; - close(kc->fd); - free(kc); - return p_udesc; - } + if ((kc->fd = kdbus_open_system_bus()) < 0) + goto err; - strncpy(p_udesc->user, pwd->pw_name, sizeof(p_udesc->user)-1); - strncpy(p_udesc->group, gg->gr_name, sizeof(p_udesc->group)-1); - p_udesc->conn = kc; + if (kdbus_hello(kc, hello_flags, attach_flags_send, attach_flags_recv) < 0) + goto err; - fdl = open("/proc/self/attr/current", 0, S_IRUSR); - if (fdl < 0) - { - dbuspolicy1_free(p_udesc); - return NULL; - } + if (__internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY) < 0 + && __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY) < 0) + goto err; - r = read(fdl, p_udesc->label, 256); - if (r < 0) - { - close(fdl); - dbuspolicy1_free(p_udesc); - return NULL; - } - close(fdl); + if (dbuspolicy_init_udesc(kc, bus_type, p_udesc) < 0) + goto err; + return p_udesc; - } - } else { - p_udesc = NULL; - close(kc->fd); - free(kc); - } - return p_udesc; +err: + dbuspolicy1_free(p_udesc); + if (kc && kc->fd != -1) + close(kc->fd); + free(kc); + free(p_udesc); + + return NULL; } DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration) -- 2.7.4 From 3e2096a97a45af1d16666fbf1b1970f19744d65b Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Thu, 7 Apr 2016 17:51:46 +0200 Subject: [PATCH 02/16] Change default configuration files as used from dbus-1.10 Change-Id: Ib986f757efe923b7c2003d89fbcbfe15370f1ba7 --- src/dbuspolicy1/libdbuspolicy1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbuspolicy1/libdbuspolicy1.h b/src/dbuspolicy1/libdbuspolicy1.h index 846a227..a0f7dcd 100644 --- a/src/dbuspolicy1/libdbuspolicy1.h +++ b/src/dbuspolicy1/libdbuspolicy1.h @@ -26,8 +26,8 @@ extern "C" { #define SYSTEM_BUS_CONF_FILE_PRIMARY "/usr/share/dbus-1/system.conf" #define SESSION_BUS_CONF_FILE_PRIMARY "/usr/share/dbus-1/session.conf" -#define SYSTEM_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/system.conf" -#define SESSION_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/session.conf" +#define SYSTEM_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/system-local.conf" +#define SESSION_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/session-local.conf" #define SYSTEM_BUS 1 #define SESSION_BUS 2 -- 2.7.4 From acf0d2572f88b0859b080e5516c83cf79667b86a Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 8 Apr 2016 15:04:27 +0200 Subject: [PATCH 03/16] packaging: Do not strip binaries on install Having debug info will allow debug information to be extracted and placed into separate .debug{info,source} packages automatically. Change-Id: I64d7dd1468c58a32fdb9d978f07547e3fc65fd18 --- packaging/libdbuspolicy.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libdbuspolicy.spec b/packaging/libdbuspolicy.spec index 2d3bb0c..591b048 100644 --- a/packaging/libdbuspolicy.spec +++ b/packaging/libdbuspolicy.spec @@ -36,7 +36,7 @@ cp %{SOURCE1001} . make %install -make DESTDIR=%{buildroot} install-strip +make DESTDIR=%{buildroot} install rm %{buildroot}%{_libdir}/libdbuspolicy1.la %post -p /sbin/ldconfig -- 2.7.4 From 986263670052a6bc5e60b96c55fd0dd2d6145d80 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 8 Apr 2016 15:04:59 +0200 Subject: [PATCH 04/16] refactor: drop unused variable Change-Id: I7069cabbf73110823eb7ae2a8806405fdb278d56 --- src/libdbuspolicy1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 8be9445..b7628d6 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -131,7 +131,7 @@ static int kdbus_get_creds_from_name(struct kconn* kc, struct kcreds* kcr, const struct kdbus_info* conn_info; struct kdbus_item *item; char** tmp_names; - int j, r, l, counter, type; + int j, r, l, counter; unsigned int size; counter = 0; -- 2.7.4 From 6dc5ac08cd7b500f9d11bb2ca0c3a8fde56a8a38 Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Wed, 20 Apr 2016 12:41:48 +0900 Subject: [PATCH 05/16] svace:delete double free Change-Id: Ieeeef6057ec005206d9d4d29f7ce682f991e13b4 Signed-off-by: sanghyeok.oh --- src/libdbuspolicy1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index b7628d6..9ba7f47 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -301,7 +301,6 @@ err: if (kc && kc->fd != -1) close(kc->fd); free(kc); - free(p_udesc); return NULL; } -- 2.7.4 From 00d4d82cbb13c8fb0c59720de8ce37a3b6890b61 Mon Sep 17 00:00:00 2001 From: Lukasz Skalski Date: Mon, 25 Apr 2016 13:35:24 +0200 Subject: [PATCH 06/16] Fix: properly check getgrgid_r() and getpwuid_r() function results Change-Id: I3c780f9067d1b4aca2a0bc40f6ff2d2a1adf0347 --- src/libdbuspolicy1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 9ba7f47..d8163b7 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -246,6 +246,9 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct if (getgrgid_r(p_udesc->gid, &grent, buf, sizeof(buf), &gg)) return -1; + if (!pwd || !gg) + return -1; + len = sizeof(p_udesc->user) - 1; strncpy(p_udesc->user, pwd->pw_name, len); p_udesc->group[len] = 0; -- 2.7.4 From 653f2dc647e1a80a257978d7a8f15f20d242aae4 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Tue, 26 Apr 2016 15:05:09 +0200 Subject: [PATCH 07/16] dbuspolicy: fix initialization Change-Id: Ib904512ef25e3da70f784dcd3662f0afd272e3c8 --- src/libdbuspolicy1.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index d8163b7..119e460 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -280,8 +280,7 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init(unsigned int bus_type) struct udesc* p_udesc = NULL; kc = (struct kconn*) calloc(1, sizeof(struct kconn)); - p_udesc = (struct udesc*)malloc(sizeof(struct udesc)); - if (!kc || !p_udesc) + if (!kc) goto err; if ((kc->fd = kdbus_open_system_bus()) < 0) @@ -294,16 +293,20 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init(unsigned int bus_type) && __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY) < 0) goto err; + p_udesc = (struct udesc*)malloc(sizeof(struct udesc)); + if (!p_udesc) + goto err; + if (dbuspolicy_init_udesc(kc, bus_type, p_udesc) < 0) goto err; return p_udesc; err: - dbuspolicy1_free(p_udesc); if (kc && kc->fd != -1) close(kc->fd); free(kc); + free(p_udesc); return NULL; } -- 2.7.4 From 6cd319fd90ef296a27847eb091c31c79ee8eb1e2 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 27 Apr 2016 15:18:47 +0200 Subject: [PATCH 08/16] Fix: do not call get(pw/gr)uid on uninitialized memory This commit fixes bug introduced in commit 869f3003 ("Fix: close file descriptior leak in dbuspolicy_init error path"). Change-Id: Ieec0fdb4b23a014f25c20aecb731ff2e14a8864a --- src/libdbuspolicy1.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 119e460..b97c68d 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -240,6 +240,9 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct if (r < 0) /* read */ return -1; + p_udesc->uid = getuid(); + p_udesc->gid = getgid(); + if (getpwuid_r(p_udesc->uid, &pwent, buf, sizeof(buf), &pwd)) return -1; @@ -258,8 +261,6 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct p_udesc->group[len] = 0; p_udesc->bus_type = bus_type; - p_udesc->uid = getuid(); - p_udesc->gid = getgid(); p_udesc->conn = kc; return 0; -- 2.7.4 From 44f0b122fa257e98454b21f7219d47db6e8ca47a Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 27 Apr 2016 16:00:32 +0200 Subject: [PATCH 09/16] Fix: ensure Smack label is null terminated in internal representation Change-Id: Ifbb8d651b407111668ba61d1e279938fb6509589 --- src/libdbuspolicy1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index b97c68d..5178e88 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -233,13 +233,15 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct attr_fd = open("/proc/self/attr/current", O_RDONLY); if (attr_fd < 0) return -1; - r = read(attr_fd, p_udesc->label, 256); + r = read(attr_fd, buf, sizeof(buf)); close(attr_fd); - if (r < 0) /* read */ + if (r < 0 || r >= (long int)sizeof(p_udesc->label)) /* read */ return -1; + snprintf(p_udesc->label, r + 1 /* additional byte for \0 */, "%s", buf); + p_udesc->uid = getuid(); p_udesc->gid = getgid(); -- 2.7.4 From 4e46a80e1ebaa6daeb909e750314794828493c87 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 27 Apr 2016 16:03:03 +0200 Subject: [PATCH 10/16] Janitorial: use snprintf() for string operations snprintf() guarantees terminating \0 byte for given size. Change-Id: I65cb90ea4466d0356cc02919d269da8843a7302f --- src/libdbuspolicy1.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 5178e88..e10d43b 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -228,7 +228,6 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct char buf[1024]; int attr_fd; int r; - int len; attr_fd = open("/proc/self/attr/current", O_RDONLY); if (attr_fd < 0) @@ -254,13 +253,8 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct if (!pwd || !gg) return -1; - len = sizeof(p_udesc->user) - 1; - strncpy(p_udesc->user, pwd->pw_name, len); - p_udesc->group[len] = 0; - - len = sizeof(p_udesc->group) - 1; - strncpy(p_udesc->group, gg->gr_name, len); - p_udesc->group[len] = 0; + snprintf(p_udesc->user, sizeof(p_udesc->user), "%s", pwd->pw_name); + snprintf(p_udesc->group, sizeof(p_udesc->group), "%s", gg->gr_name); p_udesc->bus_type = bus_type; p_udesc->conn = kc; -- 2.7.4 From f2e9323ecfcd034cd012e768d3a3d73927179387 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Thu, 28 Apr 2016 14:06:38 +0200 Subject: [PATCH 11/16] Initialize policy database based on bus path Currently library has no reliable way of determining which path was already opened by libdbus/glib when only bus type is given. This commit changes API to allow client libraries pass bus path directly eliminating possible ambiguities. Change-Id: I732c391898f661b923fa61d4a2aebb402fb0ec3c --- src/dbuspolicy1/libdbuspolicy1.h | 16 +++++++++--- src/libdbuspolicy1.c | 53 ++++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/dbuspolicy1/libdbuspolicy1.h b/src/dbuspolicy1/libdbuspolicy1.h index a0f7dcd..0037fc7 100644 --- a/src/dbuspolicy1/libdbuspolicy1.h +++ b/src/dbuspolicy1/libdbuspolicy1.h @@ -46,13 +46,21 @@ extern "C" { struct udesc; /*! - libdbuspolicy init - \param bus_type bus type (SYSTEM or SESSION) + Initialize libdbuspolicy configuration context + \param bus_path path to the kdbus bus (system or session) + + \note This function should be called only on well known kdbus buses + - the system bus (/sys/fs/kdbus/0-system/bus) and session bus + (/sys/fs/kdbus/getuid()-user/bus). If any other bus is specified + function will not succeed. + + \return On success pointer to configuration context is returned. On + error NULL is returned. */ -void* dbuspolicy1_init(unsigned int bus_type); +void* dbuspolicy1_init(const char *bus_path); /*! - libdbuspolicy free + Free libdbuspolicy configuration context \param configuration pointer with policy configuration acquired using dbuspolicy1_init */ void dbuspolicy1_free(void* configuration); diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index e10d43b..68f13a9 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -30,12 +30,15 @@ #include #include #include +#include #include #include "libdbuspolicy1-private.h" #include "internal/internal.h" +#define KDBUS_PATH_PREFIX "/sys/fs/kdbus/" #define KDBUS_SYSTEM_BUS_PATH "/sys/fs/kdbus/0-system/bus" + #define KDBUS_POOL_SIZE (16 * 1024UL * 1024UL) #define ALIGN8(l) (((l) + 7) & ~7) @@ -90,9 +93,9 @@ struct udesc { }; -static int kdbus_open_system_bus(void) +static int kdbus_open_bus(const char *path) { - return open(KDBUS_SYSTEM_BUS_PATH, O_RDWR|O_NOCTTY|O_LARGEFILE|O_CLOEXEC ); + return open(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) @@ -262,25 +265,55 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct return 0; } -/** - * 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) +static int bus_path_resolve(const char *bus_path, char *resolved_path, unsigned resolved_path_size, unsigned int *bus_type) +{ + char rp[PATH_MAX]; + char *p; + const char user_suffix[] = "-user/bus"; + int suffix_pos; + + p = realpath(bus_path, rp); + if (!p) + return -1; + + if (0 != strncmp(p, KDBUS_PATH_PREFIX, strlen(KDBUS_PATH_PREFIX))) + return -1; + + if (0 == strcmp(p, KDBUS_SYSTEM_BUS_PATH)) { + *bus_type = SYSTEM_BUS; + } else { + suffix_pos = strlen(p) - strlen(user_suffix); + if (suffix_pos < 0) + return -1; + + if (0 != strcmp(p + suffix_pos, user_suffix)) + return -1; + + *bus_type = SESSION_BUS; + } + + snprintf(resolved_path, resolved_path_size, "%s", p); + return 0; +} + +DBUSPOLICY1_EXPORT void* dbuspolicy1_init(const char *bus_path) { uint64_t hello_flags = 0; uint64_t attach_flags_send = _KDBUS_ATTACH_ANY; uint64_t attach_flags_recv = _KDBUS_ATTACH_ALL; struct kconn* kc = NULL; struct udesc* p_udesc = NULL; + unsigned int bus_type = -1; + char resolved_path[PATH_MAX] = { 0 }; + + if (bus_path_resolve(bus_path, resolved_path, sizeof(resolved_path), &bus_type) < 0) + goto err; kc = (struct kconn*) calloc(1, sizeof(struct kconn)); if (!kc) goto err; - if ((kc->fd = kdbus_open_system_bus()) < 0) + if ((kc->fd = kdbus_open_bus(resolved_path)) < 0) goto err; if (kdbus_hello(kc, hello_flags, attach_flags_send, attach_flags_recv) < 0) -- 2.7.4 From bc76cd6e15bd66b6c13a29a64a29a68d3bfe225f Mon Sep 17 00:00:00 2001 From: Konrad Lipinski Date: Wed, 13 Apr 2016 10:58:43 +0200 Subject: [PATCH 12/16] Fixed series of bugs and optimalised arguments preparation Fixed kdbus pool memory managment. Refactored tslog (getenv called only once). Removed duplicated credential information. Dropped unused timeouts. Added lockless calls when logs are disabled. Removed udesc allocation. Decreased KDBUS_POOL_SIZE from 16M to 1M. Minor fixes. Change-Id: I1e5fda8df4dbd1dd6dfecae60aff6d7d67705a3b --- src/dbuspolicy1/libdbuspolicy1.h | 3 - src/internal/internal.cpp | 65 +++- src/internal/internal.h | 11 +- src/internal/libdbuspolicy1-private.hpp | 11 +- src/internal/timer.hpp | 77 ----- src/internal/tslog.hpp | 89 +----- src/internal/xml_parser.hpp | 227 +++++--------- src/internal/xml_policy.hpp | 359 +++++++++------------- src/libdbuspolicy1-private.h | 3 + src/libdbuspolicy1.c | 515 ++++++++++++++------------------ 10 files changed, 515 insertions(+), 845 deletions(-) delete mode 100644 src/internal/timer.hpp diff --git a/src/dbuspolicy1/libdbuspolicy1.h b/src/dbuspolicy1/libdbuspolicy1.h index 0037fc7..ae9b0c2 100644 --- a/src/dbuspolicy1/libdbuspolicy1.h +++ b/src/dbuspolicy1/libdbuspolicy1.h @@ -29,9 +29,6 @@ extern "C" { #define SYSTEM_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/system-local.conf" #define SESSION_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/session-local.conf" -#define SYSTEM_BUS 1 -#define SESSION_BUS 2 - /** used when check policy for message prepared to send */ #define DBUSPOLICY_DIRECTION_SENDING 0 diff --git a/src/internal/internal.cpp b/src/internal/internal.cpp index 274d321..e26c510 100644 --- a/src/internal/internal.cpp +++ b/src/internal/internal.cpp @@ -23,14 +23,20 @@ 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 std::string get_strv(const char *s) { + unsigned i = 0; + if (s) { + i = -1; + char c; + while ((c = s[++i]) && ' ' != c); + } + return std::string{s, i}; +} + static const char* get_message_type(int type) { const char* sztype; switch(type) { @@ -43,14 +49,41 @@ static const char* get_message_type(int type) { return sztype; } -int __internal_init(unsigned int bus_type, const char* const config_name) +int __internal_init(bool 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)); + _ldp_xml_parser::XmlParser p; + auto err = p.parse_policy(bus_type, get_str(config_name)); return err.get(); } -int __internal_can_send(unsigned int bus_type, +pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; + +void __internal_init_once() +{ + tslog::init(); +} + +void __internal_init_flush_logs() +{ + if (tslog::enabled()) { + pthread_mutex_lock(&g_mutex); + std::cout << std::flush; + pthread_mutex_unlock(&g_mutex); + } +} + +void __internal_enter() +{ + if (tslog::enabled()) + pthread_mutex_lock(&g_mutex); +} +void __internal_exit() +{ + if (tslog::enabled()) + pthread_mutex_unlock(&g_mutex); +} + +int __internal_can_send(bool bus_type, const char* const user, const char* const group, const char* const label, @@ -60,12 +93,12 @@ int __internal_can_send(unsigned int bus_type, 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)); + _ldp_xml_parser::XmlParser p; + auto err = p.can_send(bus_type, get_str(user), get_str(group), get_str(label), get_strv(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, +int __internal_can_recv(bool bus_type, const char* const user, const char* const group, const char* const label, @@ -75,18 +108,18 @@ int __internal_can_recv(unsigned int bus_type, 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)); + _ldp_xml_parser::XmlParser p; + auto err = p.can_recv(bus_type, get_str(user), get_str(group), get_str(label), get_strv(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, +int __internal_can_own(bool 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)); + _ldp_xml_parser::XmlParser p; + auto err = p.can_own(bus_type, get_str(user), get_str(group), get_str(service)); return err.get(); } diff --git a/src/internal/internal.h b/src/internal/internal.h index 84a1069..0914abe 100644 --- a/src/internal/internal.h +++ b/src/internal/internal.h @@ -22,8 +22,13 @@ extern "C" { #endif int __internal_init(unsigned int bus_type, const char* const config_name); +void __internal_init_once(void); +extern pthread_mutex_t g_mutex; +void __internal_init_flush_logs(void); +void __internal_enter(void); +void __internal_exit(void); -int __internal_can_send(unsigned int bus_type, +int __internal_can_send(bool bus_type, const char* const user, const char* const group, const char* const label, @@ -33,7 +38,7 @@ int __internal_can_send(unsigned int bus_type, const char* const member, int type); -int __internal_can_recv(unsigned int bus_type, +int __internal_can_recv(bool bus_type, const char* const user, const char* const group, const char* const label, @@ -43,7 +48,7 @@ int __internal_can_recv(unsigned int bus_type, const char* const member, int type); -int __internal_can_own(unsigned int bus_type, +int __internal_can_own(bool bus_type, const char* const user, const char* const group, const char* const service); diff --git a/src/internal/libdbuspolicy1-private.hpp b/src/internal/libdbuspolicy1-private.hpp index 4b467b4..0cef333 100644 --- a/src/internal/libdbuspolicy1-private.hpp +++ b/src/internal/libdbuspolicy1-private.hpp @@ -19,6 +19,12 @@ #include +namespace arraySizeDetail { + template constexpr size_t size(T const (&)[S]) { return S; } + template constexpr size_t size(std::initializer_list const &l) { return l.size(); } +} +#define TABSIZE(...) (::arraySizeDetail::size(__VA_ARGS__)) + namespace { class ErrCode { int m_err; @@ -26,7 +32,6 @@ namespace { 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"); @@ -41,10 +46,6 @@ namespace { return ErrCode(-1, what); } - static ErrCode timeout(const std::string& what) { - return ErrCode(-99, std::string("Timeout: ") + what); - } - int get() const { return m_err; } diff --git a/src/internal/timer.hpp b/src/internal/timer.hpp deleted file mode 100644 index 2d856b3..0000000 --- a/src/internal/timer.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 -#include - -namespace _ldp_timer -{ - template - class Duration : public BaseTimeUnit { - public: - void setNanoTime(std::chrono::nanoseconds nano) { - BaseTimeUnit d = std::chrono::duration_cast(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& 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 nanosec; - typedef Duration microsec; - typedef Duration millisec; - typedef Duration sec; - - template - 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 diff --git a/src/internal/tslog.hpp b/src/internal/tslog.hpp index 3452dbc..dd57976 100644 --- a/src/internal/tslog.hpp +++ b/src/internal/tslog.hpp @@ -19,87 +19,26 @@ #include #include -#include +#include #include -namespace _ldp_tslog -{ - typedef std::ostream& (*t_ManFun)(std::ostream&); - - namespace { - static constexpr bool LOG_DEFAULT_ENABLE = false; - static constexpr bool LOG_DEFAULT_VERBOSE = false; - static const std::string LDP_ENV_VERBOSE_NAME = "LDP_VERBOSE"; - static const std::string LDP_ENV_LOG_NAME = "LDP_LOG"; - - const bool get_log_env(const std::string& name) { - bool bret; - char* ldp_log_mode = getenv(name.c_str()); - if(ldp_log_mode) { - const std::string slog(ldp_log_mode); - bret = (slog == "0") ? false : true; - } else { - bret = (name == LDP_ENV_LOG_NAME) ? LOG_DEFAULT_ENABLE : LOG_DEFAULT_VERBOSE; - } - return bret; - } - } - - const bool get_verbose() { - return get_log_env(LDP_ENV_VERBOSE_NAME); - } - - const bool get_enable() { - return get_log_env(LDP_ENV_LOG_NAME); - } - - class TsLog - { - private: - static bool m_verbose; - static std::mutex m_mtx; - std::ostream& m_os; - bool m_enable; +typedef std::ostream& (*t_ManFun)(std::ostream&); - template - TsLog& lckLog(const T& t) { - if(m_enable) { - std::unique_lock 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() {} +namespace tslog +{ + int8_t g_verbosity; // <0 disable 0 brief >0 verbose - template - TsLog& operator<< (const T& t) { - return lckLog(t); - } + bool get_log_env(char const *name) { + char const *ldp_log_mode = getenv(name); + return ldp_log_mode && '0' != *ldp_log_mode; + } - TsLog& operator<< (t_ManFun f) { - return lckLog(f); - } + void init() { + g_verbosity = get_log_env("LDP_LOG") ? get_log_env("LDP_VERBOSE") : -1; + } - }; - std::mutex TsLog::m_mtx; + bool enabled() { return g_verbosity >= 0; } + bool verbose() { return g_verbosity > 0; } } -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 diff --git a/src/internal/xml_parser.hpp b/src/internal/xml_parser.hpp index 05df566..61e60e4 100644 --- a/src/internal/xml_parser.hpp +++ b/src/internal/xml_parser.hpp @@ -17,39 +17,26 @@ #ifndef _XML_PARSER_HPP #define _XML_PARSER_HPP -#include -#include -#include +#include #include #include #include -#include #include #include -#include "timer.hpp" #include "xml_policy.hpp" namespace _ldp_xml_parser { - class XmlAsyncParser : boost::noncopyable + class XmlParser : boost::noncopyable { public: - XmlAsyncParser() { - } - - virtual ~XmlAsyncParser() { - } - - ErrCode parse_policy(const std::string bus, - const std::string fname, - const std::chrono::milliseconds timeout = std::chrono::milliseconds(std::numeric_limits::max())) { - set_policy_bus_filename(bus, fname); - m_xml_policy.init(); - ErrCode err = parse(timeout); + ErrCode parse_policy(bool bus, + std::string const &fname) { + ErrCode err = parse(bus, fname); return err; } - ErrCode can_send(const std::string bus, + ErrCode can_send(bool bus, const std::string user, const std::string group, const std::string label, @@ -62,7 +49,7 @@ namespace _ldp_xml_parser return m_xml_policy.can_send_to(bus, idx_v, label); } - ErrCode can_recv(const std::string bus, + ErrCode can_recv(bool bus, const std::string user, const std::string group, const std::string label, @@ -75,7 +62,7 @@ namespace _ldp_xml_parser return m_xml_policy.can_recv_from(bus, idx_v, label); } - ErrCode can_own(const std::string bus, + ErrCode can_own(bool bus, const std::string user, const std::string group, const std::string service) { @@ -86,173 +73,95 @@ namespace _ldp_xml_parser private: //IO operation - std::string m_bus; - std::string m_filename; - static std::map m_hashes; - static std::mutex m_io_xml_mtx; + static std::set m_parsed; //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 parse(bool bus, std::string const &filename) { ErrCode err; std::vector incl_files; - err = parse(get_policy_filename(), incl_files, timeout); - if(err.is_ok()) { + err = parse(bus, true, filename, incl_files); + if (err.is_ok()) for(const auto& x : incl_files) { - err = parse(x, incl_files, timeout); - if(err.is_error()) { break; } + err = parse(bus, false, x, incl_files); + if (err.is_error()) break; } - } - if(err.is_ok()) { - m_xml_policy.print_decision_trees(); - } + if(err.is_ok()) + m_xml_policy.print_decision_trees(bus); return err; } - ErrCode parse(const std::string& filename, std::vector& included_files, const std::chrono::milliseconds timeout) { + ErrCode parse(bool bus, bool first, const std::string& filename, std::vector& included_files) { std::pair errparam; - verbose::tout << "=== XML PARSING BEGIN === : " << filename << std::endl; + if (tslog::verbose()) + std::cout << "=== XML PARSING BEGIN === : " << filename << '\n'; - 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"); - } + errparam = xml_parse(bus, filename); + if (first && errparam.first.get() >= 0 && errparam.second != "") + get_included_files(filename, errparam.second, included_files); - verbose::tout << "=== XML PARSING END ===" << std::endl << std::endl; - tout << "Processing of " << filename << " -> [" << errparam.first.get() << ", " << errparam.first.get_str() << "]" << std::endl; + if (tslog::enabled()) { + if (tslog::verbose()) + std::cout << "=== XML PARSING END ===\n\n"; + std::cout << "Processing of " << filename << " -> [" << errparam.first.get() << ", " << errparam.first.get_str() << "]\n"; + } 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& 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(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::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 async_xml_parse(const std::string& filename) { + DIR *dir; + struct dirent *ent; + std::string fname; + std::copy(filename.begin(), filename.end(), fname.begin()); + std::string dname = dirname(const_cast(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); + + if (tslog::enabled()) { + std::cout << "\nincludedir for " << filename << " is " << incldir << ", " << files.size() << " included files found:\n"; + std::copy(files.begin(), files.end(), std::ostream_iterator(std::cout, "\n")); + std::cout << '\n'; + } + } else if (tslog::enabled()) + std::cout << "could not open directory " << dname << '\n'; + } + + std::pair xml_parse(bool bus, const std::string& filename) { std::pair ret; - _ldp_timer::microsec latency; - try { - boost::property_tree::ptree pt; + if (m_parsed.insert(filename).second) + try { + boost::property_tree::ptree pt; + read_xml(filename, pt); + if (!pt.empty()) { + m_xml_policy.update(bus, pt); + ret.second = pt.get("busconfig.includedir", ""); + } + } 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")); + } - //XML file IO critical section - { - std::unique_lock 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(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 XmlAsyncParser::m_hashes; - std::mutex XmlAsyncParser::m_io_xml_mtx; - XmlPolicy XmlAsyncParser::m_xml_policy; } //namespace #endif diff --git a/src/internal/xml_policy.hpp b/src/internal/xml_policy.hpp index 63fe956..48fa7f9 100644 --- a/src/internal/xml_policy.hpp +++ b/src/internal/xml_policy.hpp @@ -20,11 +20,17 @@ #include #include #include +#include #include "libdbuspolicy1-private.hpp" -#include "timer.hpp" #include "tslog.hpp" #include "cynara.hpp" +enum class TreeType : uint8_t { + SEND, + RECV, + OWN +}; + namespace _ldp_xml_parser { namespace { @@ -56,7 +62,6 @@ namespace _ldp_xml_parser 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 m_path_content; std::string m_privilege; bool m_bsend; @@ -66,9 +71,8 @@ namespace _ldp_xml_parser bool m_ballow; static size_t m_weight; - Key(const std::string& bus) - : m_bus(bus), - m_path_content(std::vector(IDX_TOTAL_LENGTH, ANY)), + Key(bool bus) + : m_path_content(std::vector(IDX_TOTAL_LENGTH, ANY)), m_bsend(false), m_brecv(false), m_bown(false), @@ -85,9 +89,8 @@ namespace _ldp_xml_parser 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); - } + for(auto it = m_path_content.cbegin(); it != it_cend; ++it) + (path += Key::DELIM) += *it; return path; } }; @@ -121,11 +124,10 @@ namespace _ldp_xml_parser } friend std::ostream& operator<<(std::ostream& os, const Leaf& lf) { - if(lf.m_check) { + if(lf.m_check) os << "check," << lf.m_privilege << "," << lf.m_weight; - } else { + else os << (lf.m_decision ? "true" : "false") << "," << lf.m_weight; - } return os; } @@ -138,24 +140,20 @@ namespace _ldp_xml_parser 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) { + if(size > 2) lf.m_check = (*it == "check") ? true : false; - } else { + else lf.m_decision = (*it == "true") ? true : false; - } - } else if(it == it_last) { + } else if(it == it_last) lf.m_weight = std::stoul(*it); - } else { - if(size > 2) { - lf.m_privilege = *it; - } - } + else if(size > 2) + lf.m_privilege = *it; } return is; } }; - static const std::string get_context_str(const CtxType& ctx_type) { + static char const *get_context_str(const CtxType& ctx_type) { switch(ctx_type) { case CtxType::DEFAULT: return "(default)"; break; case CtxType::SPECIFIC: return "(specific)"; break; @@ -165,34 +163,24 @@ namespace _ldp_xml_parser } static const std::string get_field_str(const std::string& field) { - return (field == "") ? Key::ANY : field; + return field == "" ? Key::ANY : field; } //Data obtained from XML parsing - decision trees - typedef std::map Trees_t; - std::map 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 m_dec_trees[2][3]; + + boost::property_tree::ptree &get_decision_tree(bool bus, TreeType tree_type) { + return m_dec_trees[bus][static_cast(tree_type)]; } - 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"; } + boost::property_tree::ptree* get_decision_tree(bool bus, const Key& key) { + TreeType tree_type; + if(key.m_bsend) tree_type = TreeType::SEND; + else if(key.m_brecv) tree_type = TreeType::RECV; + else if(key.m_bown) tree_type = TreeType::OWN; + else return NULL; - return get_decision_tree(key.m_bus, tree_type); + return &get_decision_tree(bus, tree_type); } void print_decision_tree(const boost::property_tree::ptree& pt, int level = 0) { @@ -202,31 +190,30 @@ namespace _ldp_xml_parser } } - 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 #"; } + void print_decision_key(bool bus, const Key& key) { + if (tslog::verbose()) { + std::string s = 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 + std::cout << s << (key.m_bcheck ? "check " : std::to_string(key.m_ballow)) << prv << " : " << key.get_path() << " (weight: " << key.m_weight - << ")" - << std::endl; + << ")\n"; } } - void update_decision_tree(const Key& key) { + void update_decision_tree(bool bus, const Key& key) { if(!key.get_path().empty()) { - print_decision_key(key); + print_decision_key(bus, key); //update - boost::property_tree::ptree* const p_tree = get_decision_tree(key); + boost::property_tree::ptree* const p_tree = get_decision_tree(bus, 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)); @@ -260,7 +247,7 @@ namespace _ldp_xml_parser ++key.m_weight; } else { if(attr) { - std::string data_str = (v.second.data() == "*") ? Key::ANY : v.second.data(); + 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; @@ -272,20 +259,16 @@ namespace _ldp_xml_parser current_ctx = CtxType::DEFAULT; } } else if(v.first == "user") { - if(current_ctx == CtxType::SPECIFIC) { + if(current_ctx == CtxType::SPECIFIC) key.m_path_content[Key::IDX_USER] = data_str; - } } else if(v.first == "group") { - if(current_ctx == CtxType::SPECIFIC) { + if(current_ctx == CtxType::SPECIFIC) key.m_path_content[Key::IDX_GROUP] = data_str; - } } else { - if(field_has(v, "send_")) { + if(field_has(v, "send_")) key.m_bsend = true; - } - if(field_has(v, "receive_")) { + 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; @@ -294,27 +277,20 @@ namespace _ldp_xml_parser key.m_bown = true; key.m_path_content[Key::IDX_SERVICE] = data_str + "*"; } - if(field_has(v, "_destination")) { + if(field_has(v, "_destination")) key.m_path_content[Key::IDX_DEST] = data_str; - } - if(field_has(v, "_sender")) { + if(field_has(v, "_sender")) key.m_path_content[Key::IDX_SENDER] = data_str; - } - if(field_has(v, "_path")) { + if(field_has(v, "_path")) key.m_path_content[Key::IDX_PATH] = data_str; - } - if(field_has(v, "_interface")) { + if(field_has(v, "_interface")) key.m_path_content[Key::IDX_IFACE] = data_str; - } - if(field_has(v, "_member")) { + if(field_has(v, "_member")) key.m_path_content[Key::IDX_MEMBER] = data_str; - } - if(field_has(v, "_type")) { + if(field_has(v, "_type")) key.m_path_content[Key::IDX_TYPE] = data_str; - } - if(v.first == "privilege") { + if(v.first == "privilege") key.m_privilege = data_str; - } key.m_bcheck = bcheck; key.m_ballow = allden; @@ -328,14 +304,15 @@ namespace _ldp_xml_parser } 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; + std::cout << ((level > 0) ? std::string((level - 1) * 8, ' ') + std::string(8, '.') : "") + << v.first + << " : " + << v.second.data() + << '\n'; } - void xml_traversal(const boost::property_tree::ptree& pt, + void xml_traversal(bool bus, + const boost::property_tree::ptree& pt, Key& key, CtxType& current_ctx, bool allden = false, @@ -349,20 +326,18 @@ namespace _ldp_xml_parser if(v.first == "") { 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 (tslog::verbose()) print_field(v, level); + xml_traversal(bus, 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; - } + if(!pt.empty() && attr && level > 1) + update_decision_tree(bus, key); + } else if (tslog::enabled()) + std::cout << "XML traversal max level reached: " << level << '\n'; } void print_indexing_path(size_t idx, const std::string& path, const Leaf& leaf = Leaf(), bool empty = true) { - if(_ldp_tslog::get_verbose()) { + if (tslog::verbose()) { std::string s; if(!empty) { s = " : <"; @@ -373,72 +348,59 @@ namespace _ldp_xml_parser s += std::string(">"); } - verbose::tout << "path #" - << idx - << " : " - << path - << s - << std::endl; + std::cout << "path #" + << idx + << " : " + << path + << s + << '\n'; } } void prepare_indexing_path(const std::vector& idx_v, - const size_t pattern, + size_t pattern, const size_t usrgrp_obfuscate_order, const bool obfuscate_params, const CtxType& ctx_type, std::string& path) { - const size_t offset = Key::IDX_DEFAULT; + constexpr size_t offset = Key::IDX_DEFAULT; path = "R"; if(ctx_type == CtxType::SPECIFIC) { - switch(usrgrp_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); - } - } + path += Key::DELIM; + if (usrgrp_obfuscate_order & 1) // 1 3 + path += Key::ANY; + else + path += get_field_str(idx_v[Key::IDX_USER]); + path += Key::DELIM; + if ((usrgrp_obfuscate_order+1) & 2) // 1 2 + path += get_field_str(idx_v[Key::IDX_GROUP]); + else + path += Key::ANY; + } else + for(size_t i = 0; i < offset; ++i) + (path += Key::DELIM) += ctx_type == CtxType::MANDATORY ? Key::MRY : Key::DEF; - 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]); + for (size_t i = 0; i < n; ++i) { path += Key::DELIM; - if(obfuscate_params && (pattern & (m << i))) { - path += Key::ANY; - } else { - path += s; - } + if (obfuscate_params && pattern & 1) + path += Key::ANY; + else + path += get_field_str(idx_v[i + offset]); + pattern >>= 1; } } ErrCode service_leaf_found(const Leaf& leaf, const std::string& label, const std::vector& idx_v) { ErrCode err; if(leaf.get_check()) { - verbose::tout << __func__ - << ": cynara check needed for privilege " << leaf.get_privilege() - << ", weight " << leaf.get_weight() - << std::endl; + if (tslog::verbose()) + std::cout << __func__ + << ": cynara check needed for privilege " << leaf.get_privilege() + << ", weight " << leaf.get_weight() + << '\n'; //cynara check try { @@ -487,14 +449,16 @@ namespace _ldp_xml_parser if(!found) { err = ErrCode::error("No path"); } } catch(...) { print_indexing_path(p, path); - verbose::tout << "Unknown exception while indexing decision tree!" << std::endl; + if (tslog::verbose()) + std::cout << "Unknown exception while indexing decision tree!\n"; if(!found) { err = ErrCode::error("Unknown err, no path"); } } } if(found) { err = service_leaf_found(leaf_found, label, idx_v); - verbose::tout << __func__ << ": returning decision #" << err.get() << " " << err.get_str() << ", weight " << leaf_found.get_weight() << std::endl; + if (tslog::verbose()) + std::cout << __func__ << ": returning decision #" << err.get() << " " << err.get_str() << ", weight " << leaf_found.get_weight() << '\n'; break; } } @@ -509,85 +473,63 @@ namespace _ldp_xml_parser 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::cout, ", ")); } - tout << std::endl; + if (tslog::enabled()) { + std::cout << "context: " << get_context_str(ctx_type) << ", indexing arguments: "; + std::copy(idx_v.begin(), idx_v.end(), std::ostream_iterator(std::cout, ", ")); + std::cout << '\n'; + } //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, obfuscate_params, ctx_type); - } + err = index_decision_tree(pt, idx_v, label, obfuscate_params, ctx_type); - tout << __func__ << ": #" << err.get() << " " << err.get_str() << " " << get_context_str(ctx_type) << std::endl; - tout << "tree indexing latency: " << latency << std::endl; + if (tslog::enabled()) + std::cout << __func__ << ": #" << err.get() << " " << err.get_str() << " " << get_context_str(ctx_type) << '\n'; return err; } - ErrCode can_do_action(const std::string& bus, - const std::string& tree_type, + ErrCode can_do_action(bool bus, + TreeType tree_type, const std::vector& idx_v, const std::string& label = "", const bool analyze_prefix = false) { - std::unique_lock 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, !analyze_prefix, CtxType::MANDATORY); - if(!err.is_ok()) { - err = index_decision_tree_lat(*p_tree, idx_v, label, !analyze_prefix, CtxType::SPECIFIC); - if(!err.is_ok()) { - err = index_decision_tree_lat(*p_tree, idx_v, label, !analyze_prefix, CtxType::DEFAULT); - } - } - } else { - err = ErrCode::error("Get decision tree returned NULL ptr"); - } - tout << __func__ << ": #" << err.get() << " " << err.get_str() << std::endl; + boost::property_tree::ptree const &p_tree = get_decision_tree(bus, tree_type); + err = index_decision_tree_lat(p_tree, idx_v, label, !analyze_prefix, CtxType::MANDATORY); + if(!err.is_ok()) { + err = index_decision_tree_lat(p_tree, idx_v, label, !analyze_prefix, CtxType::SPECIFIC); + if(!err.is_ok()) + err = index_decision_tree_lat(p_tree, idx_v, label, !analyze_prefix, CtxType::DEFAULT); + } + if (tslog::enabled()) + std::cout << __func__ << ": #" << err.get() << " " << err.get_str() << '\n'; 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 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 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); - } - } - } + void update(bool bus, const boost::property_tree::ptree& pt) { + 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(bus, x.second, key, current_ctx); + } + } } - ErrCode can_send_to(const std::string bus, const std::vector& idx_v, const std::string label) { - return can_do_action(bus, "SEND", idx_v, label); + ErrCode can_send_to(bool bus, const std::vector& idx_v, const std::string label) { + return can_do_action(bus, TreeType::SEND, idx_v, label); } - ErrCode can_recv_from(const std::string bus, const std::vector& idx_v, const std::string label) { - return can_do_action(bus, "RECV", idx_v, label); + ErrCode can_recv_from(bool bus, const std::vector& idx_v, const std::string label) { + return can_do_action(bus, TreeType::RECV, idx_v, label); } - ErrCode can_own_what(const std::string bus, const std::vector& idx_v) { + ErrCode can_own_what(bool bus, const std::vector& idx_v) { ErrCode err; //Evaluate own_prefix @@ -596,34 +538,29 @@ namespace _ldp_xml_parser const size_t srv_size = srv.size(); for(size_t n = 1; n <= srv_size; ++n) { const std::string sub = srv.substr(0, n) + "*"; - verbose::tout << "own_prefix: " << sub << std::endl; + if (tslog::enabled()) + std::cout << "own_prefix: " << sub << '\n'; iv.pop_back(); iv.push_back(sub); - err = can_do_action(bus, "OWN", iv, "", true); - if(err.is_ok()) { + err = can_do_action(bus, TreeType::OWN, iv, "", true); + if(err.is_ok()) break; - } } //Evaluate own - if(err.is_error()) { - err = can_do_action(bus, "OWN", idx_v); - } + if(err.is_error()) + err = can_do_action(bus, TreeType::OWN, idx_v); return err; } - void print_decision_trees() { - if(_ldp_tslog::get_verbose()) { - std::unique_lock 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; + void print_decision_trees(bool bus) { + if (tslog::verbose()) + for (unsigned i = 0; i < TABSIZE(m_dec_trees[bus]); ++i) + for(auto const& y : m_dec_trees[bus][i]) { + std::cout << i << " " << y.first << " " << (y.second.empty() ? "(empty)" : "") << '\n'; print_decision_tree(y.second); } - } - } } }; //XmlPolicy diff --git a/src/libdbuspolicy1-private.h b/src/libdbuspolicy1-private.h index 58e27bd..24c3d02 100644 --- a/src/libdbuspolicy1-private.h +++ b/src/libdbuspolicy1-private.h @@ -26,4 +26,7 @@ #define DBUSPOLICY1_EXPORT __attribute__ ((visibility("default"))) +typedef uint8_t dbus_name_len; +#define MAX_DBUS_NAME_LEN 255 + #endif diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 68f13a9..0ff7d6b 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "libdbuspolicy1-private.h" @@ -38,30 +39,30 @@ #define KDBUS_PATH_PREFIX "/sys/fs/kdbus/" #define KDBUS_SYSTEM_BUS_PATH "/sys/fs/kdbus/0-system/bus" +#define KDBUS_POOL_SIZE (1024UL * 1024UL) -#define KDBUS_POOL_SIZE (16 * 1024UL * 1024UL) +#define SYSTEM_BUS 0 +#define SESSION_BUS 1 #define ALIGN8(l) (((l) + 7) & ~7) +#define ALIGNDN8(l) ((l) & ~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));\ -strncpy(os, s, sizeof(char*)*(l+1)-1);\ -});\ -i < l;\ -i++) - -#define GET_NEXT_STR(i,s,os)\ - os = s+i;\ - for(;s[i] && s[i] != ' ';i++);\ - s[i] = 0; - +static char const *foreach_strv_advance(char const *str) { + char c; + while ((c = *str++)) + if (' ' == c) + return str; + return NULL; +} +/* iterate over STR; iterate once with "" if !STR or !*STR */ +#define FOREACH_STRV_DEFAULT(ITERLVALPTR,STR) for (\ + ITERLVALPTR = (!STR || !*STR) ? "" : STR;\ + ITERLVALPTR;\ + ITERLVALPTR = foreach_strv_advance(ITERLVALPTR)\ +) /** A process ID */ typedef unsigned long dbus_pid_t; @@ -70,159 +71,64 @@ 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; -}; +} g_conn[2]; + 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; -}; - +} g_udesc; static int kdbus_open_bus(const char *path) { return open(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) +static int kdbus_hello(bool bus_type, uint64_t hello_flags, uint64_t attach_flags_send, uint64_t attach_flags_recv) { - struct kdbus_cmd_hello kcmd_hello; - int r; + struct kdbus_cmd_hello cmd; + int fd = g_conn[bus_type].fd; - 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; + cmd.size = sizeof(cmd); + cmd.flags = hello_flags; + cmd.attach_flags_send = attach_flags_send; + cmd.attach_flags_recv = attach_flags_recv; + cmd.pool_size = KDBUS_POOL_SIZE; - r = ioctl(kc->fd, KDBUS_CMD_HELLO, &kcmd_hello); - if (r < 0) + if (ioctl(fd, KDBUS_CMD_HELLO, &cmd) < 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) + g_conn[bus_type].id = cmd.id; + if (MAP_FAILED == (g_conn[bus_type].pool = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0))) return -errno; return 0; } -static int kdbus_is_unique_id(const char* name) +static bool kdbus_is_unique_id(const char* name) { - return (strlen(name)>3 && name[0]==':' && isdigit(name[1]) && name[2]=='.'); + return ':' == name[0]; } -static int kdbus_get_creds_from_name(struct kconn* kc, struct kcreds* kcr, const char* name) +static uint64_t kdbus_unique_id(char const *name) { - unsigned long long int unique_id; - struct kdbus_cmd_info* cmd; - struct kdbus_info* conn_info; - struct kdbus_item *item; - char** tmp_names; - int j, r, l, counter; - unsigned int size; - - counter = 0; - kcr->names = calloc(counter+1, sizeof(char *)); - - kcr->uid = UID_INVALID; - kcr->gid = GID_INVALID; - kcr->label = NULL; - - if (kdbus_is_unique_id(name)) { - l = sizeof(unique_id); - unique_id = strtoull(name+3, NULL, 10); - size = sizeof(struct kdbus_cmd_info); - cmd = aligned_alloc(8, size); - memset(cmd, 0, sizeof(struct kdbus_cmd_info)); - cmd->id = unique_id; - cmd->size = size; - cmd->attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_SECLABEL | KDBUS_ATTACH_NAMES; - } else { - l = strlen(name) + 1; - size = offsetof(struct kdbus_cmd_info, items) + ALIGN8((l) + offsetof(struct kdbus_item, data)); - 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); + uint64_t res; + unsigned i = 2; + int c; + while (!(c = name[++i] - '0')); + res = c; + while ((c = (int)(name[++i]) - '0') > 0) + res = res*10 + c; + return res; } -static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct udesc* p_udesc) +static bool dbuspolicy_init_once(void) { struct passwd pwent; struct passwd *pwd; @@ -239,30 +145,28 @@ static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct close(attr_fd); - if (r < 0 || r >= (long int)sizeof(p_udesc->label)) /* read */ - return -1; - - snprintf(p_udesc->label, r + 1 /* additional byte for \0 */, "%s", buf); + if (r < 0 || r >= (long int)sizeof(g_udesc.label)) /* read */ + return true; - p_udesc->uid = getuid(); - p_udesc->gid = getgid(); + snprintf(g_udesc.label, r + 1 /* additional byte for \0 */, "%s", buf); + if (getpwuid_r(g_udesc.uid, &pwent, buf, sizeof(buf), &pwd)) + return true; - if (getpwuid_r(p_udesc->uid, &pwent, buf, sizeof(buf), &pwd)) - return -1; - - if (getgrgid_r(p_udesc->gid, &grent, buf, sizeof(buf), &gg)) - return -1; + if (getgrgid_r(g_udesc.gid, &grent, buf, sizeof(buf), &gg)) + return true; if (!pwd || !gg) return -1; - snprintf(p_udesc->user, sizeof(p_udesc->user), "%s", pwd->pw_name); - snprintf(p_udesc->group, sizeof(p_udesc->group), "%s", gg->gr_name); + snprintf(g_udesc.user, sizeof(g_udesc.user), "%s", pwd->pw_name); + snprintf(g_udesc.group, sizeof(g_udesc.group), "%s", gg->gr_name); - p_udesc->bus_type = bus_type; - p_udesc->conn = kc; + g_udesc.uid = getuid(); + g_udesc.gid = getgid(); - return 0; + __internal_init_once(); + + return false; } static int bus_path_resolve(const char *bus_path, char *resolved_path, unsigned resolved_path_size, unsigned int *bus_type) @@ -296,62 +200,62 @@ static int bus_path_resolve(const char *bus_path, char *resolved_path, unsigned return 0; } +static bool init_once_done = false; + DBUSPOLICY1_EXPORT void* dbuspolicy1_init(const char *bus_path) { - uint64_t hello_flags = 0; - uint64_t attach_flags_send = _KDBUS_ATTACH_ANY; - uint64_t attach_flags_recv = _KDBUS_ATTACH_ALL; - struct kconn* kc = NULL; - struct udesc* p_udesc = NULL; - unsigned int bus_type = -1; - char resolved_path[PATH_MAX] = { 0 }; - - if (bus_path_resolve(bus_path, resolved_path, sizeof(resolved_path), &bus_type) < 0) - goto err; - - kc = (struct kconn*) calloc(1, sizeof(struct kconn)); - if (!kc) - goto err; - - if ((kc->fd = kdbus_open_bus(resolved_path)) < 0) - goto err; - - if (kdbus_hello(kc, hello_flags, attach_flags_send, attach_flags_recv) < 0) - goto err; - - if (__internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY) < 0 - && __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY) < 0) - goto err; - - p_udesc = (struct udesc*)malloc(sizeof(struct udesc)); - if (!p_udesc) - goto err; - - if (dbuspolicy_init_udesc(kc, bus_type, p_udesc) < 0) - goto err; - - return p_udesc; - + unsigned int bus_type = -1; + char resolved_path[PATH_MAX] = { 0 }; + int rp, rs; + bool rb; + + _Static_assert(SYSTEM_BUS == 0, "SYSTEM_BUS not 0"); + _Static_assert(SESSION_BUS == 1, "SESSION_BUS not 0"); + + if (bus_path_resolve(bus_path, resolved_path, sizeof(resolved_path), &bus_type) < 0) + return NULL; + + if (bus_type) + bus_type = SESSION_BUS; + + rb = false; + pthread_mutex_lock(&g_mutex); + if (!init_once_done) { + init_once_done = true; + rb = dbuspolicy_init_once(); + } + pthread_mutex_unlock(&g_mutex); + if (rb) + goto err_close; + + if ((g_conn[bus_type].fd = kdbus_open_bus(resolved_path)) < 0) + goto err; + + if (kdbus_hello(bus_type, 0, _KDBUS_ATTACH_ALL, 0) < 0) + goto err_close; + + rp = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY); + rs = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY); + __internal_init_flush_logs(); + if ((rp & rs) < 0) /* when both negative */ + goto err_close; + + return &g_conn[bus_type]; + +err_close: + close(g_conn[bus_type].fd); err: - if (kc && kc->fd != -1) - close(kc->fd); - free(kc); - free(p_udesc); - - return NULL; + return NULL; } DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration) { - struct udesc* p_udesc = (struct udesc*)configuration; - if(p_udesc) { - close(p_udesc->conn->fd); - free(p_udesc->conn); - free(p_udesc); - p_udesc = NULL; - } + if (configuration) + close(((typeof(&g_conn[0]))configuration)->fd); } +static bool configuration_bus_type(struct kconn const *configuration) { return configuration != g_conn; } + /** * dbuspolicy1_can_send * @param: <> @@ -370,62 +274,103 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration, 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; - } - } + char const *label = NULL; + int r; + uid_t uid_n = UID_INVALID; + gid_t gid_n = GID_INVALID; + bool free_offset = false; + bool empty_names = true; + bool bus_type = configuration_bus_type(configuration); + union { + struct kdbus_cmd_info cmd_info; + struct kdbus_cmd_free cmd_free; + uint8_t _buffer_[sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(MAX_DBUS_NAME_LEN+1)]; + } cmd; + + __internal_enter(); + + if (DBUSPOLICY_MESSAGE_TYPE_SIGNAL != message_type || (destination && *destination)) { + struct kdbus_info *conn_info; + struct kdbus_item *item; + uintptr_t items_end; + + cmd.cmd_info.flags = 0; + cmd.cmd_info.attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_NAMES | (DBUSPOLICY_MESSAGE_TYPE_SIGNAL != message_type ? KDBUS_ATTACH_SECLABEL : 0); + + if (kdbus_is_unique_id(destination)) { + cmd.cmd_info.size = sizeof(cmd.cmd_info); + cmd.cmd_info.id = kdbus_unique_id(destination); + } else { + int l = strlen(destination); + cmd.cmd_info.size = sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(l+1); + cmd.cmd_info.id = 0; + cmd.cmd_info.items->size = offsetof(struct kdbus_item, data) + l+1; + cmd.cmd_info.items->type = KDBUS_ITEM_NAME; + *(uint64_t*)ALIGNDN8((uintptr_t)cmd.cmd_info.items->str + l) = 0; /* trailing zero + padding */ + memcpy(cmd.cmd_info.items->str, destination, l); + } + + r = ioctl(g_conn[bus_type].fd, KDBUS_CMD_CONN_INFO, &cmd.cmd_info); + if (r < 0) { + r = -errno; + goto end; + } + + cmd.cmd_free.size = sizeof(cmd.cmd_free); + /* flags already 0 */ + _Static_assert(sizeof(cmd.cmd_info.flags) == sizeof(cmd.cmd_free.flags), "cmd_info/cmd_free: flag sizeof differs"); + _Static_assert(offsetof(typeof(cmd.cmd_info), flags) == offsetof(typeof(cmd.cmd_free), flags), "cmd_info/cmd_free: flag offsetof differs"); + cmd.cmd_free.offset = cmd.cmd_info.offset; + + free_offset = true; + + conn_info = (struct kdbus_info *) ((uint8_t *) g_conn[bus_type].pool + cmd.cmd_info.offset); + items_end = (uintptr_t)conn_info + (unsigned)conn_info->size; + + _Static_assert((unsigned)KDBUS_ITEM_CREDS == KDBUS_ITEM_CREDS, "KDBUS_ITEM_CREDS not preserved when cast to unsigned"); + _Static_assert((unsigned)KDBUS_ITEM_SECLABEL == KDBUS_ITEM_SECLABEL, "KDBUS_ITEM_SECLABEL not preserved when cast to unsigned"); + _Static_assert((unsigned)KDBUS_ITEM_OWNED_NAME == KDBUS_ITEM_OWNED_NAME, "KDBUS_ITEM_OWNED_NAME not preserved when cast to unsigned"); + + for (item = conn_info->items; (uintptr_t)item < items_end; item = (typeof(item))ALIGN8((uintptr_t)item + (unsigned)item->size)) + switch ((unsigned)item->type) + { + case KDBUS_ITEM_CREDS: + uid_n = item->creds.euid; + gid_n = item->creds.egid; + break; + case KDBUS_ITEM_SECLABEL: + label = item->str; + break; + case KDBUS_ITEM_OWNED_NAME: + empty_names = false; + if (r <= 0) + r = __internal_can_send(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, item->name.name, path, interface, member, message_type); + 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 || !(*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; - } + r = __internal_can_send(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, destination, path, interface, member, message_type); + + if (r > 0 && message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) { + char gid[25], uid[25]; + char const *ptr; + snprintf(uid, sizeof(uid), "%lu", (unsigned long)uid_n); + snprintf(gid, sizeof(gid), "%lu", (unsigned long)gid_n); + + FOREACH_STRV_DEFAULT(ptr, sender) + if (0 < (r = __internal_can_recv(bus_type, uid, gid, label, ptr, path, interface, member, message_type))) + break; } - free(name); - kcreds_free(p_creds); + if (free_offset) + ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &cmd.cmd_free); - if(rs > 0 && rr > 0) { r = 1; } - if(rs < 0 || rr < 0) { r = -1; } +end: + __internal_exit(); return r; } + /** * dbuspolicy1_can_send * @param: <> @@ -447,55 +392,29 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration, 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 const *ptr; + int r; 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 || !(*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); - name = NULL; - - if(message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) { - rr = 0; - - if (!sender || !(*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); + bool bus_type = configuration_bus_type(configuration); + + snprintf(uid, sizeof(uid), "%lu", (unsigned long)sender_uid); + snprintf(gid, sizeof(gid), "%lu", (unsigned long)sender_gid); + + __internal_enter(); - if(rs > 0 && rr > 0) { r = 1; } - if(rs < 0 || rr < 0) { r = -1; } + FOREACH_STRV_DEFAULT(ptr, destination) + if (0 < (r = __internal_can_send(bus_type, uid, gid, sender_label, ptr, path, interface, member, message_type))) + break; + + if (r > 0 && message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) + FOREACH_STRV_DEFAULT(ptr, sender) + if (0 < (r = __internal_can_recv(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, ptr, path, interface, member, message_type))) + break; + + __internal_exit(); return r; } - /** * dbuspolicy1_can_send * @param: <> @@ -505,6 +424,10 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration, **/ 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); + int r; + bool bus_type = configuration_bus_type(configuration); + __internal_enter(); + r = __internal_can_own(bus_type, g_udesc.user, g_udesc.group, service); + __internal_exit(); + return r; } -- 2.7.4 From 62b1c6efb1952ccdd416433f3dbb1c30cce1c51b Mon Sep 17 00:00:00 2001 From: Kazimierz Krosman Date: Fri, 27 May 2016 11:24:06 +0200 Subject: [PATCH 13/16] Allow incremental build Change-Id: Id8c02912d1ddf0d3a86bb5e5f999a1dbce035943 --- packaging/libdbuspolicy.spec | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packaging/libdbuspolicy.spec b/packaging/libdbuspolicy.spec index 591b048..3234296 100644 --- a/packaging/libdbuspolicy.spec +++ b/packaging/libdbuspolicy.spec @@ -28,11 +28,7 @@ development files. cp %{SOURCE1001} . %build -./autogen.sh -./configure \ - --libdir=%{_libdir} \ - --prefix=/usr - +%reconfigure --libdir=%{_libdir} --prefix=/usr make %install -- 2.7.4 From 32bc86464494593a4676cf4548f5ac845bb5269e Mon Sep 17 00:00:00 2001 From: Kazimierz Krosman Date: Fri, 20 May 2016 13:15:10 +0200 Subject: [PATCH 14/16] Tree policy engine decision checker replacement Tree policy engine decision checker was replaced by naive search algorithm. For each check call, libdbuspolicy iterate via policy rules in the reverse order. First rule that matches request is used to return decision. Multiple sender's and receiver's names are proceeded during search procedure (algorithm try to match current rule for each name). Previous version search all database for each name. Added unit tests (make check) Change-Id: Ie78ae8eec285a7042d275d02333372bca4d76d28 --- Makefile.am | 51 +++- configure.ac | 7 + packaging/libdbuspolicy.spec | 6 +- src/dbuspolicy1/libdbuspolicy1.h | 4 +- src/internal/cynara.cpp | 72 +++++ src/internal/cynara.hpp | 86 ++---- src/internal/cynara_mockup.cpp | 27 ++ src/internal/internal.cpp | 98 ++++--- src/internal/internal.h | 54 ++-- src/internal/naive_policy_checker.cpp | 144 ++++++++++ src/internal/naive_policy_checker.hpp | 61 ++++ src/internal/naive_policy_db.cpp | 145 ++++++++++ src/internal/naive_policy_db.hpp | 86 ++++++ src/internal/policy.cpp | 528 ++++++++++++++++++++++++++++++++++ src/internal/policy.hpp | 194 +++++++++++++ src/internal/tslog.cpp | 17 ++ src/internal/tslog.hpp | 14 +- src/internal/xml_parser.cpp | 3 + src/internal/xml_parser.hpp | 48 +--- src/libdbuspolicy1.c | 92 +++--- src/libdbuspolicy1.sym | 11 +- src/test-libdbuspolicy1-method.cpp | 82 ++++++ src/test-libdbuspolicy1-ownership.cpp | 71 +++++ src/test-libdbuspolicy1-signal.cpp | 51 ++++ tests/system.conf | 83 ++++++ tests/system.d/cynara.test.conf | 10 + tests/system.d/methods.test.conf | 41 +++ tests/system.d/ownerships.test.conf | 35 +++ tests/system.d/signals.test.conf | 13 + 29 files changed, 1891 insertions(+), 243 deletions(-) create mode 100644 src/internal/cynara.cpp create mode 100644 src/internal/cynara_mockup.cpp create mode 100644 src/internal/naive_policy_checker.cpp create mode 100644 src/internal/naive_policy_checker.hpp create mode 100644 src/internal/naive_policy_db.cpp create mode 100644 src/internal/naive_policy_db.hpp create mode 100644 src/internal/policy.cpp create mode 100644 src/internal/policy.hpp create mode 100644 src/internal/tslog.cpp create mode 100644 src/internal/xml_parser.cpp create mode 100644 src/test-libdbuspolicy1-method.cpp create mode 100644 src/test-libdbuspolicy1-ownership.cpp create mode 100644 src/test-libdbuspolicy1-signal.cpp create mode 100644 tests/system.conf create mode 100644 tests/system.d/cynara.test.conf create mode 100644 tests/system.d/methods.test.conf create mode 100644 tests/system.d/ownerships.test.conf create mode 100644 tests/system.d/signals.test.conf diff --git a/Makefile.am b/Makefile.am index d457aaa..12f16c5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,9 +20,9 @@ AM_CFLAGS = ${my_CFLAGS} \ AM_LDFLAGS = \ -Wl,--gc-sections \ -Wl,--as-needed \ - $(CYNARA_CFLAGS) \ -$(CYNARA_LIBS)\ - -pthread + $(CYNARA_CFLAGS) \ + $(CYNARA_LIBS)\ + -pthread SED_PROCESS = \ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(SED) \ @@ -46,7 +46,13 @@ lib_LTLIBRARIES = src/libdbuspolicy1.la src_libdbuspolicy1_la_SOURCES =\ src/libdbuspolicy1-private.h \ src/libdbuspolicy1.c \ - src/internal/internal.cpp + src/internal/internal.cpp \ + src/internal/naive_policy_checker.cpp \ + src/internal/naive_policy_db.cpp \ + src/internal/policy.cpp \ + src/internal/xml_parser.cpp \ + src/internal/tslog.cpp \ + src/internal/cynara.cpp EXTRA_DIST += src/libdbuspolicy1.sym @@ -61,8 +67,37 @@ pkgconfig_DATA = src/libdbuspolicy1.pc EXTRA_DIST += src/libdbuspolicy1.pc.in CLEANFILES += src/libdbuspolicy1.pc -TESTS = src/test-libdbuspolicy1 +TESTS = src/test-libdbuspolicy1-ownership \ + src/test-libdbuspolicy1-signal \ + src/test-libdbuspolicy1-method + +check_PROGRAMS = src/test-libdbuspolicy1-ownership \ + src/test-libdbuspolicy1-signal \ + src/test-libdbuspolicy1-method + +src_test_libdbuspolicy1_ownership_SOURCES = src/test-libdbuspolicy1-ownership.cpp +src_test_libdbuspolicy1_signal_SOURCES = src/test-libdbuspolicy1-signal.cpp +src_test_libdbuspolicy1_method_SOURCES = src/test-libdbuspolicy1-method.cpp + +noinst_LTLIBRARIES = src/libinternal.a +src_libinternal_a_SOURCES =\ + src/libdbuspolicy1-private.h \ + src/internal/internal.cpp \ + src/libdbuspolicy1.c \ + src/internal/naive_policy_checker.cpp \ + src/internal/naive_policy_db.cpp \ + src/internal/policy.cpp \ + src/internal/xml_parser.cpp \ + src/internal/tslog.cpp \ + src/internal/cynara_mockup.cpp + +libinternal_a_LIBADD = $(CYNARA_LIBS) + +src_test_libdbuspolicy1_ownership_LDADD = $(CYNARA_LIBS) \ + src/libinternal.a + +src_test_libdbuspolicy1_signal_LDADD = $(CYNARA_LIBS) \ + src/libinternal.a -check_PROGRAMS = src/test-libdbuspolicy1 -src_test_libdbuspolicy1_SOURCES = src/test-libdbuspolicy1.c -src_test_libdbuspolicy1_LDADD = src/libdbuspolicy1.la $(CYNARA_LIBS) +src_test_libdbuspolicy1_method_LDADD = $(CYNARA_LIBS) \ + src/libinternal.a diff --git a/configure.ac b/configure.ac index 440b0c2..8e9a190 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,13 @@ AS_IF([test "x$enable_debug" = "xyes"], [ AC_DEFINE(ENABLE_DEBUG, [1], [Debug messages.]) ]) +AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests], [Add API function that allows to change credentials during execution]), + [with_tests=yes], + with_tests=no) +if test "x$with_tests" = "xyes"; then + AC_DEFINE(LIBDBUSPOLICY_TESTS_API, 1, [Define if tests are enabled]) +fi + AC_CHECK_FUNCS([ \ __secure_getenv \ secure_getenv\ diff --git a/packaging/libdbuspolicy.spec b/packaging/libdbuspolicy.spec index 3234296..9713e86 100644 --- a/packaging/libdbuspolicy.spec +++ b/packaging/libdbuspolicy.spec @@ -28,8 +28,12 @@ development files. cp %{SOURCE1001} . %build -%reconfigure --libdir=%{_libdir} --prefix=/usr +%reconfigure --libdir=%{_libdir} --prefix=/usr \ +%if 0%{?test_version} +--enable-tests +%endif make +make check %install make DESTDIR=%{buildroot} install diff --git a/src/dbuspolicy1/libdbuspolicy1.h b/src/dbuspolicy1/libdbuspolicy1.h index ae9b0c2..cc0040e 100644 --- a/src/dbuspolicy1/libdbuspolicy1.h +++ b/src/dbuspolicy1/libdbuspolicy1.h @@ -26,8 +26,8 @@ extern "C" { #define SYSTEM_BUS_CONF_FILE_PRIMARY "/usr/share/dbus-1/system.conf" #define SESSION_BUS_CONF_FILE_PRIMARY "/usr/share/dbus-1/session.conf" -#define SYSTEM_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/system-local.conf" -#define SESSION_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/session-local.conf" +#define SYSTEM_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/system.conf" +#define SESSION_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/session.conf" /** used when check policy for message prepared to send */ #define DBUSPOLICY_DIRECTION_SENDING 0 diff --git a/src/internal/cynara.cpp b/src/internal/cynara.cpp new file mode 100644 index 0000000..ce191c0 --- /dev/null +++ b/src/internal/cynara.cpp @@ -0,0 +1,72 @@ +#include "cynara.hpp" +#include "libdbuspolicy1-private.hpp" +#include +#include +#include +#include + +using namespace _ldp_cynara; + +pthread_mutex_t Cynara::__mutex = PTHREAD_MUTEX_INITIALIZER; + +Cynara::Cynara() : __inited(false) { +} + +Cynara::~Cynara() { + int r = cynara_finish(__cynara); + if (r != CYNARA_API_SUCCESS) { + //TODO: reaction + //destructor is usually called when proccess is closed + //there is no good way to serve this case. + } +} + +bool Cynara::init() { + if (!__inited) { + int r = cynara_initialize(&__cynara, NULL); + if (r != CYNARA_API_SUCCESS) + return false; + + __session = cynara_session_from_pid(getpid()); + __inited = true; + } + return true; +} + +Cynara& Cynara::getInstance() { + static Cynara __self; + return __self; +} + +CynaraResult Cynara::check(const char* label, const char* privilege, const char* uid) { + + const char* _label=""; + const char* _uid=""; + const char* _privilege=""; + CynaraResult ret; + + if (label) + _label=label; + + if (privilege) + _privilege=privilege; + + if (uid) + _uid=uid; + + pthread_mutex_lock(&__mutex); + Cynara& c = Cynara::getInstance(); + if (!c.init()) + ret = CynaraResult::ERROR_INIT; + else { + int r = cynara_check (c.__cynara, _label, c.__session, _uid, _privilege); + if (r == CYNARA_API_ACCESS_ALLOWED) + ret = CynaraResult::ALLOW; + else if (r == CYNARA_API_ACCESS_DENIED) + ret = CynaraResult::DENY; + else + ret = CynaraResult::ERROR_CHECK; + } + pthread_mutex_unlock(&__mutex); + return ret; +} diff --git a/src/internal/cynara.hpp b/src/internal/cynara.hpp index 7f74f35..684e2a9 100644 --- a/src/internal/cynara.hpp +++ b/src/internal/cynara.hpp @@ -19,73 +19,31 @@ #include #include +#include + +#include namespace _ldp_cynara { + enum class CynaraResult : uint8_t { + ALLOW, + DENY, + ERROR_CHECK, + ERROR_INIT + }; 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"); - } + private: + static pthread_mutex_t __mutex; + cynara* __cynara; + const char* __session; + bool __inited; + Cynara(); + ~Cynara(); + + bool init(); + static Cynara& getInstance(); + public: + + static CynaraResult check(const char* label, const char* privilege, const char* uid); }; } //namespace #endif diff --git a/src/internal/cynara_mockup.cpp b/src/internal/cynara_mockup.cpp new file mode 100644 index 0000000..4392df2 --- /dev/null +++ b/src/internal/cynara_mockup.cpp @@ -0,0 +1,27 @@ +#include "cynara.hpp" +#include "libdbuspolicy1-private.hpp" +#include +#include +#include + +using namespace _ldp_cynara; + +Cynara::Cynara() { +} + +Cynara::~Cynara() { +} + +bool Cynara::init() { + return true; +} + +Cynara& Cynara::getInstance() { + static Cynara __self; + return __self; +} + + +CynaraResult Cynara::check(const char* label, const char* privilege, const char* uid) { + return CynaraResult::ALLOW; +} diff --git a/src/internal/internal.cpp b/src/internal/internal.cpp index e26c510..2b030fc 100644 --- a/src/internal/internal.cpp +++ b/src/internal/internal.cpp @@ -18,40 +18,45 @@ #include #include #include "xml_parser.hpp" +#include "policy.hpp" +#include "naive_policy_checker.hpp" +#include "internal.h" -#ifdef __cplusplus -extern "C" { -#endif +#include "../libdbuspolicy1-private.h" + +static _ldp_xml_parser::NaivePolicyChecker policy_checker; static const char* get_str(const char* const szstr) { return (szstr != NULL) ? szstr : ""; } -static std::string get_strv(const char *s) { - unsigned i = 0; +static const char** get_strv(const char *s, const char** result) { + int i = 0; + unsigned k = 0; if (s) { - i = -1; - char c; - while ((c = s[++i]) && ' ' != c); + while (s[i] && k < KDBUS_CONN_MAX_NAMES + 1) { + char c; + while ((c = s[i++]) && ' ' != c); + result[k++] = s; + s += i; + i = 0; + } + if (k >= KDBUS_CONN_MAX_NAMES + 1) + return NULL; + if (k) + result[k++] = NULL; } - return std::string{s, i}; -} - -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; + if (!k) { + result[0] = ""; + result[1] = NULL; + } + return result; } int __internal_init(bool bus_type, const char* const config_name) { _ldp_xml_parser::XmlParser p; + p.registerAdapter(policy_checker.generateAdapter()); auto err = p.parse_policy(bus_type, get_str(config_name)); return err.get(); } @@ -84,8 +89,8 @@ void __internal_exit() } int __internal_can_send(bool bus_type, - const char* const user, - const char* const group, + const uid_t user, + const gid_t group, const char* const label, const char* const destination, const char* const path, @@ -93,14 +98,32 @@ int __internal_can_send(bool bus_type, const char* const member, int type) { - _ldp_xml_parser::XmlParser p; - auto err = p.can_send(bus_type, get_str(user), get_str(group), get_str(label), get_strv(destination), get_str(path), get_str(interface), get_str(member), get_message_type(type)); - return err.get(); + const char* names[KDBUS_CONN_MAX_NAMES+1]; + const char** ns = get_strv(destination, names); + if (!ns) { + if (tslog::verbose()) + std::cout << "Destination too long: "<(type), _ldp_xml_parser::MessageDirection::SEND); +} + +int __internal_can_send_multi_dest(bool bus_type, + const uid_t user, + const gid_t group, + const char* const label, + const char** const destination, + const char* const path, + const char* const interface, + const char* const member, + int type) +{ + return policy_checker.check(bus_type, user, group, label, destination, interface, member, path, static_cast<_ldp_xml_parser::MessageType>(type), _ldp_xml_parser::MessageDirection::SEND); } int __internal_can_recv(bool bus_type, - const char* const user, - const char* const group, + const uid_t user, + const gid_t group, const char* const label, const char* const sender, const char* const path, @@ -108,21 +131,16 @@ int __internal_can_recv(bool bus_type, const char* const member, int type) { - _ldp_xml_parser::XmlParser p; - auto err = p.can_recv(bus_type, get_str(user), get_str(group), get_str(label), get_strv(sender), get_str(path), get_str(interface), get_str(member), get_message_type(type)); - return err.get(); + const char* names[KDBUS_CONN_MAX_NAMES+1]; + const char** ns = get_strv(sender, names); + return policy_checker.check(bus_type, user, group, label, ns, interface, member, path, static_cast<_ldp_xml_parser::MessageType>(type), _ldp_xml_parser::MessageDirection::RECEIVE); } int __internal_can_own(bool bus_type, - const char* const user, - const char* const group, + const uid_t user, + const gid_t group, + const char* const label, const char* const service) { - _ldp_xml_parser::XmlParser p; - auto err = p.can_own(bus_type, get_str(user), get_str(group), get_str(service)); - return err.get(); + return policy_checker.check(bus_type, user, group, label, service); } - -#ifdef __cplusplus -} /* extern "C" */ -#endif diff --git a/src/internal/internal.h b/src/internal/internal.h index 0914abe..270b13a 100644 --- a/src/internal/internal.h +++ b/src/internal/internal.h @@ -21,7 +21,9 @@ extern "C" { #endif -int __internal_init(unsigned int bus_type, const char* const config_name); +#define KDBUS_CONN_MAX_NAMES 256 + +int __internal_init(bool bus_type, const char* const config_name); void __internal_init_once(void); extern pthread_mutex_t g_mutex; void __internal_init_flush_logs(void); @@ -29,30 +31,40 @@ void __internal_enter(void); void __internal_exit(void); int __internal_can_send(bool 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); + const uid_t user, + const gid_t 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_send_multi_dest(bool bus_type, + const uid_t user, + const gid_t 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(bool 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); + uid_t user, + gid_t 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(bool bus_type, - const char* const user, - const char* const group, - const char* const service); - + uid_t user, + gid_t group, + const char* const label, + const char* const service); #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/internal/naive_policy_checker.cpp b/src/internal/naive_policy_checker.cpp new file mode 100644 index 0000000..5cf9d05 --- /dev/null +++ b/src/internal/naive_policy_checker.cpp @@ -0,0 +1,144 @@ +#include "naive_policy_checker.hpp" +#include "cynara.hpp" +#include "tslog.hpp" +using namespace _ldp_xml_parser; + +DbAdapter& NaivePolicyChecker::generateAdapter() { + if (!m_adapter) + m_adapter = new DbAdapter (m_bus_db[0], m_bus_db[1]); + + return *m_adapter; +} + +Decision NaivePolicyChecker::checkPolicy(const NaivePolicyDb::Policy& policy, + const Item& item, + const char*& privilege) +{ + if (tslog::verbose()) { + char tmp[MAX_LOG_LINE]; + const char* i_str = item.toString(tmp); + std::cout << "checkpolicy for: " << i_str <toString(tmp); + std::cout << "-readed: " << i_str <match(&item)) { + if (tslog::verbose()) { + char tmp[MAX_LOG_LINE]; + const char* i_str = i->toString(tmp); + std::cout << "-matched: " << i_str <getPrivilege(); + return i->getDecision(); + } + } + + return Decision::ANY; +} + +NaivePolicyDb& NaivePolicyChecker::getPolicyDb(bool type) { + return m_bus_db[type]; +} + +bool NaivePolicyChecker::parseDecision(Decision decision, + uid_t uid, + const char* label, + const char* privilege) { + + char uid_str[17]; + if (tslog::verbose()) { + std::cout<<"----Decision made\n"; + } + switch (decision) + { + case Decision::ALLOW: + return true; + case Decision::ANY: + case Decision::DENY: + return false; + case Decision::CHECK: + std::sprintf(uid_str, "%lu", (unsigned long)uid); + return _ldp_cynara::Cynara::check(label, privilege, uid_str) == _ldp_cynara::CynaraResult::ALLOW; + } + + return false; +} + +NaivePolicyChecker::~NaivePolicyChecker() { + delete m_adapter; +} + +bool NaivePolicyChecker::checkItem(bool bus_type, uid_t uid, gid_t gid, const char* label, const Item& item) { + NaivePolicyDb& policy_db = getPolicyDb(bus_type); + ItemType type = item.getType(); + Decision ret = Decision::ANY; + const char* privilege; + const NaivePolicyDb::Policy* curr_policy = NULL; + + if (ret == Decision::ANY) { + curr_policy = policy_db.getPolicy(type, PolicyType::CONTEXT, PolicyTypeValue(ContextType::MANDATORY)); + if (curr_policy) + ret = checkPolicy(*curr_policy, item, privilege); + } + + if (ret == Decision::ANY) { + curr_policy = policy_db.getPolicy(type, PolicyType::USER, PolicyTypeValue(uid)); + if (curr_policy) + ret = checkPolicy(*curr_policy, item, privilege); + } + + if (ret == Decision::ANY) { + curr_policy = policy_db.getPolicy(type, PolicyType::GROUP, PolicyTypeValue(gid)); + if (curr_policy) + ret = checkPolicy(*curr_policy, item, privilege); + } + + if (ret == Decision::ANY) { + curr_policy = policy_db.getPolicy(type, PolicyType::CONTEXT, PolicyTypeValue(ContextType::DEFAULT)); + if (curr_policy) + ret = checkPolicy(*curr_policy, item, privilege); + } + + if (ret != Decision::ANY) + return parseDecision(ret, uid, label, privilege); + else + return false; +} + +bool NaivePolicyChecker::check(bool bus_type, + uid_t uid, + gid_t gid, + const char* const label, + const char* const name) { + try { + ItemOwn item = ItemOwn(name); + return checkItem(bus_type, uid, gid, label, item); + } catch (std::runtime_error& err) { + if (tslog::enabled()) + std::cout << err.what() << std::endl; + } + return false; +} + +bool NaivePolicyChecker::check(bool bus_type, + uid_t uid, + gid_t gid, + const char* const label, + const char** const names, + const char* const interface, + const char* const member, + const char* const path, + MessageType message_type, + MessageDirection message_dir) { + try { + ItemSendReceive item = ItemSendReceive(names, interface, member, path, message_type, message_dir); + return checkItem(bus_type, uid, gid, label, item); + } catch (std::runtime_error& err) { + if (tslog::enabled()) + std::cout << err.what() << std::endl; + } + return false; +} diff --git a/src/internal/naive_policy_checker.hpp b/src/internal/naive_policy_checker.hpp new file mode 100644 index 0000000..4f6478f --- /dev/null +++ b/src/internal/naive_policy_checker.hpp @@ -0,0 +1,61 @@ +/* + * 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 _NAIVE_DECISIONER_H +#define _NAIVE_DECISIONER_H + +#include "policy.hpp" +#include "naive_policy_db.hpp" + +namespace _ldp_xml_parser +{ + class NaivePolicyChecker { + private: + NaivePolicyDb m_bus_db[2]; + DbAdapter* m_adapter; + NaivePolicyDb& getPolicyDb(bool type); + Decision checkPolicy(const NaivePolicyDb::Policy& policy, + const Item& item, + const char*& privilege); + bool parseDecision(Decision decision, + uid_t uid, + const char* label, + const char* privilege); + bool checkItem(bool bus_type, + uid_t uid, + gid_t gid, + const char* label, + const Item& item); + public: + ~NaivePolicyChecker(); + DbAdapter& generateAdapter(); + bool check(bool bus_type, + uid_t uid, + gid_t gid, + const char* const label, + const char* const name); + bool check(bool bus_type, + uid_t uid, + gid_t gid, + const char* const label, + const char** const names, + const char* const interface, + const char* const member, + const char* const path, + MessageType message_type, + MessageDirection message_dir); + }; +} +#endif diff --git a/src/internal/naive_policy_db.cpp b/src/internal/naive_policy_db.cpp new file mode 100644 index 0000000..ae3c571 --- /dev/null +++ b/src/internal/naive_policy_db.cpp @@ -0,0 +1,145 @@ +#include "naive_policy_db.hpp" +#include +#include "tslog.hpp" + +using namespace _ldp_xml_parser; + +NaivePolicyDb::Policy::PolicyConstIterator::PolicyConstIterator(const std::vector& items, int position) + : m_items(items), m_index(position) { +} + + Item* const& NaivePolicyDb::Policy::PolicyConstIterator::operator*() const { + return m_items[m_index]; +} + +NaivePolicyDb::Policy::PolicyConstIterator& NaivePolicyDb::Policy::PolicyConstIterator::operator++() { + if (m_index >= 0) + --m_index; + return *this; +} + +bool NaivePolicyDb::Policy::PolicyConstIterator::operator!=(const PolicyConstIterator& it) const { + return m_index != it.m_index; +} + +NaivePolicyDb::Policy::PolicyIterator::PolicyIterator(std::vector& items, int position) + : m_items(items), m_index(position) { +} + +Item*& NaivePolicyDb::Policy::PolicyIterator::operator*() { + return m_items[m_index]; +} + +NaivePolicyDb::Policy::PolicyIterator& NaivePolicyDb::Policy::PolicyIterator::operator++() { + if (m_index >= 0) + --m_index; + return *this; +} + +bool NaivePolicyDb::Policy::PolicyIterator::operator!=(const PolicyIterator& it) const { + return m_index != it.m_index; +} + +NaivePolicyDb::Policy::PolicyIterator NaivePolicyDb::Policy::begin() { + int s = m_items.size() - 1; + return NaivePolicyDb::Policy::PolicyIterator(m_items, s); +} +NaivePolicyDb::Policy::PolicyIterator NaivePolicyDb::Policy::end() { + return NaivePolicyDb::Policy::PolicyIterator(m_items, -1); +} +NaivePolicyDb::Policy::PolicyConstIterator NaivePolicyDb::Policy::begin() const { + int s = m_items.size() - 1; + return NaivePolicyDb::Policy::PolicyConstIterator(m_items, s); +} +NaivePolicyDb::Policy::PolicyConstIterator NaivePolicyDb::Policy::end() const { + return NaivePolicyDb::Policy::PolicyConstIterator(m_items, -1); +} + +void NaivePolicyDb::Policy::addItem(Item* item) { + m_items.push_back(item); +} + +NaivePolicyDb::~NaivePolicyDb() { + +} + +const NaivePolicyDb::Policy* NaivePolicyDb::getPolicy(const ItemType item_type, + const PolicyType policy_type, + const PolicyTypeValue policy_type_value) { + PolicyTypeSet* set = NULL; + switch (item_type) { + case ItemType::OWN: + set = &m_own_set; + break; + case ItemType::SEND: + set = &m_send_set; + break; + case ItemType::RECEIVE: + set = &m_receive_set; + break; + default: + break; + } + if (tslog::enabled()) + std::cout<<"---policy_type ="; + switch (policy_type) { + case PolicyType::CONTEXT: + if (tslog::enabled()) + std::cout << "CONTEXT =" << (int)policy_type_value.context << std::endl; + return &set->context[static_cast(policy_type_value.context) ]; + case PolicyType::USER: + if (tslog::enabled()) + std::cout << "USER =" << (int)policy_type_value.user << std::endl; + return &set->user[policy_type_value.user]; + case PolicyType::GROUP: + if (tslog::enabled()) + std::cout << "GROUP = " << (int)policy_type_value.group << std::endl; + return &set->group[policy_type_value.group]; + } + if (tslog::enabled()) + std::cout << "NO POLICY\n"; + return NULL; +} + +void NaivePolicyDb::addItem(NaivePolicyDb::PolicyTypeSet& set, + const PolicyType policy_type, + const PolicyTypeValue policy_type_value, + Item* const item) { + switch (policy_type) { + case PolicyType::CONTEXT: + set.context[static_cast(policy_type_value.context)].addItem(item); + break; + case PolicyType::USER: + set.user[policy_type_value.user].addItem(item); + break; + case PolicyType::GROUP: + set.group[policy_type_value.group].addItem(item); + break; + } +} + +void NaivePolicyDb::addItem(const PolicyType policy_type, + const PolicyTypeValue policy_type_value, + Item* const item) { + const ItemSendReceive* it; + + if (tslog::enabled()) { + char tmp[MAX_LOG_LINE]; + const char* i_str = item->toString(tmp); + std::cout<<"Add item: "<< i_str <(item)) + addItem(m_own_set, policy_type, policy_type_value, item); + else if ((it = dynamic_cast(item))) { + const MessageDirection dir = it->getDirection(); + if (dir == MessageDirection::SEND) + addItem(m_send_set, policy_type, policy_type_value, item); + else if (dir == MessageDirection::RECEIVE) + addItem(m_receive_set, policy_type, policy_type_value, item); + else { + addItem(m_send_set, policy_type, policy_type_value, item); + addItem(m_receive_set, policy_type, policy_type_value, item); + } + } +} diff --git a/src/internal/naive_policy_db.hpp b/src/internal/naive_policy_db.hpp new file mode 100644 index 0000000..015eb13 --- /dev/null +++ b/src/internal/naive_policy_db.hpp @@ -0,0 +1,86 @@ +/* + * 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 _NAIVE_DB_H +#define _NAIVE_DB_H + +#include +#include +#include "policy.hpp" + +namespace _ldp_xml_parser +{ + class NaivePolicyDb { + public: + class Policy { + private: + std::vector m_items; + public: + class PolicyConstIterator { + private: + const std::vector& m_items; + int m_index; + public: + PolicyConstIterator(const std::vector& items, int position); + Item* const& operator*() const; + PolicyConstIterator& operator++(); + bool operator!=(const PolicyConstIterator& it) const; + }; + + class PolicyIterator { + private: + std::vector& m_items; + int m_index; + public: + PolicyIterator(std::vector& items, int position); + Item*& operator*(); + PolicyIterator& operator++(); + bool operator!=(const PolicyIterator& it) const; + }; + + PolicyIterator begin(); + PolicyIterator end(); + PolicyConstIterator begin() const; + PolicyConstIterator end() const; + void addItem(Item* item); + }; + + ~NaivePolicyDb(); + + const Policy* getPolicy(const ItemType item_type, + const PolicyType policy_type, + const PolicyTypeValue policy_type_value); + + void addItem(const PolicyType policy_type, + const PolicyTypeValue policy_type_value, + Item* const item); + private: + struct PolicyTypeSet { + Policy context[static_cast(ContextType::MAX)]; + std::map user; + std::map group; + }; + + PolicyTypeSet m_own_set; + PolicyTypeSet m_send_set; + PolicyTypeSet m_receive_set; + void addItem(PolicyTypeSet& set, + const PolicyType policy_type, + const PolicyTypeValue policy_type_value, + Item* const item); + }; +} + +#endif diff --git a/src/internal/policy.cpp b/src/internal/policy.cpp new file mode 100644 index 0000000..dcbde77 --- /dev/null +++ b/src/internal/policy.cpp @@ -0,0 +1,528 @@ +#include "policy.hpp" +#include "naive_policy_db.hpp" +//#include "tslog.hpp" +#include +#include +#include +#include + +using namespace _ldp_xml_parser; + +static const char* message_type[] = { "ANY", "METHOD_CALL", "METHOD_RETURN", "ERROR", "SIGNAL"}; +static const char* message_dir[] = { "ANY", "SEND", "RECEIVE"}; +static const char* message_decision[] = {"NO_DECISION", "ALLOW", "DENY", "CHECK"}; + +static bool __compare_str(const char* a, const char* b) { + + while(*a && *b && *a != ' ' && *b != ' ') { + if (*a != *b) + return false; + a++; b++; + } + return ((*a == 0 || *a == ' ') && (*b == 0 || *b != ' ')); +} + +static MessageType __str_to_message_type(const char* str) { + if (!std::strcmp(str, "method_call")) + return MessageType::METHOD_CALL; + else if (!std::strcmp(str, "method_return")) + return MessageType::METHOD_RETURN; + else if (!std::strcmp(str, "error")) + return MessageType::ERROR; + else if (!std::strcmp(str, "signal")) + return MessageType::SIGNAL; + + return MessageType::ANY; +} + +static inline const char* __message_type_to_str(MessageType type) { + return message_type[static_cast(type)]; +} + +static inline const char* __message_dir_to_str(MessageDirection type) { + return message_dir[static_cast(type)]; +} + +static inline const char* __decision_to_str(Decision dec) { + return message_decision[static_cast(dec)]; +} + +DbAdapter::DbAdapter(NaivePolicyDb& system, NaivePolicyDb& session) + : __system_db(system), __session_db(session), __attr(false), __tag_state(NONE) { +} + +uid_t DbAdapter::convertToUid(const char* user) { + errno = 0; + long val = std::strtol(user, NULL, 10); + if (!errno) + return (uid_t)val; + + struct passwd pwent; + struct passwd *pwd; + char buf[1024]; + if (getpwnam_r(user, &pwent, buf, sizeof(buf), &pwd) && pwd) + return (uid_t)-1; + + return pwd->pw_uid; +} + +gid_t DbAdapter::convertToGid(const char* group) { + errno = 0; + long val = std::strtol(group, NULL, 10); + if (!errno) + return (gid_t)val; + struct group grent; + struct group *gg; + char buf[1024]; + if (getgrnam_r(group, &grent, buf, sizeof(buf), &gg) && gg) + return (gid_t)-1; + + return gg->gr_gid; +} + +static bool field_has(const boost::property_tree::ptree::value_type& v, const std::string& substr) { + return (v.first.find(substr) != std::string::npos); +} + +void DbAdapter::updateDecision(const boost::property_tree::ptree::value_type& v, + PolicyType& policy_type, + PolicyTypeValue& policy_type_value, + state& t, + bool& attr) { + const char* value = NULL; + if(v.first == "allow" && t == POLICY) { + __builder.reset(); + __builder.addDecision(Decision::ALLOW); + t = ALLOW_DENY_CHECK; + attr = false; + } else if(v.first == "deny" && t == POLICY) { + __builder.reset(); + __builder.addDecision(Decision::DENY); + t = ALLOW_DENY_CHECK; + attr = false; + } else if(v.first == "check" && t == POLICY) { + __builder.reset(); + __builder.addDecision(Decision::CHECK); + t = ALLOW_DENY_CHECK; + attr = false; + } else if(v.first == "") { + attr = true; + } else if(attr && t == POLICY) { + if (v.second.data() != "*") + value = v.second.data().c_str(); + + if(v.first == "context") { + if(std::strcmp(value,"mandatory") == 0 ) { + policy_type = PolicyType::CONTEXT; + policy_type_value.context = ContextType::MANDATORY; + } else if(std::strcmp(value, "default") == 0) { + policy_type = PolicyType::CONTEXT; + policy_type_value.context = ContextType::DEFAULT; + } + } else if(v.first == "user") { + policy_type = PolicyType::USER; + policy_type_value.user = convertToUid(value); + } else if(v.first == "group") { + policy_type = PolicyType::GROUP; + policy_type_value.group = convertToGid(value); + } else { + attr = false; + t = NONE; + } + } else if (attr && t == ALLOW_DENY_CHECK) { + if (v.second.data() != "*") + value = v.second.data().c_str(); + + if(field_has(v, "send_")) { + __builder.addDirection(MessageDirection::SEND); + } else if(field_has(v, "receive_")) { + __builder.addDirection(MessageDirection::RECEIVE); + } else if(v.first == "own") { + __builder.addOwner(value); + __builder.setPrefix(false); + } else if(v.first == "own_prefix") { + __builder.addOwner(value); + __builder.setPrefix(true); + } else if(v.first == "privilege") + __builder.addPrivilege(value); + + if(field_has(v, "_destination")) + __builder.addName(value); + else if(field_has(v, "_sender")) + __builder.addName(value); + else if(field_has(v, "_path")) + __builder.addPath(value); + else if(field_has(v, "_interface")) + __builder.addInterface(value); + else if(field_has(v, "_member")) + __builder.addMember(value); + else if(field_has(v, "_type")) + __builder.addMessageType(__str_to_message_type(value)); + } else { + attr = false; + t = NONE; + } +} + +void DbAdapter::xmlTraversal(bool bus, + const boost::property_tree::ptree& pt, + DbAdapter::state tag, + PolicyType& policy_type, + PolicyTypeValue& policy_type_value, + bool attr, + int level) { + static const int Q_XML_MAX_LEVEL = 10; + if(level < Q_XML_MAX_LEVEL) { + for(const auto& v : pt) { + if(v.first == "") { continue; } + state t = tag; + updateDecision(v, policy_type, policy_type_value, t, attr); + xmlTraversal(bus, v.second, t, policy_type, policy_type_value, attr, level + 1); + } + + if(!pt.empty() && level > 1) { + Item* it = __builder.generateItem(); + if (it) { + if (bus) + __session_db.addItem(policy_type, policy_type_value, it); + else + __system_db.addItem(policy_type, policy_type_value, it); + } + } + } +} + +void DbAdapter::updateDb(bool bus, boost::property_tree::ptree& xmlTree) { + const auto& children = xmlTree.get_child("busconfig"); + PolicyType policy_type; + PolicyTypeValue policy_type_value; + for(const auto& x : children) { + if(x.first == "policy") { + __tag_state = POLICY; + __attr = false; + xmlTraversal(bus, x.second, POLICY, policy_type, policy_type_value); + } + } +} + +Item::Item(Decision decision, const char* privilege, bool isOwner) + : _decision(decision), _privilege(privilege), _is_owner(isOwner) { + +} + +Item::~Item() { + if (_is_owner) { + delete[] _privilege; + } +} + +bool Item::match(const Item& item) const { + return match(&item); +} + +bool Item::match(const Item* item) const { + return true; +} + +Decision Item::getDecision() const { + return _decision; +} + +const char* Item::getPrivilege() const { + return _privilege; +} + +ItemType Item::getType() const { + return ItemType::GENERIC; +} + +const char* Item::toString(char* str) const { + snprintf(str, MAX_LOG_LINE, "Item: dec(%s) owner(%d) priv(%s)", __decision_to_str(_decision), _is_owner, _privilege); + return str; +} + +ItemOwn::ItemOwn(const char* name, + bool is_prefix, + Decision decision, + const char* privilege) +: Item(decision, privilege), __name(name), __is_prefix(is_prefix) { +} + +ItemOwn::~ItemOwn() { + if (_is_owner) { + delete[] __name; + } +} +ItemType ItemOwn::getType() const { + return ItemType::OWN; +} +bool ItemOwn::match(const Item* item) const { + const ItemOwn* it = dynamic_cast(item); + if (__is_prefix) { + int i = 0; + if (!__name) + return false; + + for (i = 0; __name[i] && it->__name[i]; i++) + if (__name[i] != it->__name[i]) + return false; + + if (__name[i] != 0) + return false; + + return true; + } else if (!__name) + return true; + else { + return std::strcmp(__name, it->__name) == 0; + } +} + +const char* ItemOwn::toString(char* str) const { + char parent[MAX_LOG_LINE]; + const char* t = Item::toString(parent); + snprintf(str, MAX_LOG_LINE, "ItemOwn: service(%s), pref(%d) <- %s", __name, __is_prefix, t); + return str; +} + +ItemSendReceive::ItemSendReceive(const char** names, + const char* interface, + const char* member, const char* path, + MessageType type, MessageDirection direction, + Decision decision, + const char* privilege) + : Item(decision, privilege), + __names(names), + __interface(interface), + __member(member), + __path(path), + __type(type), + __direction(direction) { +} +const char* ItemSendReceive::toString(char* str) const { + char parent[MAX_LOG_LINE]; + char buff[MAX_LOG_LINE]; + char* curr = buff; + const char* t = Item::toString(parent); + int i = 0; + int k = 0; + while(__names && __names[i]){ + for (k = 0; __names[i][k] && __names[i][k] != ' ';k++){ + *curr = __names[i][k]; + curr +=1; + } + *curr = ' '; + curr += 1; + i++; + } + *curr = 0; + curr += 1; + snprintf(str, MAX_LOG_LINE, "ItemSR: name(%s), inter(%s), member(%s), path(%s), type(%s), dir(%s) <- %s", buff, __interface, __member, __path, __message_type_to_str(__type), __message_dir_to_str(__direction), t); + return str; +} +ItemSendReceive::~ItemSendReceive() { + if (_is_owner) { + delete[] __interface; + delete[] __member; + delete[] __path; + + if (__names) { + int i = 0; + while (__names[i]) + delete[] __names[i++]; + delete[] __names; + } + } +} + +bool ItemSendReceive::match(const Item* item) const { + const ItemSendReceive* it = dynamic_cast(item); + + if (__type != MessageType::ANY && __type != it->__type) + return false; + + if (__direction != it->__direction) + return false; + + if (__interface && it->__interface && std::strcmp(__interface, it->__interface)) + return false; + + if (__path && it->__path && std::strcmp(__path, it->__path)) + return false; + + if (__member && it->__member && std::strcmp(__member, it->__member)) + return false; + + if (__names && __names[0]) { + int i = 0; + bool f = false; + if (it->__names) { + while (it->__names[i]) { + if (__compare_str(it->__names[i++], __names[0])) { + f = true; + break; + } + } + if (!f) + return false; + } + } + + return true; +} + +ItemType ItemSendReceive::getType() const { + if (__direction == MessageDirection::SEND) + return ItemType::SEND; + else + return ItemType::RECEIVE; +} + + +MessageDirection ItemSendReceive::getDirection() const { + return __direction; +} + +ItemOwn* ItemBuilder::getOwnItem() { + if (!__current) { + __current = new ItemOwn(); + prepareItem(); + } + return dynamic_cast(__current); +} + +ItemSendReceive* ItemBuilder::getSendReceiveItem() { + if (!__current) { + __current = new ItemSendReceive(); + prepareItem(); + } + return dynamic_cast(__current); +} + +ItemBuilder::ItemBuilder() : __current(NULL), __delayed_privilege(NULL) { +} + +ItemBuilder::~ItemBuilder(){ + if (__delayed_privilege) + delete[] __delayed_privilege; + if (__current) + delete __current; +} + +void ItemBuilder::reset() { + if (__delayed_privilege) + delete[] __delayed_privilege; + if (__current) + delete __current; + + __current = NULL; + __delayed_privilege = NULL; +} + +char* ItemBuilder::duplicate(const char* str) { + char* ret; + int i = 0; + int len; + + if (!str) + return NULL; + + len = strlen(str) + 1; + ret = new char[len]; + for (i = 0; i < len; i++) + ret[i] = str[i]; + + return ret; +} + +void ItemBuilder::prepareItem() { + __current->_is_owner = true; + if (__delayed_privilege) + __current->_privilege = __delayed_privilege; + + __current->_decision = __delayed_decision; + __delayed_privilege = NULL; +} + +Item* ItemBuilder::generateItem() { + Item* ret = __current; + __current = NULL; + __delayed_decision = Decision::ANY; + __delayed_privilege = NULL; + return ret; +} + +void ItemBuilder::addOwner(const char* owner) { + ItemOwn* o = getOwnItem(); + if (o->__name) + delete o->__name; + o->__name = duplicate(owner); +} + +void ItemBuilder::addName(const char* name) { + ItemSendReceive* sr = getSendReceiveItem(); + if (sr->__names) { + delete sr->__names[0]; + delete[] sr->__names; + } + if (!name) + sr->__names = NULL; + else { + sr->__names = new const char*[2]; + sr->__names[0] = duplicate(name); + sr->__names[1] = NULL; + } +} + +void ItemBuilder::addInterface(const char* interface) { + ItemSendReceive* sr = getSendReceiveItem(); + sr->__interface = duplicate(interface); +} + +void ItemBuilder::addMember(const char* member) { + ItemSendReceive* sr = getSendReceiveItem(); + sr->__member = duplicate(member); +} + +void ItemBuilder::addPath(const char* path) { + ItemSendReceive* sr = getSendReceiveItem(); + sr->__path = duplicate(path); +} + +void ItemBuilder::addMessageType(MessageType type) { + ItemSendReceive* sr = getSendReceiveItem(); + sr->__type = type; +} + +void ItemBuilder::addDirection(MessageDirection direction) { + ItemSendReceive* sr = getSendReceiveItem(); + sr->__direction = direction; +} + +void ItemBuilder::addPrivilege(const char* privilege) { + if (!__current) + __delayed_privilege = duplicate(privilege); + else + __current->_privilege = duplicate(privilege); +} + +void ItemBuilder::addDecision(Decision decision) { + if (!__current) + __delayed_decision = decision; + else + __current->_decision = decision; +} + +void ItemBuilder::setPrefix(bool value) { + ItemOwn* o = getOwnItem(); + o->__is_prefix = value; +} + +PolicyTypeValue::PolicyTypeValue() : context(ContextType::DEFAULT) { +} + +PolicyTypeValue::PolicyTypeValue(ContextType type) : context(type) { +} + +PolicyTypeValue::PolicyTypeValue(uid_t us) : user(us) { +} diff --git a/src/internal/policy.hpp b/src/internal/policy.hpp new file mode 100644 index 0000000..848c53c --- /dev/null +++ b/src/internal/policy.hpp @@ -0,0 +1,194 @@ +/* + * 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 _POLICY_H +#define _POLICY_H + +#include +#include +#include +#define MAX_LOG_LINE 1024 + +namespace _ldp_xml_parser +{ + enum class MessageType : uint8_t { + ANY = 0, + METHOD_CALL, + METHOD_RETURN, + ERROR, + SIGNAL + }; + + enum class MessageDirection : uint8_t { + ANY, + SEND, + RECEIVE + }; + + enum class ItemType : uint8_t{ + GENERIC, + OWN, + SEND, + RECEIVE + }; + + enum class PolicyType : uint8_t { + CONTEXT, + USER, + GROUP + }; + + enum class ContextType : uint8_t { + DEFAULT, + MANDATORY, + MAX + }; + + enum class Decision : uint8_t { + ANY, + ALLOW, + DENY, + CHECK + }; + + union PolicyTypeValue { + PolicyTypeValue(); + PolicyTypeValue(ContextType type); + PolicyTypeValue(uid_t us); + ContextType context; + uid_t user; + gid_t group; + }; + + class ItemBuilder; + + class Item { + protected: + Decision _decision; + const char* _privilege; + bool _is_owner; + public: + friend class ItemBuilder; + Item(Decision decision = Decision::ANY, const char* privilege = NULL, bool isOwner = false); + virtual ~Item(); + virtual bool match(const Item& item) const; + virtual bool match(const Item* item) const; + virtual Decision getDecision() const; + virtual const char* getPrivilege() const; + virtual ItemType getType() const; + virtual const char* toString(char* str) const; + }; + + class ItemOwn : public Item { + private: + const char* __name; + bool __is_prefix; + public: + friend class ItemBuilder; + ItemOwn(const char* name = NULL, + bool is_prefix = false, + Decision decision = Decision::ANY, + const char* privilege = NULL); + virtual ~ItemOwn(); + virtual bool match(const Item* item) const; + virtual ItemType getType() const; + virtual const char* toString(char* str) const; + }; + + class ItemSendReceive : public Item { + const char** __names; + const char* __interface; + const char* __member; + const char* __path; + MessageType __type; + MessageDirection __direction; + public: + friend class ItemBuilder; + ItemSendReceive(const char** names = NULL, + const char* interface = NULL, + const char* member = NULL, + const char* path = NULL, + MessageType type = MessageType::ANY, + MessageDirection direction = MessageDirection::ANY, + Decision decision = Decision::ANY, + const char* privilege = NULL); + virtual ~ItemSendReceive(); + virtual bool match(const Item* item) const; + MessageDirection getDirection() const; + virtual ItemType getType() const; + virtual const char* toString(char* str) const; + }; + + class ItemBuilder { + private: + Item* __current; + Decision __delayed_decision; + const char* __delayed_privilege; + ItemOwn* getOwnItem(); + ItemSendReceive* getSendReceiveItem(); + char* duplicate(const char* str); + void prepareItem(); + public: + ItemBuilder(); + ~ItemBuilder(); + Item* generateItem(); + void reset(); + void addUser(const char* name); + void addGroup(const char* name); + void addOwner(const char* owner); + void addName(const char* name); + void addInterface(const char* interface); + void addMember(const char* member); + void addPath(const char* path); + void addMessageType(MessageType type); + void addDirection(MessageDirection direction); + void addPrivilege(const char* privilege); + void addDecision(Decision decision); + void setPrefix(bool value); + }; + + class NaivePolicyDb; + class DbAdapter { + private: + enum state { + NONE, + POLICY, + ALLOW_DENY_CHECK + }; + NaivePolicyDb& __system_db; + NaivePolicyDb& __session_db; + bool __attr; + state __tag_state; + ItemBuilder __builder; + void updateDecision(const boost::property_tree::ptree::value_type& v, + PolicyType& policy_type, + PolicyTypeValue& policy_type_value, + state& tag, + bool& attr); + void xmlTraversal(bool bus, + const boost::property_tree::ptree& pt, + state tag, + PolicyType& policy_type, + PolicyTypeValue& policy_type_value, + bool attr = false, + int level = 0); + public: + DbAdapter(NaivePolicyDb& system, NaivePolicyDb& session); + void updateDb(bool bus, boost::property_tree::ptree& xmlTree); + static uid_t convertToUid(const char* user); + static gid_t convertToGid(const char* group); + }; +} +#endif diff --git a/src/internal/tslog.cpp b/src/internal/tslog.cpp new file mode 100644 index 0000000..fa5b579 --- /dev/null +++ b/src/internal/tslog.cpp @@ -0,0 +1,17 @@ +#include "tslog.hpp" + +namespace tslog { +int8_t g_verbosity; +} + +bool tslog::get_log_env(char const *name) { + char const *ldp_log_mode = getenv(name); + return ldp_log_mode && '0' != *ldp_log_mode; +} + +void tslog::init() { + g_verbosity = get_log_env("LDP_LOG") ? get_log_env("LDP_VERBOSE") : -1; +} + +bool tslog::enabled() { return g_verbosity >= 0; } +bool tslog::verbose() { return g_verbosity > 0; } diff --git a/src/internal/tslog.hpp b/src/internal/tslog.hpp index dd57976..07fc383 100644 --- a/src/internal/tslog.hpp +++ b/src/internal/tslog.hpp @@ -26,19 +26,13 @@ typedef std::ostream& (*t_ManFun)(std::ostream&); namespace tslog { - int8_t g_verbosity; // <0 disable 0 brief >0 verbose - bool get_log_env(char const *name) { - char const *ldp_log_mode = getenv(name); - return ldp_log_mode && '0' != *ldp_log_mode; - } + bool get_log_env(char const *name); - void init() { - g_verbosity = get_log_env("LDP_LOG") ? get_log_env("LDP_VERBOSE") : -1; - } + void init(); - bool enabled() { return g_verbosity >= 0; } - bool verbose() { return g_verbosity > 0; } + bool enabled(); + bool verbose(); } #endif diff --git a/src/internal/xml_parser.cpp b/src/internal/xml_parser.cpp new file mode 100644 index 0000000..2c793f6 --- /dev/null +++ b/src/internal/xml_parser.cpp @@ -0,0 +1,3 @@ +#include "xml_parser.hpp" + +std::set _ldp_xml_parser::XmlParser::m_parsed; diff --git a/src/internal/xml_parser.hpp b/src/internal/xml_parser.hpp index 61e60e4..948f2c6 100644 --- a/src/internal/xml_parser.hpp +++ b/src/internal/xml_parser.hpp @@ -23,7 +23,10 @@ #include #include #include -#include "xml_policy.hpp" +//#include "xml_policy.hpp" +#include "libdbuspolicy1-private.hpp" +#include "tslog.hpp" +#include "policy.hpp" namespace _ldp_xml_parser { @@ -36,47 +39,16 @@ namespace _ldp_xml_parser return err; } - ErrCode can_send(bool 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 idx_v = { user, group, destination, path, interface, member, type }; - return m_xml_policy.can_send_to(bus, idx_v, label); + void registerAdapter(DbAdapter& adapter) { + m_adapter = &adapter; } - ErrCode can_recv(bool 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 idx_v = { user, group, sender, path, interface, member, type }; - return m_xml_policy.can_recv_from(bus, idx_v, label); - } - - ErrCode can_own(bool bus, - const std::string user, - const std::string group, - const std::string service) { - std::vector idx_v = { user, group, service }; - return m_xml_policy.can_own_what(bus, idx_v); - } - - private: //IO operation static std::set m_parsed; + DbAdapter* m_adapter; //Data obtained from XML - static XmlPolicy m_xml_policy; ErrCode parse(bool bus, std::string const &filename) { ErrCode err; @@ -88,10 +60,6 @@ namespace _ldp_xml_parser err = parse(bus, false, x, incl_files); if (err.is_error()) break; } - - if(err.is_ok()) - m_xml_policy.print_decision_trees(bus); - return err; } @@ -148,7 +116,7 @@ namespace _ldp_xml_parser boost::property_tree::ptree pt; read_xml(filename, pt); if (!pt.empty()) { - m_xml_policy.update(bus, pt); + m_adapter->updateDb(bus, pt); ret.second = pt.get("busconfig.includedir", ""); } } catch(const boost::property_tree::xml_parser::xml_parser_error& ex) { diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 0ff7d6b..1878d9e 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -49,21 +49,6 @@ #define UID_INVALID ((uid_t) -1) #define GID_INVALID ((gid_t) -1) -static char const *foreach_strv_advance(char const *str) { - char c; - while ((c = *str++)) - if (' ' == c) - return str; - return NULL; -} - -/* iterate over STR; iterate once with "" if !STR or !*STR */ -#define FOREACH_STRV_DEFAULT(ITERLVALPTR,STR) for (\ - ITERLVALPTR = (!STR || !*STR) ? "" : STR;\ - ITERLVALPTR;\ - ITERLVALPTR = foreach_strv_advance(ITERLVALPTR)\ -) - /** A process ID */ typedef unsigned long dbus_pid_t; /** A user ID */ @@ -148,22 +133,22 @@ static bool dbuspolicy_init_once(void) if (r < 0 || r >= (long int)sizeof(g_udesc.label)) /* read */ return true; + g_udesc.uid = getuid(); + g_udesc.gid = getgid(); + snprintf(g_udesc.label, r + 1 /* additional byte for \0 */, "%s", buf); if (getpwuid_r(g_udesc.uid, &pwent, buf, sizeof(buf), &pwd)) - return true; + return true; if (getgrgid_r(g_udesc.gid, &grent, buf, sizeof(buf), &gg)) - return true; + return true; if (!pwd || !gg) - return -1; + return false; snprintf(g_udesc.user, sizeof(g_udesc.user), "%s", pwd->pw_name); snprintf(g_udesc.group, sizeof(g_udesc.group), "%s", gg->gr_name); - g_udesc.uid = getuid(); - g_udesc.gid = getgid(); - __internal_init_once(); return false; @@ -224,7 +209,6 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init(const char *bus_path) init_once_done = true; rb = dbuspolicy_init_once(); } - pthread_mutex_unlock(&g_mutex); if (rb) goto err_close; @@ -237,14 +221,17 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init(const char *bus_path) rp = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY); rs = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY); __internal_init_flush_logs(); + if ((rp & rs) < 0) /* when both negative */ goto err_close; + pthread_mutex_unlock(&g_mutex); return &g_conn[bus_type]; err_close: close(g_conn[bus_type].fd); err: + pthread_mutex_unlock(&g_mutex); return NULL; } @@ -254,6 +241,15 @@ DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration) close(((typeof(&g_conn[0]))configuration)->fd); } +#ifdef LIBDBUSPOLICY_TESTS_API +DBUSPOLICY1_EXPORT void __dbuspolicy1_change_creds(void* configuration, uid_t uid, gid_t gid,const char* label) { + g_udesc.uid = uid; + g_udesc.gid = gid; + if (label) + strcpy (g_udesc.label, label); +} +#endif + static bool configuration_bus_type(struct kconn const *configuration) { return configuration != g_conn; } /** @@ -275,6 +271,8 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration, int requested_reply) { char const *label = NULL; + const char* k_names[KDBUS_CONN_MAX_NAMES+1]; + int k_i = 0; int r; uid_t uid_n = UID_INVALID; gid_t gid_n = GID_INVALID; @@ -344,29 +342,27 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration, case KDBUS_ITEM_OWNED_NAME: empty_names = false; if (r <= 0) - r = __internal_can_send(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, item->name.name, path, interface, member, message_type); + k_names[k_i++] = item->name.name; break; } } if (empty_names) - r = __internal_can_send(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, destination, path, interface, member, message_type); - - if (r > 0 && message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) { - char gid[25], uid[25]; - char const *ptr; - snprintf(uid, sizeof(uid), "%lu", (unsigned long)uid_n); - snprintf(gid, sizeof(gid), "%lu", (unsigned long)gid_n); + r = __internal_can_send(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, destination, path, interface, member, message_type); + else { + k_names[k_i++] = NULL; + r = __internal_can_send_multi_dest(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, k_names, path, interface, member, message_type); + } + if (r <= 0) + goto end; - FOREACH_STRV_DEFAULT(ptr, sender) - if (0 < (r = __internal_can_recv(bus_type, uid, gid, label, ptr, path, interface, member, message_type))) - break; - } + if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) + r = __internal_can_recv(bus_type, uid_n, gid_n, label, sender, path, interface, member, message_type); +end: if (free_offset) ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &cmd.cmd_free); -end: __internal_exit(); return r; } @@ -392,26 +388,22 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration, int reply_serial, int requested_reply) { - char const *ptr; int r; - char gid[25], uid[25]; bool bus_type = configuration_bus_type(configuration); - snprintf(uid, sizeof(uid), "%lu", (unsigned long)sender_uid); - snprintf(gid, sizeof(gid), "%lu", (unsigned long)sender_gid); - __internal_enter(); - FOREACH_STRV_DEFAULT(ptr, destination) - if (0 < (r = __internal_can_send(bus_type, uid, gid, sender_label, ptr, path, interface, member, message_type))) - break; - - if (r > 0 && message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) - FOREACH_STRV_DEFAULT(ptr, sender) - if (0 < (r = __internal_can_recv(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, ptr, path, interface, member, message_type))) - break; + r = __internal_can_send(bus_type, sender_uid, sender_gid, sender_label, destination, path, interface, member, message_type); + if (r <= 0) + goto end; - __internal_exit(); + if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) { + r = __internal_can_recv(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, sender, path, interface, member, message_type); + if (r <= 0) + goto end; + } +end: + __internal_exit(); return r; } @@ -427,7 +419,7 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_can_own(void* configuration, const char* cons int r; bool bus_type = configuration_bus_type(configuration); __internal_enter(); - r = __internal_can_own(bus_type, g_udesc.user, g_udesc.group, service); + r = __internal_can_own(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, service); __internal_exit(); return r; } diff --git a/src/libdbuspolicy1.sym b/src/libdbuspolicy1.sym index 051e64e..c472731 100644 --- a/src/libdbuspolicy1.sym +++ b/src/libdbuspolicy1.sym @@ -5,15 +5,12 @@ global: dbuspolicy1_check_in; dbuspolicy1_check_out; dbuspolicy1_can_own; + __dbuspolicy1_change_creds; local: *; }; -LIBDBUSPOLICY1_3 { +LIBDBUSPOLICY1_1_TEST { global: - dbuspolicy1_thing_ref; - dbuspolicy1_thing_unref; - dbuspolicy1_thing_get_ctx; - dbuspolicy1_thing_new_from_string; - dbuspolicy1_thing_get_some_list_entry; -} LIBDBUSPOLICY1_1; + __dbuspolicy1_change_creds; +}; diff --git a/src/test-libdbuspolicy1-method.cpp b/src/test-libdbuspolicy1-method.cpp new file mode 100644 index 0000000..8aa3738 --- /dev/null +++ b/src/test-libdbuspolicy1-method.cpp @@ -0,0 +1,82 @@ + +#include +#include +#include +#include +#include "internal/internal.h" +#include "internal/policy.hpp" + +using namespace _ldp_xml_parser; + +const char* system_path = "tests/system.conf"; + +struct MethodTest { + bool expected_result; + uid_t user; + gid_t group; + const char* label; + const char* name; + const char* path; + const char* interface; + const char* member; + MessageType type; + MessageDirection recv_send; +}; + +struct MethodTest method_tests[]={ + (struct MethodTest){true, 0, 0, "test", "org.test.test2", NULL, "org.test.Itest1", "DoIt", MessageType::METHOD_CALL, MessageDirection::SEND}, + (struct MethodTest){true, 0, 0, "test", "org.test.test3", NULL, "org.test.Itest1", "DoIt", MessageType::METHOD_CALL, MessageDirection::RECEIVE}, + + (struct MethodTest){true, 5001, 100, "test", "org.test.test3", NULL, "org.test.Itest1", "DoIt", MessageType::METHOD_CALL, MessageDirection::RECEIVE}, + (struct MethodTest){true, 0, 0, "test", "org.test.test2", NULL, "org.test.Itest1", "DoIt", MessageType::METHOD_CALL, MessageDirection::SEND}, + + (struct MethodTest){false, 0, 0, "test", "org.test.test2", NULL, "org.test.Itest1", "DontDoIt", MessageType::METHOD_CALL, MessageDirection::SEND}, + (struct MethodTest){true, 0, 0, "test", "org.test.test3", NULL, "org.test.Itest1", "DontDoIt", MessageType::METHOD_CALL, MessageDirection::RECEIVE}, + + (struct MethodTest){false, 0, 0, "test", "org.test.test2", NULL, "org.test.Itest1", "DontDoIt", MessageType::METHOD_CALL, MessageDirection::SEND}, + (struct MethodTest){false, 5001, 100, "test", "org.test.test3", NULL, "org.test.Itest1", "DontDoIt", MessageType::METHOD_CALL, MessageDirection::RECEIVE}, + + (struct MethodTest){true, 0, 0, "test", "test.te34.fg4 a.b.c.d.e org.test.test2", NULL, "org.test.Itest1", "NotKnown", MessageType::METHOD_CALL, MessageDirection::SEND}, + (struct MethodTest){false, 0, 0, "test", "test.te34.fg4 a.b.c.d.e", NULL, "org.test.Itest1", "NotKnown", MessageType::METHOD_CALL, MessageDirection::SEND}, + (struct MethodTest){true, 0, 0, "test", "org.test.test3", NULL, "org.test.Itest1", "NotKnown", MessageType::METHOD_CALL, MessageDirection::RECEIVE}, + + (struct MethodTest){true, 0, 0, "test", "org.test.test2", NULL, "org.test.Itest1", "NotKnown", MessageType::METHOD_CALL, MessageDirection::SEND}, + (struct MethodTest){false, 5001, 100, "test", "org.test.test3", NULL, "org.test.Itest1", "NotKnown", MessageType::METHOD_CALL, MessageDirection::RECEIVE}, + + (struct MethodTest){false, 0, 0, "test", "org.test.test2", NULL, "org.test.Itest2", "NotKnown", MessageType::METHOD_CALL, MessageDirection::SEND}, + (struct MethodTest){true, 5001, 100, "test", "org.test.test3", NULL, "org.test.Itest2", "NotKnown", MessageType::METHOD_CALL, MessageDirection::RECEIVE}, +}; + +void methodTest_print(struct MethodTest* t, bool result) { + printf("uid = %lu, gid = %lu, label = %s, name = %s, path = %s, interface = %s, member = %s, expected = %d, result = %d (type=%d)", + (unsigned long)t->user, (unsigned long)t->group, t->label, t->name, t->path, t->interface, t->member, !((int)t->expected_result), (int)result, t->recv_send); +} + +bool method_test() { + unsigned i = 0; + bool flag = true; + bool ret = true; + __internal_init(false, "tests/system.conf"); + for (i = 0;i < sizeof(method_tests)/sizeof(struct MethodTest);i++) { + if (method_tests[i].recv_send == MessageDirection::SEND) + { + ret = __internal_can_send(false, method_tests[i].user, method_tests[i].group, method_tests[i].label, method_tests[i].name, method_tests[i].path, method_tests[i].interface, method_tests[i].member, static_cast(method_tests[i].type)); + } else if (method_tests[i].recv_send == MessageDirection::RECEIVE) { + ret = __internal_can_recv(false, method_tests[i].user, method_tests[i].group, method_tests[i].label, method_tests[i].name, method_tests[i].path, method_tests[i].interface, method_tests[i].member, static_cast(method_tests[i].type)); + } + if ( (int)((method_tests[i].expected_result)) != ret) { + printf("[ERROR][%d] method test failed: %d %d ", i, (int)((method_tests[i].expected_result)), ret); + methodTest_print(&method_tests[i], ret); + printf("\n"); + flag = false; + } + } + return flag; +} + +int main () { + __internal_init_once(); + if (!method_test()) + return -1; +return 0; +} diff --git a/src/test-libdbuspolicy1-ownership.cpp b/src/test-libdbuspolicy1-ownership.cpp new file mode 100644 index 0000000..30c3fa7 --- /dev/null +++ b/src/test-libdbuspolicy1-ownership.cpp @@ -0,0 +1,71 @@ + +#include +#include +#include +#include +#include "internal/internal.h" + +const char* system_path = "tests/system.conf"; + +struct OwnershipTest { + bool expected_result; + uid_t user; + gid_t group; + const char* label; + const char* service; +}; + +struct OwnershipTest ownership_tests[]={ + (struct OwnershipTest){true, 0, 0, "test", "org.test.test1"}, + (struct OwnershipTest){true, 5009, 0, "test", "org.test.test1"}, + + (struct OwnershipTest){false, 0, 0, "test", "org.test.test2"}, + (struct OwnershipTest){false, 5009, 0, "test", "org.test.test2"}, + + (struct OwnershipTest){false, 0, 0, "test", "org.test.test3"}, + (struct OwnershipTest){false, 5009, 0, "test", "org.test.test3"}, + + (struct OwnershipTest){false, 0, 0, "test", "org.test.test4"}, + (struct OwnershipTest){true, 5009, 0, "test", "org.test.test4"}, + + (struct OwnershipTest){false, 0, 0, "test", "org.test.test5"}, + + (struct OwnershipTest){true, 0, 0, "test", "org.test.test6"}, + + (struct OwnershipTest){true, 0, 0, "test", "org.test.test7"}, + + (struct OwnershipTest){true, 0, 0, "test", "a.b.c"}, + (struct OwnershipTest){true, 0, 0, "test", "a.b"}, + (struct OwnershipTest){false, 0, 0, "test", "c"}, + (struct OwnershipTest){false, 0, 0, "test", "a.c"}, + (struct OwnershipTest){false, 0, 0, "test", "b.c"}, +}; + +void ownershipTest_print(struct OwnershipTest* t, bool result) { + printf("uid = %lu, gid = %lu, label = %s, service = %s, expected = %d, result = %d", + (unsigned long)t->user, (unsigned long)t->group, t->label, t->service, !((int)t->expected_result), (int)result); +} + +bool ownership_test() { + unsigned i = 0; + bool flag = true; + bool ret = true; + __internal_init(false, "tests/system.conf"); + for (i = 0;i < sizeof(ownership_tests)/sizeof(struct OwnershipTest);i++) { + ret = __internal_can_own(false, ownership_tests[i].user, ownership_tests[i].group, ownership_tests[i].label, ownership_tests[i].service); + if ( (int)((ownership_tests[i].expected_result)) != ret) { + printf("[ERROR][%d] ownership test failed: %d %d ", i, (int)((ownership_tests[i].expected_result)), ret); + ownershipTest_print(&ownership_tests[i], ret); + printf("\n"); + flag = false; + } + } + return flag; +} + +int main () { + __internal_init_once(); + if (!ownership_test()) + return -1; +return 0; +} diff --git a/src/test-libdbuspolicy1-signal.cpp b/src/test-libdbuspolicy1-signal.cpp new file mode 100644 index 0000000..19cc2e9 --- /dev/null +++ b/src/test-libdbuspolicy1-signal.cpp @@ -0,0 +1,51 @@ + +#include +#include +#include +#include +#include "internal/internal.h" + +const char* system_path = "tests/system.conf"; + +struct SignalTest { + bool expected_result; + uid_t user; + gid_t group; + const char* label; + const char* dest; + const char* interface; +}; + +struct SignalTest signal_tests[]={ + (struct SignalTest){true, 0, 0, "test", "bli.bla.blubb test.test1 test.tes3", "/an/object/path"}, + (struct SignalTest){false, 5010, 0, "test", "bli.bla.blubb", "/an/object/path"}, +}; + +void signalTest_print(struct SignalTest* t, bool result) { + printf("uid = %lu, gid = %lu, label = %s, dest = %s, interface = %s, expected = %d, result = %d", + (unsigned long)t->user, (unsigned long)t->group, t->label, t->dest, t->interface, !((int)t->expected_result), (int)result); +} + +bool signal_test() { + unsigned i = 0; + bool flag = true; + bool ret = true; + __internal_init(false, "tests/system.conf"); + for (i = 0;i < sizeof(signal_tests)/sizeof(struct SignalTest);i++) { + ret = __internal_can_send(false, signal_tests[i].user, signal_tests[i].group, signal_tests[i].label, signal_tests[i].dest, NULL, signal_tests[i].interface, NULL, DBUSPOLICY_MESSAGE_TYPE_SIGNAL); + if ( (int)((signal_tests[i].expected_result)) != ret) { + printf("[ERROR][%d] signal test failed: %d %d ", i, (int)((signal_tests[i].expected_result)), ret); + signalTest_print(&signal_tests[i], ret); + printf("\n"); + flag = false; + } + } + return flag; +} + +int main () { + __internal_init_once(); + if (!signal_test()) + return -1; +return 0; +} diff --git a/tests/system.conf b/tests/system.conf new file mode 100644 index 0000000..0ba5b64 --- /dev/null +++ b/tests/system.conf @@ -0,0 +1,83 @@ + + + + + + + + + system + + + dbus + + + + + + + + + /usr/lib/dbus/dbus-daemon-launch-helper + + + /var/run/dbus/pid + + + + + + EXTERNAL + + + kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket + + + + + + + + + + + + + + + + + + + + + + + + + + + + system.d + + + system-local.conf + + contexts/dbus_contexts + + diff --git a/tests/system.d/cynara.test.conf b/tests/system.d/cynara.test.conf new file mode 100644 index 0000000..e988385 --- /dev/null +++ b/tests/system.d/cynara.test.conf @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/tests/system.d/methods.test.conf b/tests/system.d/methods.test.conf new file mode 100644 index 0000000..7928557 --- /dev/null +++ b/tests/system.d/methods.test.conf @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/system.d/ownerships.test.conf b/tests/system.d/ownerships.test.conf new file mode 100644 index 0000000..7a6e625 --- /dev/null +++ b/tests/system.d/ownerships.test.conf @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/system.d/signals.test.conf b/tests/system.d/signals.test.conf new file mode 100644 index 0000000..e44decf --- /dev/null +++ b/tests/system.d/signals.test.conf @@ -0,0 +1,13 @@ + + + + + + + + + + + + -- 2.7.4 From 4b067f8dd7e2a60117b18525678a360a76a51924 Mon Sep 17 00:00:00 2001 From: Kazimierz Krosman Date: Fri, 20 May 2016 17:23:39 +0200 Subject: [PATCH 15/16] libdbuspolicyt refactoring to meet Tizen coding style Change-Id: I9765dd74342d695d50b223185c71a84d7f0f1aa3 --- src/dbuspolicy1/libdbuspolicy1.h | 42 +++---- src/internal/cynara.cpp | 2 +- src/internal/cynara.hpp | 2 +- src/internal/cynara_mockup.cpp | 2 +- src/internal/internal.cpp | 44 +++---- src/internal/naive_policy_checker.cpp | 4 +- src/internal/naive_policy_checker.hpp | 2 +- src/internal/naive_policy_db.cpp | 2 +- src/internal/naive_policy_db.hpp | 2 +- src/internal/policy.cpp | 2 +- src/internal/policy.hpp | 2 +- src/internal/xml_parser.cpp | 2 +- src/internal/xml_parser.hpp | 22 ++-- src/internal/xml_policy.hpp | 2 +- src/libdbuspolicy1.c | 226 +++++++++++++++++----------------- src/test-libdbuspolicy1-method.cpp | 2 +- 16 files changed, 180 insertions(+), 180 deletions(-) diff --git a/src/dbuspolicy1/libdbuspolicy1.h b/src/dbuspolicy1/libdbuspolicy1.h index cc0040e..1b15b19 100644 --- a/src/dbuspolicy1/libdbuspolicy1.h +++ b/src/dbuspolicy1/libdbuspolicy1.h @@ -76,15 +76,15 @@ void dbuspolicy1_free(void* configuration); \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); + 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 @@ -103,18 +103,18 @@ int dbuspolicy1_check_out(void* configuration, \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); + 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 diff --git a/src/internal/cynara.cpp b/src/internal/cynara.cpp index ce191c0..ca4c79d 100644 --- a/src/internal/cynara.cpp +++ b/src/internal/cynara.cpp @@ -5,7 +5,7 @@ #include #include -using namespace _ldp_cynara; +using namespace ldp_cynara; pthread_mutex_t Cynara::__mutex = PTHREAD_MUTEX_INITIALIZER; diff --git a/src/internal/cynara.hpp b/src/internal/cynara.hpp index 684e2a9..84fbbd2 100644 --- a/src/internal/cynara.hpp +++ b/src/internal/cynara.hpp @@ -23,7 +23,7 @@ #include -namespace _ldp_cynara { +namespace ldp_cynara { enum class CynaraResult : uint8_t { ALLOW, DENY, diff --git a/src/internal/cynara_mockup.cpp b/src/internal/cynara_mockup.cpp index 4392df2..520761f 100644 --- a/src/internal/cynara_mockup.cpp +++ b/src/internal/cynara_mockup.cpp @@ -4,7 +4,7 @@ #include #include -using namespace _ldp_cynara; +using namespace ldp_cynara; Cynara::Cynara() { } diff --git a/src/internal/internal.cpp b/src/internal/internal.cpp index 2b030fc..b17cdec 100644 --- a/src/internal/internal.cpp +++ b/src/internal/internal.cpp @@ -24,7 +24,7 @@ #include "../libdbuspolicy1-private.h" -static _ldp_xml_parser::NaivePolicyChecker policy_checker; +static ldp_xml_parser::NaivePolicyChecker policy_checker; static const char* get_str(const char* const szstr) { return (szstr != NULL) ? szstr : ""; @@ -55,9 +55,9 @@ static const char** get_strv(const char *s, const char** result) { int __internal_init(bool bus_type, const char* const config_name) { - _ldp_xml_parser::XmlParser p; + ldp_xml_parser::XmlParser p; p.registerAdapter(policy_checker.generateAdapter()); - auto err = p.parse_policy(bus_type, get_str(config_name)); + auto err = p.parsePolicy(bus_type, get_str(config_name)); return err.get(); } @@ -89,14 +89,14 @@ void __internal_exit() } int __internal_can_send(bool bus_type, - const uid_t user, - const gid_t group, - const char* const label, - const char* const destination, - const char* const path, - const char* const interface, - const char* const member, - int type) + const uid_t user, + const gid_t group, + const char* const label, + const char* const destination, + const char* const path, + const char* const interface, + const char* const member, + int type) { const char* names[KDBUS_CONN_MAX_NAMES+1]; const char** ns = get_strv(destination, names); @@ -105,20 +105,20 @@ int __internal_can_send(bool bus_type, std::cout << "Destination too long: "<(type), _ldp_xml_parser::MessageDirection::SEND); + return policy_checker.check(bus_type, user, group, label, ns, interface, member, path, static_cast(type), ldp_xml_parser::MessageDirection::SEND); } int __internal_can_send_multi_dest(bool bus_type, - const uid_t user, - const gid_t group, - const char* const label, - const char** const destination, - const char* const path, - const char* const interface, - const char* const member, - int type) + const uid_t user, + const gid_t group, + const char* const label, + const char** const destination, + const char* const path, + const char* const interface, + const char* const member, + int type) { - return policy_checker.check(bus_type, user, group, label, destination, interface, member, path, static_cast<_ldp_xml_parser::MessageType>(type), _ldp_xml_parser::MessageDirection::SEND); + return policy_checker.check(bus_type, user, group, label, destination, interface, member, path, static_cast(type), ldp_xml_parser::MessageDirection::SEND); } int __internal_can_recv(bool bus_type, @@ -133,7 +133,7 @@ int __internal_can_recv(bool bus_type, { const char* names[KDBUS_CONN_MAX_NAMES+1]; const char** ns = get_strv(sender, names); - return policy_checker.check(bus_type, user, group, label, ns, interface, member, path, static_cast<_ldp_xml_parser::MessageType>(type), _ldp_xml_parser::MessageDirection::RECEIVE); + return policy_checker.check(bus_type, user, group, label, ns, interface, member, path, static_cast(type), ldp_xml_parser::MessageDirection::RECEIVE); } int __internal_can_own(bool bus_type, diff --git a/src/internal/naive_policy_checker.cpp b/src/internal/naive_policy_checker.cpp index 5cf9d05..8fc311a 100644 --- a/src/internal/naive_policy_checker.cpp +++ b/src/internal/naive_policy_checker.cpp @@ -1,7 +1,7 @@ #include "naive_policy_checker.hpp" #include "cynara.hpp" #include "tslog.hpp" -using namespace _ldp_xml_parser; +using namespace ldp_xml_parser; DbAdapter& NaivePolicyChecker::generateAdapter() { if (!m_adapter) @@ -61,7 +61,7 @@ bool NaivePolicyChecker::parseDecision(Decision decision, return false; case Decision::CHECK: std::sprintf(uid_str, "%lu", (unsigned long)uid); - return _ldp_cynara::Cynara::check(label, privilege, uid_str) == _ldp_cynara::CynaraResult::ALLOW; + return ldp_cynara::Cynara::check(label, privilege, uid_str) == ldp_cynara::CynaraResult::ALLOW; } return false; diff --git a/src/internal/naive_policy_checker.hpp b/src/internal/naive_policy_checker.hpp index 4f6478f..4f75466 100644 --- a/src/internal/naive_policy_checker.hpp +++ b/src/internal/naive_policy_checker.hpp @@ -19,7 +19,7 @@ #include "policy.hpp" #include "naive_policy_db.hpp" -namespace _ldp_xml_parser +namespace ldp_xml_parser { class NaivePolicyChecker { private: diff --git a/src/internal/naive_policy_db.cpp b/src/internal/naive_policy_db.cpp index ae3c571..bccf9e3 100644 --- a/src/internal/naive_policy_db.cpp +++ b/src/internal/naive_policy_db.cpp @@ -2,7 +2,7 @@ #include #include "tslog.hpp" -using namespace _ldp_xml_parser; +using namespace ldp_xml_parser; NaivePolicyDb::Policy::PolicyConstIterator::PolicyConstIterator(const std::vector& items, int position) : m_items(items), m_index(position) { diff --git a/src/internal/naive_policy_db.hpp b/src/internal/naive_policy_db.hpp index 015eb13..fdbd0c1 100644 --- a/src/internal/naive_policy_db.hpp +++ b/src/internal/naive_policy_db.hpp @@ -20,7 +20,7 @@ #include #include "policy.hpp" -namespace _ldp_xml_parser +namespace ldp_xml_parser { class NaivePolicyDb { public: diff --git a/src/internal/policy.cpp b/src/internal/policy.cpp index dcbde77..021a4be 100644 --- a/src/internal/policy.cpp +++ b/src/internal/policy.cpp @@ -6,7 +6,7 @@ #include #include -using namespace _ldp_xml_parser; +using namespace ldp_xml_parser; static const char* message_type[] = { "ANY", "METHOD_CALL", "METHOD_RETURN", "ERROR", "SIGNAL"}; static const char* message_dir[] = { "ANY", "SEND", "RECEIVE"}; diff --git a/src/internal/policy.hpp b/src/internal/policy.hpp index 848c53c..4909e4e 100644 --- a/src/internal/policy.hpp +++ b/src/internal/policy.hpp @@ -21,7 +21,7 @@ #include #define MAX_LOG_LINE 1024 -namespace _ldp_xml_parser +namespace ldp_xml_parser { enum class MessageType : uint8_t { ANY = 0, diff --git a/src/internal/xml_parser.cpp b/src/internal/xml_parser.cpp index 2c793f6..5606a33 100644 --- a/src/internal/xml_parser.cpp +++ b/src/internal/xml_parser.cpp @@ -1,3 +1,3 @@ #include "xml_parser.hpp" -std::set _ldp_xml_parser::XmlParser::m_parsed; +std::set ldp_xml_parser::XmlParser::__parsed; diff --git a/src/internal/xml_parser.hpp b/src/internal/xml_parser.hpp index 948f2c6..26aee38 100644 --- a/src/internal/xml_parser.hpp +++ b/src/internal/xml_parser.hpp @@ -28,26 +28,26 @@ #include "tslog.hpp" #include "policy.hpp" -namespace _ldp_xml_parser +namespace ldp_xml_parser { class XmlParser : boost::noncopyable { public: - ErrCode parse_policy(bool bus, + ErrCode parsePolicy(bool bus, std::string const &fname) { ErrCode err = parse(bus, fname); return err; } void registerAdapter(DbAdapter& adapter) { - m_adapter = &adapter; + __adapter = &adapter; } private: //IO operation - static std::set m_parsed; + static std::set __parsed; - DbAdapter* m_adapter; + DbAdapter* __adapter; //Data obtained from XML ErrCode parse(bool bus, std::string const &filename) { @@ -69,9 +69,9 @@ namespace _ldp_xml_parser if (tslog::verbose()) std::cout << "=== XML PARSING BEGIN === : " << filename << '\n'; - errparam = xml_parse(bus, filename); + errparam = parseXml(bus, filename); if (first && errparam.first.get() >= 0 && errparam.second != "") - get_included_files(filename, errparam.second, included_files); + getIncludedFiles(filename, errparam.second, included_files); if (tslog::enabled()) { if (tslog::verbose()) @@ -82,7 +82,7 @@ namespace _ldp_xml_parser } //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& files) { + void getIncludedFiles(const std::string& filename, const std::string& incldir, std::vector& files) { DIR *dir; struct dirent *ent; std::string fname; @@ -108,15 +108,15 @@ namespace _ldp_xml_parser std::cout << "could not open directory " << dname << '\n'; } - std::pair xml_parse(bool bus, const std::string& filename) { + std::pair parseXml(bool bus, const std::string& filename) { std::pair ret; - if (m_parsed.insert(filename).second) + if (__parsed.insert(filename).second) try { boost::property_tree::ptree pt; read_xml(filename, pt); if (!pt.empty()) { - m_adapter->updateDb(bus, pt); + __adapter->updateDb(bus, pt); ret.second = pt.get("busconfig.includedir", ""); } } catch(const boost::property_tree::xml_parser::xml_parser_error& ex) { diff --git a/src/internal/xml_policy.hpp b/src/internal/xml_policy.hpp index 48fa7f9..2e790ed 100644 --- a/src/internal/xml_policy.hpp +++ b/src/internal/xml_policy.hpp @@ -31,7 +31,7 @@ enum class TreeType : uint8_t { OWN }; -namespace _ldp_xml_parser +namespace ldp_xml_parser { namespace { static const std::string ROOT_FIELD = "busconfig"; diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 1878d9e..7ad44dd 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -57,48 +57,48 @@ typedef unsigned long dbus_uid_t; typedef unsigned long dbus_gid_t; struct kconn { - int fd; - uint64_t id; - char *pool; + int fd; + uint64_t id; + char *pool; } g_conn[2]; struct udesc { - char user[256]; - dbus_uid_t uid; - char group[256]; - dbus_gid_t gid; - char label[256]; + char user[256]; + dbus_uid_t uid; + char group[256]; + dbus_gid_t gid; + char label[256]; } g_udesc; static int kdbus_open_bus(const char *path) { - return open(path, O_RDWR|O_NOCTTY|O_LARGEFILE|O_CLOEXEC); + return open(path, O_RDWR|O_NOCTTY|O_LARGEFILE|O_CLOEXEC); } static int kdbus_hello(bool bus_type, uint64_t hello_flags, uint64_t attach_flags_send, uint64_t attach_flags_recv) { - struct kdbus_cmd_hello cmd; + struct kdbus_cmd_hello cmd; int fd = g_conn[bus_type].fd; - cmd.size = sizeof(cmd); - cmd.flags = hello_flags; - cmd.attach_flags_send = attach_flags_send; - cmd.attach_flags_recv = attach_flags_recv; - cmd.pool_size = KDBUS_POOL_SIZE; + cmd.size = sizeof(cmd); + cmd.flags = hello_flags; + cmd.attach_flags_send = attach_flags_send; + cmd.attach_flags_recv = attach_flags_recv; + cmd.pool_size = KDBUS_POOL_SIZE; - if (ioctl(fd, KDBUS_CMD_HELLO, &cmd) < 0) - return -errno; + if (ioctl(fd, KDBUS_CMD_HELLO, &cmd) < 0) + return -errno; - g_conn[bus_type].id = cmd.id; - if (MAP_FAILED == (g_conn[bus_type].pool = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0))) - return -errno; + g_conn[bus_type].id = cmd.id; + if (MAP_FAILED == (g_conn[bus_type].pool = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0))) + return -errno; - return 0; + return 0; } static bool kdbus_is_unique_id(const char* name) { - return ':' == name[0]; + return ':' == name[0]; } static uint64_t kdbus_unique_id(char const *name) @@ -115,74 +115,74 @@ static uint64_t kdbus_unique_id(char const *name) static bool dbuspolicy_init_once(void) { - struct passwd pwent; - struct passwd *pwd; - struct group grent; - struct group *gg; - char buf[1024]; - int attr_fd; - int r; + struct passwd pwent; + struct passwd *pwd; + struct group grent; + struct group *gg; + char buf[1024]; + int attr_fd; + int r; - attr_fd = open("/proc/self/attr/current", O_RDONLY); - if (attr_fd < 0) - return -1; - r = read(attr_fd, buf, sizeof(buf)); + attr_fd = open("/proc/self/attr/current", O_RDONLY); + if (attr_fd < 0) + return -1; + r = read(attr_fd, buf, sizeof(buf)); - close(attr_fd); + close(attr_fd); - if (r < 0 || r >= (long int)sizeof(g_udesc.label)) /* read */ - return true; + if (r < 0 || r >= (long int)sizeof(g_udesc.label)) /* read */ + return true; - g_udesc.uid = getuid(); - g_udesc.gid = getgid(); + g_udesc.uid = getuid(); + g_udesc.gid = getgid(); - snprintf(g_udesc.label, r + 1 /* additional byte for \0 */, "%s", buf); - if (getpwuid_r(g_udesc.uid, &pwent, buf, sizeof(buf), &pwd)) - return true; + snprintf(g_udesc.label, r + 1 /* additional byte for \0 */, "%s", buf); + if (getpwuid_r(g_udesc.uid, &pwent, buf, sizeof(buf), &pwd)) + return true; - if (getgrgid_r(g_udesc.gid, &grent, buf, sizeof(buf), &gg)) - return true; + if (getgrgid_r(g_udesc.gid, &grent, buf, sizeof(buf), &gg)) + return true; - if (!pwd || !gg) - return false; + if (!pwd || !gg) + return false; - snprintf(g_udesc.user, sizeof(g_udesc.user), "%s", pwd->pw_name); - snprintf(g_udesc.group, sizeof(g_udesc.group), "%s", gg->gr_name); + snprintf(g_udesc.user, sizeof(g_udesc.user), "%s", pwd->pw_name); + snprintf(g_udesc.group, sizeof(g_udesc.group), "%s", gg->gr_name); __internal_init_once(); - return false; + return false; } static int bus_path_resolve(const char *bus_path, char *resolved_path, unsigned resolved_path_size, unsigned int *bus_type) { - char rp[PATH_MAX]; - char *p; - const char user_suffix[] = "-user/bus"; - int suffix_pos; + char rp[PATH_MAX]; + char *p; + const char user_suffix[] = "-user/bus"; + int suffix_pos; - p = realpath(bus_path, rp); - if (!p) - return -1; + p = realpath(bus_path, rp); + if (!p) + return -1; - if (0 != strncmp(p, KDBUS_PATH_PREFIX, strlen(KDBUS_PATH_PREFIX))) - return -1; + if (0 != strncmp(p, KDBUS_PATH_PREFIX, strlen(KDBUS_PATH_PREFIX))) + return -1; - if (0 == strcmp(p, KDBUS_SYSTEM_BUS_PATH)) { - *bus_type = SYSTEM_BUS; - } else { - suffix_pos = strlen(p) - strlen(user_suffix); - if (suffix_pos < 0) - return -1; + if (0 == strcmp(p, KDBUS_SYSTEM_BUS_PATH)) { + *bus_type = SYSTEM_BUS; + } else { + suffix_pos = strlen(p) - strlen(user_suffix); + if (suffix_pos < 0) + return -1; - if (0 != strcmp(p + suffix_pos, user_suffix)) - return -1; + if (0 != strcmp(p + suffix_pos, user_suffix)) + return -1; - *bus_type = SESSION_BUS; - } + *bus_type = SESSION_BUS; + } - snprintf(resolved_path, resolved_path_size, "%s", p); - return 0; + snprintf(resolved_path, resolved_path_size, "%s", p); + return 0; } static bool init_once_done = false; @@ -260,15 +260,15 @@ static bool configuration_bus_type(struct kconn const *configuration) { return c * 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) + 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) { char const *label = NULL; const char* k_names[KDBUS_CONN_MAX_NAMES+1]; @@ -332,23 +332,23 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration, for (item = conn_info->items; (uintptr_t)item < items_end; item = (typeof(item))ALIGN8((uintptr_t)item + (unsigned)item->size)) switch ((unsigned)item->type) { - case KDBUS_ITEM_CREDS: - uid_n = item->creds.euid; - gid_n = item->creds.egid; - break; - case KDBUS_ITEM_SECLABEL: - label = item->str; - break; - case KDBUS_ITEM_OWNED_NAME: - empty_names = false; - if (r <= 0) - k_names[k_i++] = item->name.name; - break; + case KDBUS_ITEM_CREDS: + uid_n = item->creds.euid; + gid_n = item->creds.egid; + break; + case KDBUS_ITEM_SECLABEL: + label = item->str; + break; + case KDBUS_ITEM_OWNED_NAME: + empty_names = false; + if (r <= 0) + k_names[k_i++] = item->name.name; + break; } } - if (empty_names) - r = __internal_can_send(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, destination, path, interface, member, message_type); + if (empty_names) + r = __internal_can_send(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, destination, path, interface, member, message_type); else { k_names[k_i++] = NULL; r = __internal_can_send_multi_dest(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, k_names, path, interface, member, message_type); @@ -364,7 +364,7 @@ end: ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &cmd.cmd_free); __internal_exit(); - return r; + return r; } /** @@ -375,36 +375,36 @@ end: * 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) + 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) { - int r; + int r; bool bus_type = configuration_bus_type(configuration); __internal_enter(); - r = __internal_can_send(bus_type, sender_uid, sender_gid, sender_label, destination, path, interface, member, message_type); + r = __internal_can_send(bus_type, sender_uid, sender_gid, sender_label, destination, path, interface, member, message_type); if (r <= 0) goto end; if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) { r = __internal_can_recv(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, sender, path, interface, member, message_type); - if (r <= 0) - goto end; - } + if (r <= 0) + goto end; + } end: - __internal_exit(); - return r; + __internal_exit(); + return r; } /** @@ -419,7 +419,7 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_can_own(void* configuration, const char* cons int r; bool bus_type = configuration_bus_type(configuration); __internal_enter(); - r = __internal_can_own(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, service); + r = __internal_can_own(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, service); __internal_exit(); return r; } diff --git a/src/test-libdbuspolicy1-method.cpp b/src/test-libdbuspolicy1-method.cpp index 8aa3738..d1116da 100644 --- a/src/test-libdbuspolicy1-method.cpp +++ b/src/test-libdbuspolicy1-method.cpp @@ -6,7 +6,7 @@ #include "internal/internal.h" #include "internal/policy.hpp" -using namespace _ldp_xml_parser; +using namespace ldp_xml_parser; const char* system_path = "tests/system.conf"; -- 2.7.4 From 54a071e9e09e08497ac6c01c511372f722638b38 Mon Sep 17 00:00:00 2001 From: Kazimierz Krosman Date: Mon, 30 May 2016 15:43:01 +0200 Subject: [PATCH 16/16] Fix: xml parser + minor fixes Fixed xml parser bug that causes that only first works as it should. Removed deadlock in init when logs are enabled Minor refactors Change-Id: I94c97efff478cf919cc5809f106bca1bb1465889 --- src/internal/policy.cpp | 5 +++-- src/internal/policy.hpp | 2 +- src/internal/xml_parser.hpp | 20 +++++++++++--------- src/libdbuspolicy1.c | 10 +++++++--- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/internal/policy.cpp b/src/internal/policy.cpp index 021a4be..da65a5c 100644 --- a/src/internal/policy.cpp +++ b/src/internal/policy.cpp @@ -1,6 +1,5 @@ #include "policy.hpp" #include "naive_policy_db.hpp" -//#include "tslog.hpp" #include #include #include @@ -192,7 +191,7 @@ void DbAdapter::xmlTraversal(bool bus, } } -void DbAdapter::updateDb(bool bus, boost::property_tree::ptree& xmlTree) { +void DbAdapter::updateDb(bool bus, boost::property_tree::ptree& xmlTree, std::vector& incl_dirs) { const auto& children = xmlTree.get_child("busconfig"); PolicyType policy_type; PolicyTypeValue policy_type_value; @@ -201,6 +200,8 @@ void DbAdapter::updateDb(bool bus, boost::property_tree::ptree& xmlTree) { __tag_state = POLICY; __attr = false; xmlTraversal(bus, x.second, POLICY, policy_type, policy_type_value); + } else if (x.first == "includedir") { + incl_dirs.push_back(x.second.data()); } } } diff --git a/src/internal/policy.hpp b/src/internal/policy.hpp index 4909e4e..aa93cc8 100644 --- a/src/internal/policy.hpp +++ b/src/internal/policy.hpp @@ -186,7 +186,7 @@ namespace ldp_xml_parser int level = 0); public: DbAdapter(NaivePolicyDb& system, NaivePolicyDb& session); - void updateDb(bool bus, boost::property_tree::ptree& xmlTree); + void updateDb(bool bus, boost::property_tree::ptree& xmlTree, std::vector& incl_dirs); static uid_t convertToUid(const char* user); static gid_t convertToGid(const char* group); }; diff --git a/src/internal/xml_parser.hpp b/src/internal/xml_parser.hpp index 26aee38..0dfb668 100644 --- a/src/internal/xml_parser.hpp +++ b/src/internal/xml_parser.hpp @@ -23,7 +23,6 @@ #include #include #include -//#include "xml_policy.hpp" #include "libdbuspolicy1-private.hpp" #include "tslog.hpp" #include "policy.hpp" @@ -65,13 +64,14 @@ namespace ldp_xml_parser ErrCode parse(bool bus, bool first, const std::string& filename, std::vector& included_files) { std::pair errparam; - + std::vector incl_dirs; if (tslog::verbose()) std::cout << "=== XML PARSING BEGIN === : " << filename << '\n'; - errparam = parseXml(bus, filename); - if (first && errparam.first.get() >= 0 && errparam.second != "") - getIncludedFiles(filename, errparam.second, included_files); + errparam = parseXml(bus, filename, incl_dirs); + for (int i = 0; i < incl_dirs.size(); i++) { + getIncludedFiles(filename, incl_dirs[i], included_files); + } if (tslog::enabled()) { if (tslog::verbose()) @@ -88,7 +88,10 @@ namespace ldp_xml_parser std::string fname; std::copy(filename.begin(), filename.end(), fname.begin()); std::string dname = dirname(const_cast(fname.c_str())); - dname += (std::string("/") + incldir); + if (incldir[0] != '/') + dname += (std::string("/") + incldir); + else + dname = incldir; files.clear(); if((dir = opendir(dname.c_str())) != NULL) { while((ent = readdir(dir)) != NULL) { @@ -108,7 +111,7 @@ namespace ldp_xml_parser std::cout << "could not open directory " << dname << '\n'; } - std::pair parseXml(bool bus, const std::string& filename) { + std::pair parseXml(bool bus, const std::string& filename, std::vector& incl_dirs) { std::pair ret; if (__parsed.insert(filename).second) @@ -116,8 +119,7 @@ namespace ldp_xml_parser boost::property_tree::ptree pt; read_xml(filename, pt); if (!pt.empty()) { - __adapter->updateDb(bus, pt); - ret.second = pt.get("busconfig.includedir", ""); + __adapter->updateDb(bus, pt, incl_dirs); } } catch(const boost::property_tree::xml_parser::xml_parser_error& ex) { ret.first = ErrCode::error(ex.what()); diff --git a/src/libdbuspolicy1.c b/src/libdbuspolicy1.c index 7ad44dd..c274833 100644 --- a/src/libdbuspolicy1.c +++ b/src/libdbuspolicy1.c @@ -219,13 +219,17 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init(const char *bus_path) goto err_close; rp = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY); - rs = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY); + if (rp < 0) + rs = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY); + else + rs = 1; + + pthread_mutex_unlock(&g_mutex); __internal_init_flush_logs(); - if ((rp & rs) < 0) /* when both negative */ + if (rp < 0 && rs < 0) /* when both negative */ goto err_close; - pthread_mutex_unlock(&g_mutex); return &g_conn[bus_type]; err_close: -- 2.7.4