Apply cynara 10/37610/8 tizen_3.0.2015.q2_common accepted/tizen/common/20150521.125406 accepted/tizen/mobile/20150409.080806 accepted/tizen/tv/20150409.080315 accepted/tizen/wearable/20150409.080539 submit/tizen/20150409.010930 submit/tizen_common/20150520.888883
authorSunggoo Kim <sung.goo.kim@samsung.com>
Wed, 1 Apr 2015 03:40:45 +0000 (12:40 +0900)
committerSunggoo Kim <sung.goo.kim@samsung.com>
Wed, 8 Apr 2015 22:41:00 +0000 (07:41 +0900)
Change-Id: Ifff36ce80f5ae65e14e5e91a788c3c3b56a1c0a1

CMakeLists.txt
include/pims-ipc-svc.h
packaging/pims-ipc.spec
pims-ipc.pc.in
src/pims-ipc-svc.c

index 21863e1..55de936 100755 (executable)
@@ -14,8 +14,6 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(EXEC_PREFIX "\${prefix}")
 
 SET(INCLUDEDIR "\${prefix}/${DEST_INCLUDE_DIR}")
-SET(VERSION_MAJOR 0)
-SET(VERSION "${VERSION_MAJOR}.1.6")
 
 INCLUDE_DIRECTORIES(${SRC_INCLUDE_DIR})
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -I${CMAKE_SOURCE_DIR}/src -I${SRC_INCLUDE_DIR}")
@@ -23,7 +21,7 @@ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -I${CMAKE_SOURCE_DIR}/src -I${SRC_INCLUDE_DIR}
 FILE(GLOB SRCS src/*.c)
 
 INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog libsystemd-daemon)
+pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog libsystemd-daemon cynara-client cynara-creds-socket cynara-session)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
@@ -37,8 +35,8 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -Wall -g -fPIC -std=c++0
 ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
 
 ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
-SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
-SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${FULLVER})
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
 
 CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
index 918d105..87410d7 100644 (file)
@@ -40,6 +40,10 @@ void pims_ipc_svc_run_main_loop(GMainLoop* main_loop);
 
 void pims_ipc_svc_set_client_disconnected_cb(pims_ipc_svc_client_disconnected_cb callback, void *userdata);
 
+int pims_ipc_svc_get_smack_label(pims_ipc_h ipc, char **p_smack);
+bool pims_ipc_svc_check_privilege(pims_ipc_h ipc, char *privilege);
+
+
 #ifdef __cplusplus
 }
 #endif
index 48237d6..1905b63 100644 (file)
@@ -1,15 +1,19 @@
 Name:       pims-ipc
 Summary:    library for PIMs IPC
-Version:    0.1.6
+Version:    0.1.7
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
 
+BuildRequires: awk
 BuildRequires: cmake
 BuildRequires: pkgconfig(glib-2.0)
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(libsystemd-daemon)
+BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(cynara-creds-socket)
+BuildRequires: pkgconfig(cynara-session)
 
 %description
 library for PIMs IPC
@@ -30,7 +34,9 @@ library for PIMs IPC (developement files)
 export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
 export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
 export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
-%cmake .
+
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+%cmake . -DMAJORVER=${MAJORVER} -DFULLVER=%{version}
 make %{?jobs:-j%jobs}
 
 %install
index 20e62ee..c6931e6 100755 (executable)
@@ -7,7 +7,7 @@ includedir=@INCLUDE_INSTALL_DIR@/pims-ipc
 
 Name: @PROJECT_NAME@
 Description: @PROJECT_NAME@ library
-Version: @VERSION@
+Version: @FULLVER@
 Requires: glib-2.0
 Libs: -L${libdir} -l@PROJECT_NAME@
 Cflags: -I${includedir}
index 796caa4..0d86912 100644 (file)
 #include <sys/socket.h>                //socket
 #include <sys/types.h>
 
+#include <cynara-client.h>
+#include <cynara-session.h>
+#include <cynara-creds-socket.h>
+
 #include "pims-internal.h"
 #include "pims-debug.h"
 #include "pims-socket.h"
@@ -92,9 +96,22 @@ typedef struct {
        // managed by manager, router find idle worker when connecting new client in router thread => remove from idle workers
        GList *workers;          // worker_fd list, not need mutex
        /////////////////////////////////////////////
+       cynara *cynara;
+       pthread_mutex_t cynara_mutex;
+
+       int unique_sequence_number;
+       pthread_mutex_t client_info_mutex;
+       GHashTable *worker_client_info_map; // key : worker_id, data : pims_ipc_client_info_s*
+       GHashTable *client_info_map; // key : client_id, data : pims_ipc_client_info_s*
 } pims_ipc_svc_s;
 
 typedef struct {
+       char *smack;
+       char *uid;
+       char *client_session;
+} pims_ipc_client_info_s ;
+
+typedef struct {
        char *service;
        gid_t group;
        mode_t mode;
@@ -182,6 +199,18 @@ static void __worker_data_free(gpointer data)
        free(worker_data);
 }
 
+static void _destroy_client_info(gpointer p)
+{
+       pims_ipc_client_info_s *client_info = p;
+
+       if (NULL == client_info)
+               return;
+       free(client_info->smack);
+       free(client_info->uid);
+       free(client_info->client_session);
+       free(client_info);
+}
+
 API int pims_ipc_svc_init(char *service, gid_t group, mode_t mode)
 {
        if (_g_singleton) {
@@ -189,6 +218,14 @@ API int pims_ipc_svc_init(char *service, gid_t group, mode_t mode)
                return -1;
        }
 
+       int ret = cynara_initialize(&_g_singleton->cynara, NULL);
+       if (CYNARA_API_SUCCESS != ret) {
+               char errmsg[1024];
+               cynara_strerror(ret, errmsg, sizeof(errmsg));
+               ERROR("cynara_initialize() Fail(%d,%s)", ret, errmsg);
+               return -1;
+       }
+
        _g_singleton = g_new0(pims_ipc_svc_s, 1);
        _g_singleton->service = g_strdup(service);
        _g_singleton->group = group;
@@ -216,6 +253,13 @@ API int pims_ipc_svc_init(char *service, gid_t group, mode_t mode)
        _g_singleton->manager_queue_from_worker = NULL;
        _g_singleton->workers = NULL;
 
+       _g_singleton->unique_sequence_number = 0;
+
+       _g_singleton->worker_client_info_map = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _destroy_client_info);
+       _g_singleton->client_info_map = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _destroy_client_info);
+       pthread_mutex_init(&_g_singleton->client_info_mutex, 0);
+
+       pthread_mutex_init(&_g_singleton->cynara_mutex, 0);
        _g_singleton->epoll_stop_thread = false;
 
        return 0;
@@ -253,6 +297,20 @@ API int pims_ipc_svc_deinit(void)
        }
        g_list_free(_g_singleton->client_id_fd_map);
 
+       pthread_mutex_destroy(&_g_singleton->client_info_mutex);
+       g_hash_table_destroy(_g_singleton->worker_client_info_map);
+       g_hash_table_destroy(_g_singleton->client_info_map);
+
+       pthread_mutex_lock(&_g_singleton->cynara_mutex);
+       int ret = cynara_finish(_g_singleton->cynara);
+       if (CYNARA_API_SUCCESS != ret) {
+               char errmsg[1024];
+               cynara_strerror(ret, errmsg, sizeof(errmsg));
+               ERROR("cynara_finish() Fail(%d,%s)", ret, errmsg);
+       }
+       pthread_mutex_unlock(&_g_singleton->cynara_mutex);
+       pthread_mutex_destroy(&_g_singleton->cynara_mutex);
+
        g_list_free(_g_singleton->workers);
        g_free(_g_singleton);
        _g_singleton = NULL;
@@ -612,6 +670,10 @@ static void* __worker_loop(void *data)
                ERROR("client fd closed, worker_fd : %d", worker_fd);
        INFO("task thread terminated --------------------------- (worker_fd : %d)", worker_fd);
 
+       pthread_mutex_lock(&ipc_svc->client_info_mutex);
+       g_hash_table_remove(ipc_svc->worker_client_info_map, GINT_TO_POINTER(worker_id));
+       pthread_mutex_unlock(&ipc_svc->client_info_mutex);
+
        pthread_mutex_lock(&ipc_svc->task_fds_mutex);
        g_hash_table_remove(ipc_svc->task_fds, GINT_TO_POINTER(worker_fd));             // __worker_data_free will be called
        pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
@@ -647,20 +709,20 @@ static gboolean __is_worker_available()
                return FALSE;
 }
 
-static int __get_worker(const char *client_id, int *worker_id)
+static int __get_worker(const char *client_id, int *worker_fd)
 {
        ASSERT(client_id);
-       ASSERT(worker_id);
+       ASSERT(worker_fd);
 
        if (!__is_worker_available()) {
                ERROR("There is no idle worker");
                return -1;
        }
-       *worker_id = (int)(g_list_first(_g_singleton->workers)->data);
+       *worker_fd = (int)(g_list_first(_g_singleton->workers)->data);
        _g_singleton->workers = g_list_delete_link(_g_singleton->workers,
                        g_list_first(_g_singleton->workers));
 
-       g_hash_table_insert(_g_singleton->client_worker_map, g_strdup(client_id), GINT_TO_POINTER(*worker_id));
+       g_hash_table_insert(_g_singleton->client_worker_map, g_strdup(client_id), GINT_TO_POINTER(*worker_fd));
 
        return 0;
 }
@@ -714,6 +776,113 @@ static bool __worker_raw_data_push(pims_ipc_worker_data_s *worker_data, int clie
        return true;
 }
 
+static int _find_worker_id(pims_ipc_svc_s *ipc_svc, int worker_fd)
+{
+       int worker_id = 0;
+       pims_ipc_worker_data_s *worker_data = NULL;
+       pthread_mutex_lock(&ipc_svc->task_fds_mutex);
+       worker_data = g_hash_table_lookup(ipc_svc->task_fds, GINT_TO_POINTER(worker_fd));
+       if (NULL == worker_data) {
+               ERROR("g_hash_table_lookup(%d) return NULL", worker_fd);
+               pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+               return -1;
+       }
+       worker_id = worker_data->worker_id;
+       pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+       return worker_id;
+}
+
+static int _create_client_info(int fd, pims_ipc_client_info_s **p_client_info)
+{
+       int ret;
+       pid_t pid;
+       char errmsg[1024];
+
+       pims_ipc_client_info_s *client_info = calloc(1, sizeof(pims_ipc_client_info_s));
+       if (NULL == client_info) {
+               ERROR("calloc() return NULL");
+               return -1;
+       }
+
+       ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_SMACK, &(client_info->smack));
+       if (CYNARA_API_SUCCESS != ret) {
+               cynara_strerror(ret, errmsg, sizeof(errmsg));
+               ERROR("cynara_creds_socket_get_client() Fail(%d,%s)", ret, errmsg);
+               _destroy_client_info(client_info);
+               return -1;
+       }
+
+       ret = cynara_creds_socket_get_user(fd, USER_METHOD_UID, &(client_info->uid));
+       if (CYNARA_API_SUCCESS != ret) {
+               cynara_strerror(ret, errmsg, sizeof(errmsg));
+               ERROR("cynara_creds_socket_get_user() Fail(%d,%s)", ret, errmsg);
+               _destroy_client_info(client_info);
+               return -1;
+       }
+
+       ret = cynara_creds_socket_get_pid(fd, &pid);
+       if (CYNARA_API_SUCCESS != ret) {
+               cynara_strerror(ret, errmsg, sizeof(errmsg));
+               ERROR("cynara_creds_socket_get_pid() Fail(%d,%s)", ret, errmsg);
+               _destroy_client_info(client_info);
+               return -1;
+       }
+
+       client_info->client_session = cynara_session_from_pid(pid);
+       if (NULL == client_info->client_session) {
+               ERROR("cynara_session_from_pid() return NULL");
+               _destroy_client_info(client_info);
+               return -1;
+       }
+       *p_client_info = client_info;
+
+       return 0;
+}
+
+static pims_ipc_client_info_s* _clone_client_info(pims_ipc_client_info_s *client_info)
+{
+       if (NULL == client_info) {
+               ERROR("client_info is NULL");
+               return NULL;
+       }
+
+       pims_ipc_client_info_s *clone = calloc(1, sizeof(pims_ipc_client_info_s));
+       if (NULL == clone) {
+               ERROR("calloc() Fail");
+               return NULL;
+       }
+
+       if (client_info->smack) {
+               clone->smack = strdup(client_info->smack);
+               if (NULL == clone->smack) {
+                       ERROR("strdup() Fail");
+                       _destroy_client_info(clone);
+                       return NULL;
+               }
+       }
+
+       if (client_info->uid) {
+               clone->uid = strdup(client_info->uid);
+               if (NULL == clone->uid) {
+                       ERROR("strdup() Fail");
+                       _destroy_client_info(clone);
+                       return NULL;
+               }
+       }
+
+       if (client_info->client_session) {
+               clone->client_session = strdup(client_info->client_session);
+               if (NULL == clone->client_session) {
+                       ERROR("strdup() Fail");
+                       _destroy_client_info(clone);
+                       return NULL;
+               }
+       }
+
+       return clone;
+}
+
+
 static int __process_router_event(pims_ipc_svc_s *ipc_svc, gboolean for_queue)
 {
        gboolean is_valid = FALSE;
@@ -767,6 +936,12 @@ static int __process_router_event(pims_ipc_svc_s *ipc_svc, gboolean for_queue)
                                        is_valid = TRUE;
                                        break;
                                }
+                               int worker_id = _find_worker_id(ipc_svc, worker_fd);
+                               pthread_mutex_lock(&ipc_svc->client_info_mutex);
+                               pims_ipc_client_info_s *client_info = g_hash_table_lookup(ipc_svc->client_info_map, client_id);
+                               pims_ipc_client_info_s *client_info_clone = _clone_client_info(client_info);
+                               g_hash_table_insert(ipc_svc->worker_client_info_map, GINT_TO_POINTER(worker_id), client_info_clone);
+                               pthread_mutex_unlock(&ipc_svc->client_info_mutex);
                        }
                        else {
                                // Find a worker
@@ -1118,11 +1293,14 @@ static gboolean __request_handler(GIOChannel *src, GIOCondition condition, gpoin
 
                // Send client_id to manager to terminate worker thread
                if (client_id) {
+                       pthread_mutex_lock(&ipc_svc->client_info_mutex);
+                       g_hash_table_remove(ipc_svc->client_info_map, client_id);
+                       pthread_mutex_unlock(&ipc_svc->client_info_mutex);
+
                        pthread_mutex_lock(&ipc_svc->manager_queue_from_epoll_mutex);
                        ipc_svc->manager_queue_from_epoll = g_list_append(ipc_svc->manager_queue_from_epoll, (void*)g_strdup(client_id));
                        pthread_mutex_unlock(&ipc_svc->manager_queue_from_epoll_mutex);
                        write_command(ipc_svc->manager, 1);
-
                        __delete_request_queue(ipc_svc, client_id);
                        free(client_id);
                }
@@ -1141,18 +1319,29 @@ static gboolean __request_handler(GIOChannel *src, GIOCondition condition, gpoin
                if (identity) {
                        pims_ipc_client_map_s *client = (pims_ipc_client_map_s*)calloc(1, sizeof(pims_ipc_client_map_s));
                        client->fd = event_fd;
-                       client->id = req->client_id;
+
+                       char temp[100];
+                       snprintf(temp, sizeof(temp), "%d_%s", ipc_svc->unique_sequence_number++, req->client_id);
+                       client->id = strdup(temp);
+                       free(req->client_id);
                        req->client_id = NULL;
                        ipc_svc->client_id_fd_map = g_list_append(ipc_svc->client_id_fd_map, client);
 
                        // send server pid to client
-                       char temp[100];
                        snprintf(temp, sizeof(temp), "%x", getpid());
                        ret = __send_identify(event_fd, req->seq_no, temp, strlen(temp));
 
                        __free_raw_data(req);
                        if (ret < 0)
                                return FALSE;
+
+                       pims_ipc_client_info_s *client_info = NULL;
+                       if (0 != _create_client_info(event_fd, &client_info))
+                               ERROR("_create_client_info() Fail");
+                       pthread_mutex_lock(&ipc_svc->client_info_mutex);
+                       g_hash_table_insert(ipc_svc->client_info_map, g_strdup(client->id), client_info);
+                       pthread_mutex_unlock(&ipc_svc->client_info_mutex);
+
                        return TRUE;
                }
 
@@ -1502,4 +1691,68 @@ API void pims_ipc_svc_set_client_disconnected_cb(pims_ipc_svc_client_disconnecte
        _client_disconnected_cb.user_data = user_data;
 }
 
+API bool pims_ipc_svc_check_privilege(pims_ipc_h ipc, char *privilege)
+{
+       int ret;
+       int worker_id = (int)ipc;
+       pims_ipc_client_info_s *client_info = NULL;
+       pims_ipc_client_info_s *client_info_clone = NULL;
+
+       if (NULL == privilege) {
+               ERROR("privilege is NULL");
+               return false;
+       }
+
+       pthread_mutex_lock(&_g_singleton->client_info_mutex);
+       client_info = g_hash_table_lookup(_g_singleton->worker_client_info_map, GINT_TO_POINTER(worker_id));
+       if (NULL == client_info) {
+               ERROR("client_info is NULL");
+               pthread_mutex_unlock(&_g_singleton->client_info_mutex);
+               return false;
+       }
+       client_info_clone = _clone_client_info(client_info);
+       pthread_mutex_unlock(&_g_singleton->client_info_mutex);
+
+       if (NULL == client_info_clone) {
+               ERROR("client_info_clone is NULL");
+               return false;
+       }
+
+       pthread_mutex_lock(&_g_singleton->cynara_mutex);
+       ret = cynara_check(_g_singleton->cynara, client_info_clone->smack, client_info_clone->client_session, client_info_clone->uid, privilege);
+       pthread_mutex_unlock(&_g_singleton->cynara_mutex);
+
+       _destroy_client_info(client_info_clone);
+
+       if (CYNARA_API_ACCESS_ALLOWED == ret)
+               return true;
+
+       return false;
+}
+
+API int pims_ipc_svc_get_smack_label(pims_ipc_h ipc, char **p_smack)
+{
+       pims_ipc_client_info_s *client_info = NULL;
+       int worker_id = (int)ipc;
+
+       pthread_mutex_lock(&_g_singleton->client_info_mutex);
+       client_info = g_hash_table_lookup(_g_singleton->worker_client_info_map, GINT_TO_POINTER(worker_id));
+       if (NULL == client_info) {
+               ERROR("g_hash_table_lookup(%d) return NULL", worker_id);
+               pthread_mutex_unlock(&_g_singleton->client_info_mutex);
+               return -1;
+       }
+
+       if (client_info->smack) {
+               *p_smack = strdup(client_info->smack);
+               if (NULL == *p_smack) {
+                       ERROR("strdup() return NULL");
+                       pthread_mutex_unlock(&_g_singleton->client_info_mutex);
+                       return -1;
+               }
+       }
+       pthread_mutex_unlock(&_g_singleton->client_info_mutex);
+
+       return 0;
+}