Don't remove "User" Smack rules on application uninstall
[platform/core/security/security-manager.git] / src / server / service / cynara.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Rafal Krypa <r.krypa@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18 /*
19  * @file        cynara.cpp
20  * @author      Rafal Krypa <r.krypa@samsung.com>
21  * @brief       Wrapper class for Cynara interface
22  */
23
24 #include <cstring>
25 #include <string>
26 #include <vector>
27 #include "cynara.h"
28
29 #include <dpl/log/log.h>
30
31 namespace SecurityManager {
32
33
34 CynaraAdminPolicy::CynaraAdminPolicy(const std::string &client, const std::string &user,
35         const std::string &privilege, Operation operation,
36         const std::string &bucket)
37 {
38     this->client = strdup(client.c_str());
39     this->user = strdup(user.c_str());
40     this->privilege = strdup(privilege.c_str());
41     this->bucket = strdup(bucket.c_str());
42
43     if (this->bucket == nullptr || this->client == nullptr ||
44         this->user == nullptr || this->privilege == nullptr) {
45         free(this->bucket);
46         free(this->client);
47         free(this->user);
48         free(this->privilege);
49         ThrowMsg(CynaraException::OutOfMemory,
50                 std::string("Error in CynaraAdminPolicy allocation."));
51     }
52
53     this->result = static_cast<int>(operation);
54     this->result_extra = nullptr;
55 }
56
57 CynaraAdminPolicy::CynaraAdminPolicy(const std::string &client, const std::string &user,
58     const std::string &privilege, const std::string &goToBucket,
59     const std::string &bucket)
60 {
61     this->bucket = strdup(bucket.c_str());
62     this->client = strdup(client.c_str());
63     this->user = strdup(user.c_str());
64     this->privilege = strdup(privilege.c_str());
65     this->result_extra = strdup(goToBucket.c_str());
66     this->result = CYNARA_ADMIN_BUCKET;
67
68     if (this->bucket == nullptr || this->client == nullptr ||
69         this->user == nullptr || this->privilege == nullptr ||
70         this->result_extra == nullptr) {
71         free(this->bucket);
72         free(this->client);
73         free(this->user);
74         free(this->privilege);
75         free(this->result_extra);
76         ThrowMsg(CynaraException::OutOfMemory,
77                 std::string("Error in CynaraAdminPolicy allocation."));
78     }
79 }
80
81 CynaraAdminPolicy::CynaraAdminPolicy(CynaraAdminPolicy &&that)
82 {
83     bucket = that.bucket;
84     client = that.client;
85     user = that.user;
86     privilege = that.privilege;
87     result_extra = that.result_extra;
88     result = that.result;
89
90     that.bucket = nullptr;
91     that.client = nullptr;
92     that.user = nullptr;
93     that.privilege = nullptr;
94     that.result_extra = nullptr;
95 }
96
97 CynaraAdminPolicy::~CynaraAdminPolicy()
98 {
99     free(this->bucket);
100     free(this->client);
101     free(this->user);
102     free(this->privilege);
103     free(this->result_extra);
104 }
105
106 static bool checkCynaraError(int result, const std::string &msg)
107 {
108     switch (result) {
109         case CYNARA_API_SUCCESS:
110         case CYNARA_API_ACCESS_ALLOWED:
111             return true;
112         case CYNARA_API_ACCESS_DENIED:
113             return false;
114         case CYNARA_API_OUT_OF_MEMORY:
115             ThrowMsg(CynaraException::OutOfMemory, msg);
116         case CYNARA_API_INVALID_PARAM:
117             ThrowMsg(CynaraException::InvalidParam, msg);
118         case CYNARA_API_SERVICE_NOT_AVAILABLE:
119             ThrowMsg(CynaraException::ServiceNotAvailable, msg);
120         default:
121             ThrowMsg(CynaraException::UnknownError, msg);
122     }
123 }
124
125 CynaraAdmin::CynaraAdmin()
126 {
127     checkCynaraError(
128         cynara_admin_initialize(&m_CynaraAdmin),
129         "Cannot connect to Cynara administrative interface.");
130 }
131
132 CynaraAdmin::~CynaraAdmin()
133 {
134     cynara_admin_finish(m_CynaraAdmin);
135 }
136
137 void CynaraAdmin::SetPolicies(const std::vector<CynaraAdminPolicy> &policies)
138 {
139     std::vector<const struct cynara_admin_policy *> pp_policies(policies.size() + 1);
140
141     LogDebug("Sending " << policies.size() << " policies to Cynara");
142     for (std::size_t i = 0; i < policies.size(); ++i) {
143         pp_policies[i] = static_cast<const struct cynara_admin_policy *>(&policies[i]);
144         LogDebug("policies[" << i << "] = {" <<
145             ".bucket = " << pp_policies[i]->bucket << ", " <<
146             ".client = " << pp_policies[i]->client << ", " <<
147             ".user = " << pp_policies[i]->user << ", " <<
148             ".privilege = " << pp_policies[i]->privilege << ", " <<
149             ".result = " << pp_policies[i]->result << ", " <<
150             ".result_extra = " << pp_policies[i]->result_extra << "}");
151     }
152
153     pp_policies[policies.size()] = nullptr;
154
155     checkCynaraError(
156         cynara_admin_set_policies(m_CynaraAdmin, pp_policies.data()),
157         "Error while updating Cynara policy.");
158 }
159
160 void CynaraAdmin::UpdatePackagePolicy(
161     const std::string &label,
162     const std::string &user,
163     const std::vector<std::string> &oldPrivileges,
164     const std::vector<std::string> &newPrivileges)
165 {
166     CynaraAdmin cynaraAdmin;
167     std::vector<CynaraAdminPolicy> policies;
168
169     // Perform sort-merge join on oldPrivileges and newPrivileges.
170     // Assume that they are already sorted and without duplicates.
171     auto oldIter = oldPrivileges.begin();
172     auto newIter = newPrivileges.begin();
173
174     while (oldIter != oldPrivileges.end() && newIter != newPrivileges.end()) {
175         int compare = oldIter->compare(*newIter);
176         if (compare == 0) {
177             LogDebug("(user = " << user << " label = " << label << ") " <<
178                 "keeping privilege " << *newIter);
179             ++oldIter;
180             ++newIter;
181             continue;
182         } else if (compare < 0) {
183             LogDebug("(user = " << user << " label = " << label << ") " <<
184                 "removing privilege " << *oldIter);
185             policies.push_back(CynaraAdminPolicy(label, user, *oldIter,
186                     CynaraAdminPolicy::Operation::Delete));
187             ++oldIter;
188         } else {
189             LogDebug("(user = " << user << " label = " << label << ") " <<
190                 "adding privilege " << *newIter);
191             policies.push_back(CynaraAdminPolicy(label, user, *newIter,
192                     CynaraAdminPolicy::Operation::Allow));
193             ++newIter;
194         }
195     }
196
197     for (; oldIter != oldPrivileges.end(); ++oldIter) {
198         LogDebug("(user = " << user << " label = " << label << ") " <<
199             "removing privilege " << *oldIter);
200         policies.push_back(CynaraAdminPolicy(label, user, *oldIter,
201                     CynaraAdminPolicy::Operation::Delete));
202     }
203
204     for (; newIter != newPrivileges.end(); ++newIter) {
205         LogDebug("(user = " << user << " label = " << label << ") " <<
206             "adding privilege " << *newIter);
207         policies.push_back(CynaraAdminPolicy(label, user, *newIter,
208                     CynaraAdminPolicy::Operation::Allow));
209     }
210
211     cynaraAdmin.SetPolicies(policies);
212 }
213
214 Cynara::Cynara()
215 {
216     checkCynaraError(
217         cynara_initialize(&m_Cynara, nullptr),
218         "Cannot connect to Cynara policy interface.");
219 }
220
221 Cynara::~Cynara()
222 {
223     cynara_finish(m_Cynara);
224 }
225
226 bool Cynara::check(const std::string &label, const std::string &privilege,
227         const std::string &user, const std::string &session)
228 {
229     return checkCynaraError(
230         cynara_check(m_Cynara,
231             label.c_str(), session.c_str(), user.c_str(), privilege.c_str()),
232         "Cannot check permission with Cynara.");
233 }
234
235 } // namespace SecurityManager