modify logs
[platform/core/security/privacy-manager.git] / client / src / PrivacyChecker.cpp
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <PrivacyChecker.h>
18 #include <PrivacyIdInfo.h>
19 #include <PrivacyManagerClient.h>
20 #include <SocketClient.h>
21 #include <algorithm> 
22 #include <memory>
23 #include <Utils.h>
24 #include <dlog.h>
25 #include <sqlite3.h>
26 #include <dbus/dbus-glib-lowlevel.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29
30 bool PrivacyChecker::m_isInitialized = false;
31 std::map < std::string, bool >PrivacyChecker::m_privacyCache;
32 std::map < std::string, std::map < std::string, bool > > PrivacyChecker::m_privacyInfoCache;
33 std::mutex PrivacyChecker::m_cacheMutex;
34 std::string PrivacyChecker::m_pkgId;
35 DBusConnection* PrivacyChecker::m_pDBusConnection;
36 GMainLoop* PrivacyChecker::m_pLoop = NULL;
37 GMainContext* PrivacyChecker::m_pHandlerGMainContext = NULL;
38 const int MAX_LOCAL_BUF_SIZE = 128;
39 pthread_t PrivacyChecker::m_signalThread;
40
41 int
42 PrivacyChecker::initialize(const std::string pkgId)
43 {
44         if (m_isInitialized) {
45                 return PRIV_MGR_ERROR_SUCCESS;
46         }
47
48         m_pkgId = pkgId;
49
50         std::lock_guard < std::mutex > guard(m_cacheMutex);
51
52         int res = updateCache(m_pkgId, m_privacyCache);
53         TryReturn(res == 0, res, m_pkgId.clear(), "Failed to update cache : %d", res);
54
55         res = initialize();
56         TryReturn(res == 0, res, m_pkgId.clear(), "Failed to initialize() : %d", res);
57
58         return PRIV_MGR_ERROR_SUCCESS;
59 }
60
61 int
62 PrivacyChecker::initialize(void)
63 {
64         TryReturn(!m_isInitialized, PRIV_MGR_ERROR_SUCCESS, , "Already Initalized");
65
66         m_pHandlerGMainContext = g_main_context_new();
67         TryReturn(m_pHandlerGMainContext != NULL, PRIV_MGR_ERROR_SYSTEM_ERROR, m_pkgId.clear(), "cannot create m_pHandlerGMainContext");
68
69         m_pLoop = g_main_loop_new(m_pHandlerGMainContext, FALSE);
70         TryReturn(m_pLoop != NULL, PRIV_MGR_ERROR_SYSTEM_ERROR, m_pkgId.clear(), "cannot create m_pLoop");
71
72         int res = pthread_create(&m_signalThread, NULL, &runSignalListenerThread, NULL);
73         TryReturn(res >= 0, PRIV_MGR_ERROR_SYSTEM_ERROR, errno = res;, "Failed to create listener thread :%s", strerror(res));
74
75         m_isInitialized = true;
76
77         return PRIV_MGR_ERROR_SUCCESS;
78 }
79
80 void*
81 PrivacyChecker::runSignalListenerThread(void* pData)
82 {
83         pthread_detach(pthread_self());
84         LOGI("Running g main loop for signal");
85
86         initializeDbus();
87
88         g_main_loop_run(m_pLoop);
89
90         finalizeDbus();
91
92         pthread_exit(NULL);
93
94         return (void*) 0;
95 }
96
97 int
98 PrivacyChecker::initializeDbus(void)
99 {
100         DBusError error;
101         dbus_error_init(&error);
102
103         m_pDBusConnection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
104         TryReturn(m_pDBusConnection != NULL, PRIV_MGR_ERROR_SYSTEM_ERROR, dbus_error_free(&error), "dbus_bus_get_private [%s] : %d", PRIV_MGR_ERROR_SYSTEM_ERROR);
105
106         dbus_connection_setup_with_g_main(m_pDBusConnection, m_pHandlerGMainContext);
107         std::unique_ptr < char[] > pRule(new char[MAX_LOCAL_BUF_SIZE]);
108
109         snprintf(pRule.get(), MAX_LOCAL_BUF_SIZE, "path='%s',type='signal',interface='%s'", DBUS_PATH.c_str(), DBUS_SIGNAL_INTERFACE.c_str());
110         dbus_bus_add_match(m_pDBusConnection, pRule.get(), &error);
111         TryReturn(!dbus_error_is_set(&error), PRIV_MGR_ERROR_SYSTEM_ERROR, dbus_error_free(&error), "dbus_bus_add_match[%s] : %d", error.message, PRIV_MGR_ERROR_SYSTEM_ERROR);
112
113         dbus_bool_t r = dbus_connection_add_filter(m_pDBusConnection, handleNotification, NULL, NULL);
114         TryReturn(r, PRIV_MGR_ERROR_SYSTEM_ERROR, , "dbus_connection_add_filter: %d", PRIV_MGR_ERROR_SYSTEM_ERROR);
115
116         return PRIV_MGR_ERROR_SUCCESS;
117 }
118
119 int
120 PrivacyChecker::finalizeDbus(void)
121 {
122         dbus_connection_remove_filter(m_pDBusConnection, handleNotification, NULL);
123         dbus_connection_close(m_pDBusConnection);
124         m_pDBusConnection = NULL;
125
126         return PRIV_MGR_ERROR_SUCCESS;
127 }
128
129
130 DBusHandlerResult
131 PrivacyChecker::handleNotification(DBusConnection* connection, DBusMessage* message, void* user_data)
132 {
133         DBusError error;
134         dbus_bool_t r;
135         dbus_error_init(&error);
136
137         char* pPkgId;
138         char* pPrivacyId;
139
140         if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE.c_str(), DBUS_SIGNAL_SETTING_CHANGED.c_str()))
141         {
142                 r = dbus_message_get_args(message, &error,
143                         DBUS_TYPE_STRING, &pPkgId,
144                         DBUS_TYPE_STRING, &pPrivacyId,
145                         DBUS_TYPE_INVALID);
146                 TryReturn(r, DBUS_HANDLER_RESULT_NOT_YET_HANDLED, , "Fail to get data : %s", error.message);
147                 
148                 std::lock_guard < std::mutex > guard(m_cacheMutex);
149
150                 if (std::string(pPkgId) == m_pkgId)
151                 {
152                         LOGI("Current app pkg privacy information updated");
153                         updateCache(m_pkgId, pPrivacyId, m_privacyCache);
154                         //printCache();
155                 }
156
157                 std::map < std::string, std::map < std::string, bool > > :: iterator iter = m_privacyInfoCache.find(std::string(pPkgId));
158                 if (iter != m_privacyInfoCache.end())
159                 {
160                         LOGI("Current pkg privacy is in cache");
161                         updateCache(std::string(pPkgId), pPrivacyId, iter->second);
162                 }
163                 
164         }
165         else if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE.c_str(), DBUS_SIGNAL_PKG_REMOVED.c_str()))
166         {
167                 r = dbus_message_get_args(message, &error,
168                         DBUS_TYPE_STRING, &pPkgId,
169                         DBUS_TYPE_INVALID);
170                 TryReturn(r, DBUS_HANDLER_RESULT_NOT_YET_HANDLED, , "Fail to get data : %s", error.message);
171
172                 std::lock_guard < std::mutex > guard(m_cacheMutex);
173
174                 std::map < std::string, std::map < std::string, bool > > :: iterator iter = m_privacyInfoCache.find(std::string(pPkgId));
175                 if (iter != m_privacyInfoCache.end())
176                 {
177                         m_privacyInfoCache.erase(iter);
178                 }
179         }
180 //      else
181 //      {
182 //              return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
183 //      }
184         
185
186         // This event is not only for specific handler. All handlers of daemons should be check it and handle it.
187         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
188 }
189
190 int
191 PrivacyChecker::check(const std::string privacyId, std::map < std::string, bool >& privacyMap)
192 {
193         TryReturn(m_isInitialized, PRIV_MGR_ERROR_NOT_INITIALIZED, , "Not initialized");
194
195         std::map < std::string, bool >::iterator iter;
196
197         iter = privacyMap.find(privacyId);
198         if (iter == privacyMap.end() )
199         {
200                 LOGD("The application cannot access the privacy inforamtion.");
201                 return PRIV_MGR_ERROR_USER_NOT_CONSENTED;
202         }
203         else if (!iter->second)
204         {
205                 LOGD("User does not consented to access the privacy information");
206                 return PRIV_MGR_ERROR_USER_NOT_CONSENTED;
207         }
208
209         return PRIV_MGR_ERROR_SUCCESS;
210 }
211
212 int
213 PrivacyChecker::check(const std::string privacyId)
214 {
215         if (!m_isInitialized)
216                 return PRIV_MGR_ERROR_NOT_INITIALIZED;
217
218         std::lock_guard < std::mutex > guard(m_cacheMutex);
219
220         int res = check(privacyId, m_privacyCache);
221
222         return res;
223 }
224
225 int
226 PrivacyChecker::check(const std::string pkgId, const std::string privacyId)
227 {
228         if (!m_isInitialized)
229                 initialize();
230
231         std::lock_guard < std::mutex > guard(m_cacheMutex);
232         int res;
233
234         std::map < std::string, std::map < std::string, bool > >::iterator iter = m_privacyInfoCache.find(pkgId);
235         if (iter == m_privacyInfoCache.end() )
236         {
237                 std::map < std::string, bool > pkgCacheMap;
238                 res = updateCache(pkgId, pkgCacheMap);
239                 TryReturn( res == PRIV_MGR_ERROR_SUCCESS, PRIV_MGR_ERROR_DB_ERROR, , "Failed to update cache : %d", res);
240
241                 m_privacyInfoCache.insert( std::map < std::string, std::map < std::string, bool > >::value_type(std::string(pkgId), pkgCacheMap));
242                 iter = m_privacyInfoCache.find(pkgId);
243         }
244
245         if (iter->second.size() == 0)
246         {
247                 return PRIV_MGR_ERROR_USER_NOT_CONSENTED;
248         }
249
250         res = check(privacyId, iter->second);
251
252         return res;
253 }
254
255 int
256 PrivacyChecker::checkWithPrivilege(const std::string pkgId, const std::string privilege)
257 {
258         std::string privacyId;
259         int res = PrivacyIdInfo::getPrivacyIdFromPrivilege(privilege, privacyId);
260         if (res == PRIV_MGR_ERROR_NO_DATA) {
261                 return PRIV_MGR_ERROR_SUCCESS;
262         }
263
264         TryReturn( res == PRIV_MGR_ERROR_SUCCESS, res, , "getPrivacyIdFromPrivilege : %d", res);
265
266         return check(pkgId, privacyId);
267 }
268
269 int
270 PrivacyChecker::checkWithPrivilege(const std::string privilege)
271 {
272         std::string privacyId;
273         int res = PrivacyIdInfo::getPrivacyIdFromPrivilege(privilege, privacyId);
274         if (res == PRIV_MGR_ERROR_NO_DATA) {
275                 return PRIV_MGR_ERROR_SUCCESS;
276         }
277
278         TryReturn( res == PRIV_MGR_ERROR_SUCCESS, res, , "getPrivacyIdFromPrivilege : %d", res);
279
280         return check(privacyId);
281 }
282
283 int
284 PrivacyChecker::finalize(void)
285 {
286         std::lock_guard <std::mutex> guard (m_cacheMutex);
287         m_privacyCache.clear();
288         m_privacyInfoCache.clear();
289
290         if (m_pLoop != NULL)
291         {
292                 g_main_loop_quit(m_pLoop);
293                 m_pLoop = NULL;
294         }
295
296         if (m_pHandlerGMainContext != NULL) 
297         {
298                 g_main_context_unref(m_pHandlerGMainContext);
299                 m_pHandlerGMainContext = NULL;
300         }
301
302         m_isInitialized = false;
303
304         return PRIV_MGR_ERROR_SUCCESS;
305 }
306
307 void
308 PrivacyChecker::printCache(void)
309 {
310         std::map < std::string, bool >::const_iterator iter = m_privacyCache.begin();
311         for (; iter != m_privacyCache.end(); ++iter)
312         {
313                 LOGD(" %s : %d", iter->first.c_str(), iter->second);
314         }
315 }
316
317 int
318 PrivacyChecker::updateCache(const std::string pkgId, std::string privacyId, std::map < std::string, bool >& pkgCacheMap)
319 {
320         static const std::string PrivacyQuery = "SELECT IS_ENABLED from PrivacyInfo where PKG_ID=? and PRIVACY_ID=?";
321         
322         openDb(PRIVACY_DB_PATH.c_str(), pDbH, SQLITE_OPEN_READONLY);
323         prepareDb(pDbH, PrivacyQuery.c_str(), pPrivacyStmt);
324         int res = sqlite3_bind_text(pPrivacyStmt.get(), 1, pkgId.c_str(),  -1, SQLITE_TRANSIENT);
325         TryReturn( res == 0, PRIV_MGR_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
326
327         res = sqlite3_bind_text(pPrivacyStmt.get(), 2, privacyId.c_str(),  -1, SQLITE_TRANSIENT);
328         TryReturn( res == 0, PRIV_MGR_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
329
330         while ( sqlite3_step(pPrivacyStmt.get()) == SQLITE_ROW )
331         {
332                 bool privacyEnabled = sqlite3_column_int(pPrivacyStmt.get(), 0) > 0 ? true : false;
333
334                 SECURE_LOGD("Set result : %s : %d", privacyId.c_str(), privacyEnabled );
335                 pkgCacheMap.erase(privacyId);
336                 pkgCacheMap.insert(std::map < std::string, bool >::value_type(privacyId, privacyEnabled));
337         }
338         
339         return PRIV_MGR_ERROR_SUCCESS;
340 }
341
342 int
343 PrivacyChecker::updateCache(std::string pkgId, std::map < std::string, bool >& pkgCacheMap)
344 {
345         static const std::string PrivacyQuery = "SELECT PRIVACY_ID, IS_ENABLED from PrivacyInfo where PKG_ID=?";
346
347         pkgCacheMap.clear();
348         
349         openDb(PRIVACY_DB_PATH.c_str(), pDbH, SQLITE_OPEN_READONLY);
350         prepareDb(pDbH, PrivacyQuery.c_str(), pPrivacyStmt);
351         int res = sqlite3_bind_text(pPrivacyStmt.get(), 1, pkgId.c_str(), -1, SQLITE_TRANSIENT);
352         TryReturn( res == SQLITE_OK, PRIV_MGR_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
353
354         while ( (res = sqlite3_step(pPrivacyStmt.get())) == SQLITE_ROW )
355         {
356                 const char* privacyId =  reinterpret_cast < const char* > (sqlite3_column_text(pPrivacyStmt.get(), 0));
357                 bool privacyEnabled = sqlite3_column_int(pPrivacyStmt.get(), 1) > 0 ? true : false;
358
359                 pkgCacheMap.insert(std::map < std::string, bool >::value_type(std::string(privacyId), privacyEnabled));
360
361                 SECURE_LOGD("Privacy found : %s %d", privacyId, privacyEnabled);
362         }
363         return PRIV_MGR_ERROR_SUCCESS;
364 }