501464c2a9934d808f9eebb90169a48393451c7c
[platform/core/security/askuser.git] / src / common / policy / Policy.cpp
1 /*
2  *  Copyright (c) 2016-2017 Samsung Electronics Co.
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  * @file        src/agent/main/Policy.cpp
18  * @author      Zofia Abramowska <z.abramowska@samsung.com>
19  * @brief       Implementation of Policy wrappers
20  */
21
22 #include <memory>
23 #include <vector>
24
25 #include <security-manager.h>
26
27 #include <exception/Exception.h>
28 #include <log/alog.h>
29
30 #include "PkgInfo.h"
31 #include "Policy.h"
32 #include "PrivilegeInfo.h"
33
34 namespace AskUser {
35
36 namespace {
37 inline void throwOnSMError(std::string err, int ret)
38 {
39     if (ret != SECURITY_MANAGER_SUCCESS)
40         throw AskUser::Exception("SM error : " + err + " : " + std::to_string(ret));
41 }
42
43 inline void throwOnSMNullptr(std::string err, const char *ret)
44 {
45     if (ret == nullptr)
46         throw AskUser::Exception("SM returned null : " + err);
47 }
48
49 } // namespace anonymous
50
51 PolicyEntryCopy::PolicyEntryCopy(policy_entry *entry) {
52     const char *app;
53     throwOnSMNullptr("security_manager_policy_entry_get_application",
54                      app = security_manager_policy_entry_get_application(entry));
55     m_appId = app;
56
57     const char *user;
58     throwOnSMNullptr("security_manager_policy_entry_get_user",
59                      user = security_manager_policy_entry_get_user(entry));
60     m_user = user;
61
62     const char *privilege;
63     throwOnSMNullptr("security_manager_policy_entry_get_privilege",
64                      privilege = security_manager_policy_entry_get_privilege(entry));
65     m_privilege = privilege;
66
67     const char *level;
68     throwOnSMNullptr("security_manager_policy_entry_get_level",
69             level = security_manager_policy_entry_get_level(entry));
70     m_level = level;
71 }
72
73 Policy getMinimumPolicy(const std::vector<Policy> &policies) {
74     Policy minimumPolicy = "Allow";
75
76     for (auto &policy : policies) {
77         if (policy == "Deny") {
78             minimumPolicy = "Deny";
79             break;
80         } else if (policy != minimumPolicy && policy == "Ask user") {
81             minimumPolicy = "Ask user";
82         }
83     }
84     return minimumPolicy;
85 }
86
87 Policy calculatePolicyForPrivacy(const std::string &appId, const Privacy &privacy) {
88     ALOGD("Calculating privacy " << privacy);
89     std::vector<Policy> privsPolicies;
90     auto privileges = PrivilegeInfo::getPrivacyPrivileges(privacy);
91     for (const auto &privilege : privileges) {
92         ALOGD("Calculating policy for privilege " << privilege);
93
94         std::string policyLevel = getPrivilegePolicy(appId, privilege);
95
96         if (policyLevel.empty()) {
97             ALOGE("Couldn't get policy level, skipping");
98             continue;
99         }
100
101         ALOGD("Fetched policy level : " << policyLevel);
102         privsPolicies.push_back(std::move(policyLevel));
103     }
104     return getMinimumPolicy(privsPolicies);
105 }
106
107 Policy getPrivilegePolicy(const std::string &appId, const Privilege &privilege) {
108     PolicyEntry filter;
109     filter.setApp(appId);
110     filter.setUser(std::to_string(geteuid()));
111     filter.setPrivilege(privilege);
112
113     PolicyFetchRequest fetch(std::move(filter));
114     auto policies = fetch.fetchPolicy();
115     if (policies.size() == 0) {
116         ALOGD("No policy for given privilege " << privilege);
117         return "";
118     }
119     if (policies.size() > 1) {
120         ALOGW("Something went wrong, there should be no more than one policy for specific filter");
121         // FIXME : don't really know what to do with it. Lets ignore it for now.
122         return "";
123     }
124     return policies[0].getLevel();
125 }
126
127 Policy getPrivaciesPolicy(const std::string &appId, const std::vector<Privacy> &privacies) {
128     std::vector<Policy> policies;
129     for (auto &privacy : privacies) {
130         policies.push_back(calculatePolicyForPrivacy(appId, privacy));
131     }
132     return getMinimumPolicy(policies);
133 }
134
135 void identifyApp(const std::string &client, std::string &appId, std::string &pkgLabel)
136 {
137     char *pkgName = nullptr;
138     char *appName = nullptr;
139
140     int ret = security_manager_identify_app_from_cynara_client(client.c_str(), &pkgName, &appName);
141     std::unique_ptr<char, decltype(free)*> pkg_name_p(pkgName, free);
142     std::unique_ptr<char, decltype(free)*> app_name_p(appName, free);
143     throwOnSMError("security_manager_identify_app_from_cynara_client", ret);
144
145     if (!pkgName) {
146         ALOGE("Couldn't identify clients package id");
147         return;
148     }
149
150     PkgInfo pkgInfo(pkgName, geteuid());
151     if (!appName)
152         appId = pkgInfo.mainAppId();
153
154     pkgLabel = pkgInfo.pkgLabel();
155 }
156
157 Policy getPrivilegeMappedPolicy(const std::string &appId, const std::string &privilege) {
158     std::vector<Privacy> privacies = PrivilegeInfo::getPrivilegePrivaciesMapping(appId, privilege);
159     if (privacies.empty()) {
160         ALOGE("Privilege doesn't map to any privacy");
161         return "";
162     }
163
164     return getPrivaciesPolicy(appId, privacies);
165 }
166
167 std::string getOwnAppId()
168 {
169     char *pkgName = nullptr;
170     char *appName = nullptr;
171
172     int ret = security_manager_identify_app_from_pid(getpid(), &pkgName, &appName);
173     std::unique_ptr<char, decltype(free)*> pkg_name_p(pkgName, free);
174     std::unique_ptr<char, decltype(free)*> app_name_p(appName, free);
175     throwOnSMError("security_manager_identify_app_from_pid", ret);
176
177     PkgInfo pkgInfo(pkgName, geteuid());
178     if (!appName)
179         return pkgInfo.mainAppId();
180
181     return std::string();
182 }
183
184 PolicyEntry::PolicyEntry() : m_entry(nullptr) {
185     throwOnSMError("security_manager_policy_entry_new",
186                                   security_manager_policy_entry_new(&m_entry));
187 }
188
189 PolicyEntry::PolicyEntry(PolicyEntry &&other) : m_entry(std::move(other.m_entry)) {
190     other.m_entry = nullptr;
191 }
192
193 PolicyEntry::~PolicyEntry() {
194     security_manager_policy_entry_free(m_entry);
195 }
196
197 void PolicyEntry::setApp(const std::string &appId) {
198     throwOnSMError("security_manager_policy_entry_set_application",
199                    security_manager_policy_entry_set_application(m_entry, appId.c_str()));
200 }
201
202 std::string PolicyEntry::getAppId() {
203     const char *app;
204     throwOnSMNullptr("security_manager_policy_entry_get_application",
205                      app = security_manager_policy_entry_get_application(m_entry));
206     return app;
207 }
208
209 void PolicyEntry::setUser(const std::string &user) {
210     throwOnSMError("security_manager_policy_entry_set_user",
211                    security_manager_policy_entry_set_user(m_entry, user.c_str()));
212 }
213
214 std::string PolicyEntry::getUser() {
215     const char *user;
216     throwOnSMNullptr("security_manager_policy_entry_get_user",
217                      user = security_manager_policy_entry_get_user(m_entry));
218     return user;
219 }
220
221 void PolicyEntry::setPrivilege(const std::string &privilege) {
222     throwOnSMError("security_manager_policy_entry_set_privilege",
223                    security_manager_policy_entry_set_privilege(m_entry, privilege.c_str()));
224 }
225
226 std::string PolicyEntry::getPrivilege() {
227     const char *privilege;
228     throwOnSMNullptr("security_manager_policy_entry_get_privilege",
229                      privilege = security_manager_policy_entry_get_privilege(m_entry));
230     return privilege;
231 }
232
233 void PolicyEntry::setLevel(const std::string &level) {
234     throwOnSMError("security_manager_policy_entry_admin_set_level",
235                    security_manager_policy_entry_set_level(m_entry, level.c_str()));
236 }
237
238 std::string PolicyEntry::getLevel() {
239     const char *level;
240     throwOnSMNullptr("security_manager_policy_entry_get_level",
241             level = security_manager_policy_entry_get_level(m_entry));
242     ALOGD("Level : " << level);
243     return level;
244 }
245
246
247 PolicyRequest::PolicyRequest() {
248     throwOnSMError("security_manager_policy_update_req_new",
249                    security_manager_policy_update_req_new(&m_req));
250 }
251
252 PolicyRequest::~PolicyRequest() {
253     m_entries.clear();
254     security_manager_policy_update_req_free(m_req);
255 }
256
257 void PolicyRequest::addEntry(PolicyEntry &&entry) {
258     throwOnSMError("security_manager_policy_update_req_add_entry",
259                    security_manager_policy_update_req_add_entry(m_req, entry.get()));
260     m_entries.emplace_back(std::move(entry));
261 }
262
263 void PolicyRequest::updatePolicy() {
264     throwOnSMError("security_manager_policy_update_send",
265                    security_manager_policy_update_send(m_req));
266 }
267
268
269 std::vector<PolicyEntryCopy> PolicyFetchRequest::fetchPolicy() {
270     policy_entry **pp_entries;
271     size_t p_size;
272     throwOnSMError("security_manager_get_configured_policy_for_self",
273                    security_manager_get_configured_policy_for_self(m_filter.get(), &pp_entries, &p_size));
274     std::unique_ptr<policy_entry *, std::function<void(policy_entry **)>> ppPtr(pp_entries,
275             [p_size](policy_entry **p) {
276                 security_manager_policy_entries_free(p, p_size);
277             }
278     );
279     std::vector<PolicyEntryCopy> entries;
280     for (size_t i = 0; i < p_size; i++) {
281         entries.emplace_back(PolicyEntryCopy(pp_entries[i]));
282     }
283     return entries;
284 }
285
286 } /* namespace AskUser */