From 0eb3a9972113efc2cd94a5daaea7195953cb4704 Mon Sep 17 00:00:00 2001 From: Minje Ahn Date: Tue, 25 Aug 2015 14:10:54 +0900 Subject: [PATCH] Append cynara Change-Id: Icd7c51a22dfae370b3e991dc290df2d4dab18682 Signed-off-by: Minje Ahn --- CMakeLists.txt | 2 +- packaging/capi-media-controller.spec | 2 + svc/CMakeLists.txt | 2 +- svc/daemon/media_controller_main.c | 8 ++ svc/media_controller_cynara.c | 159 +++++++++++++++++++++++++++++++++++ svc/media_controller_cynara.h | 40 +++++++++ svc/media_controller_svc.c | 47 ++++++----- 7 files changed, 236 insertions(+), 24 deletions(-) create mode 100644 svc/media_controller_cynara.c create mode 100644 svc/media_controller_cynara.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1635d53..4d52595 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ SET(service "media") SET(submodule "controller") # for package file -SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog sqlite3 db-util aul bundle libtzplatform-config") +SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog sqlite3 db-util aul bundle libtzplatform-config cynara-client cynara-session cynara-creds-socket") SET(fw_name "${project_prefix}-${service}-${submodule}") PROJECT(${fw_name}) diff --git a/packaging/capi-media-controller.spec b/packaging/capi-media-controller.spec index 8ec2b2b..6e88114 100755 --- a/packaging/capi-media-controller.spec +++ b/packaging/capi-media-controller.spec @@ -21,6 +21,8 @@ BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(bundle) BuildRequires: pkgconfig(libsystemd-daemon) BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-session) %description A media controller library in SLP C API diff --git a/svc/CMakeLists.txt b/svc/CMakeLists.txt index 1ed8b1a..e967ced 100755 --- a/svc/CMakeLists.txt +++ b/svc/CMakeLists.txt @@ -1,5 +1,5 @@ # for package file -SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog sqlite3 db-util libsystemd-daemon libtzplatform-config") +SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog sqlite3 db-util libsystemd-daemon libtzplatform-config cynara-client cynara-session cynara-creds-socket") SET(fw_svc "media-controller-svc") PROJECT(${fw_svc}) diff --git a/svc/daemon/media_controller_main.c b/svc/daemon/media_controller_main.c index 5eba81c..c653530 100755 --- a/svc/daemon/media_controller_main.c +++ b/svc/daemon/media_controller_main.c @@ -17,6 +17,7 @@ #include "media_controller_private.h" #include "../media_controller_socket.h" #include "../media_controller_svc.h" +#include "media_controller_cynara.h" GMainLoop *g_mc_mainloop = NULL; static int g_mc_timer_id = 0; @@ -68,6 +69,11 @@ int main(int argc, char **argv) /*Init main loop*/ g_mc_mainloop = g_main_loop_new(NULL, FALSE); + if(mc_cynara_initialize() != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("Failed to initialize cynara"); + return -1; + } + fd = mc_create_socket_activation(); if (fd < 0) { mc_error("Failed to socekt creation"); @@ -86,6 +92,8 @@ int main(int argc, char **argv) g_thread_join(svc_thread); g_main_loop_unref(g_mc_mainloop); + mc_cynara_finish(); + mc_debug("*** Media Controller Daemon is stopped ***"); return 0; diff --git a/svc/media_controller_cynara.c b/svc/media_controller_cynara.c new file mode 100644 index 0000000..02f98d3 --- /dev/null +++ b/svc/media_controller_cynara.c @@ -0,0 +1,159 @@ +/* +* Copyright (c) 2011 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. +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* this definition is missing in glibc headers (version 2.21). It was introduced in kernel version 2.6.17 */ +#ifndef SCM_SECURITY +#define SCM_SECURITY 0x03 +#endif + +static cynara *_cynara = NULL; +G_LOCK_DEFINE_STATIC(cynara_mutex); + +static void mc_cynara_dbg_err(const char *prefix, int error_code) +{ + char error_buffer[256]; + int err; + error_buffer[0] = '\0'; + + err = cynara_strerror(error_code, error_buffer, sizeof(error_buffer)); + if (err == CYNARA_API_SUCCESS) { + mc_error("%s: %s", prefix, error_buffer); + } else { + mc_error("%s: error code %i", prefix, error_code); + } +} + +int mc_cynara_initialize(void) +{ + int ret = cynara_initialize(&_cynara, NULL); + if (ret != CYNARA_API_SUCCESS) { + mc_cynara_dbg_err("cynara_initialize", ret); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + return MEDIA_CONTROLLER_ERROR_NONE; +} + +void mc_cynara_finish(void) +{ + cynara_finish(_cynara); + _cynara = NULL; +} + +int mc_cynara_receive_untrusted_message(int sockfd, mc_comm_msg_s *recv_msg, mc_peer_creds *credentials) +{ + int ret = 0; + int recv_msg_size = 0; + + if (!recv_msg ||!credentials) + return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; + + if ((recv_msg_size = read(sockfd, recv_msg, sizeof(mc_comm_msg_s))) < 0) { + if (errno == EWOULDBLOCK) { + mc_error("Timeout. Can't try any more"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } else { + mc_stderror("recv failed"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + } + +/* mc_debug("receive msg[%d] from [%d(%d)] %d, %s", recv_msg_size, recv_msg->pid, recv_msg->uid, recv_msg->msg_type, recv_msg->msg); */ + + ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid)); + if(ret < 0) { + mc_error("cynara_creds_socket_get_pid failed"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid)); + if(ret < 0) { + mc_error("cynara_creds_socket_get_user failed"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack)); + if(ret < 0) { + mc_error("cynara_creds_socket_get_client failed"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + +/* mc_error("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack); */ + + return MEDIA_CONTROLLER_ERROR_NONE; +} + +int mc_cynara_check(const mc_peer_creds *creds, const char *privilege) +{ + int result; + char *session; + + if (!creds || !privilege) + return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER; + + session = cynara_session_from_pid(creds->pid); + if (session == NULL) { + mc_error("cynara_session_from_pid failed"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + G_LOCK(cynara_mutex); + result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege); + G_UNLOCK(cynara_mutex); + + if (result != CYNARA_API_ACCESS_ALLOWED) + mc_cynara_dbg_err("cynara_check", result); + + MC_SAFE_FREE(session); + return result == CYNARA_API_ACCESS_ALLOWED ? MEDIA_CONTROLLER_ERROR_NONE: MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; +} + +int mc_cynara_enable_credentials_passing(int sockfd) +{ + const int optval = 1; + int err = 0; + + err = setsockopt(sockfd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval)); + if (err != 0) { + mc_error("Failed to set SO_PASSSEC socket option"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + err = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)); + if (err != 0) { + mc_error("Failed to set SO_PASSCRED socket option"); + return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION; + } + + return MEDIA_CONTROLLER_ERROR_NONE; +} diff --git a/svc/media_controller_cynara.h b/svc/media_controller_cynara.h new file mode 100644 index 0000000..1e0e569 --- /dev/null +++ b/svc/media_controller_cynara.h @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2011 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 __TIZEN_MEDIA_CONTROLLER_CYNARA_H__ +#define __TIZEN_MEDIA_CONTROLLER_CYNARA_H__ + +#include + +#include + +#define MC_CLIENT_PRIVILEGE "http://tizen.org/privilege/mediacontroller.client" +#define MC_SERVER_PRIVILEGE "http://tizen.org/privilege/mediacontroller.server" + +typedef struct { + pid_t pid; + char *uid; + char *smack; +} mc_peer_creds; + +int mc_cynara_initialize(void); +int mc_cynara_check(const mc_peer_creds *creds, const char *privilege); +int mc_cynara_receive_untrusted_message(int sockfd, mc_comm_msg_s *recv_msg, mc_peer_creds *credentials); +int mc_cynara_enable_credentials_passing(int sockfd); +void mc_cynara_finish(void); + + +#endif/* _MEDIA_CONTROLLER_CYNARA_H_ */ diff --git a/svc/media_controller_svc.c b/svc/media_controller_svc.c index 4b999cb..bb2f101 100755 --- a/svc/media_controller_svc.c +++ b/svc/media_controller_svc.c @@ -21,25 +21,11 @@ #include "media_controller_private.h" #include "media_controller_socket.h" #include "media_controller_db_util.h" +#include "media_controller_cynara.h" static GMainLoop *g_mc_svc_mainloop = NULL; static int g_connection_cnt = -1; -static int __mc_privilege_ask(int client_sockfd, const char *type, const char *privilege_object) -{ - int ret = MEDIA_CONTROLLER_ERROR_NONE; -#if 0 - ret = security_server_check_privilege_by_sockfd(client_sockfd, type, privilege_object); - if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) { - mc_error("You do not have permission for this operation."); - ret = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; - } else { - mc_debug("PERMISSION OK"); - } -#endif - return ret; -} - static int __create_socket_activation(void) { int fd = -1; @@ -69,6 +55,7 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi bool is_duplicated = FALSE; unsigned int i = 0; mc_svc_data_t *mc_svc_data = (mc_svc_data_t*)data; + mc_peer_creds creds = {0, }; mc_debug("mc_read_service_request_tcp_socket is called!!!!!"); @@ -84,7 +71,9 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi return TRUE; } - ret = mc_ipc_receive_message_tcp(client_sock, &recv_msg); + memset(&creds, 0, sizeof(mc_peer_creds)); + + ret = mc_cynara_receive_untrusted_message(client_sock, &recv_msg, &creds); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { mc_error("mc_ipc_receive_message_tcp failed [%d]", ret); send_msg = ret; @@ -114,13 +103,16 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi } } else if (recv_msg.msg_type == MC_MSG_CLIENT_SET) { /* check privileage */ - ret = __mc_privilege_ask(client_sock, "mediacontroller::svc", "w"); - if (ret == MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED) { - mc_error("permission is denied!"); + ret = mc_cynara_check(&creds, MC_CLIENT_PRIVILEGE); + if (ret != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("permission is denied![%d]", ret); send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; goto ERROR; } + MC_SAFE_FREE(creds.uid); + MC_SAFE_FREE(creds.smack); + for (i = 0; i < g_list_length(mc_svc_data->mc_svc_list); i++) { char *nth_data = (char *)g_list_nth_data(mc_svc_data->mc_svc_list, i); if (nth_data != NULL && strcmp(nth_data, recv_msg.msg) == 0) { @@ -132,13 +124,16 @@ gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condi } } else if (recv_msg.msg_type == MC_MSG_CLIENT_GET) { /* check privileage */ - ret = __mc_privilege_ask(client_sock, "mediacontroller::svc", "r"); - if (ret == MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED) { - mc_error("permission is denied!"); + ret = mc_cynara_check(&creds, MC_SERVER_PRIVILEGE); + if (ret != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("permission is denied![%d]", ret); send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; goto ERROR; } + MC_SAFE_FREE(creds.uid); + MC_SAFE_FREE(creds.smack); + for (i = 0; i < g_list_length(mc_svc_data->mc_svc_list); i++) { send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED; char *nth_data = (char *)g_list_nth_data(mc_svc_data->mc_svc_list, i); @@ -196,6 +191,8 @@ ERROR: if (close(client_sock) < 0) { mc_stderror("close failed"); } + MC_SAFE_FREE(creds.uid); + MC_SAFE_FREE(creds.smack); return TRUE; } @@ -229,6 +226,12 @@ gboolean mc_svc_thread(void *data) return FALSE; } + ret = mc_cynara_enable_credentials_passing(sockfd); + if(ret != MEDIA_CONTROLLER_ERROR_NONE) { + mc_error("Failed to append socket options"); + return FALSE; + } + /* Create list for command*/ mc_svc_data->mc_svc_list = g_list_alloc(); if (mc_svc_data->mc_svc_list == NULL) { -- 2.7.4