5a39e99f025d7bfd53335b52d6e26c9e92cc5866
[platform/core/security/privacy-guard.git] / server / src / CynaraService.cpp
1 /*
2  * Copyright (c) 2013 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 <errno.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #if defined(USE_PTHREAD_WAITING)
21 #include <sys/time.h>
22 #endif
23 #include <signal.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <memory>
27 #include <thread>
28 #include <cynara-monitor.h>
29 #include "PrivacyGuardTypes.h"
30 #include "Utils.h"
31 #include "CynaraService.h"
32 #include "PrivacyGuardDb.h"
33 #include "PrivacyIdInfo.h"
34
35 #define BUF_SIZE 256
36
37 static cynara_monitor_configuration *p_conf;
38 static cynara_monitor *p_cynara_monitor;
39 static cynara_monitor_entry **monitor_entries;
40 static bool exit_flag;
41
42 #if defined(USE_PTHREAD_WAITING)
43 static pthread_cond_t g_condition;
44 static pthread_mutex_t g_mutex;
45 #endif
46
47 CynaraService::CynaraService(void)
48         : m_signalToClose(-1)
49         , m_cynaraThread(-1)
50 {
51 }
52
53 CynaraService::~CynaraService(void)
54 {
55 }
56
57 int
58 CynaraService::initialize(void)
59 {
60         PG_LOGD("[cynara_service] CynaraService initializing");
61
62         int res = cynara_monitor_configuration_create(&p_conf);
63         if(res != CYNARA_API_SUCCESS){
64                 PG_LOGE("cynara_monitor_configuration_create() is failed.");
65                 return PRIV_GUARD_ERROR_SYSTEM_ERROR;
66         }
67
68         res = cynara_monitor_configuration_set_buffer_size(p_conf, CYNARA_BUFFER_SIZE);
69         if(res != CYNARA_API_SUCCESS){
70                 PG_LOGE("cynara_monitor_configuration_set_buffer_size() is failed.");
71                 return PRIV_GUARD_ERROR_SYSTEM_ERROR;
72         }
73
74         res = cynara_monitor_initialize(&p_cynara_monitor, p_conf);
75         if(res != CYNARA_API_SUCCESS){
76                 PG_LOGE("cynara_monitor_initialize() is failed.");
77                 return PRIV_GUARD_ERROR_SYSTEM_ERROR;
78         }
79
80 //      cynara_monitor_configuration_set_filter
81
82         PG_LOGI("CynaraService initialized");
83
84         return PRIV_GUARD_ERROR_SUCCESS;
85 }
86
87 int
88 CynaraService::start(void)
89 {
90         PG_LOGI("[cynara_service] CynaraService starting");
91
92         int res = 0;
93         char buf[256];
94
95         sigset_t sigset;
96         sigemptyset(&sigset);
97         res = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
98         TryReturn( res >= 0, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "pthread_sigmask : %s", strerror_r(errno, buf, sizeof(buf)));
99
100 #if defined(USE_PTHREAD_WAITING)
101         pthread_mutex_init(&g_mutex, NULL);
102         pthread_cond_init(&g_condition, NULL);
103 #endif
104
105         pthread_t cynaraThread;
106         PG_LOGD("starting new thread (getEntriesThread)");
107         res = pthread_create(&cynaraThread, NULL, &getEntriesThread, this);
108         TryReturn( res >= 0, PRIV_GUARD_ERROR_SYSTEM_ERROR, errno = res, "pthread_create : %s", strerror_r(errno, buf, sizeof(buf)));
109         PG_LOGD("new thread (getEntriesThread) started");
110
111         m_cynaraThread = cynaraThread;
112
113         exit_flag = false;
114
115         PG_LOGD("CynaraService started");
116
117         return PRIV_GUARD_ERROR_SUCCESS;
118 }
119
120 void*
121 CynaraService::getEntriesThread(void* pData)
122 {
123         PG_LOGD("[cynara_service] Running get entries thread");
124
125         int res = -1;
126
127         pthread_detach(pthread_self());
128
129         while (exit_flag == false) {
130                 if (monitor_entries) {
131                         cynara_monitor_entries_free(monitor_entries);
132                         monitor_entries = NULL;
133                 }
134
135                 // returned when the cynara buffer is full or cynara_monitor_entries_flush() is called from another thread
136                 res = cynara_monitor_entries_get(p_cynara_monitor, &monitor_entries);
137                 if(res != CYNARA_API_SUCCESS){
138                         PG_LOGE("cynara_monitor_entries_get() is failed. [%d]", res);
139 #if defined(USE_PTHREAD_WAITING)
140                         struct timeval now;
141                         struct timespec ts;
142                         gettimeofday(&now, NULL);
143                         ts.tv_sec = now.tv_sec + 1;
144                         ts.tv_nsec = now.tv_usec * 1000;
145
146                         pthread_mutex_lock(&g_mutex);
147                         PG_LOGD("now waiting wakeup signal about 1 sec..");
148                         pthread_cond_timedwait(&g_condition, &g_mutex, &ts);
149                         PG_LOGD("ok, i'm wakeup..");
150                         pthread_mutex_unlock(&g_mutex);
151 #else
152                         usleep(SLEEP_TIME * 20);        // 1 SEC
153 #endif
154                 } else {
155                         if (monitor_entries) {
156                                 res = CynaraService::updateDb(monitor_entries);
157                                 if(res != PRIV_GUARD_ERROR_SUCCESS) {
158                                         PG_LOGE("CynaraService::updateDb() is failed. [%d]", res);
159                                 }
160                         }
161                 }
162
163                 if (monitor_entries) {
164                         cynara_monitor_entries_free(monitor_entries);
165                         monitor_entries = NULL;
166                 }
167         }
168
169         return (void*) PRIV_GUARD_ERROR_SUCCESS;
170 }
171
172 int
173 CynaraService::updateDb(cynara_monitor_entry **monitor_entries)
174 {
175         cynara_monitor_entry **entryIter = monitor_entries;
176
177         // DB update
178         const char *user = NULL, *client = NULL, *privilege = NULL;
179         const timespec *timestamp = NULL;
180         int userId;
181         std::string packageId, privacyId;
182         time_t date;
183         int res = -1;
184
185         while (*entryIter != nullptr) {
186                 privilege = cynara_monitor_entry_get_privilege(*entryIter);
187                 TryReturn(privilege != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "Privilege Id in the entry is NULL");
188
189                 // change from privilege to privacy
190                 res = PrivacyIdInfo::getPrivacyIdFromPrivilege(privilege, privacyId);
191                 if (res != PRIV_GUARD_ERROR_NO_DATA) {
192                         // User ID - string
193                         user = cynara_monitor_entry_get_user(*entryIter);
194                         TryReturn(user != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "User Id in the entry is NULL");
195
196                         // Package ID - string
197                         client = cynara_monitor_entry_get_client(*entryIter);
198                         TryReturn(client != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "Package Id in the entry is NULL");
199
200                         // timestamp
201                         timestamp = cynara_monitor_entry_get_timestamp(*entryIter);
202                         TryReturn(timestamp != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "timestamp in the entry is NULL");
203
204                         // convert string to integer
205                         userId = atoi(user);
206
207                         // check package ID
208                         std::string tempPackageId = client;
209                         PG_LOGD("Package ID from cynara: [%s]", client);
210                         if (tempPackageId.substr(0, USER_APP_PREFIX_LEN).compare(USER_APP_PREFIX) == 0) {
211                                 packageId = tempPackageId.substr(USER_APP_PREFIX_LEN, tempPackageId.length() - USER_APP_PREFIX_LEN);
212                                 PG_LOGD("Fixed Package ID: [%s]", packageId.c_str());
213                         } else {
214                                 packageId = client;
215                                 PG_LOGD("Fixed Package ID: [%s]", client);
216                         }
217
218                         // datetime
219                         date = timestamp->tv_sec;
220
221                         // add access log
222                         int ret = PrivacyGuardDb::getInstance()->PgAddPrivacyAccessLogForCynara(userId, packageId, privacyId, date);
223                         if(ret == PRIV_GUARD_ERROR_SUCCESS){
224                                 PG_LOGD("Succeeded to add access log to DB. UserID:[%d], PackageID:[%s], Privacy:[%s]", userId, packageId.c_str(), privacyId.c_str());
225                         }
226                         else{
227                                 PG_LOGE("Failed to add access log to DB. UserID:[%d], PackageID:[%s], Privacy:[%s]", userId, packageId.c_str(), privacyId.c_str());                             
228                         }
229                 }
230                 ++entryIter;
231         }
232
233         return PRIV_GUARD_ERROR_SUCCESS;
234 }
235
236
237 int
238 CynaraService::stop(void)
239 {
240         char buf[BUF_SIZE];
241         int ret;
242
243         // set thread exit condition
244         exit_flag = true;
245
246         // [CYNARA] Flush Entries
247         ret = cynara_monitor_entries_flush(p_cynara_monitor);
248         if(ret != CYNARA_API_SUCCESS) {
249                 if (ret == CYNARA_API_OPERATION_NOT_ALLOWED) {
250                         PG_LOGD("There is no logs in the cynara buffer.");
251                 } else {
252                         PG_LOGE("cynara_monitor_entries_flush FAIL [%d]", ret);
253                         return PRIV_GUARD_ERROR_SYSTEM_ERROR;
254                 }
255         }
256
257         if((ret = pthread_kill(m_cynaraThread, m_signalToClose)) < 0) {
258                 PG_LOGE("pthread_kill(): %s", strerror_r(ret, buf, sizeof(buf)));
259                 return PRIV_GUARD_ERROR_IPC_ERROR;
260         }
261         pthread_join(m_cynaraThread, NULL);
262
263 #if defined(USE_PTHREAD_WAITING)
264         pthread_cond_destroy(&g_condition);
265         pthread_mutex_destroy(&g_mutex);
266 #endif
267
268         ret = cynara_monitor_finish(p_cynara_monitor);
269         if(ret != CYNARA_API_SUCCESS) {
270                 PG_LOGE("cynara_monitor_finish() is failed. [%d]", ret);
271                 return PRIV_GUARD_ERROR_SYSTEM_ERROR;
272         }
273
274         return PRIV_GUARD_ERROR_SUCCESS;
275 }
276
277 int
278 CynaraService::shutdown(void)
279 {
280         cynara_monitor_configuration_destroy(p_conf);
281
282         return PRIV_GUARD_ERROR_SUCCESS;
283 }