/*
* security.c
- *
+ *
* Copyright (C) 2017 Samsung Electronics
* Uladzislau Harbuz <u.harbuz@samsung.com>
*
* 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
+ * 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,
#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;
-static const char* system_ta_paths[N_SYS_TA_PATHS]= {
- "/usr/lib/optee_armtz/",
+#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;
+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(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;
+/* 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);
+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;
- }
- }
+ if(file_exists(ta_full_path)) {
+ return FILE_WAS_FOUND;
+ }
+ }
- return 0;
+ return 0;
}
-bool ca_has_access_to_ta(int ca_fd, const char* ta_name){
- int ret;
- g_ta_name = ta_name;
+bool ca_has_access_to_ta(int ca_fd, const char* ta_name) {
+ int ret;
+ g_ta_name = ta_name;
- char *pkg_id_ca;
+ 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");
+ 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};
+ 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);
+ /* 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;
- }
+ if(file_exists(ta_full_path)){
+ return true;
+ }
- memset(ta_full_path, 0, MAX_PATH_LENGTH);
- }
+ memset(ta_full_path, 0, MAX_PATH_LENGTH);
+ }
- return false;
- }
+ return false;
+ }
- if(ret != SECURITY_MANAGER_SUCCESS){
- EMSG("security_manager_identify_app_from_cynara_client() failed with CA");
- 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;
- }
+ 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;
+ }
- ret = nftw(ca_pkg_path, cmp_ta_name, MAX_OPENED_FD, 0);
- if(ret == FILE_WAS_FOUND){
- free(pkg_id_ca);
- return true;
- }
+/* 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;
+ 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;
+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);
+ free(user);
exit_error1:
- free(session);
+ free(session);
exit_error2:
- free(label);
+ free(label);
exit_error3:
- ret = cynara_finish(cynara);
- if(ret != CYNARA_API_SUCCESS){
- EMSG("Cynara finish failed with error code %d", ret);
- }
+ ret = cynara_finish(cynara);
+ if(ret != CYNARA_API_SUCCESS) {
+ EMSG("Cynara finish failed with error code %d", ret);
+ }
- return false;
+ return false;
}