Adding manifest.
Setting root of tee fs to /opt.
Little spec cleanup.
Adding udev and service configuration.
Set SYS_TA_PATH to /usr/lib/tastore
Some fixes for cynara usage.
Change-Id: I2fe99d30d88cc1776380a83308b656445d61cf8f
TEEC_CFLAGS := $(addprefix -I, $(TEEC_INCLUDES)) $(CFLAGS) -D_GNU_SOURCE \
-DDEBUGLEVEL_$(CFG_TEE_CLIENT_LOG_LEVEL) \
-- -DBINARY_PREFIX=\"TEEC\"
++ -DBINARY_PREFIX=\"TEEC\" -DTEEC_LOG_FILE=\"$(TEEC_LOG_FILE)\"
TEEC_LFLAGS := -lpthread
TEEC_LIBRARY := $(OUT_DIR)/$(LIB_MAJ_MIN)
+++ /dev/null
--%define major_version 2
--%define minor_version 4
--
- Name: optee-client
- Summary: Library for applications which use OPTEE functions.
- Version: %{major_version}.%{minor_version}
-Name: tef-optee
-Summary: TEF TrustZone OpTEE backend
-Version: %{major_version}.%{minor_version}.0
--Release: 1%{?dist}
--Group: Security/Testing
--License: BSD-2-Clause
--URL: N/A
--Source0: %{name}-%{version}.tar.gz
- Provides: libteec
-Source1: %{name}.manifest
-ExclusiveArch: armv6l armv7hl armv7l aarch64
-Provides: %{name}
--
--BuildRequires: make
- BuildRequires: pkgconfig(cynara-client)
- BuildRequires: pkgconfig(cynara-creds-socket)
- BuildRequires: pkgconfig(cynara-session)
- BuildRequires: pkgconfig(security-manager)
- BuildRequires: pkgconfig(security-privilege-manager)
- BuildRequires: pkgconfig(libtzplatform-config)
-BuildRequires: cmake
-
-%{?systemd_requires}
-
-%define bin_dir %{?TZ_SYS_BIN:%TZ_SYS_BIN}%{!?TZ_SYS_BIN:%_bindir}
-%define udev_dir %_libdir/udev/rules.d/
-%define build_udev_dir %{buildroot}/%{udev_dir}
-%define build_unit_dir %{buildroot}%{_unitdir}
-
-%define smack_domain_name System
-
-%define compile_param CROSS_COMPILE="" MAJOR_VERSION="%{major_version}" MINOR_VERSION="%{minor_version}"
--
--%description
- Library for applications which use OPTEE functions.
-TEF Trustzone OpTEE provides daemon to support OpTEE OS solution.
-
-%package -n %{name}-client
-Summary: TEF TrustZone OpTEE Client contains a libteec library.
-Group: Security/Libraries
-License: BSD-2-Clause
-Provides: %{name}-client
-
-BuildRequires: make
-
-%description -n %{name}-client
-TEF TrustZone OpTEE Client contains a libteec library, which is tef-libteec backend.
--
--%prep
--%setup -q
-cp -a %{SOURCE1} .
--
--%build
- make build CROSS_COMPILE="" MAJOR_VERSION=%{major_version} MINOR_VERSION=%{minor_version} CFLAGS='-fPIC -D_GNU_SOURCE -DTEEC_LOAD_PATH="\"\"" -I%{_includedir}/cynara -L%{_libdir}'
-export TEE_FS_SUBPATH="/opt/data" TEE_FS_PATH="/opt/data/tee"
-make %{compile_param} build
-
-cd systemd
-cmake . \
- -DUDEV_RULES_DIR=%{build_udev_dir} \
- -DSYSTEMD_UNIT_DIR=%{build_unit_dir} \
- -DSYSTEMD_CFG_BIN_DIR=%{bin_dir} \
- -DSMACK_DOMAIN_NAME=%{smack_domain_name}
-cd -
--
--%install
- make CROSS_COMPILE="" MAJOR_VERSION=%{major_version} MINOR_VERSION=%{minor_version} DESTDIR=%{buildroot}/%{_prefix} install
-make %{compile_param} DESTDIR=%{buildroot}/%{_prefix}/ LIBDIR=%{_lib}/tef/optee install
--
- if [ "%{_libdir}" == "%{_exec_prefix}/lib64" ]
- then
- mkdir -p %{buildroot}/%{_libdir}
- cp -f %{buildroot}/usr/lib/libteec.so* %{buildroot}/%{_libdir}/
- rm -rf %{buildroot}/usr/lib
- fi
-rm -rf %{buildroot}/%{_includedir}
-cd systemd
-make install
-cd -
--
- rm -rf %{buildroot}%{_libdir}/debug
-%post
-./usr/sbin/tef-update.sh optee
-
-%postun
-./usr/sbin/tef-update.sh
--
--%files
- %defattr(-, root, root, -)
-%license LICENSE
--%{_bindir}/tee-supplicant
- %{_libdir}/libteec.so*
- %{_includedir}/tee_client_api.h
- %{_includedir}/tee_client_api_extensions.h
- %{_includedir}/teec_trace.h
-
- %post
- ln -sf %{_libdir}/libteec.so.%{version} %{_libdir}/libteec.so.%{major_version}
- ln -sf %{_libdir}/libteec.so.%{major_version} %{_libdir}/libteec.so
-%{_unitdir}/tef-optee.service
-%{udev_dir}/90-teedaemon.rules
--
- /sbin/ldconfig
-%files -n %{name}-client
-%license LICENSE
-%defattr(-, root, root, -)
-%{_libdir}/tef/optee/libteec.so*
--
--%changelog
--- /dev/null
--- /dev/null
++<manifest>
++ <request>
++ <domain name="_" />
++ </request>
++</manifest>
--- /dev/null
--- /dev/null
++%define major_version 2
++%define minor_version 4
++
++Name: tef-optee-client
++Summary: TEF TrustZone OpTEE backend
++Version: %{major_version}.%{minor_version}.0
++Release: 1%{?dist}
++Group: Security/Libraries
++License: BSD-2-Clause
++URL: N/A
++Source0: %{name}-%{version}.tar.gz
++Source1: %{name}.manifest
++ExclusiveArch: armv6l armv7hl armv7l aarch64
++Provides: %{name}
++
++BuildRequires: make
++BuildRequires: pkgconfig(cynara-client)
++BuildRequires: pkgconfig(cynara-creds-socket)
++BuildRequires: pkgconfig(cynara-session)
++BuildRequires: pkgconfig(security-manager)
++BuildRequires: pkgconfig(security-privilege-manager)
++BuildRequires: pkgconfig(libtzplatform-config)
++BuildRequires: cmake
++Requires: tef-libteec
++
++%{?systemd_requires}
++
++%define bin_dir %{?TZ_SYS_BIN:%TZ_SYS_BIN}%{!?TZ_SYS_BIN:%_bindir}
++%define udev_dir %_libdir/udev/rules.d/
++%define build_udev_dir %{buildroot}/%{udev_dir}
++%define build_unit_dir %{buildroot}%{_unitdir}
++%define optee_libteec /%{_lib}/tef/optee
++
++%define smack_domain_name System
++
++%define compile_param CROSS_COMPILE="" MAJOR_VERSION="%{major_version}" MINOR_VERSION="%{minor_version}" CFLAGS='-fPIC -D_GNU_SOURCE -I%{_includedir}/cynara'
++
++%description
++TEF Trustzone OpTEE provides daemon to support OpTEE OS solution and libteec library,
++which is tef-libteec backend.
++
++%prep
++%setup -q
++cp -a %{SOURCE1} .
++
++%build
++export TEE_FS_SUBPATH="/opt/data" TEE_FS_PATH="/opt/data/tee" TEEC_LOAD_PATH="\/" TEEC_LOG_FILE="/opt/data/var.log" CFG_TEE_CLIENT_LOG_LEVEL=4 CFG_TEE_SUPP_LOG_LEVEL=4 CFG_TA_TEST_PATH=n
++make %{compile_param} build
++
++cd systemd
++cmake . \
++ -DUDEV_RULES_DIR=%{build_udev_dir} \
++ -DSYSTEMD_UNIT_DIR=%{build_unit_dir} \
++ -DSYSTEMD_CFG_BIN_DIR=%{bin_dir} \
++ -DSMACK_DOMAIN_NAME=%{smack_domain_name}
++cd -
++
++%install
++make %{compile_param} DESTDIR=%{buildroot} LIBDIR=%{optee_libteec} install
++
++mkdir %{buildroot}/%{_prefix}
++mv %{buildroot}/%{optee_libteec}/libteec.so.%{major_version}.%{minor_version} %{buildroot}/%{optee_libteec}/libteec.so.%{version}
++mv %{buildroot}/bin %{buildroot}/%{_prefix}
++cd systemd
++make install
++cd -
++
++rm -rf %{buildroot}/include
++rm -rf %{buildroot}/%{_libdir}/debug
++rm -rf %{buildroot}/%{optee_libteec}/libteec.so.%{major_version} %{buildroot}/%{optee_libteec}/libteec.so
++
++%post
++mkdir -p -m 774 %{_libdir}/tastore
++chown root:security_fw %{_libdir}/tastore
++
++#./usr/sbin/tef-update.sh optee
++ln -sf %{optee_libteec}/libteec.so.%{version} %{optee_libteec}/libteec.so.%{major_version}
++ln -sf %{optee_libteec}/libteec.so.%{major_version} %{optee_libteec}/libteec.so
++
++%postun
++./usr/sbin/tef-update.sh
++
++%files
++%license LICENSE
++%{_bindir}/tee-supplicant
++%{_unitdir}/tef-optee.service
++%{udev_dir}/90-teedaemon.rules
++%{optee_libteec}/libteec.so.%{version}
++
++%changelog
--- /dev/null
-Group=root
+ [Unit]
+ Description=TEF OpTEE Daemon
+ DefaultDependencies=no
+ After=opt.mount
+
+
+ [Service]
+ User=root
++Group=security_fw
+ SmackProcessLabel=@SMACK_DOMAIN_NAME@
+ ExecStart=@SYSTEMD_CFG_BIN_DIR@/tee-supplicant
+ RuntimeDirectory=@SERVICE_NAME@
++StandardOutput=journal
tee_supp_fs.c \
rpmb.c \
handle.c \
- unix_socket.c
+ security.c \
++ unix_socket.c \
+ ../../libteec/src/teec_trace.c
ifeq ($(CFG_GP_SOCKETS),y)
TEES_CFLAGS := $(addprefix -I, $(TEES_INCLUDES)) $(CFLAGS) \
-DDEBUGLEVEL_$(CFG_TEE_SUPP_LOG_LEVEL) \
-DBINARY_PREFIX=\"TEES\"
--TEES_CFLAGS += -DTEE_FS_SUBPATH=\"$(TEE_FS_SUBPATH)\" -DTEE_FS_PATH=\"$(TEE_FS_PATH)\"
++TEES_CFLAGS += -DTEE_FS_SUBPATH=\"$(TEE_FS_SUBPATH)\" -DTEE_FS_PATH=\"$(TEE_FS_PATH)\" -DTEEC_LOAD_PATH=\"$(TEEC_LOAD_PATH)\"
ifeq ($(CFG_GP_SOCKETS),y)
TEES_CFLAGS += -DCFG_GP_SOCKETS=1
endif
--- /dev/null
- ret = cynara_creds_socket_get_user(ca_fd, CLIENT_METHOD_SMACK, &user);
+/*
+ * Copyright (c) 2017, Samsung Electronics
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <teec_trace.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.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"
+#include <pthread.h>
+#include <tzplatform_config.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+
+/* Global instance of cynara. Get it by function get_cynara_instance, DO NOT USE IT directly! */
+static cynara *p_cynara = NULL;
+
+#define CYNARA_CACHE_SIZE 100U
+#define RETURN_UNLOCK(ret, mtx) {pthread_mutex_unlock(&mtx); return ret; }
+
+static const char* system_ta_paths[] = {
+ SYS_TA_PATH,
+};
+
+pthread_mutex_t cynara_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+const size_t n_sys_ta_paths = sizeof(system_ta_paths)/sizeof(system_ta_paths[0]);
+
+
+/* Call it before locking cynara */
+static cynara* get_cynara_instance()
+{
+ if (p_cynara == NULL) {
+ pthread_mutex_lock(&cynara_mutex);
+ int ret = -1;
+ cynara_configuration *p_conf = NULL;
+
+ ret = cynara_configuration_create(&p_conf);
+ if (ret != CYNARA_API_SUCCESS) {
+ EMSG("Cynara configuration initialization failed");
+ RETURN_UNLOCK(NULL, cynara_mutex);
+ }
+
+ ret = cynara_configuration_set_cache_size(p_conf, CYNARA_CACHE_SIZE);
+ if (ret != CYNARA_API_SUCCESS) {
+ EMSG("Set cynara cache size failed");
+ RETURN_UNLOCK(NULL, cynara_mutex);
+ }
+
+ ret = cynara_initialize(&p_cynara, p_conf);
+ if (ret != CYNARA_API_SUCCESS) {
+ p_cynara = NULL;
+ EMSG("Cynara initialize faied");
+ RETURN_UNLOCK(NULL, cynara_mutex);
+ }
+
+ RETURN_UNLOCK(p_cynara, cynara_mutex);
+ }
+
+ return p_cynara;
+}
+
+
+static bool file_exists(const char* fname)
+{
+ return access(fname, F_OK) == 0;
+}
+
+
+static bool get_ca_full_path_from_fd(int caFd, char* path)
+{
+
+ pid_t ca_pid = -1;
+ int ret = -1;
+
+ char ca_path[MAX_PATH_LENGTH] = {0};
+
+ enum tzplatform_variable ids[] = {TZ_USER_APP, TZ_SYS_RW_APP, TZ_SYS_RO_APP};
+ const size_t N_IDS = sizeof(ids)/sizeof(*ids);
+
+ struct ucred ucred;
+ int len = sizeof(struct ucred);
+
+ if (getsockopt(caFd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) {
+ EMSG("Can't get client's uid");
+ return false;
+ }
+
+ struct tzplatform_context *ctx;
+ if (tzplatform_context_create(&ctx) != 0) {
+ EMSG("Can not create tizen context");
+ return false;
+ }
+
+ if (tzplatform_context_set_user(ctx, ucred.uid) != 0) {
+ EMSG("Can not set user for context");
+ tzplatform_context_destroy(ctx);
+ return false;
+ }
+
+ for (int i = 0; i < N_IDS; ++i) {
+ strncpy(ca_path, tzplatform_context_getenv(ctx, ids[i]), MAX_PATH_LENGTH);
+ if (strlen(ca_path) > 0) break;
+ }
+
+ ret = readlink(ca_path, path, MAX_PATH_LENGTH);
+
+ if (ret == -1) {
+ EMSG("readlink() failed");
+ tzplatform_context_destroy(ctx);
+ return false;
+ }
+
+ tzplatform_context_destroy(ctx);
+ return true;
+}
+
+
+bool find_requested_ta(int ca_fd, const char* ta_name, char** allowed_path)
+{
+ int ret;
+ char* pkg_id_ca;
+ *allowed_path = NULL;
+
+ 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)) {
+ *allowed_path = (char*)calloc(strlen(system_ta_paths[i])+1, sizeof(**allowed_path));
+ strcpy(*allowed_path, system_ta_paths[i]);
+ return true;
+ }
+
+ memset(ta_full_path, 0, MAX_PATH_LENGTH);
+ }
+
+ return false;
+ }
+
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ EMSG("security_manager_identify_app_from_socket failed with CA");
+ return false;
+ }
+
+ free(pkg_id_ca);
+
+ char ca_pkg_path[MAX_PATH_LENGTH];
+ if (!get_ca_full_path_from_fd(ca_fd, ca_pkg_path)) {
+ EMSG("Error while loading client's path");
+ return false;
+ }
+
+ strncat(ca_pkg_path, TA_LOCAL_PATH, MAX_PATH_LENGTH - strlen(ca_pkg_path));
+ char ta_full_path[MAX_PATH_LENGTH] = {0};
+ snprintf(ta_full_path, MAX_PATH_LENGTH, "%s/%s", ca_pkg_path, ta_name);
+
+ if (!file_exists(ta_full_path)) {
+ EMSG("TA %s not found in res/tee/", ta_name);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool client_has_cynara_permission(int ca_fd, const char *privelege)
+{
+ cynara *cynara = get_cynara_instance();
+ if (cynara == NULL) {
+ EMSG("Cynara is not initialized");
+ return false;
+ }
+
+ int ret = -1;
+ char *user = NULL;
+ char *session = NULL;
+ char *label = NULL;
+ pid_t ca_pid = -1;
+
+ pthread_mutex_lock(&cynara_mutex);
+
+ 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, USER_METHOD_DEFAULT, &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);
+ pthread_mutex_unlock(&cynara_mutex);
+
+ return true;
+
+exit_error0:
+ free(user);
+
+exit_error1:
+ free(session);
+
+exit_error2:
+ free(label);
+
+exit_error3:
+ pthread_mutex_unlock(&cynara_mutex);
+
+ return false;
+}
--- /dev/null
- #define SYS_TA_PATH "/usr/lib/optee_armtz"
+/*
+ * Copyright (c) 2017, Samsung Electronics
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef SECURITY_H
+#define SECURITY_H
+
+#include <stdbool.h>
+
+#define MAX_PATH_LENGTH 100
+#define MAX_OPENED_FD 5
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
++#define SYS_TA_PATH "/usr/lib/tastore"
+#define TA_LOCAL_PATH "/res/tee"
+
+/**
+ * This function try to find TA by its name in allowed for client (given by
+ * socket's file descriptor) by security policies directories.
+ *
+ * @param ca_fd File descriptor to opened socket for client.
+ * @param ta_name Name of ta to connect for.
+ * @param allowed_ta_path Out parameter, if function returns true, it
+ * contains found path to TA with given name,
+ * otherwise pointer is NULL.
+ * User must free it after use.
+ * @return true if TA was found, otherwise false.
+ */
+bool find_requested_ta(int ca_fd, const char* ta_name, char** allowed_ta_path);
+
+/**
+ * Check if client given by socket file descriptor has Tizen permission
+ * for use TEE.
+ *
+ * @param ca_fd File descriptor to opened socket for client.
+ * @param privelege Privilege to check for.
+ * @return true if client has permission, otherwise false.
+ */
+bool client_has_cynara_permission(int ca_fd, const char* privilege);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* SECURITY_H */
--- /dev/null
+/*
+ * Copyright (c) 2017, Samsung Electronics
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include "unix_socket.h"
++#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define WAIT_SEC 10
+#define SOCK_PATH_PREFIX "/tmp/"
+
+int open_socket_for_ca(const char *ca_id, struct sock_data* open_sockets[])
+{
+ int sockfd = -1;
+ int newsockfd = -1;
+ int portno = 0;
+ int free_index = -1;
+
+ char path[MAX_PATH_LENGTH] = {0};
+ sprintf(path, SOCK_PATH_PREFIX"%s", ca_id);
+
+ if (access(path, F_OK) == -1) {
+ DMSG("Socket file doesn't exist. Creating");
+ close_socket_by_addr(path, open_sockets);
+ }
+
+ /* check if this socket already open and find first free place in array */
+ for (int i = 0; i < MAX_TA_NUMBER; ++i) {
+ if (open_sockets[i] == NULL && free_index == -1) free_index = i;
+ if (open_sockets[i] && strcmp(path, open_sockets[i]->addr) == 0) {
+ DMSG("Socket already exists");
+ return open_sockets[i]->fd;
+ }
+ }
+
+ if (free_index < 0 || free_index >= MAX_TA_NUMBER) {
+ EMSG("Limit of simultaneously opened TA is reached");
+ return -1;
+ }
+
+ struct sockaddr_un serv_addr;
+ int ret = -1;
+
+ sockfd = socket(AF_UNIX, SOCK_STREAM, portno);
+ if (sockfd < 0) {
+ EMSG("Couldn't open socket");
+ return sockfd;
+ }
+
+ bzero((char*) &serv_addr, sizeof(serv_addr));
+
+ serv_addr.sun_family = AF_UNIX;
+ strncpy(serv_addr.sun_path, path, sizeof(serv_addr) - 1);
+
+ int yes = 1;
+ ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
+ if (ret < 0) {
+ EMSG("Configure socket error: %s", strerror(errno));
+ return ret;
+ }
+
+ ret = bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));
+ if (ret < 0) {
+ EMSG("Binding of socket adress failed with error: %s", strerror(errno));
+ return ret;
+ }
+
+ char mode[] = "0777";
+ int imode = strtol(mode, NULL, 8);
+ ret = chmod(path, imode);
+ if (ret != 0) {
+ EMSG("Error changing permission for socket: %s", strerror(errno));
+ return -1;
+ }
+
+ listen(sockfd, N_CONNECTIONS);
+
+ DMSG("Waiting for accept...");
+
+ /* Set timeout for waiting for connection from client */
+ struct timeval tv;
+ tv.tv_sec = WAIT_SEC;
+ tv.tv_usec = 0;
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(sockfd, &fds);
+
+ ret = select(sockfd + 1, &fds, NULL, NULL, &tv);
+ if (ret == -1) {
+ EMSG("ERROR of select socket: %s", strerror(errno));
+ close(newsockfd);
+ close(sockfd);
+ unlink(path);
+ return -1;
+ }
+
+ if (ret == 0) {
+ EMSG("Server timeout");
+ close(newsockfd);
+ close(sockfd);
+ unlink(path);
+ return -1;
+ }
+
+ newsockfd = accept(sockfd, NULL, NULL);
+ if (newsockfd < 0) {
+ EMSG("Open socket failed");
+ }
+
+ open_sockets[free_index] = (struct sock_data*)malloc(sizeof(struct sock_data));
+ open_sockets[free_index]->addr = (char*)calloc(strlen(path), sizeof(char));
+ strcpy(open_sockets[free_index]->addr, path);
+ open_sockets[free_index]->fd = newsockfd;
+ open_sockets[free_index]->parent_fd = sockfd;
+
+ return newsockfd;
+}
+
+int close_socket_by_addr(const char* path, struct sock_data* open_sockets[])
+{
+ int index = -1;
+
+ for (int i = 0; i < MAX_TA_NUMBER; ++i) {
+ if (open_sockets[i] && strcmp(open_sockets[i]->addr, path) == 0) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0 || index >= MAX_TA_NUMBER) {
+ EMSG("Could't find socket %s", path);
+ return -1;
+ }
+
+ close(open_sockets[index]->fd);
+ close(open_sockets[index]->parent_fd);
+ unlink(open_sockets[index]->addr);
+
+ free(open_sockets[index]->addr);
+ open_sockets[index]->addr = NULL;
+ free(open_sockets[index]);
+ open_sockets[index] = NULL;
+
+ return 0;
+}