Add security checking. 59/137059/1
authoru.harbuz <u.harbuz@samsung.com>
Fri, 23 Jun 2017 09:13:39 +0000 (11:13 +0200)
committerLukasz Kostyra <l.kostyra@samsung.com>
Tue, 4 Jul 2017 08:27:05 +0000 (10:27 +0200)
Change-Id: I09aacf1d31af84da2c6fb37e0aad3ed908504e8d

build/simulatordaemon/src/subdir.mk
simulatordaemon/inc/SecurityChecker.h [new file with mode: 0644]
simulatordaemon/inc/TEEContext.h
simulatordaemon/inc/security.h [new file with mode: 0644]
simulatordaemon/src/SecurityChecker.cpp [new file with mode: 0644]
simulatordaemon/src/Session.cpp
simulatordaemon/src/SimulatorDaemonServer.cpp
simulatordaemon/src/TEEContext.cpp
simulatordaemon/src/security.c [new file with mode: 0644]

index f2c0e3c..a34517c 100755 (executable)
@@ -2,12 +2,14 @@
 CPP_SRCS += \
 $(SIMDAEMON_SOURCE)/src/ConnectionSession.cpp \
 $(SIMDAEMON_SOURCE)/src/Session.cpp \
+$(SIMDAEMON_SOURCE)/src/SecurityChecker.cpp \
 $(SIMDAEMON_SOURCE)/src/SimulatorDaemon.cpp \
 $(SIMDAEMON_SOURCE)/src/SimulatorDaemonServer.cpp \
 $(SIMDAEMON_SOURCE)/src/TAFactory.cpp \
 $(SIMDAEMON_SOURCE)/src/TAInstance.cpp \
 $(SIMDAEMON_SOURCE)/src/TEEContext.cpp \
-$(SIMDAEMON_SOURCE)/src/ioService.cpp 
+$(SIMDAEMON_SOURCE)/src/ioService.cpp \
+$(SIMDAEMON_SOURCE)/src/security.c 
 
 OBJS += \
 ./src/ConnectionSession.o \
@@ -17,7 +19,9 @@ OBJS += \
 ./src/TAFactory.o \
 ./src/TAInstance.o \
 ./src/TEEContext.o \
-./src/ioService.o 
+./src/ioService.o \
+./src/SecurityChecker.o \
+./src/security.o
 
 CPP_DEPS += \
 ./src/ConnectionSession.d \
@@ -27,7 +31,9 @@ CPP_DEPS += \
 ./src/TAFactory.d \
 ./src/TAInstance.d \
 ./src/TEEContext.d \
-./src/ioService.d 
+./src/ioService.d \
+./src/SecurityChecker.d \
+./src/security.d 
 
 
 # Each subdirectory must supply rules for building sources it contributes
diff --git a/simulatordaemon/inc/SecurityChecker.h b/simulatordaemon/inc/SecurityChecker.h
new file mode 100644 (file)
index 0000000..e040afa
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * =====================================================================================
+ *
+ *       Filename:  SecurityChecker.h
+ *
+ *    Description:  Class to check if client application has access to TEE
+ *
+ *        Version:  1.0
+ *        Created:  19 June 2017 14:00:03  IST
+ *       Revision:  Original
+ *       Compiler:  gcc
+ *
+ *         Author:  Uladzislau Harbuz, u.harbuz@samsung.com
+ *   Organization:  Samsung Electronics
+ *
+ * =====================================================================================
+ */
+
+#ifndef SECURITYCHECKER_H
+#define SECURITYCHECKER_H
+
+#include <string>
+#include "ConnectionSession.h"
+#include "log.h"
+#include "security.h"
+
+
+using std::string;
+
+class SecurityChecker{
+private:
+    ConnectionSession* mConnSess;
+
+public:
+
+    SecurityChecker(ConnectionSession* ses);
+
+    static bool clientHasAccessToTa(ConnectionSession *ses, string taName);
+    static bool clientHasCynaraPermission(ConnectionSession *ses, string privelege);
+
+    bool clientHasAccessToTa(string taName); 
+    bool clientHasCynaraPermission(string privelege);
+
+    ~SecurityChecker();
+
+};
+#endif /* SECURITYCHECKER_H */
index ac0669f..5c70da7 100755 (executable)
@@ -31,6 +31,8 @@
 #include "Session.h"
 #include "tee_command.h"
 #include "IConnectionSession.h"
+#include "ConnectionSession.h"
+#include "SecurityChecker.h"
 
 using namespace std;
 /*-----------------------------------------------------------------------------
@@ -53,11 +55,14 @@ public:
        IConnectionSession* mConnSess;
        // ContextID assigned to the instance
        uint32_t mContextID;
+        /* Security checker wich can tell us if client has different Tizen's policy permissions*/
+        SecurityChecker mConnSecChecker;
+
        /* For TA internal APIs support, dummy Context is created and for recognizing
         * the context as dummy isInternal member variable is used
         */
        bool isInternal;
-       TEEContext(uint32_t contextID, IConnectionSession* connSession);
+       TEEContext(uint32_t contextID, ConnectionSession* connSession);
        TEEC_Result initContext(InitContextData* data);
        void finContext(FinalizeContextData data);
        TEEC_Result openSession(OpenSessionData data);
diff --git a/simulatordaemon/inc/security.h b/simulatordaemon/inc/security.h
new file mode 100644 (file)
index 0000000..b8153ca
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * security.h
+ *
+ * Copyright (C) 2017 Samsung Electronics
+ * Uladzislau Harbuz <u.harbuz@samsung.com>
+ *
+ * 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 SECURITY_H
+#define SECURITY_H
+
+#include <stdbool.h>
+#include <cynara/cynara-creds-socket.h>
+#include <cynara/cynara-client.h>
+#include <cynara/cynara-session.h>
+#include <security-manager/app-runtime.h>
+
+#define MAX_PATH_LENGTH 100
+#define MAX_TA_NAME_LENGTH 36
+
+#define FILE_WAS_FOUND 1 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* TODO: */
+const char* system_ta_paths[]= {
+    "/usr/lib/optee_armtz/",
+}
+#define N_SYS_TA_PATHS 1
+
+bool ca_has_access_to_ta(int ca_fd, const char* ta_name);
+bool client_has_cynara_permission(int ca_fd, const char* privelege);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* SECURITY_H */
diff --git a/simulatordaemon/src/SecurityChecker.cpp b/simulatordaemon/src/SecurityChecker.cpp
new file mode 100644 (file)
index 0000000..7b629a6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * =====================================================================================
+ *
+ *       Filename:  SecurityChecker.cpp
+ *
+ *    Description:  Class to check if client application has access to TEE
+ *
+ *        Version:  1.0
+ *        Created:  19 June 2017 14:37:03  IST
+ *       Revision:  Original
+ *       Compiler:  gcc
+ *
+ *         Author:  Uladzislau Harbuz, u.harbuz@samsung.com
+ *   Organization:  Samsung Electronics
+ *
+ * =====================================================================================
+ */
+
+#include "SecurityChecker.h"
+
+
+SecurityChecker(ConnectionSession* ses){
+    mConnSess = ses;
+}
+
+
+bool SecurityChecker::clientHasAccessToTa(ConnectionSession *ses, string taName){
+    return ca_has_access_to_ta(ses->socket().native(), taName.c_str());
+}
+
+
+bool SecurityChecker::clientHasCynaraPermission(ConnectionSession *ses, string privelege){
+    return client_has_cynara_permission(ses->socket().native(), privelege.c_str());
+}
+
+
+bool SecurityChecker::clientHasCynaraPermission(string privelege){
+    return SecurityChecker::clientHasCynaraPermission(mConnSess, privelege);
+}
+
+
+bool SecurityChecker::clientHasAccessToTa(string taName){
+    return SecurityChecker::clientHasAccessToTa(mConnSess, taName);
+}
+
+
+~SecurityChecker(){
+}
index 0739089..e6340e1 100755 (executable)
@@ -102,6 +102,11 @@ TEEC_Result Session::createSession(OpenSessionData data) {
        string TAUUID = TABin->getUUIDAsString(data.uuid);
        string argvPort = TABin->getPort(TAUUID);
 
+        if(!mContext->nConnSecChecker.clientHasAccessToTa(TAUUID)){
+               LOGE(SIM_DAEMON, "Client has no permission for access TA: %s ", TAUUID.c_str());
+               return TEEC_ERROR_ACCESS_DENIED;
+        }
+
        if (argvPort != "") {
                pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock);
                multimap<string, TAInstancePtr>::iterator itr;
index 7d06878..42a3da5 100755 (executable)
@@ -20,6 +20,7 @@
  *  Include files
  *-----------------------------------------------------------------------------*/
 #include "SimulatorDaemonServer.h"
+#include "SecurityChecker.h"
 
 /*-----------------------------------------------------------------------------
  *  Member functions
@@ -45,6 +46,7 @@ void SimulatorDaemonServer::startAccept() {
        ConnectionSession::session_ptr new_session = ConnectionSession::create(
            acceptor.get_io_service());
 
+
        acceptor.async_accept(new_session->socket(),
            boost::bind(&SimulatorDaemonServer::handleAccept, this, new_session,
                boost::asio::placeholders::error));
@@ -58,7 +60,14 @@ void SimulatorDaemonServer::startAccept() {
 void SimulatorDaemonServer::handleAccept(
     ConnectionSession::session_ptr new_session,
     const boost::system::error_code& error) {
+
+        const string privelege("http://tizen.org/privilege/account.read");
        LOGD(SIM_DAEMON, "Entry");
+        if (!SecurityChecker::clientHasCynaraPermission(new_session.get(), privelege)){
+            LOGE("Client has no permission to use TEE");
+            return;
+        }
+
        if (!error) {
                new_session->start();
        }
index 3e352f7..f2cbea4 100755 (executable)
@@ -36,7 +36,9 @@ uint32_t sessID = 51;
  * @param contextID ID for Context reference
  * @param connSession ConnectionSession instance associated with the context
  */
-TEEContext::TEEContext(uint32_t contextID, IConnectionSession* connSession) {
+TEEContext::TEEContext(uint32_t contextID, ConnectionSession* connSession)
+    :mConnSecChecker(connSession)
+{
 
        LOGD(SIM_DAEMON, "ContextID: %d", contextID);
 
diff --git a/simulatordaemon/src/security.c b/simulatordaemon/src/security.c
new file mode 100644 (file)
index 0000000..ae73646
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * security.c
+ *
+ * Copyright (C) 2017 Samsung Electronics
+ * Uladzislau Harbuz <u.harbuz@samsung.com>
+ *
+ * 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 <teec_trace.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <ftw.h>
+#include "security.h"
+
+/* This variable is for nftw searching of ta */
+static const char* g_ta_name = NULL;
+
+
+static bool file_exists(const char* fname){
+    struct stat st;
+    return stat(fname, &st) == 0;
+}
+
+
+static bool get_ca_full_path_from_socket(int fd, char* path){
+   /* How to get full path from pkgid? */ 
+    pid_t ca_pid = -1;
+    cynara *cynara = NULL;
+    int ret = -1;
+    
+    ret = cynara_initialize(&cynara, NULL);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Cynara initialization failed with error code %d", ret);
+        return false;
+    }
+
+    ret = cynara_creds_socket_get_pid(ca_fd, &ca_pid);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Couldn't get pid of the client. Error code: %d", ret);
+        cynara_finish(cynara);
+        return false;
+    }
+
+    char ca_path[MAX_PATH_LENGTH] = {0};
+    snprintf(ca_path, MAX_PATH_LENGTH, "/proc/%d/exe", ca_pid);
+    ret = readlink(ca_path, path, MAX_PATH_LENGTH);
+
+    if(ret == -1){
+        EMSG("readlink() failed");
+        cynara_finish(cynara);
+        return false;
+    }
+
+    cynara_finish(cynara);
+
+    return true;
+}
+
+
+static int cmp_ta_name(const char *fpath, const struct stat *sb, 
+        int tflag, struct FTW *ftwbuf)
+{
+    if(tflag == FTW_D){
+        char ta_full_path[MAX_PATH_LENGTH] = {0};
+        snprintf(ta_full_name, MAX_PATH_LENGTH, "%s/%s", fpath, g_ta_name);
+
+        if(file_exists(ta_full_path)){
+            return FILE_WAS_FOUND;
+        }
+    }
+
+    return 0;
+}
+
+
+bool ca_has_access_to_ta(int ca_fd, const char* ta_name){
+    int ret;
+    g_ta_name = ta_name;
+
+    char *pkg_id_ca;
+
+    ret = security_manager_identify_app_from_socket(ca_fd, &pkg_id_ca, NULL);
+    if(ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT){
+        DMSG("Owner of socket has no pkgid");
+
+        char ta_full_path[MAX_PATH_LENGTH] = {0};
+
+        /* Check if any of system ta directories contains our ta */
+        for(int i = 0; i < N_SYS_TA_PATHS; ++i){
+            strcpy(ta_full_path, system_ta_paths[i]);
+            strcat(ta_full_path, ta_name);
+
+            if(file_exists(ta_full_name)){
+                return true;
+            }
+
+            memset(ta_full_path, 0, MAX_PATH_LENGTH);
+        }
+
+        return false;
+    }
+
+    if(ret != SECURITY_MANAGER_SUCCESS){
+        EMSG("security_manager_identify_app_from_cynara_client() failed with CA");
+        return false;
+    }
+
+    char ca_pkg_path[MAX_PATH_LENGTH];
+    if(!get_full_ca_path_from_socket(ca_fd, ca_pkg_path)){
+        EMSG("Error while loading client's path");
+        free(pkg_id_ca);
+        return false;
+    }
+
+    ret = nftw(ca_pkg_path, cmp_ta_name, MAX_OPENED_FD, 0);
+    if(ret == FILE_WAS_FOUND){
+        free(pkg_id_ca);
+        return true;
+    }
+
+    free(pkg_id_ca);
+    return false;
+}
+
+
+bool client_has_cynara_permission(int ca_fd, const char *privelege){
+    cynara *cynara = NULL;
+    int ret = -1;
+    char *user;
+    char *session = NULL;
+    char *label;
+    pid_t ca_pid = -1;
+
+    ret = cynara_initialize(&cynara, NULL);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Cynara initialization failed with error code %d", ret);
+        return false;
+    }
+
+    ret = cynara_creds_socket_get_client(ca_fd, CLIENT_METHOD_SMACK, &label);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Couldn't get smack label of the client. Error code: %d", ret);
+        goto exit_error3;
+    }
+
+    ret = cynara_creds_socket_get_pid(ca_fd, &ca_pid);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Couldn't get pid of the client. Error code: %d", ret);
+        goto exit_error2;
+    }
+
+    session = cynara_session_from_pid(ca_pid);
+    if(!session){
+        EMSG("Couldn't get client's cynara session.");
+        goto exit_error2;
+    }
+
+    ret = cynara_creds_socket_get_user(ca_fd, CLIENT_METHOD_SMACK, &user);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Couldn't get user. Error code: %d", ret);
+        goto exit_error1;
+    }
+
+    ret = cynara_check(cynara, label, session, user, privelege);
+    if(ret == CYNARA_API_ACCESS_DENIED){
+        EMSG("Cynara access denied.");
+        goto exit_error0;
+    }
+    else if(ret != CYNARA_API_ACCESS_ALLOWED){
+        EMSG("Error during cynara_check(). Error code: %d", ret);
+        goto exit_error0;
+    }
+
+
+    ret = cynara_finish(cynara);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Cynara finish failed with error code %d", ret);
+    }
+
+    free(session);
+    free(label);
+    free(user);
+    
+    return true;
+
+
+exit_error0:
+    free(user);
+
+exit_error1:
+    free(session);
+
+exit_error2:
+    free(label);
+
+exit_error3:
+    ret = cynara_finish(cynara);
+    if(ret != CYNARA_API_SUCCESS){
+        EMSG("Cynara finish failed with error code %d", ret);
+    }
+
+    return false;
+}