Add pkg-mgr plugin and modify some code
[platform/core/security/privacy-manager.git] / client / src / PrivacyChecker.cpp
1 /*\r
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved\r
3  *\r
4  *    Licensed under the Apache License, Version 2.0 (the "License");\r
5  *    you may not use this file except in compliance with the License.\r
6  *    You may obtain a copy of the License at\r
7  *\r
8  *        http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  *    Unless required by applicable law or agreed to in writing, software\r
11  *    distributed under the License is distributed on an "AS IS" BASIS,\r
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  *    See the License for the specific language governing permissions and\r
14  *    limitations under the License.\r
15  */\r
16 \r
17 #include <PrivacyChecker.h>\r
18 #include <PrivacyManagerClient.h>\r
19 #include <SocketClient.h>\r
20 #include <algorithm> \r
21 #include <memory>\r
22 #include <Utils.h>\r
23 #include <dlog.h>\r
24 #include <sqlite3.h>\r
25 #include <dbus/dbus-glib-lowlevel.h>\r
26 #include <sys/types.h>\r
27 #include <unistd.h>\r
28 \r
29 bool PrivacyChecker::m_isInitialized = false;\r
30 std::map < std::string, bool >PrivacyChecker::m_privacyCache;\r
31 std::map < std::string, std::map < std::string, bool > > PrivacyChecker::m_privacyInfoCache;\r
32 std::mutex PrivacyChecker::m_cacheMutex;\r
33 std::string PrivacyChecker::m_pkgId;\r
34 DBusConnection* PrivacyChecker::m_pDBusConnection;\r
35 GMainLoop* PrivacyChecker::m_pLoop = NULL;\r
36 \r
37 const int MAX_LOCAL_BUF_SIZE = 128;\r
38 \r
39 int\r
40 PrivacyChecker::initialize(const std::string pkgId)\r
41 {\r
42         LOGI("enter");\r
43 \r
44         if (m_isInitialized)\r
45                 return PRIV_MGR_ERROR_SUCCESS;\r
46 \r
47         int res;\r
48         pthread_t signalThread;\r
49         res = pthread_create(&signalThread, NULL, &runSignalListenerThread, NULL);\r
50         TryReturn(res >= 0, PRIV_MGR_ERROR_SYSTEM_ERROR, errno = res;, "Failed to create listener thread :%s", strerror(res));\r
51 \r
52         m_pkgId = pkgId;\r
53         res = updateCache(m_privacyCache);\r
54         TryReturn(res == 0, res, m_pkgId.clear(), "Failed to update cache : %d", res);\r
55 \r
56         m_isInitialized = true;\r
57 \r
58         LOGI("leave");\r
59 \r
60         return PRIV_MGR_ERROR_SUCCESS;\r
61 }\r
62 \r
63 void*\r
64 PrivacyChecker::runSignalListenerThread(void* pData)\r
65 {\r
66         pthread_detach(pthread_self());\r
67         LOGI("Running g main loop for signal");\r
68         \r
69         if (m_pLoop != NULL)\r
70                 return (void*) 0;\r
71         \r
72         m_pLoop = g_main_new(TRUE);\r
73 \r
74         initializeDbus();\r
75 \r
76         g_main_loop_run(m_pLoop);\r
77 \r
78         finalizeDbus();\r
79 \r
80         pthread_exit(NULL);\r
81 \r
82         return (void*) 0;\r
83 }\r
84 \r
85 int\r
86 PrivacyChecker::initializeDbus(void)\r
87 {\r
88         LOGI("enter");\r
89         DBusError error;\r
90         dbus_error_init(&error);\r
91 \r
92         m_pDBusConnection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);\r
93         TryReturn(m_pDBusConnection != NULL, PRIV_MGR_ERROR_SYSTEM_ERROR, dbus_error_free(&error), "dbus_bus_get_private [%s] : %d", PRIV_MGR_ERROR_SYSTEM_ERROR);\r
94 \r
95         dbus_connection_setup_with_g_main(m_pDBusConnection, NULL);\r
96         std::unique_ptr < char[] > pRule(new char[MAX_LOCAL_BUF_SIZE]);\r
97 \r
98         snprintf(pRule.get(), MAX_LOCAL_BUF_SIZE, "path='%s',type='signal',interface='%s'", DBUS_PATH.c_str(), DBUS_SIGNAL_INTERFACE.c_str());\r
99         dbus_bus_add_match(m_pDBusConnection, pRule.get(), &error);\r
100         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);\r
101 \r
102         dbus_bool_t r = dbus_connection_add_filter(m_pDBusConnection, handleNotification, NULL, NULL);\r
103         TryReturn(r, PRIV_MGR_ERROR_SYSTEM_ERROR, , "dbus_connection_add_filter: %d", PRIV_MGR_ERROR_SYSTEM_ERROR);\r
104 \r
105         LOGI("leave");\r
106 \r
107         return PRIV_MGR_ERROR_SUCCESS;\r
108 }\r
109 \r
110 int\r
111 PrivacyChecker::finalizeDbus(void)\r
112 {\r
113         dbus_connection_remove_filter(m_pDBusConnection, handleNotification, NULL);\r
114         dbus_connection_close(m_pDBusConnection);\r
115         m_pDBusConnection = NULL;\r
116 \r
117         return PRIV_MGR_ERROR_SUCCESS;\r
118 }\r
119 \r
120 \r
121 DBusHandlerResult\r
122 PrivacyChecker::handleNotification(DBusConnection* connection, DBusMessage* message, void* user_data)\r
123 {\r
124         DBusError error;\r
125         dbus_bool_t r;\r
126         dbus_error_init(&error);\r
127 \r
128         char* pPkgId;\r
129         char* pPrivacyId;\r
130 \r
131         if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE.c_str(), DBUS_SIGNAL_NAME.c_str()))\r
132         {\r
133                 r = dbus_message_get_args(message, &error,\r
134                         DBUS_TYPE_STRING, &pPkgId,\r
135                         DBUS_TYPE_STRING, &pPrivacyId,\r
136                         DBUS_TYPE_INVALID);\r
137                 TryReturn(r, DBUS_HANDLER_RESULT_NOT_YET_HANDLED, , "Fail to get data : %s", error.message);\r
138                 \r
139                 std::lock_guard < std::mutex > guard(m_cacheMutex);\r
140 \r
141                 if (std::string(pPkgId) == m_pkgId)\r
142                 {\r
143                         LOGI("Current app pkg privacy information updated");\r
144                         updateCache(pPrivacyId, m_privacyCache);\r
145                         printCache();\r
146                 }\r
147 \r
148                 std::map < std::string, std::map < std::string, bool > > :: iterator iter = m_privacyInfoCache.find(std::string(pPkgId));\r
149                 if (iter != m_privacyInfoCache.end())\r
150                 {\r
151                         updateCache(pPrivacyId, iter->second);\r
152                 }\r
153                 \r
154         }\r
155         else\r
156         {\r
157                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\r
158         }\r
159         \r
160         return DBUS_HANDLER_RESULT_HANDLED;\r
161 }\r
162 \r
163 int\r
164 PrivacyChecker::check(const std::string privacyId)\r
165 {\r
166         LOGI("enter");\r
167 \r
168         std::lock_guard < std::mutex > guard(m_cacheMutex);\r
169 \r
170         int ret = check(privacyId, m_privacyCache);\r
171 \r
172         LOGI("leave");\r
173 \r
174         return ret;\r
175 }\r
176 \r
177 int\r
178 PrivacyChecker::check(const std::string privacyId, std::map < std::string, bool >& privacyMap)\r
179 {\r
180         LOGI("enter");\r
181 \r
182         TryReturn(m_isInitialized, PRIV_MGR_ERROR_NOT_INITIALIZED, , "Not initialized");\r
183 \r
184         std::map < std::string, bool >::const_iterator iter = privacyMap.find(privacyId);\r
185         if (iter == privacyMap.end() )\r
186         {\r
187                 LOGD("NO matcheded");\r
188                 return PRIV_MGR_ERROR_USER_NOT_CONSENTED;\r
189         }\r
190         else if (!iter->second)\r
191         {\r
192                 LOGD("NOT allowed");\r
193                 return PRIV_MGR_ERROR_USER_NOT_CONSENTED;\r
194         }\r
195         LOGD("OK");\r
196 \r
197         return PRIV_MGR_ERROR_SUCCESS;\r
198 }\r
199 \r
200 int\r
201 PrivacyChecker::check(const std::string pkgId, const std::string privacyId)\r
202 {\r
203         LOGI("enter");\r
204 \r
205         std::lock_guard < std::mutex > guard(m_cacheMutex);\r
206 \r
207         int res;\r
208 \r
209         std::map < std::string, std::map < std::string, bool > >::iterator iter = m_privacyInfoCache.find(pkgId);\r
210         if (iter == m_privacyInfoCache.end() )\r
211         {\r
212                 std::map < std::string, bool > pkgCacheMap;\r
213                 res = updateCache(pkgCacheMap);\r
214                 TryReturn( res == PRIV_MGR_ERROR_SUCCESS, PRIV_MGR_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);\r
215 \r
216                 m_privacyInfoCache.insert( std::map < std::string, std::map < std::string, bool > >::value_type(std::string(pkgId), pkgCacheMap));\r
217 \r
218                 iter = m_privacyInfoCache.find(pkgId);\r
219         }\r
220         if (iter->second.size() == 0)\r
221                 return PRIV_MGR_ERROR_USER_NOT_CONSENTED;\r
222 \r
223         res = check(privacyId, iter->second);\r
224 \r
225         LOGI("leave");\r
226 \r
227         return res;\r
228 }\r
229 \r
230 int\r
231 PrivacyChecker::finalize(void)\r
232 {\r
233         std::lock_guard <std::mutex> guard (m_cacheMutex);\r
234         m_privacyCache.clear();\r
235         \r
236         if (m_pLoop != NULL)\r
237         {\r
238                 g_main_loop_quit(m_pLoop);\r
239                 m_pLoop = NULL;\r
240         }\r
241 \r
242         m_isInitialized = false;\r
243 \r
244         return PRIV_MGR_ERROR_SUCCESS;\r
245 }\r
246 \r
247 void\r
248 PrivacyChecker::printCache(void)\r
249 {\r
250         std::map < std::string, bool >::const_iterator iter = m_privacyCache.begin();\r
251         for (; iter != m_privacyCache.end(); ++iter)\r
252         {\r
253                 LOGD(" %s : %d", iter->first.c_str(), iter->second);\r
254         }\r
255 }\r
256 \r
257 int\r
258 PrivacyChecker::updateCache(const std::string privacyId, std::map < std::string, bool >& pkgCacheMap)\r
259 {\r
260         LOGI("enter");\r
261         static const std::string PrivacyQuery = "SELECT IS_ENABLED from PrivacyInfo where PKG_ID=? and PRIVACY_ID=?";\r
262         \r
263         openDb(PRIVACY_DB_PATH.c_str(), pDbH, SQLITE_OPEN_READONLY);\r
264         prepareDb(pDbH, PrivacyQuery.c_str(), pPrivacyStmt);\r
265         int res = sqlite3_bind_text(pPrivacyStmt.get(), 1, m_pkgId.c_str(),  -1, SQLITE_TRANSIENT);\r
266         TryReturn( res == 0, PRIV_MGR_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);\r
267 \r
268         res = sqlite3_bind_text(pPrivacyStmt.get(), 2, privacyId.c_str(),  -1, SQLITE_TRANSIENT);\r
269         TryReturn( res == 0, PRIV_MGR_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);\r
270 \r
271         while ( sqlite3_step(pPrivacyStmt.get()) == SQLITE_ROW )\r
272         {\r
273                 bool privacyEnabled = sqlite3_column_int(pPrivacyStmt.get(), 0) > 0 ? true : false;\r
274 \r
275                 std::lock_guard < std::mutex > guard(m_cacheMutex);\r
276                 pkgCacheMap.erase(privacyId);\r
277                 pkgCacheMap.insert(std::map < std::string, bool >::value_type(privacyId, privacyEnabled));\r
278         }\r
279         \r
280         LOGI("leave");\r
281 \r
282         return PRIV_MGR_ERROR_SUCCESS;\r
283 }\r
284 \r
285 \r
286 int\r
287 PrivacyChecker::updateCache(std::map < std::string, bool >& pkgCacheMap)\r
288 {\r
289         LOGI("enter");\r
290         static const std::string PrivacyQuery = "SELECT PRIVACY_ID, IS_ENABLED from PrivacyInfo where PKG_ID=?";\r
291 \r
292         pkgCacheMap.clear();\r
293         \r
294         openDb(PRIVACY_DB_PATH.c_str(), pDbH, SQLITE_OPEN_READONLY);\r
295         prepareDb(pDbH, PrivacyQuery.c_str(), pPrivacyStmt);\r
296         int res = sqlite3_bind_text(pPrivacyStmt.get(), 1, m_pkgId.c_str(), -1, SQLITE_TRANSIENT);\r
297         TryReturn( res == 0, PRIV_MGR_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);\r
298 \r
299         while ( sqlite3_step(pPrivacyStmt.get()) == SQLITE_ROW )\r
300         {\r
301                 LOGI("start");\r
302                 const char* privacyId =  reinterpret_cast < const char* > (sqlite3_column_text(pPrivacyStmt.get(), 0));\r
303                 bool privacyEnabled = sqlite3_column_int(pPrivacyStmt.get(), 1) > 0 ? true : false;\r
304 \r
305                 pkgCacheMap.insert(std::map < std::string, bool >::value_type(std::string(privacyId), privacyEnabled));\r
306 \r
307                 LOGD("Privacy found : %s %d", privacyId, privacyEnabled);\r
308         }\r
309         LOGI("leave");\r
310         return PRIV_MGR_ERROR_SUCCESS;\r
311 }