2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * @author Uladzislau Harbuz (u.harbuz@samsung.com)
20 * @brief SecurityContext class
24 #include "SecurityContext.h"
25 #include <cynara/cynara-creds-socket.h>
26 #include <cynara/cynara-session.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
35 using p_char = std::unique_ptr<char, std::function<void(void*)>>;
36 using p_cynara_conf = std::unique_ptr<cynara_configuration, std::function<void(cynara_configuration*)>>;
38 constexpr const char* SecurityContext::sysTaPaths[];
40 cynara* SecurityContext::_cynara = SecurityContext::initCynara();
42 pthread_mutex_t cynara_mutex = PTHREAD_MUTEX_INITIALIZER;
44 #define BOOST_FILESYSTEM_VERSION 3
45 #define RETURN_UNLOCK(ret, mtx) {pthread_mutex_unlock(&mtx); return ret;}
48 bool SecurityContext::clientHasCynaraPermission(const std::string &privelege) {
51 pthread_mutex_lock(&cynara_mutex);
53 char *label = nullptr;
54 ret = cynara_creds_socket_get_client(connFd, CLIENT_METHOD_SMACK, &label);
55 if (ret != CYNARA_API_SUCCESS) {
56 LOGE(SIM_DAEMON, "Couldn't get smack label of the client. Error code: %d", ret);
57 RETURN_UNLOCK(false, cynara_mutex);
59 p_char p_label(label, &free);
62 ret = cynara_creds_socket_get_pid(connFd, &ca_pid);
63 if (ret != CYNARA_API_SUCCESS) {
64 LOGE(SIM_DAEMON, "Couldn't get pid of the client. Error code: %d", ret);
65 RETURN_UNLOCK(false, cynara_mutex);
68 char *session = nullptr;
69 session = cynara_session_from_pid(ca_pid);
71 LOGE(SIM_DAEMON, "Couldn't get client's cynara session.");
72 RETURN_UNLOCK(false, cynara_mutex);
74 p_char p_session(session, &free);
77 ret = cynara_creds_socket_get_user(connFd, USER_METHOD_DEFAULT, &user);
78 if (ret != CYNARA_API_SUCCESS) {
79 LOGE(SIM_DAEMON, "Couldn't get user. Error code: %d", ret);
80 RETURN_UNLOCK(false, cynara_mutex);
82 p_char p_user(user, &free);
84 ret = cynara_check(_cynara, p_label.get(), p_session.get(), p_user.get(), privelege.c_str());
86 if (ret == CYNARA_API_ACCESS_DENIED) {
87 LOGE(SIM_DAEMON, "Cynara access denied.");
88 RETURN_UNLOCK(false, cynara_mutex);
90 if (ret != CYNARA_API_ACCESS_ALLOWED) {
91 LOGE(SIM_DAEMON, "Error during cynara_check(). Error code: %d", ret);
92 RETURN_UNLOCK(false, cynara_mutex);
95 RETURN_UNLOCK(true, cynara_mutex);
99 cynara* SecurityContext::initCynara() {
101 cynara_configuration *p_conf = nullptr;
102 cynara* result = nullptr;
104 ret = cynara_configuration_create(&p_conf);
105 if (ret != CYNARA_API_SUCCESS) {
106 LOGE(SIM_DAEMON, "Cynara configuration creation failed");
110 p_cynara_conf conf(p_conf, &cynara_configuration_destroy);
112 ret = cynara_configuration_set_cache_size(p_conf, CYNARA_CACHE_SIZE);
113 if (ret != CYNARA_API_SUCCESS) {
114 LOGE(SIM_DAEMON, "Set cynara cache size failed");
118 ret = cynara_initialize(&result, conf.get());
119 if (ret != CYNARA_API_SUCCESS) {
120 LOGE(SIM_DAEMON, "Cynara initialize failed");
128 SecurityContext::SecurityContext():
129 SecurityContext(-1) {
133 SecurityContext::SecurityContext(int connFd):
135 if (_cynara == nullptr) throw std::runtime_error("Cynara is not initialized");
139 SecurityContext::~SecurityContext() {