53190fa8c0a16ccf74981b6fc799779cef5d7be0
[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::getQuery(QueryType 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     delete mSqlConnection;
89 }
90
91 PrivilegeDb &PrivilegeDb::getInstance()
92 {
93     static PrivilegeDb privilegeDb;
94     return privilegeDb;
95 }
96
97 void PrivilegeDb::BeginTransaction(void)
98 {
99     try_catch<void>([&] {
100         mSqlConnection->BeginTransaction();
101     });
102 }
103
104 void PrivilegeDb::CommitTransaction(void)
105 {
106     try_catch<void>([&] {
107         mSqlConnection->CommitTransaction();
108     });
109 }
110
111 void PrivilegeDb::RollbackTransaction(void)
112 {
113     try_catch<void>([&] {
114         mSqlConnection->RollbackTransaction();
115     });
116 }
117
118 bool PrivilegeDb::PkgIdExists(const std::string &pkgId)
119 {
120     return try_catch<bool>([&] {
121         auto &command = getQuery(QueryType::EPkgIdExists);
122         command->BindString(1, pkgId.c_str());
123         return command->Step();
124     });
125 }
126
127 bool PrivilegeDb::GetAppPkgId(const std::string &appId, std::string &pkgId)
128 {
129     return try_catch<bool>([&] {
130         auto &command = getQuery(QueryType::EGetPkgId);
131         command->BindString(1, appId.c_str());
132
133         if (!command->Step()) {
134             // No application with such appId
135             return false;
136         }
137
138         // application package found in the database, get it
139         pkgId = command->GetColumnString(0);
140
141         return true;
142     });
143 }
144
145 void PrivilegeDb::AddApplication(const std::string &appId,
146         const std::string &pkgId, uid_t uid)
147 {
148     try_catch<void>([&] {
149         auto &command = getQuery(QueryType::EAddApplication);
150         command->BindString(1, appId.c_str());
151         command->BindString(2, pkgId.c_str());
152         command->BindInteger(3, static_cast<unsigned int>(uid));
153
154         if (command->Step()) {
155             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
156                     Queries.at(QueryType::EAddApplication));
157         };
158
159         LogDebug("Added appId: " << appId << ", pkgId: " << pkgId);
160     });
161 }
162
163 void PrivilegeDb::RemoveApplication(const std::string &appId, uid_t uid,
164         bool &pkgIdIsNoMore)
165 {
166     try_catch<void>([&] {
167         std::string pkgId;
168         if (!GetAppPkgId(appId, pkgId)) {
169             pkgIdIsNoMore = false;
170             return;
171         }
172
173         auto &command = getQuery(QueryType::ERemoveApplication);
174         command->BindString(1, appId.c_str());
175         command->BindInteger(2, static_cast<unsigned int>(uid));
176
177         if (command->Step()) {
178             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
179                     Queries.at(QueryType::ERemoveApplication));
180         };
181
182         LogDebug("Removed appId: " << appId);
183
184         pkgIdIsNoMore = !(this->PkgIdExists(pkgId));
185     });
186 }
187
188 void PrivilegeDb::GetPkgPrivileges(const std::string &pkgId, uid_t uid,
189         std::vector<std::string> &currentPrivileges)
190 {
191     try_catch<void>([&] {
192         auto &command = getQuery(QueryType::EGetPkgPrivileges);
193         command->BindString(1, pkgId.c_str());
194         command->BindInteger(2, static_cast<unsigned int>(uid));
195
196         while (command->Step()) {
197             std::string privilege = command->GetColumnString(0);
198             LogDebug("Got privilege: " << privilege);
199             currentPrivileges.push_back(privilege);
200         };
201     });
202 }
203
204 void PrivilegeDb::GetAppPrivileges(const std::string &appId, uid_t uid,
205         std::vector<std::string> &currentPrivileges)
206 {
207     try_catch<void>([&] {
208         DB::SqlConnection::DataCommandAutoPtr &command =
209                 m_commands.at(static_cast<size_t>(QueryType::EGetAppPrivileges));
210
211         command->Reset();
212         command->BindString(1, appId.c_str());
213         command->BindInteger(2, static_cast<unsigned int>(uid));
214         currentPrivileges.clear();
215
216         while (command->Step()) {
217             std::string privilege = command->GetColumnString(0);
218             LogDebug("Got privilege: " << privilege);
219             currentPrivileges.push_back(privilege);
220         };
221     });
222 }
223
224 void PrivilegeDb::RemoveAppPrivileges(const std::string &appId, uid_t uid)
225 {
226     try_catch<void>([&] {
227         auto &command = getQuery(QueryType::ERemoveAppPrivileges);
228         command->BindString(1, appId.c_str());
229         command->BindInteger(2, static_cast<unsigned int>(uid));
230         if (command->Step()) {
231             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
232                     Queries.at(QueryType::ERemoveAppPrivileges));
233         }
234
235         LogDebug("Removed all privileges for appId: " << appId);
236     });
237 }
238
239 void PrivilegeDb::UpdateAppPrivileges(const std::string &appId, uid_t uid,
240         const std::vector<std::string> &privileges)
241 {
242     try_catch<void>([&] {
243         auto &command = getQuery(QueryType::EAddAppPrivileges);
244         command->BindString(1, appId.c_str());
245         command->BindInteger(2, static_cast<unsigned int>(uid));
246
247         RemoveAppPrivileges(appId, uid);
248
249         for (const auto &privilege : privileges) {
250             command->BindString(3, privilege.c_str());
251             command->Step();
252             command->Reset();
253             LogDebug("Added privilege: " << privilege << " to appId: " << appId);
254         }
255     });
256 }
257
258 void PrivilegeDb::GetPrivilegeGroups(const std::string &privilege,
259         std::vector<std::string> &groups)
260 {
261    try_catch<void>([&] {
262         auto &command = getQuery(QueryType::EGetPrivilegeGroups);
263         command->BindString(1, privilege.c_str());
264
265         while (command->Step()) {
266             std::string groupName = command->GetColumnString(0);
267             LogDebug("Privilege " << privilege << " gives access to group: " << groupName);
268             groups.push_back(groupName);
269         };
270     });
271 }
272
273 void PrivilegeDb::GetUserApps(uid_t uid, std::vector<std::string> &apps)
274 {
275    try_catch<void>([&] {
276         auto &command = getQuery(QueryType::EGetUserApps);
277         command->BindInteger(1, static_cast<unsigned int>(uid));
278         apps.clear();
279         while (command->Step()) {
280             std::string app = command->GetColumnString(0);
281             LogDebug("User " << uid << " has app " << app << " installed");
282             apps.push_back(app);
283         };
284     });
285 }
286
287 void PrivilegeDb::GetAppIdsForPkgId(const std::string &pkgId,
288         std::vector<std::string> &appIds)
289 {
290     try_catch<void>([&] {
291         DB::SqlConnection::DataCommandAutoPtr &command =
292                 m_commands.at(static_cast<size_t>(QueryType::EGetAppsInPkg));
293
294         command->Reset();
295         command->BindString(1, pkgId.c_str());
296         appIds.clear();
297
298         while (command->Step()) {
299             std::string appId = command->GetColumnString (0);
300             LogDebug ("Got appid: " << appId << " for pkgId " << pkgId);
301             appIds.push_back(appId);
302         };
303     });
304 }
305
306 } //namespace SecurityManager