98addbb7686fab070a56fe6d9fccef3b6ea8db30
[platform/core/appfw/rpc-port.git] / src / ac-internal.cc
1 /*
2  * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <aul.h>
18 #include <cynara-creds-socket.h>
19 #include <cynara-error.h>
20 #include <dlog.h>
21 #include <pkgmgr-info.h>
22
23 #include <utility>
24
25 #include "ac-internal.hh"
26 #include "aul-internal.hh"
27 #include "log-private.hh"
28
29 namespace rpc_port {
30 namespace internal {
31 namespace {
32
33 constexpr const uid_t kRegularUidMin = 5000;
34
35 }  // namespace
36
37 void AccessController::AddPrivilege(std::string privilege) {
38   privileges_.push_back(std::move(privilege));
39 }
40
41 void AccessController::SetTrusted(const bool trusted) {
42   trusted_ = trusted;
43 }
44
45 int AccessController::CheckPrivilege(const Cynara& c) {
46   for (auto& privilege : privileges_) {
47     if (c.Check(privilege) != 0) {
48       return -1;
49     }
50   }
51
52   return 0;
53 }
54
55 int AccessController::CheckTrusted(const std::string& sender_appid) {
56   if (getuid() < kRegularUidMin)
57     return 0;
58
59   if (appid_.empty())
60     appid_ = Aul::GetAppId(getpid());
61
62   _D("CheckCertificate : %s :: %s", appid_.c_str(), sender_appid.c_str());
63   pkgmgrinfo_cert_compare_result_type_e res;
64   int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(appid_.c_str(),
65       sender_appid.c_str(), getuid(), &res);
66   if (ret < 0) {
67     _E("CheckCertificate() Failed");
68     return -1;
69   }
70   if (res != PMINFO_CERT_COMPARE_MATCH) {
71     _E("CheckCertificate() Failed : Certificate Not Matched");
72     return -1;
73   }
74
75   return 0;
76 }
77
78 int AccessController::Check(int fd, const std::string& sender_appid) {
79   Cynara cynara;
80   int ret = cynara.FetchCredsFromSocket(fd);
81   if (ret != 0)
82     return -1;
83
84   if (!privileges_.empty()) {
85     ret = CheckPrivilege(cynara);
86     if (ret != 0)
87       return ret;
88   }
89
90   if (trusted_)
91     ret = CheckTrusted(sender_appid);
92
93   return ret;
94 }
95
96 AccessController::Cynara::Cynara()
97     : cynara_(nullptr, cynara_finish), client_(nullptr, std::free),
98     user_(nullptr, std::free) {
99   cynara* cynara_inst = nullptr;
100
101   if (cynara_initialize(&cynara_inst, NULL) != CYNARA_API_SUCCESS) {
102     _E("cynara_initialize() is failed");  // LCOV_EXL_LINE
103   } else {
104     cynara_.reset(cynara_inst);
105   }
106 }
107
108 AccessController::Cynara::~Cynara() = default;
109
110 int AccessController::Cynara::FetchCredsFromSocket(int fd) {
111   char* user = nullptr;
112   int ret = cynara_creds_socket_get_user(fd, USER_METHOD_DEFAULT, &user);
113   if (ret != CYNARA_API_SUCCESS) {
114     char buf[128] = { 0, };
115     cynara_strerror(ret, buf, sizeof(buf));
116     _E("cynara_creds_socket_get_user() is failed. fd(%d), error(%d:%s)",
117         fd, ret, buf);
118     return -1;
119   }
120   user_.reset(user);
121
122   char* client = nullptr;
123   ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_DEFAULT, &client);
124   if (ret != CYNARA_API_SUCCESS) {
125     char buf[128] = { 0, };
126     cynara_strerror(ret, buf, sizeof(buf));
127     _E("cynara_creds_socket_get_client() is failed. fd(%d), error(%d:%s)",
128         fd, ret, buf);
129     return -1;
130   }
131   client_.reset(client);
132
133   _D("Cred client(%s), user(%s)", client_.get(), user_.get());
134   return 0;
135 }
136
137 int AccessController::Cynara::Check(const std::string& privilege) const {
138   _D("check privilege %s", privilege.c_str());
139   if (cynara_check(cynara_.get(), client_.get(), "", user_.get(),
140       privilege.c_str()) != CYNARA_API_ACCESS_ALLOWED) {
141     _E("cynara_check() is not allowed : %s", privilege.c_str());
142     return -1;
143   }
144
145   return 0;
146 }
147
148 }  // namespace internal
149 }  // namespace rpc_port