Append cynara 88/46688/5 submit/tizen/20150828.014754
authorMinje Ahn <minje.ahn@samsung.com>
Tue, 25 Aug 2015 05:10:54 +0000 (14:10 +0900)
committerMinje Ahn <minje.ahn@samsung.com>
Wed, 26 Aug 2015 12:10:41 +0000 (21:10 +0900)
Change-Id: Icd7c51a22dfae370b3e991dc290df2d4dab18682
Signed-off-by: Minje Ahn <minje.ahn@samsung.com>
CMakeLists.txt
packaging/capi-media-controller.spec
svc/CMakeLists.txt
svc/daemon/media_controller_main.c
svc/media_controller_cynara.c [new file with mode: 0644]
svc/media_controller_cynara.h [new file with mode: 0644]
svc/media_controller_svc.c

index 1635d53..4d52595 100755 (executable)
@@ -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})
index 8ec2b2b..6e88114 100755 (executable)
@@ -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
index 1ed8b1a..e967ced 100755 (executable)
@@ -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})
index 5eba81c..c653530 100755 (executable)
@@ -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 (file)
index 0000000..02f98d3
--- /dev/null
@@ -0,0 +1,159 @@
+/*\r
+* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+* http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+\r
+#define _GNU_SOURCE\r
+\r
+#include <errno.h>\r
+#include <glib.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <sys/socket.h>\r
+#include <unistd.h>\r
+\r
+#include <media_controller_cynara.h>\r
+#include <media_controller_type.h>\r
+#include <media_controller_private.h>\r
+\r
+#include <cynara-client.h>\r
+#include <cynara-session.h>\r
+#include <cynara-error.h>\r
+#include <cynara-creds-socket.h>\r
+\r
+/* this definition is missing in glibc headers (version 2.21). It was introduced in kernel version 2.6.17 */\r
+#ifndef SCM_SECURITY\r
+#define SCM_SECURITY 0x03\r
+#endif\r
+\r
+static cynara *_cynara = NULL;\r
+G_LOCK_DEFINE_STATIC(cynara_mutex);\r
+\r
+static void mc_cynara_dbg_err(const char *prefix, int error_code)\r
+{\r
+       char error_buffer[256];\r
+       int err;\r
+       error_buffer[0] = '\0';\r
+\r
+       err = cynara_strerror(error_code, error_buffer, sizeof(error_buffer));\r
+       if (err == CYNARA_API_SUCCESS) {\r
+               mc_error("%s: %s", prefix, error_buffer);\r
+       } else {\r
+               mc_error("%s: error code %i", prefix, error_code);\r
+       }\r
+}\r
+\r
+int mc_cynara_initialize(void)\r
+{\r
+       int ret = cynara_initialize(&_cynara, NULL);\r
+       if (ret != CYNARA_API_SUCCESS) {\r
+               mc_cynara_dbg_err("cynara_initialize", ret);\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+       }\r
+       return MEDIA_CONTROLLER_ERROR_NONE;\r
+}\r
+\r
+void mc_cynara_finish(void)\r
+{\r
+       cynara_finish(_cynara);\r
+       _cynara = NULL;\r
+}\r
+\r
+int mc_cynara_receive_untrusted_message(int sockfd, mc_comm_msg_s *recv_msg, mc_peer_creds *credentials)\r
+{\r
+       int ret = 0;\r
+       int recv_msg_size = 0;\r
+\r
+       if (!recv_msg ||!credentials)\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;\r
+\r
+       if ((recv_msg_size = read(sockfd, recv_msg, sizeof(mc_comm_msg_s))) < 0) {\r
+               if (errno == EWOULDBLOCK) {\r
+                       mc_error("Timeout. Can't try any more");\r
+                       return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+               } else {\r
+                       mc_stderror("recv failed");\r
+                       return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+               }\r
+       }\r
+\r
+/*     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); */\r
+\r
+       ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));\r
+       if(ret < 0) {\r
+               mc_error("cynara_creds_socket_get_pid failed");\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+       }\r
+\r
+       ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));\r
+       if(ret < 0) {\r
+               mc_error("cynara_creds_socket_get_user failed");\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+       }\r
+\r
+       ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));\r
+       if(ret < 0) {\r
+               mc_error("cynara_creds_socket_get_client failed");\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+       }\r
+\r
+/*     mc_error("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack); */\r
+\r
+       return MEDIA_CONTROLLER_ERROR_NONE;\r
+}\r
+\r
+int mc_cynara_check(const mc_peer_creds *creds, const char *privilege)\r
+{\r
+       int result;\r
+       char *session;\r
+\r
+       if (!creds || !privilege)\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;\r
+\r
+       session = cynara_session_from_pid(creds->pid);\r
+       if (session == NULL) {\r
+               mc_error("cynara_session_from_pid failed");\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+       }\r
+\r
+       G_LOCK(cynara_mutex);\r
+       result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);\r
+       G_UNLOCK(cynara_mutex);\r
+\r
+       if (result != CYNARA_API_ACCESS_ALLOWED)\r
+               mc_cynara_dbg_err("cynara_check", result);\r
+\r
+       MC_SAFE_FREE(session);\r
+       return result == CYNARA_API_ACCESS_ALLOWED ? MEDIA_CONTROLLER_ERROR_NONE: MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED;\r
+}\r
+\r
+int mc_cynara_enable_credentials_passing(int sockfd)\r
+{\r
+       const int optval = 1;\r
+       int err = 0;\r
+\r
+       err = setsockopt(sockfd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));\r
+       if (err != 0) {\r
+               mc_error("Failed to set SO_PASSSEC socket option");\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+       }\r
+\r
+       err = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));\r
+       if (err != 0) {\r
+               mc_error("Failed to set SO_PASSCRED socket option");\r
+               return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;\r
+       }\r
+\r
+       return MEDIA_CONTROLLER_ERROR_NONE;\r
+}\r
diff --git a/svc/media_controller_cynara.h b/svc/media_controller_cynara.h
new file mode 100644 (file)
index 0000000..1e0e569
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+* http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+\r
+#ifndef __TIZEN_MEDIA_CONTROLLER_CYNARA_H__\r
+#define __TIZEN_MEDIA_CONTROLLER_CYNARA_H__\r
+\r
+#include <stdbool.h>\r
+\r
+#include <media_controller_private.h>\r
+\r
+#define MC_CLIENT_PRIVILEGE "http://tizen.org/privilege/mediacontroller.client"\r
+#define MC_SERVER_PRIVILEGE "http://tizen.org/privilege/mediacontroller.server"\r
+\r
+typedef struct {\r
+       pid_t pid;\r
+       char *uid;\r
+       char *smack;\r
+} mc_peer_creds;\r
+\r
+int mc_cynara_initialize(void);\r
+int mc_cynara_check(const mc_peer_creds *creds, const char *privilege);\r
+int mc_cynara_receive_untrusted_message(int sockfd, mc_comm_msg_s *recv_msg, mc_peer_creds *credentials);\r
+int mc_cynara_enable_credentials_passing(int sockfd);\r
+void mc_cynara_finish(void);\r
+\r
+\r
+#endif/* _MEDIA_CONTROLLER_CYNARA_H_ */\r
index 4b999cb..bb2f101 100755 (executable)
 #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) {