Move some modules to common library
[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     } catch (DB::SqlConnection::Exception::Base &e) {
64         LogError("Database initialization error: " << e.DumpToString());
65         ThrowMsg(PrivilegeDb::Exception::IOError,
66                 "Database initialization error:" << e.DumpToString());
67
68     };
69 }
70
71 PrivilegeDb::~PrivilegeDb()
72 {
73     delete mSqlConnection;
74 }
75
76 void PrivilegeDb::BeginTransaction(void)
77 {
78     try_catch<void>([&] {
79         mSqlConnection->BeginTransaction();
80     });
81 }
82
83 void PrivilegeDb::CommitTransaction(void)
84 {
85     try_catch<void>([&] {
86         mSqlConnection->CommitTransaction();
87     });
88 }
89
90 void PrivilegeDb::RollbackTransaction(void)
91 {
92     try_catch<void>([&] {
93         mSqlConnection->RollbackTransaction();
94     });
95 }
96
97 bool PrivilegeDb::PkgIdExists(const std::string &pkgId)
98 {
99     return try_catch<bool>([&] {
100         DB::SqlConnection::DataCommandAutoPtr command =
101                 mSqlConnection->PrepareDataCommand(
102                         Queries.at(QueryType::EPkgIdExists));
103         command->BindString(1, pkgId.c_str());
104         if (command->Step()) {
105             // pkgId found in the database
106             command->Reset();
107             return true;
108         };
109
110         // pkgId not found in the database
111         return false;
112     });
113 }
114
115 bool PrivilegeDb::GetAppPkgId(const std::string &appId, std::string &pkgId)
116 {
117     return try_catch<bool>([&] {
118         DB::SqlConnection::DataCommandAutoPtr command =
119             mSqlConnection->PrepareDataCommand(Queries.at(QueryType::EGetPkgId));
120         command->BindString(1, appId.c_str());
121
122         if (!command->Step()) {
123             // No application with such appId
124             return false;
125         }
126
127         // application package found in the database, get it
128         pkgId = command->GetColumnString(0);
129
130         return true;
131     });
132 }
133
134 void PrivilegeDb::AddApplication(const std::string &appId,
135         const std::string &pkgId, uid_t uid, bool &pkgIdIsNew)
136 {
137     pkgIdIsNew = !(this->PkgIdExists(pkgId));
138
139     try_catch<void>([&] {
140         DB::SqlConnection::DataCommandAutoPtr command =
141                 mSqlConnection->PrepareDataCommand(
142                         Queries.at(QueryType::EAddApplication));
143
144         command->BindString(1, appId.c_str());
145         command->BindString(2, pkgId.c_str());
146         command->BindInteger(3, static_cast<unsigned int>(uid));
147
148         if (command->Step()) {
149             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
150                     Queries.at(QueryType::EAddApplication));
151         };
152
153         command->Reset();
154         LogDebug("Added appId: " << appId << ", pkgId: " << pkgId);
155     });
156 }
157
158 void PrivilegeDb::RemoveApplication(const std::string &appId, uid_t uid,
159         bool &pkgIdIsNoMore)
160 {
161     try_catch<void>([&] {
162         std::string pkgId;
163         if (!GetAppPkgId(appId, pkgId)) {
164             pkgIdIsNoMore = false;
165             return;
166         }
167
168         DB::SqlConnection::DataCommandAutoPtr command =
169                 mSqlConnection->PrepareDataCommand(
170                         Queries.at(QueryType::ERemoveApplication));
171
172         command->BindString(1, appId.c_str());
173         command->BindInteger(2, static_cast<unsigned int>(uid));
174
175         if (command->Step()) {
176             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
177                     Queries.at(QueryType::ERemoveApplication));
178         };
179
180         command->Reset();
181         LogDebug("Removed appId: " << appId);
182
183         pkgIdIsNoMore = !(this->PkgIdExists(pkgId));
184     });
185 }
186
187 void PrivilegeDb::GetPkgPrivileges(const std::string &pkgId, uid_t uid,
188         std::vector<std::string> &currentPrivileges)
189 {
190     try_catch<void>([&] {
191         DB::SqlConnection::DataCommandAutoPtr command =
192                 mSqlConnection->PrepareDataCommand(
193                         Queries.at(QueryType::EGetPkgPrivileges));
194         command->BindString(1, pkgId.c_str());
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::RemoveAppPrivileges(const std::string &appId, uid_t uid)
206 {
207     try_catch<void>([&] {
208         DB::SqlConnection::DataCommandAutoPtr command =
209             mSqlConnection->PrepareDataCommand(Queries.at(QueryType::ERemoveAppPrivileges));
210
211         command->BindString(1, appId.c_str());
212         command->BindInteger(2, static_cast<unsigned int>(uid));
213         if (command->Step()) {
214             LogDebug("Unexpected SQLITE_ROW answer to query: " <<
215                     Queries.at(QueryType::ERemoveAppPrivileges));
216         }
217
218         LogDebug("Removed all privileges for appId: " << appId);
219     });
220 }
221
222 void PrivilegeDb::UpdateAppPrivileges(const std::string &appId, uid_t uid,
223         const std::vector<std::string> &privileges)
224 {
225     try_catch<void>([&] {
226         DB::SqlConnection::DataCommandAutoPtr command =
227             mSqlConnection->PrepareDataCommand(Queries.at(QueryType::EAddAppPrivileges));
228         command->BindString(1, appId.c_str());
229         command->BindInteger(2, static_cast<unsigned int>(uid));
230
231         RemoveAppPrivileges(appId, uid);
232
233         for (const auto &privilege : privileges) {
234             command->BindString(3, privilege.c_str());
235             command->Step();
236             command->Reset();
237             LogDebug("Added privilege: " << privilege << " to appId: " << appId);
238         }
239     });
240 }
241
242 void PrivilegeDb::GetPrivilegeGroups(const std::string &privilege,
243         std::vector<std::string> &groups)
244 {
245    try_catch<void>([&] {
246         DB::SqlConnection::DataCommandAutoPtr command =
247                 mSqlConnection->PrepareDataCommand(
248                         Queries.at(QueryType::EGetPrivilegeGroups));
249         command->BindString(1, privilege.c_str());
250
251         while (command->Step()) {
252             std::string groupName = command->GetColumnString(0);
253             LogDebug("Privilege " << privilege << " gives access to group: " << groupName);
254             groups.push_back(groupName);
255         };
256     });
257 }
258
259
260 } //namespace SecurityManager