Implement checking of Tizen policies 84/137784/39
authoru.harbuz <u.harbuz@samsung.com>
Thu, 24 Aug 2017 07:49:18 +0000 (09:49 +0200)
committerLukasz Kostyra <l.kostyra@samsung.com>
Tue, 12 Sep 2017 14:11:48 +0000 (16:11 +0200)
Change-Id: I18d2ef26f63d17b3d97d5af9fbeab0f0db4bc3e1

23 files changed:
CMakeLists.txt
packaging/tef-simulator.spec
pkgconfig/tef-simulator-devkit.pc.in
simulatordaemon/CMakeLists.txt
simulatordaemon/inc/ConnectionSession.h
simulatordaemon/inc/IConnectionSession.h
simulatordaemon/inc/ISession.h
simulatordaemon/inc/SecurityChecker.h [deleted file]
simulatordaemon/inc/SecurityContext.h [new file with mode: 0644]
simulatordaemon/inc/Session.h
simulatordaemon/inc/TAFactory.h
simulatordaemon/inc/TEEContext.h
simulatordaemon/inc/security.h [deleted file]
simulatordaemon/src/ConnectionSession.cpp
simulatordaemon/src/SecurityChecker.cpp [deleted file]
simulatordaemon/src/SecurityContext.cpp [new file with mode: 0644]
simulatordaemon/src/Session.cpp
simulatordaemon/src/SimulatorDaemonServer.cpp
simulatordaemon/src/TABinaryManager/TABinaryManager.cpp
simulatordaemon/src/TABinaryManager/TABinaryManager.h
simulatordaemon/src/TAFactory.cpp
simulatordaemon/src/TEEContext.cpp
simulatordaemon/src/security.c [deleted file]

index 3c8ff86..4afbe25 100644 (file)
@@ -47,6 +47,7 @@ ADD_DEFINITIONS("-Werror")                      # Make all warnings into errors.
 #ADD_DEFINITIONS("-Wall")                        # Generate all warnings
 #ADD_DEFINITIONS("-Wextra")                      # Generate even more extra warnings
 
+ADD_DEFINITIONS("-D_CYNARA_INTEGRATION")
 
 IF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
     ADD_DEFINITIONS("-DTIZEN_DEBUG_ENABLE")
index d2e8b61..d28dc76 100644 (file)
@@ -10,6 +10,7 @@ BuildRequires: boost-devel
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(openssl)
 BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(cynara-session)
 BuildRequires: pkgconfig(cynara-creds-socket)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(security-manager)
index 04ee70a..50a74ae 100644 (file)
@@ -7,5 +7,5 @@ Name: tef-simulator-devkit
 Description: TEF Simulator TA development kit
 Version: @PKGCFG_VERSION@
 Requires: boost dlog openssl
-Libs: -L${libdir} -lTEEStub -ltef-simulator-ssflib -ltef-simulator-log -lboost_thread -lboost_system -ldlog
+Libs: -L${libdir} -lTEEStub -ltef-simulator-ssflib -ltef-simulator-log -lboost_thread -lboost_filesystem -lboost_system -ldlog
 Cflags: -I${includedir}/
index e79bf6a..1c76541 100644 (file)
 
 PKG_CHECK_MODULES(DAEMON_DEPS REQUIRED
                   cynara-client
+                  cynara-session
                   cynara-creds-socket
                   security-manager
                   libsystemd-daemon
+                  libtzplatform-config
                   )
 
 FIND_PACKAGE(Threads REQUIRED)
@@ -29,10 +31,7 @@ FIND_PACKAGE(Threads REQUIRED)
 SET(DAEMON_SOURCES
     ${DAEMON_PATH}/src/ConnectionSession.cpp
     ${DAEMON_PATH}/src/ioService.cpp
-    # TODO change Security to cpp module
-    #${DAEMON_PATH}/src/security.c
-    # TODO lots of circular dependecies are within SecurityChecker, refactor
-    #${DAEMON_PATH}/src/SecurityChecker.cpp
+    ${DAEMON_PATH}/src/SecurityContext.cpp
     ${DAEMON_PATH}/src/Session.cpp
     ${DAEMON_PATH}/src/SimulatorDaemon.cpp
     ${DAEMON_PATH}/src/SimulatorDaemonServer.cpp
@@ -62,7 +61,6 @@ SET(DAEMON_SOURCES
     ${DAEMON_PATH}/src/TABinaryManager/TAUnpack.cpp
     )
 
-
 ADD_EXECUTABLE(${TARGET_TEF_SIMULATOR_DAEMON}
     ${DAEMON_SOURCES}
     )
@@ -93,7 +91,7 @@ TARGET_LINK_LIBRARIES(${TARGET_TEF_SIMULATOR_DAEMON}
     ${DAEMON_DEPS_LIBRARIES}
     ${TARGET_TEF_SIMULATOR_LOG}
     ${TARGET_TEF_SIMULATOR_OSAL}
-    boost_system
+    boost_system boost_filesystem
     )
 
 INSTALL(TARGETS ${TARGET_TEF_SIMULATOR_DAEMON} DESTINATION ${BIN_DIR})
index 53e02c3..9d253dd 100644 (file)
@@ -33,6 +33,7 @@
 #include "ClientCommands/MakeCommand.h"
 #include "TEEContext.h"
 #include "IConnectionSession.h"
+#include "SecurityContext.h"
 
 using namespace std;
 
@@ -66,6 +67,7 @@ public:
        }
        void start();
        TEEC_Result write(TEE_CMD command, char* data, size_t size);
+       SecurityContext getSecurityContext();
        ~ConnectionSession();
 private:
        TEEContext *TEECtx;
@@ -73,6 +75,8 @@ private:
                        size_t bytes_transferred);
        // The socket used to communicate with the client.
        stream_protocol::socket clientSocket;
+       // Security context of Connection.
+       SecurityContext secContext;
        // Buffer used to store data received from the client.
        boost::array<char, 1024> clientData;
        states currentState;
index 046a69b..f7664ae 100644 (file)
@@ -23,6 +23,7 @@
  *  Include files
  *-----------------------------------------------------------------------------*/
 #include "tee_command.h"
+#include "SecurityContext.h"
 
 /*-----------------------------------------------------------------------------
  *  Class definitions
@@ -30,6 +31,7 @@
 class IConnectionSession {
 public:
        virtual TEEC_Result write(TEE_CMD command, char* data, size_t size) = 0;
+       virtual SecurityContext getSecurityContext() = 0;
        virtual ~IConnectionSession() {}
 };
 
index 766c719..cf05546 100644 (file)
@@ -26,6 +26,7 @@
 #include "tee_command.h"
 #include "teestub_command_data.h"
 #include "ITAInstance.h"
+#include "SecurityContext.h"
 
 /*-----------------------------------------------------------------------------
  *  Class definitions
@@ -40,6 +41,7 @@ public:
        virtual bool checkInternal() = 0;
        virtual uint32_t getContextID() = 0;
        virtual uint32_t getSessionID() = 0;
+       virtual SecurityContext getSecurityContext() = 0;
        virtual TAInstancePtr getTAInstance() = 0;
        virtual TEEC_Result writeResponse(TEE_CMD command, char* data, size_t size) = 0;
        virtual void detachFromContext() = 0;
diff --git a/simulatordaemon/inc/SecurityChecker.h b/simulatordaemon/inc/SecurityChecker.h
deleted file mode 100644 (file)
index a030d72..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * =====================================================================================
- *
- *       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 ConnectionSession;
-
-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 */
diff --git a/simulatordaemon/inc/SecurityContext.h b/simulatordaemon/inc/SecurityContext.h
new file mode 100644 (file)
index 0000000..a012752
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * SecurityContext.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 SECURITYCONTEXT_H
+#define SECURITYCONTEXT_H
+
+#include <string>
+#include "log.h"
+#include "config.h"
+#include <cynara/cynara-client.h>
+
+#define TA_LOCAL_PATH "/res/tee"
+
+class SecurityContext {
+private:
+       int connFd;
+
+       static constexpr const size_t CYNARA_CACHE_SIZE = 100U;
+
+       static cynara* initCynara();
+       static cynara* _cynara;
+
+       static constexpr const char* sysTaPaths[] = {
+               TEE_TASTORE_ROOT,
+       };
+
+       static std::string getCaFullPathFromPkgId(char*);
+
+public:
+       SecurityContext();
+       SecurityContext(int connFd);
+       ~SecurityContext();
+
+/**
+ * This function tries to find TA by name in directories,
+ * which are allowed for CA according to security policies
+ *
+ * @param taName            Name of ta to connect for.
+ * @param allowedPath       Out parameter, if function returns true, it
+ *                          contains found path to TA with given name,
+ *                          otherwise it's empty.
+ * @return                  true if TA was found, otherwise false.
+ */
+       bool findRequestedTa(const std::string &taName, std::string& allowedPath);
+
+/**
+ * Check if client has Tizen permission for use TEE.
+ *
+ * @param privilege         Privilege to be checked for client.
+ * @return                  true if client has permission, otherwise false.
+ */
+       bool clientHasCynaraPermission(const std::string &privilege);
+};
+
+#endif /*SECURITYCONTEXT_H*/
index 8569059..2c95de0 100644 (file)
@@ -49,6 +49,7 @@ public:
        bool checkInternal();
        uint32_t getContextID();
        uint32_t getSessionID();
+       SecurityContext getSecurityContext();
        TAInstancePtr getTAInstance();
        TEEC_Result writeResponse(TEE_CMD command, char* data, size_t size);
        void detachFromContext();
index e3916c3..ed6b453 100644 (file)
@@ -50,7 +50,7 @@ private:
        TAFactory();
        bool checkIfTARunning(string TAUUID);
        TAInstancePtr createUninitalizedTAInstance(string TAUUID, ISession* session);
-       bool launchTA(string TAUUID, std::stringstream& str, bool debug, pid_t& pid);
+       bool launchTA(string TAPath, string TAUUID, std::stringstream& str, bool debug, pid_t& pid);
        static void* waitForChild(void *pid);
        void cleanupTAInstance(pid_t PID);
        ~TAFactory();
index 79212de..5b35f02 100644 (file)
@@ -31,6 +31,7 @@
 #include "Session.h"
 #include "tee_command.h"
 #include "IConnectionSession.h"
+#include "SecurityContext.h"
 
 using namespace std;
 /*-----------------------------------------------------------------------------
@@ -53,9 +54,8 @@ 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*/
-       // TODO refactor SecurityChecker
-       //SecurityChecker mConnSecChecker;
+       /* Security context wich stores info about low-level connection data*/
+       SecurityContext secContext;
 
        /* For TA internal APIs support, dummy Context is created and for recognizing
         * the context as dummy isInternal member variable is used
diff --git a/simulatordaemon/inc/security.h b/simulatordaemon/inc/security.h
deleted file mode 100644 (file)
index 695cc7c..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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>
-
-#define MAX_PATH_LENGTH 100
-#define MAX_OPENED_FD 5
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-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 */
index 759eab4..4c0c958 100644 (file)
@@ -40,6 +40,18 @@ uint32_t ctxID = 21;
 void ConnectionSession::start() {
        LOGD(SIM_DAEMON, "Entry");
 
+       // init SecurityContext of current session after initializing socket
+       this->secContext = SecurityContext(clientSocket.native());
+
+#ifdef _CYNARA_INTEGRATION
+       /* Check if client has cynara permission */
+       const string privilege("http://tizen.org/privilege/tee.client");
+       if (! secContext.clientHasCynaraPermission(privilege)) {
+               LOGE(SIM_DAEMON, "Client has no permission to use TEE");
+               return;
+       }
+#endif /* _CYNARA_INTEGRATION */
+
        // Create a new Context
        pthread_rwlock_wrlock(&ctxIDLock);
        TEECtx = new TEEContext(ctxID, this);
@@ -48,6 +60,7 @@ void ConnectionSession::start() {
        if (ctxID == 0) ctxID++;
        pthread_rwlock_unlock(&ctxIDLock);
        currentState = CMD_READ;
+
        // read exactly 1 byte to identify the command and execute callback when
        // command is received
        boost::asio::async_read(clientSocket, boost::asio::buffer(clientData),
@@ -200,6 +213,10 @@ TEEC_Result ConnectionSession::write(TEE_CMD cmd, char* data, size_t size) {
        return result;
 }
 
+SecurityContext ConnectionSession::getSecurityContext(){
+       return secContext;
+}
+
 ConnectionSession::~ConnectionSession() {
        LOGD(SIM_DAEMON, "Entry");
        // Destory the lock for write (connLock)
diff --git a/simulatordaemon/src/SecurityChecker.cpp b/simulatordaemon/src/SecurityChecker.cpp
deleted file mode 100644 (file)
index c9b6b12..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * =====================================================================================
- *
- *       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(){
-}
diff --git a/simulatordaemon/src/SecurityContext.cpp b/simulatordaemon/src/SecurityContext.cpp
new file mode 100644 (file)
index 0000000..0160962
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * SecurityContext.cpp
+ *
+ * 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 "SecurityContext.h"
+#include <cynara/cynara-creds-socket.h>
+#include <cynara/cynara-session.h>
+#include <security-manager/app-runtime.h>
+#include <memory>
+#include "log.h"
+#include <boost/filesystem.hpp>
+#include <pthread.h>
+#include <stdexcept>
+#include <tzplatform_config.h>
+#include <unistd.h>
+
+using p_char = std::unique_ptr<char, std::function<void(void*)>>;
+using p_cynara_conf = std::unique_ptr<cynara_configuration, std::function<void(cynara_configuration*)>>;
+using p_tzplatform_context= std::unique_ptr<tzplatform_context, std::function<void(tzplatform_context*)>>;
+
+namespace fs = boost::filesystem;
+
+constexpr const char* SecurityContext::sysTaPaths[];
+
+cynara* SecurityContext::_cynara = SecurityContext::initCynara();
+
+pthread_mutex_t cynara_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define FILE_WAS_FOUND 1
+#define MAX_OPENED_FD 5
+#define MAX_PATH_LENGTH 100
+#define BOOST_FILESYSTEM_VERSION 3
+#define RETURN_UNLOCK(ret, mtx) {pthread_mutex_unlock(&mtx); return ret;}
+
+/* TODO: this function needs to be tested.
+ */
+std::string SecurityContext::getCaFullPathFromPkgId(char* pkgid) {
+
+       std::string path;
+
+       tzplatform_variable ids[3] = {TZ_USER_APP, TZ_SYS_RW_APP, TZ_SYS_RO_APP};
+       tzplatform_context *ctx;
+       if (! tzplatform_context_create(&ctx)) {
+           LOGE(SIM_DAEMON, "Can't create tizen context");
+           return path;
+       }
+
+       p_tzplatform_context p_ctx(ctx, &free);
+
+       if (! tzplatform_context_set_user(p_ctx.get(), getuid())) {
+           LOGE(SIM_DAEMON, "Can not set user for context");
+           return path;
+       }
+
+       for (auto &id : ids) {
+           path = std::move(tzplatform_context_getenv(p_ctx.get(), id));
+           LOGD(SIM_DAEMON, "Path is : %s", path.c_str());
+           if (! path.empty()) break;
+       }
+
+       path = fs::read_symlink(fs::path(path)).parent_path().string();
+
+       if (path.empty()) {
+               LOGE(SIM_DAEMON, "Bad CA path. Does this directory exist: %s ?", path.c_str());
+       }
+
+       path += "/" + std::string(pkgid) + TA_LOCAL_PATH;
+       LOGD(SIM_DAEMON, "Path::::: &s", path.c_str());
+
+       return path;
+}
+
+
+bool SecurityContext::findRequestedTa(const std::string &ta_name, std::string &allowed_path) {
+       int ret;
+       char* pkg_id_ca;
+
+       LOGD(SIM_DAEMON, "Entry");
+       ret = security_manager_identify_app_from_socket(connFd, &pkg_id_ca, NULL);
+
+       if (ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT) {
+               LOGD(SIM_DAEMON, "Owner of socket has no pkgid");
+
+               std::string ta_full_path;
+
+               /* Check if any of system ta directories contains our ta */
+               for (const std::string& path : sysTaPaths) {
+                       ta_full_path = path + ta_name;
+
+                       if (fs::exists(ta_full_path)){
+                               allowed_path = path;
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+       if (ret != SECURITY_MANAGER_SUCCESS) {
+               LOGE(SIM_DAEMON, "security_manager_identify_app_from_socket failed with CA");
+               return false;
+       }
+
+       /* We can free it only if security_manager_identify_app_from_socket return success */
+       p_char p_pkg_id_ca(pkg_id_ca, &free);
+
+       std::string ca_pkg_path = getCaFullPathFromPkgId(pkg_id_ca);
+       if (ca_pkg_path.empty()) {
+               LOGE(SIM_DAEMON, "Error while loading client's path");
+               return false;
+       }
+
+/* Now it searches client’s TA  recursively in subdirectories of it. Maybe
+ * in future we will know exact predefined subdirectories or even
+ * map Client <-> allowed directories for it*/
+       for(fs::recursive_directory_iterator end, dir(ca_pkg_path); dir != end; ++dir){
+               std::string ta_full_path = dir->path().filename().string() + "/" + ta_name;
+               if(fs::exists(ta_full_path)){
+                       allowed_path = dir->path().filename().string();
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+bool SecurityContext::clientHasCynaraPermission(const std::string &privelege) {
+       int ret = -1;
+
+       pthread_mutex_lock(&cynara_mutex);
+
+       char *label = nullptr;
+       ret = cynara_creds_socket_get_client(connFd, CLIENT_METHOD_SMACK, &label);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGE(SIM_DAEMON, "Couldn't get smack label of the client. Error code: %d", ret);
+               RETURN_UNLOCK(false, cynara_mutex);
+       }
+       p_char p_label(label, &free);
+
+       pid_t ca_pid = -1;
+       ret = cynara_creds_socket_get_pid(connFd, &ca_pid);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGE(SIM_DAEMON, "Couldn't get pid of the client. Error code: %d", ret);
+               RETURN_UNLOCK(false, cynara_mutex);
+       }
+
+       char *session = nullptr;
+       session = cynara_session_from_pid(ca_pid);
+       if (!session) {
+               LOGE(SIM_DAEMON, "Couldn't get client's cynara session.");
+               RETURN_UNLOCK(false, cynara_mutex);
+       }
+       p_char p_session(session, &free);
+
+       char *user = nullptr;
+       ret = cynara_creds_socket_get_user(connFd, USER_METHOD_DEFAULT, &user);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGE(SIM_DAEMON, "Couldn't get user. Error code: %d", ret);
+               RETURN_UNLOCK(false, cynara_mutex);
+       }
+       p_char p_user(user, &free);
+
+       ret = cynara_check(_cynara, p_label.get(), p_session.get(), p_user.get(), privelege.c_str());
+
+       if (ret == CYNARA_API_ACCESS_DENIED) {
+               LOGE(SIM_DAEMON, "Cynara access denied.");
+               RETURN_UNLOCK(false, cynara_mutex);
+       }
+       if (ret != CYNARA_API_ACCESS_ALLOWED) {
+               LOGE(SIM_DAEMON, "Error during cynara_check(). Error code: %d", ret);
+               RETURN_UNLOCK(false, cynara_mutex);
+       }
+
+       RETURN_UNLOCK(true, cynara_mutex);
+}
+
+
+cynara* SecurityContext::initCynara() {
+       int ret = -1;
+       cynara_configuration *p_conf = nullptr;
+       cynara* result = nullptr;
+
+       ret = cynara_configuration_create(&p_conf);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGE(SIM_DAEMON, "Cynara configuration creation failed");
+               return nullptr;
+       }
+
+       p_cynara_conf conf(p_conf, &cynara_configuration_destroy);
+
+       ret = cynara_configuration_set_cache_size(p_conf, CYNARA_CACHE_SIZE);
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGE(SIM_DAEMON, "Set cynara cache size failed");
+               return nullptr;
+       }
+
+       ret = cynara_initialize(&result, conf.get());
+       if (ret != CYNARA_API_SUCCESS) {
+               LOGE(SIM_DAEMON, "Cynara initialize failed");
+               return nullptr;
+       }
+
+       return result;
+}
+
+
+SecurityContext::SecurityContext():
+       SecurityContext(-1) {
+}
+
+
+SecurityContext::SecurityContext(int connFd):
+       connFd(connFd) {
+       if (_cynara == nullptr) throw std::runtime_error("Cynara is not initialized");
+}
+
+
+SecurityContext::~SecurityContext() {
+}
index f2c71df..39f73ce 100644 (file)
@@ -58,6 +58,10 @@ TAInstancePtr Session::getTAInstance() {
        return mTAInstance;
 }
 
+SecurityContext Session::getSecurityContext() {
+       return mContext->secContext;
+}
+
 void Session::detachFromContext() {
        /* Find the Session instance in the session map */
        map<uint32_t, ISession*>::iterator it;
@@ -102,12 +106,8 @@ TEEC_Result Session::createSession(OpenSessionData data) {
        string TAUUID = TABin->getUUIDAsString(data.uuid);
        string argvPort = TABin->getPort(TAUUID);
 
-       /*string TAName(TAUUID);
+       string TAName(TAUUID);
        std::transform(TAName.begin(), TAName.end(), TAName.begin(), ::toupper);
-       if(!mContext->mConnSecChecker.clientHasAccessToTa(TAUUID)){
-               LOGE(SIM_DAEMON, "Client has no permission for access TA: %s ", TAName.c_str());
-               return TEEC_ERROR_ACCESS_DENIED;
-       }*/
 
        if (argvPort != "") {
                pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock);
index e9f04f7..767fc53 100644 (file)
@@ -20,6 +20,7 @@
  *  Include files
  *-----------------------------------------------------------------------------*/
 #include "SimulatorDaemonServer.h"
+#include "SecurityContext.h"
 
 /*-----------------------------------------------------------------------------
  *  Member functions
@@ -67,14 +68,6 @@ void SimulatorDaemonServer::handleAccept(
        ConnectionSession::session_ptr session,
        const boost::system::error_code& error)
 {
-       const string privelege("http://tizen.org/privilege/account.read");
-       LOGD(SIM_DAEMON, "Entry");
-       // TODO reenable after refactor
-       /*if (!SecurityChecker::clientHasCynaraPermission(new_session.get(), privelege)){
-               LOGE("Client has no permission to use TEE");
-               return;
-       }*/
-
        if (!error) {
                session->start();
        }
index b035dd9..27723a8 100644 (file)
@@ -154,11 +154,41 @@ TABinaryManager* TABinaryManager::getInstance() {
 }
 
 /**
+ * This function add TA at given path to BinaryManager if it exists.
+ * @return On successful completion of above operations returns true else false.
+ */
+bool TABinaryManager::initTAatPath(const string &path, const string &uuid) {
+       LOGD(SIM_DAEMON, "");
+
+       pthread_rwlock_wrlock(&binaryMapLock);
+       map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
+       StructBinaryInfo value;
+       bool res = false;
+       StructBinaryInfo info;
+
+       if (it != binaryMap.end()) {
+               pthread_mutex_lock(&taLock);
+               try {
+                       if (unpackBinary(uuid, path, info)) {
+                               binaryMap[uuid] = info;
+                               res = true;
+                       }
+               } catch (...) {
+                       res = false;
+               }
+               pthread_mutex_unlock(&taLock);
+       }
+       pthread_rwlock_unlock(&binaryMapLock);
+       return res;
+}
+
+/**
  * This function reads UUID list file and unpacks files to their respective
  * locations.
  * @return On successful completion of above operations returns true else false.
  * It is very important to check for return value from this function.
  */
+
 bool TABinaryManager::readUUIDList() {
        LOGD(SIM_DAEMON, "");
        string line;
@@ -221,7 +251,7 @@ bool TABinaryManager::readUUIDList() {
                }
 
                pthread_mutex_lock(&taLock);
-               if (unpackBinary(uuid, info)) {
+               if (unpackBinary(uuid, TA_STORE_PATH, info)) {
                        binaryMap[uuid] = info;
                }
                pthread_mutex_unlock(&taLock);
@@ -309,15 +339,16 @@ void TABinaryManager::decryptImage(StructBinaryInfo& info) {
  * @return On successful completion of above operations returns true else false.
  * It is very important to check for return value from this function.
  */
-bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) {
+
+bool TABinaryManager::unpackBinary(const string &uuid, const string &path, StructBinaryInfo& info) {
        TAUnpack* unpacker = TAUnpack::getInstance();
        bool ret = false;
        LOGE(SIM_DAEMON, "Unpacking TA");
-       if (0 == unpacker->unpackTA(string(TA_STORE_PATH), uuid)) {
+       if (0 == unpacker->unpackTA(path, uuid)) {
                LOGE(SIM_DAEMON, "Unpacked, filling info");
                // 1. Set binary info
-               info.path = string(TA_STORE_PATH) + uuid;
-               info.extractpath = string(TA_STORE_PATH) + uuid + "-ext/";
+               info.path = path + uuid;
+               info.extractpath = path + uuid + "-ext/";
                info.imagePath = info.extractpath + uuid + ".image";
                info.manifestPath = info.extractpath + uuid + ".manifest";
                // 2. Parse manifest and store results
index 00cfb90..5d6dde1 100644 (file)
@@ -63,7 +63,7 @@ private:
        time_t lastModTimeUUIDList;
        TABinaryManager();
        bool readUUIDList();
-       bool unpackBinary(const string &uuid, StructBinaryInfo& info);
+       bool unpackBinary(const string &uuid, const string &path, StructBinaryInfo& info);
        template<typename T>
        std::string IntToHex(T i, int width = sizeof(T) * 2) {
                std::stringstream stream;
@@ -86,6 +86,7 @@ public:
        pthread_mutex_t taLock;
        static TABinaryManager* getInstance();
        bool initBinaryManager();
+       bool initTAatPath(const string &path, const string &uuid);
 
        /*
         * Query functions on Binary Manager
index 6379144..67b66f9 100644 (file)
@@ -20,6 +20,7 @@
  *  Include files
  *-----------------------------------------------------------------------------*/
 #include "TAFactory.h"
+#include "SecurityContext.h"
 #include "ResponseCommands/ResMakeCommand.h"
 
 /*-----------------------------------------------------------------------------
@@ -202,7 +203,12 @@ TAInstancePtr TAFactory::createUninitalizedTAInstance(string TAUUID,
        str << TAUUID << "-";
        str << InstID;
 
-       if (launchTA(TAUUID, str, debug, pid)) {
+       string allowedTAPath;
+       if(!session->getSecurityContext().findRequestedTa(TAUUID, allowedTAPath)) {
+               LOGE(SIM_DAEMON, "Access for TA %s forbidden", TAUUID.c_str());
+               return TAInstancePtr();
+       }
+       if (launchTA(allowedTAPath, TAUUID, str, debug, pid)) {
                // TA is launched successfully, Create a new instance of TAInstance class
 
                /* Check if TA is to be keep alive and accordingly set TAInstance's
@@ -352,7 +358,7 @@ void TAFactory::cleanupTAInstance(pid_t PID) {
  * @param debug debug flag
  * @param pid PID to be update for launched TA
  */
-bool TAFactory::launchTA(string TAUUID, std::stringstream& str, bool debug,
+bool TAFactory::launchTA(string path, string TAUUID, std::stringstream& str, bool debug,
     pid_t& pid) {
 
        int32_t result = -1;
@@ -362,8 +368,10 @@ bool TAFactory::launchTA(string TAUUID, std::stringstream& str, bool debug,
        // Get TABinaryManager instance
        TABinaryManager *TABin = TABinaryManager::getInstance();
        // Get TA Image path for launching
-       LOGD(SIM_DAEMON, TAUUID.c_str());
-       string argvPath = TABin->getImagePath(TAUUID);
+       string argvPath = "";
+       if (TABin->initTAatPath(path, TAUUID)) {
+               argvPath = TABin->getImagePath(TAUUID);
+       }
        if ("" == argvPath) {
                LOGE(SIM_DAEMON, "Trusted Application does not exist");
                return false;
index 51ccd4f..f20bbb5 100644 (file)
@@ -37,7 +37,8 @@ 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, IConnectionSession* connSession):
+    secContext(connSession->getSecurityContext()) {
 
        LOGD(SIM_DAEMON, "ContextID: %d", contextID);
 
diff --git a/simulatordaemon/src/security.c b/simulatordaemon/src/security.c
deleted file mode 100644 (file)
index bf47072..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * 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 <stdlib.h>
-#include <limits.h>
-#include <unistd.h>
-#include <ftw.h>
-#include <cynara/cynara-creds-socket.h>
-#include <cynara/cynara-client.h>
-#include <cynara/cynara-session.h>
-#include <security-manager/app-runtime.h>
-#include "security.h"
-
-/* This variable is for nftw searching of ta */
-static const char* g_ta_name = NULL;
-
-#define FILE_WAS_FOUND 1
-
-#define N_SYS_TA_PATHS 1
-static const char* system_ta_paths[N_SYS_TA_PATHS]={
-       "/usr/lib/optee_armtz/",
-};
-
-
-static bool file_exists(const char* fname) {
-       struct stat st;
-       return stat(fname, &st) == 0;
-}
-
-
-/* TODO: need we get path of CA from its pkgid or we need traverse some
- * predefined directories with CA which contain its TA, or will installator of
- * it store some paired CA-TA pathces? Now it is not good mechanism for searcing
- * CA path from pid.
- */
-static bool get_ca_full_path_from_socket(int fd, char* path) {
-
-       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(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_path, 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){
-                       snprintf(ta_full_path, MAX_PATH_LENGTH, "%s/%s", system_ta_paths[i], ta_name);
-
-                       if(file_exists(ta_full_path)){
-                               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_ca_full_path_from_socket(ca_fd, ca_pkg_path)) {
-               EMSG("Error while loading client's path");
-               free(pkg_id_ca);
-               return false;
-       }
-
-/* Now it searches TA of client recursively in subdirectories of it. Maybe
- * in future we will know koncrete predefined subdirectories or even
- * map Client <-> allowed directories for it*/
-       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;
-}