#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")
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)
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}/
PKG_CHECK_MODULES(DAEMON_DEPS REQUIRED
cynara-client
+ cynara-session
cynara-creds-socket
security-manager
libsystemd-daemon
+ libtzplatform-config
)
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
${DAEMON_PATH}/src/TABinaryManager/TAUnpack.cpp
)
-
ADD_EXECUTABLE(${TARGET_TEF_SIMULATOR_DAEMON}
${DAEMON_SOURCES}
)
${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})
#include "ClientCommands/MakeCommand.h"
#include "TEEContext.h"
#include "IConnectionSession.h"
+#include "SecurityContext.h"
using namespace std;
}
void start();
TEEC_Result write(TEE_CMD command, char* data, size_t size);
+ SecurityContext getSecurityContext();
~ConnectionSession();
private:
TEEContext *TEECtx;
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;
* Include files
*-----------------------------------------------------------------------------*/
#include "tee_command.h"
+#include "SecurityContext.h"
/*-----------------------------------------------------------------------------
* Class definitions
class IConnectionSession {
public:
virtual TEEC_Result write(TEE_CMD command, char* data, size_t size) = 0;
+ virtual SecurityContext getSecurityContext() = 0;
virtual ~IConnectionSession() {}
};
#include "tee_command.h"
#include "teestub_command_data.h"
#include "ITAInstance.h"
+#include "SecurityContext.h"
/*-----------------------------------------------------------------------------
* Class definitions
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;
+++ /dev/null
-/*
- * =====================================================================================
- *
- * 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 */
--- /dev/null
+/*
+ * 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*/
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();
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();
#include "Session.h"
#include "tee_command.h"
#include "IConnectionSession.h"
+#include "SecurityContext.h"
using namespace std;
/*-----------------------------------------------------------------------------
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
+++ /dev/null
-/*
- * 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 */
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);
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),
return result;
}
+SecurityContext ConnectionSession::getSecurityContext(){
+ return secContext;
+}
+
ConnectionSession::~ConnectionSession() {
LOGD(SIM_DAEMON, "Entry");
// Destory the lock for write (connLock)
+++ /dev/null
-/*
- * =====================================================================================
- *
- * 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(){
-}
--- /dev/null
+/*
+ * 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() {
+}
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;
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);
* Include files
*-----------------------------------------------------------------------------*/
#include "SimulatorDaemonServer.h"
+#include "SecurityContext.h"
/*-----------------------------------------------------------------------------
* Member functions
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();
}
}
/**
+ * 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;
}
pthread_mutex_lock(&taLock);
- if (unpackBinary(uuid, info)) {
+ if (unpackBinary(uuid, TA_STORE_PATH, info)) {
binaryMap[uuid] = info;
}
pthread_mutex_unlock(&taLock);
* @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
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;
pthread_mutex_t taLock;
static TABinaryManager* getInstance();
bool initBinaryManager();
+ bool initTAatPath(const string &path, const string &uuid);
/*
* Query functions on Binary Manager
* Include files
*-----------------------------------------------------------------------------*/
#include "TAFactory.h"
+#include "SecurityContext.h"
#include "ResponseCommands/ResMakeCommand.h"
/*-----------------------------------------------------------------------------
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
* @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;
// 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;
* @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);
+++ /dev/null
-/*
- * 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;
-}