Add privilege mappings to PrivilegeDb
[platform/core/security/security-manager.git] / src / common / privilege_db.cpp
1 /*
2  * security-manager, database access
3  *
4  * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Rafal Krypa <r.krypa@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /*
23  * @file        privilege_db.cpp
24  * @author      Krzysztof Sasiak <k.sasiak@samsung.com>
25  * @author      Rafal Krypa <r.krypa@samsung.com>
26  * @version     0.1
27  * @brief       This file contains declaration of the API to privileges database.
28  */
29
30 #include <cstdio>
31 #include <list>
32 #include <string>
33 #include <iostream>
34
35 #include <dpl/log/log.h>
36 #include "privilege_db.h"
37
38 namespace SecurityManager {
39
40 /* Common code for handling SqlConnection exceptions */
41 template <typename T>
42 T try_catch(const std::function<T()> &func)
43 {
44     try {
45         return func();
46     } catch (DB::SqlConnection::Exception::SyntaxError &e) {
47         LogError("Syntax error in command: " << e.DumpToString());
48         ThrowMsg(PrivilegeDb::Exception::InternalError,
49             "Syntax error in command: " << e.DumpToString());
50     } catch (DB::SqlConnection::Exception::InternalError &e) {
51         LogError("Mysterious internal error in SqlConnection class" << e.DumpToString());
52         ThrowMsg(PrivilegeDb::Exception::InternalError,
53             "Mysterious internal error in SqlConnection class: " << e.DumpToString());
54     }
55 }
56
57 PrivilegeDb::PrivilegeDb(const std::string &path)
58 {
59     try {
60         mSqlConnection = new DB::SqlConnection(path,
61                 DB::SqlConnection::Flag::None,
62                 DB::SqlConnection::Flag::RW);
63         initDataCommands();
64     } catch (DB::SqlConnection::Exception::Base &e) {
65         LogError("Database initialization error: " << e.DumpToString());
66         ThrowMsg(PrivilegeDb::Exception::IOError,
67                 "Database initialization error:" << e.DumpToString());
68
69     };
70 }
71
72 void PrivilegeDb::initDataCommands()
73 {
74     for (auto &it : Queries) {
75         m_commands.push_back(mSqlConnection->PrepareDataCommand(it.second));
76     }
77 }
78
79 DB::SqlConnection::DataCommandAutoPtr & PrivilegeDb::getStatement(StmtType queryType)
80 {
81     auto &command = m_commands.at(static_cast<size_t>(queryType));
82     command->Reset();
83     return command;
84 }
85
86 PrivilegeDb::~PrivilegeDb()
87 {
88     m_commands.clear();
89     delete mSqlConnection;
90 }
91
92 PrivilegeDb &PrivilegeDb::getInstance()
93 {
94     static PrivilegeDb privilegeDb;
95     return privilegeDb;
96 }
97
98 void PrivilegeDb::BeginTransaction(void)
99 {
100     try_catch<void>([&] {
101         mSqlConnection->BeginTransaction();
102     });
103 }
104
105 void PrivilegeDb::CommitTransaction(void)
106 {
107     try_catch<void>([&] {
108         mSqlConnection->CommitTransaction();
109     });
110 }
111
112 void PrivilegeDb::RollbackTransaction(void)
113 {
114     try_catch<void>([&] {
115         mSqlConnection->RollbackTransaction();
116     });
117 }
118
119 bool PrivilegeDb::PkgIdExists(const std::string &pkgId)
120 {
121     return try_catch<bool>([&] {
122         auto &command = getStatement(StmtType::EPkgIdExists);
123         command->BindString(1, pkgId);
124         return command->Step();
125     });
126 }
127
128 bool PrivilegeDb::GetAppPkgId(const std::string &appId, std::string &pkgId)
129 {
130     return try_catch<bool>([&] {
131         auto &command = getStatement(StmtType::EGetPkgId);
132         command->BindString(1, appId);
133
134         if (!command->Step()) {
135             // No application with such appId
136             return false;
137         }
138
139         // application package found in the database, get it
140         pkgId = command->GetColumnString(0);
141
142         return true;
143     });
144 }
145
146 void PrivilegeDb::AddApplication(const std::string &appId,
147         const std::string &pkgId, uid_t uid)
148 {
149     try_catch<void>([&] {
150         auto &command = getStatement(StmtType::EAddApplication);
151         command->BindString(1, appId);
152         command->BindString(2, pkgId);
153         command->BindInteger(3, static_cast<unsigned int>(uid));
154
155         if (command->Step()) {
156             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
157                     Queries.at(StmtType::EAddApplication));
158         };
159
160         LogDebug("Added appId: " << appId << ", pkgId: " << pkgId);
161     });
162 }
163
164 void PrivilegeDb::RemoveApplication(const std::string &appId, uid_t uid,
165         bool &pkgIdIsNoMore)
166 {
167     try_catch<void>([&] {
168         std::string pkgId;
169         if (!GetAppPkgId(appId, pkgId)) {
170             pkgIdIsNoMore = false;
171             return;
172         }
173
174         auto &command = getStatement(StmtType::ERemoveApplication);
175         command->BindString(1, appId);
176         command->BindInteger(2, static_cast<unsigned int>(uid));
177
178         if (command->Step()) {
179             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
180                     Queries.at(StmtType::ERemoveApplication));
181         };
182
183         LogDebug("Removed appId: " << appId);
184
185         pkgIdIsNoMore = !(this->PkgIdExists(pkgId));
186     });
187 }
188
189 void PrivilegeDb::GetPkgPrivileges(const std::string &pkgId, uid_t uid,
190         std::vector<std::string> &currentPrivileges)
191 {
192     try_catch<void>([&] {
193         auto &command = getStatement(StmtType::EGetPkgPrivileges);
194         command->BindString(1, pkgId);
195         command->BindInteger(2, static_cast<unsigned int>(uid));
196
197         while (command->Step()) {
198             std::string privilege = command->GetColumnString(0);
199             LogDebug("Got privilege: " << privilege);
200             currentPrivileges.push_back(privilege);
201         };
202     });
203 }
204
205 void PrivilegeDb::GetAppPrivileges(const std::string &appId, uid_t uid,
206         std::vector<std::string> &currentPrivileges)
207 {
208     try_catch<void>([&] {
209         DB::SqlConnection::DataCommandAutoPtr &command =
210                 m_commands.at(static_cast<size_t>(StmtType::EGetAppPrivileges));
211
212         command->Reset();
213         command->BindString(1, appId);
214         command->BindInteger(2, static_cast<unsigned int>(uid));
215         currentPrivileges.clear();
216
217         while (command->Step()) {
218             std::string privilege = command->GetColumnString(0);
219             LogDebug("Got privilege: " << privilege);
220             currentPrivileges.push_back(privilege);
221         };
222     });
223 }
224
225 void PrivilegeDb::RemoveAppPrivileges(const std::string &appId, uid_t uid)
226 {
227     try_catch<void>([&] {
228         auto &command = getStatement(StmtType::ERemoveAppPrivileges);
229         command->BindString(1, appId);
230         command->BindInteger(2, static_cast<unsigned int>(uid));
231         if (command->Step()) {
232             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
233                     Queries.at(StmtType::ERemoveAppPrivileges));
234         }
235
236         LogDebug("Removed all privileges for appId: " << appId);
237     });
238 }
239
240 void PrivilegeDb::UpdateAppPrivileges(const std::string &appId, uid_t uid,
241         const std::vector<std::string> &privileges)
242 {
243     try_catch<void>([&] {
244         auto &command = getStatement(StmtType::EAddAppPrivileges);
245         command->BindString(1, appId);
246         command->BindInteger(2, static_cast<unsigned int>(uid));
247
248         RemoveAppPrivileges(appId, uid);
249
250         for (const auto &privilege : privileges) {
251             command->BindString(3, privilege);
252             command->Step();
253             command->Reset();
254             LogDebug("Added privilege: " << privilege << " to appId: " << appId);
255         }
256     });
257 }
258
259 void PrivilegeDb::GetPrivilegeGroups(const std::string &privilege,
260         std::vector<std::string> &groups)
261 {
262    try_catch<void>([&] {
263         auto &command = getStatement(StmtType::EGetPrivilegeGroups);
264         command->BindString(1, privilege);
265
266         while (command->Step()) {
267             std::string groupName = command->GetColumnString(0);
268             LogDebug("Privilege " << privilege << " gives access to group: " << groupName);
269             groups.push_back(groupName);
270         };
271     });
272 }
273
274 void PrivilegeDb::GetUserApps(uid_t uid, std::vector<std::string> &apps)
275 {
276    try_catch<void>([&] {
277         auto &command = getStatement(StmtType::EGetUserApps);
278         command->BindInteger(1, static_cast<unsigned int>(uid));
279         apps.clear();
280         while (command->Step()) {
281             std::string app = command->GetColumnString(0);
282             LogDebug("User " << uid << " has app " << app << " installed");
283             apps.push_back(app);
284         };
285     });
286 }
287
288 void PrivilegeDb::GetAppIdsForPkgId(const std::string &pkgId,
289         std::vector<std::string> &appIds)
290 {
291     try_catch<void>([&] {
292         DB::SqlConnection::DataCommandAutoPtr &command =
293                 m_commands.at(static_cast<size_t>(StmtType::EGetAppsInPkg));
294
295         command->Reset();
296         command->BindString(1, pkgId);
297         appIds.clear();
298
299         while (command->Step()) {
300             std::string appId = command->GetColumnString (0);
301             LogDebug ("Got appid: " << appId << " for pkgId " << pkgId);
302             appIds.push_back(appId);
303         };
304     });
305 }
306
307 void PrivilegeDb::GetDefaultMapping(const std::string &version_from,
308                                     const std::string &version_to,
309                                     std::vector<std::string> &mappings)
310 {
311     try_catch<void>([&] {
312         auto &command = getStatement(StmtType::EGetDefaultMappings);
313         command->BindString(1, version_from);
314         command->BindString(2, version_to);
315
316         mappings.clear();
317         while (command->Step()) {
318             std::string mapping = command->GetColumnString(0);
319             LogDebug("Default Privilege from version " << version_from
320                     <<" to version " << version_to << " is " << mapping);
321             mappings.push_back(mapping);
322         }
323     });
324 }
325
326 void PrivilegeDb::GetPrivilegeMappings(const std::string &version_from,
327                                        const std::string &version_to,
328                                        const std::string &privilege,
329                                        std::vector<std::string> &mappings)
330 {
331     try_catch<void>([&] {
332         auto &command = getStatement(StmtType::EGetPrivilegeMappings);
333         command->BindString(1, version_from);
334         command->BindString(2, version_to);
335         command->BindString(3, privilege);
336
337         mappings.clear();
338         while (command->Step()) {
339             std::string mapping = command->GetColumnString(0);
340             LogDebug("Privilege " << privilege << " in version " << version_from
341                     <<" has mapping " << mapping << " in version " << version_to);
342             mappings.push_back(mapping);
343         }
344     });
345 }
346
347 void PrivilegeDb::GetPrivilegesMappings(const std::string &version_from,
348                                         const std::string &version_to,
349                                         const std::vector<std::string> &privileges,
350                                         std::vector<std::string> &mappings)
351 {
352     try_catch<void>([&] {
353         auto &deleteCmd = getStatement(StmtType::EDeletePrivilegesToMap);
354         deleteCmd->Step();
355
356         auto & insertCmd = getStatement(StmtType::EInsertPrivilegeToMap);
357         for (auto &privilege : privileges) {
358             if (privilege.empty())
359                 continue;
360             insertCmd->BindString(1, privilege);
361             insertCmd->Step();
362             insertCmd->Reset();
363         }
364
365         insertCmd->BindNull(1);
366         insertCmd->Step();
367
368         auto &queryCmd = getStatement(StmtType::EGetPrivilegesMappings);
369         queryCmd->BindString(1, version_from);
370         queryCmd->BindString(2, version_to);
371
372         mappings.clear();
373         while (queryCmd->Step()) {
374             std::string mapping = queryCmd->GetColumnString(0);
375             LogDebug("Privilege set  in version " << version_from
376                      <<" has mapping " << mapping << " in version " << version_to);
377              mappings.push_back(mapping);
378         }
379     });
380 }
381
382 } //namespace SecurityManager