2 * Copyright (c) 2017 - 2021 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.
18 #include <cynara-creds-socket.h>
19 #include <cynara-error.h>
21 #include <pkgmgr-info.h>
25 #include "ac-internal.hh"
26 #include "aul-internal.hh"
27 #include "log-private.hh"
28 #include "cynara_thread.hh"
34 constexpr const uid_t kRegularUidMin = 5000;
38 void AccessController::AddPrivilege(std::string privilege) {
39 privileges_.push_back(std::move(privilege));
42 void AccessController::SetTrusted(const bool trusted) {
46 int AccessController::CheckPrivilege(const Cynara& c) {
47 for (auto& privilege : privileges_) {
48 if (c.Check(privilege) != 0) {
57 int AccessController::CheckTrusted(const std::string& sender_appid) {
58 if (getuid() < kRegularUidMin)
62 appid_ = Aul::GetAppId(getpid());
64 _D("CheckCertificate : %s :: %s", appid_.c_str(), sender_appid.c_str());
65 pkgmgrinfo_cert_compare_result_type_e res;
66 int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(appid_.c_str(),
67 sender_appid.c_str(), getuid(), &res);
69 _E("CheckCertificate() Failed");
72 if (res != PMINFO_CERT_COMPARE_MATCH) {
73 _E("CheckCertificate() Failed : Certificate Not Matched");
81 int AccessController::Check(int fd, const std::string& sender_appid) {
83 int ret = cynara.FetchCredsFromSocket(fd);
87 if (!privileges_.empty()) {
88 ret = CheckPrivilege(cynara);
94 ret = CheckTrusted(sender_appid);
99 void AccessController::CheckAsync(int fd, std::string sender_appid,
100 CompleteCallback callback) {
101 /* This is for handle freed issue */
102 auto tmp_handle = new std::shared_ptr<AccessController>(shared_from_this());
103 Job job([=]() -> Job::Type {
104 if ((*tmp_handle).use_count() == 1) {
105 delete tmp_handle; // LCOV_EXCL_LINE
106 return Job::Type::Continue; // LCOV_EXCL_LINE
109 int res = Check(fd, sender_appid);
110 auto* cbdata = new std::pair<CompleteCallback, int>(
111 std::move(callback), res);
112 guint sid = g_idle_add(
113 [](gpointer data) -> gboolean {
114 auto* cb_data = static_cast<std::pair<CompleteCallback, int>*>(data);
115 auto [callback, res] = *cb_data;
118 return G_SOURCE_REMOVE;
121 _E("Failed to call g_idle_add"); // LCOV_EXCL_LINE
122 delete cbdata; // LCOV_EXCL_LINE
126 return Job::Type::Continue;
129 CynaraThread::GetInst().Push(std::move(job));
132 AccessController::Cynara::Cynara()
133 : cynara_(nullptr, cynara_finish), client_(nullptr, std::free),
134 user_(nullptr, std::free) {
135 cynara* cynara_inst = nullptr;
137 if (cynara_initialize(&cynara_inst, NULL) != CYNARA_API_SUCCESS) {
138 _E("cynara_initialize() is failed"); // LCOV_EXCL_LINE
140 cynara_.reset(cynara_inst);
144 AccessController::Cynara::~Cynara() = default;
146 int AccessController::Cynara::FetchCredsFromSocket(int fd) {
147 char* user = nullptr;
148 int ret = cynara_creds_socket_get_user(fd, USER_METHOD_DEFAULT, &user);
149 if (ret != CYNARA_API_SUCCESS) {
151 char buf[128] = { 0, };
152 cynara_strerror(ret, buf, sizeof(buf));
153 _E("cynara_creds_socket_get_user() is failed. fd(%d), error(%d:%s)",
160 char* client = nullptr;
161 ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_DEFAULT, &client);
162 if (ret != CYNARA_API_SUCCESS) {
164 char buf[128] = { 0, };
165 cynara_strerror(ret, buf, sizeof(buf));
166 _E("cynara_creds_socket_get_client() is failed. fd(%d), error(%d:%s)",
171 client_.reset(client);
173 _W("Cred client(%s), user(%s), fd(%d)", client_.get(), user_.get(), fd);
178 int AccessController::Cynara::Check(const std::string& privilege) const {
179 _D("check privilege %s", privilege.c_str());
180 if (cynara_check(cynara_.get(), client_.get(), "", user_.get(),
181 privilege.c_str()) != CYNARA_API_ACCESS_ALLOWED) {
182 _E("cynara_check() is not allowed : %s", privilege.c_str());
190 } // namespace internal
191 } // namespace rpc_port