pio: check if the client has privilege 54/156254/2 accepted/tizen/unified/20171019.145459 submit/tizen/20171018.072430
authorkibak.yoon <kibak.yoon@samsung.com>
Tue, 17 Oct 2017 16:21:09 +0000 (01:21 +0900)
committerkibak.yoon <kibak.yoon@samsung.com>
Wed, 18 Oct 2017 01:42:40 +0000 (10:42 +0900)
Change-Id: I6cdd412fe8f17001717e68e13eccbb60fc16fd70
Signed-off-by: kibak.yoon <kibak.yoon@samsung.com>
CMakeLists.txt
packaging/peripheral-bus.spec
src/daemon/include/peripheral_bus.h
src/daemon/include/privilege_checker.h [new file with mode: 0644]
src/daemon/peripheral_bus.c
src/daemon/peripheral_bus_gdbus_gpio.c
src/daemon/peripheral_bus_util.c
src/daemon/privilege_checker.c [new file with mode: 0644]

index 44333a4..1ac4d25 100644 (file)
@@ -4,7 +4,7 @@ PROJECT(peripheral-bus C)
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(VERSION 0.0.1)
 
-SET(dependents "dlog glib-2.0 gio-2.0 gio-unix-2.0 libsystemd-daemon iniparser libudev")
+SET(dependents "dlog glib-2.0 gio-2.0 gio-unix-2.0 libsystemd-daemon iniparser libudev cynara-creds-gdbus cynara-client cynara-session")
 
 FIND_PROGRAM(GDBUS_CODEGEN NAMES gdbus-codegen)
 EXEC_PROGRAM(${GDBUS_CODEGEN} ARGS
@@ -35,6 +35,7 @@ SET(SRCS
        src/daemon/peripheral_bus_spi.c
        src/daemon/peripheral_bus_board.c
        src/daemon/peripheral_io_gdbus.c
+       src/daemon/privilege_checker.c
        src/interface/gpio.c
        src/interface/i2c.c
        src/interface/pwm.c
index 39d0bad..f773838 100644 (file)
@@ -17,6 +17,9 @@ BuildRequires:  pkgconfig(libsystemd)
 BuildRequires:  pkgconfig(capi-system-peripheral-io)
 BuildRequires:  pkgconfig(iniparser)
 BuildRequires:  pkgconfig(libudev)
+BuildRequires:  pkgconfig(cynara-creds-gdbus)
+BuildRequires:  pkgconfig(cynara-client)
+BuildRequires:  pkgconfig(cynara-session)
 
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
index 7c2f661..206c4d4 100644 (file)
@@ -22,6 +22,8 @@
 #include "peripheral_io_gdbus.h"
 #include "peripheral_bus_board.h"
 
+#define PERIPHERAL_PRIVILEGE "http://tizen.org/privilege/peripheralio"
+
 typedef enum {
        PERIPHERAL_BUS_TYPE_GPIO = 0,
        PERIPHERAL_BUS_TYPE_I2C,
diff --git a/src/daemon/include/privilege_checker.h b/src/daemon/include/privilege_checker.h
new file mode 100644 (file)
index 0000000..a39fb8d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd.
+ *
+ * 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 __PRIVILEGE_CHECKER_H__
+#define __PRIVILEGE_CHECKER_H__
+
+#include <stdbool.h>
+
+void peripheral_privilege_init(void);
+void peripheral_privilege_deinit(void);
+bool peripheral_privilege_check(const char* client, const char* session, const char* user, const char* privilege);
+
+#endif /* __PRIVILEGE_CHECKER_H__ */
index 4822915..99832de 100644 (file)
@@ -32,6 +32,8 @@
 #include "peripheral_bus_gdbus_spi.h"
 #include "peripheral_bus_gdbus_uart.h"
 
+#include "privilege_checker.h"
+
 static gboolean __gpio_init(peripheral_bus_s *pb_data)
 {
        GDBusObjectManagerServer *manager;
@@ -323,6 +325,7 @@ static void on_bus_acquired(GDBusConnection *connection,
        peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
 
        pb_data->connection = connection;
+
        if (__gpio_init(pb_data) == FALSE)
                _E("Can not signal connect");
 
@@ -395,9 +398,13 @@ int main(int argc, char *argv[])
 
        g_idle_add(peripheral_bus_notify, NULL);
 
+       peripheral_privilege_init();
+
        _D("Enter main loop!");
        g_main_loop_run(loop);
 
+       peripheral_privilege_deinit();
+
        if (pb_data) {
                peripheral_bus_board_deinit(pb_data->board);
                free(pb_data);
index ed53154..d52cac7 100644 (file)
@@ -47,9 +47,8 @@ gboolean handle_gpio_open(
        if ((ret = peripheral_bus_gpio_open(pin, &gpio_handle, user_data)) < PERIPHERAL_ERROR_NONE)
                goto out;
 
-       if (peripheral_bus_get_client_info(invocation, pb_data, &gpio_handle->client_info) < 0) {
+       if ((ret = peripheral_bus_get_client_info(invocation, pb_data, &gpio_handle->client_info)) < 0) {
                peripheral_bus_gpio_close(gpio_handle);
-               ret = PERIPHERAL_ERROR_UNKNOWN;
                gpio_handle = NULL;
                goto out;
        }
index 7fcc4b6..2c56614 100644 (file)
 #include <string.h>
 #include <gio/gio.h>
 
+#include <cynara-creds-gdbus.h>
+#include <cynara-client.h>
+#include <cynara-session.h>
+
 #include "peripheral_bus.h"
 #include "peripheral_common.h"
 
+#include "privilege_checker.h"
+
 GVariant *peripheral_bus_build_variant_ay(uint8_t *data, int length)
 {
        GVariantBuilder *builder;
@@ -98,6 +104,43 @@ int peripheral_bus_data_free(pb_data_h handle)
        return 0;
 }
 
+static int peripheral_bus_check_privilege(
+               GDBusMethodInvocation *invocation,
+               peripheral_bus_s *pb_data)
+{
+       int pid;
+       const char *sender;
+       char *session;
+       char *client;
+       char *user;
+
+       sender = g_dbus_method_invocation_get_sender(invocation);
+
+       cynara_creds_gdbus_get_pid(pb_data->connection, sender, &pid);
+       session = cynara_session_from_pid(pid);
+
+       cynara_creds_gdbus_get_client(pb_data->connection, sender, CLIENT_METHOD_DEFAULT, &client);
+       cynara_creds_gdbus_get_user(pb_data->connection, sender, USER_METHOD_DEFAULT, &user);
+
+       if (!session || !client || !user) {
+               _E("Failed to get client info");
+               return -1;
+       }
+
+       if (!peripheral_privilege_check(client, session, user, PERIPHERAL_PRIVILEGE)) {
+               g_free(session);
+               g_free(client);
+               g_free(user);
+               return -EACCES;
+       }
+
+       g_free(session);
+       g_free(client);
+       g_free(user);
+
+       return 0;
+}
+
 int peripheral_bus_get_client_info(
                GDBusMethodInvocation *invocation,
                peripheral_bus_s *pb_data,
@@ -107,6 +150,7 @@ int peripheral_bus_get_client_info(
        GError *error = NULL;
        GVariant *_ret;
        const gchar *id;
+       int err;
 
        id = g_dbus_method_invocation_get_sender(invocation);
        if (id == NULL) {
@@ -136,6 +180,11 @@ int peripheral_bus_get_client_info(
        g_variant_get(_ret, "(u)", &pid);
        g_variant_unref(_ret);
 
+       if ((err = peripheral_bus_check_privilege(invocation, pb_data)) < 0) {
+               _E("Permission denied(%d)", pid);
+               return err;
+       }
+
        client_info->pid = (pid_t)pid;
        client_info->pgid = getpgid(pid);
        client_info->id = strdup(id);
diff --git a/src/daemon/privilege_checker.c b/src/daemon/privilege_checker.c
new file mode 100644 (file)
index 0000000..20c3760
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <peripheral_io.h>
+
+#include <cynara-creds-gdbus.h>
+#include <cynara-client.h>
+#include <cynara-session.h>
+
+#include "peripheral_bus.h"
+#include "peripheral_common.h"
+
+#define CACHE_SIZE  100
+
+static cynara *__cynara;
+
+void peripheral_privilege_init(void)
+{
+       int err;
+       cynara_configuration* conf = NULL;
+
+       err = cynara_configuration_create(&conf);
+       RETM_IF(err != CYNARA_API_SUCCESS, "Failed to create cynara configuration");
+
+       err = cynara_configuration_set_cache_size(conf, CACHE_SIZE);
+       if (err != CYNARA_API_SUCCESS) {
+               _E("Failed to set cynara cache size");
+               cynara_configuration_destroy(conf);
+               return;
+       }
+
+       err = cynara_initialize(&__cynara, conf);
+       cynara_configuration_destroy(conf);
+       if (err != CYNARA_API_SUCCESS) {
+               _E("Failed to initialize cynara");
+               __cynara = NULL;
+               return;
+       }
+
+       _D("Cynara initialized");
+}
+
+void peripheral_privilege_deinit(void)
+{
+       if (__cynara)
+               cynara_finish(__cynara);
+
+       _D("Cynara deinitialized");
+}
+
+bool peripheral_privilege_check(const char* client, const char* session, const char* user, const char* privilege)
+{
+       RETVM_IF(!privilege, true, "Invalid parameter");
+       RETVM_IF(!__cynara, false, "Cynara does not initialized");
+
+       int ret = cynara_check(__cynara, client, session, user, privilege);
+       return (ret == CYNARA_API_ACCESS_ALLOWED);
+}