add comment LCOV_EXCL
[platform/core/pim/calendar-service.git] / server / cal_access_control.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <pthread.h>
21 #include <signal.h>
22 #include <string.h>
23 #include <sys/smack.h>
24
25 #include "calendar_db.h"
26 #include "cal_internal.h"
27 #include "cal_typedef.h"
28 #include "cal_view.h"
29 #include "cal_time.h"
30 #include "cal_record.h"
31 #include "cal_mutex.h"
32 #include "cal_db_util.h"
33 #include "cal_db.h"
34 #include "cal_access_control.h"
35 #include "cal_server_service.h"
36 #include "cal_utils.h"
37
38 typedef struct {
39         unsigned int thread_id;
40         void *ipc;
41         char *smack_label;
42         int *write_list;
43         int write_list_count;
44 } cal_permission_info_s;
45
46 enum {
47         CAL_SMACK_NOT_CHECKED,
48         CAL_SMACK_ENABLED, /* 1 */
49         CAL_SMACK_DISABLED, /* 0 */
50 };
51
52 static GList *__thread_list = NULL;
53 static int have_smack = CAL_SMACK_NOT_CHECKED;
54
55 static cal_permission_info_s* _cal_access_control_find_permission_info(unsigned int thread_id)
56 {
57         GList *cursor;
58
59         for (cursor = __thread_list; cursor; cursor = cursor->next) {
60                 cal_permission_info_s *info = NULL;
61                 info = cursor->data;
62                 if (info->thread_id == thread_id)
63                         return info;
64         }
65         return NULL;
66 }
67
68 /* check SMACK enable or disable */
69 static int _cal_have_smack(void)
70 {
71         if (CAL_SMACK_NOT_CHECKED == have_smack) {
72                 if (NULL == smack_smackfs_path())
73                         have_smack = CAL_SMACK_DISABLED;
74                 else
75                         have_smack = CAL_SMACK_ENABLED;
76         }
77         return have_smack;
78 }
79
80 static void _cal_access_control_set_permission_info(cal_permission_info_s *info)
81 {
82         int ret = 0;
83         bool smack_enabled = false;
84
85         if (CAL_SMACK_ENABLED == _cal_have_smack())
86                 smack_enabled = true;
87         else
88                 INFO("SAMCK disabled");
89
90         /* white listing : core module */
91         free(info->write_list);
92         info->write_list = NULL;
93         info->write_list_count = 0;
94
95         char query[CAL_DB_SQL_MAX_LEN] = {0};
96         int count = 0;
97         snprintf(query, sizeof(query), "SELECT count(id) FROM %s WHERE deleted = 0 ", CAL_TABLE_CALENDAR);
98         ret = cal_db_util_query_get_first_int_result(query, NULL, &count);
99         if (CALENDAR_ERROR_NONE != ret) {
100                 /* LCOV_EXCL_START */
101                 ERR("cal_db_util_query_get_first_int_result() Fail(%d)", ret);
102                 SECURE("query[%s]", query);
103                 return;
104                 /* LCOV_EXCL_STOP */
105         }
106
107         info->write_list = calloc(count +1, sizeof(int));
108         if (NULL == info->write_list) {
109                 /* LCOV_EXCL_START */
110                 ERR("calloc() Fail");
111                 return;
112                 /* LCOV_EXCL_STOP */
113         }
114         info->write_list_count = 0;
115
116         sqlite3_stmt *stmt = NULL;
117         snprintf(query, sizeof(query), "SELECT id, mode, owner_label FROM %s WHERE deleted = 0 ", CAL_TABLE_CALENDAR);
118         ret = cal_db_util_query_prepare(query, &stmt);
119         if (CALENDAR_ERROR_NONE != ret) {
120                 /* LCOV_EXCL_START */
121                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
122                 SECURE("query[%s]", query);
123                 return;
124                 /* LCOV_EXCL_STOP */
125         }
126
127         int write_index = 0;
128         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
129                 int id = 0;
130                 int mode = 0;
131                 char *temp = NULL;
132
133                 id = sqlite3_column_int(stmt, 0);
134                 mode = sqlite3_column_int(stmt, 1);
135                 temp = (char *)sqlite3_column_text(stmt, 2);
136
137                 if (!smack_enabled) /* smack disabled */
138                         info->write_list[write_index++] = id;
139                 else if (NULL == info->ipc) /* calendar-service daemon */
140                         info->write_list[write_index++] = id;
141                 else if (info->smack_label && temp && 0 == strcmp(temp, info->smack_label)) /* owner */
142                         info->write_list[write_index++] = id;
143                 else if (CALENDAR_BOOK_MODE_NONE == mode)
144                         info->write_list[write_index++] = id;
145         }
146         info->write_list_count = write_index;
147         sqlite3_finalize(stmt);
148 }
149
150 void cal_access_control_set_client_info(void *ipc, const char *smack_label)
151 {
152         unsigned int thread_id = (unsigned int)pthread_self();
153         cal_permission_info_s *info = NULL;
154
155         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
156         info = _cal_access_control_find_permission_info(thread_id);
157         if (NULL == info) {
158                 info = calloc(1, sizeof(cal_permission_info_s));
159                 if (NULL == info) {
160                 /* LCOV_EXCL_START */
161                         ERR("calloc() Fail");
162                         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
163                         return;
164                 /* LCOV_EXCL_STOP */
165                 }
166                 __thread_list  = g_list_append(__thread_list, info);
167         }
168         info->thread_id = thread_id;
169         info->ipc = ipc;
170
171         free(info->smack_label);
172         info->smack_label = cal_strdup(smack_label);
173         _cal_access_control_set_permission_info(info);
174
175         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
176 }
177
178 void cal_access_control_unset_client_info(void)
179 {
180         cal_permission_info_s *find = NULL;
181
182         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
183         find = _cal_access_control_find_permission_info(pthread_self());
184         if (find) {
185                 CAL_FREE(find->smack_label);
186                 CAL_FREE(find->write_list);
187                 __thread_list = g_list_remove(__thread_list, find);
188                 free(find);
189         }
190         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
191 }
192
193 char* cal_access_control_get_label(void)
194 {
195         unsigned int thread_id = (unsigned int)pthread_self();
196         cal_permission_info_s *info = NULL;
197
198         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
199         info = _cal_access_control_find_permission_info(thread_id);
200
201         char *smack_label = NULL;
202         if (info && info->smack_label)
203                 smack_label = strdup(info->smack_label);
204
205         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
206         return smack_label;
207 }
208
209 void cal_access_control_reset(void)
210 {
211         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
212         GList *cursor;
213         for (cursor = __thread_list; cursor; cursor = cursor->next) {
214                 cal_permission_info_s *info = NULL;
215                 info = cursor->data;
216                 if (info)
217                         _cal_access_control_set_permission_info(info);
218         }
219         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
220 }
221
222 bool cal_access_control_have_write_permission(int book_id)
223 {
224         cal_permission_info_s *info = NULL;
225
226         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
227         unsigned int thread_id = pthread_self();
228         info = _cal_access_control_find_permission_info(thread_id);
229         if (NULL == info) {
230                 /* LCOV_EXCL_START */
231                 cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
232                 ERR("_cal_access_control_find_permission_info() Fail");
233                 return false;
234                 /* LCOV_EXCL_STOP */
235         }
236
237         if (NULL == info->write_list) {
238                 /* LCOV_EXCL_START */
239                 cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
240                 ERR("there is no write access info");
241                 return false;
242                 /* LCOV_EXCL_STOP */
243         }
244
245         int i = 0;
246         for (i = 0; i < info->write_list_count; i++) {
247                 if (book_id == info->write_list[i]) {
248                         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
249                         return true;
250                 }
251         }
252
253         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
254         ERR("thread(0x%x), No write permission of book_id(%d)", thread_id, book_id);
255         return false;
256 }
257
258 int cal_is_owner(int book_id)
259 {
260         int ret;
261         sqlite3_stmt *stmt = NULL;
262         char query[CAL_DB_SQL_MAX_LEN] = {0};
263         char *owner_label = NULL;
264         char *saved_smack = NULL;
265
266         snprintf(query, sizeof(query), "SELECT owner_label FROM %s WHERE id = %d",
267                         CAL_TABLE_CALENDAR, book_id);
268         ret = cal_db_util_query_prepare(query, &stmt);
269         if (CALENDAR_ERROR_NONE != ret) {
270                 /* LCOV_EXCL_START */
271                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
272                 SECURE("query[%s]", query);
273                 return ret;
274                 /* LCOV_EXCL_STOP */
275         }
276
277         if (CAL_SQLITE_ROW != cal_db_util_stmt_step(stmt)) {
278                 /* LCOV_EXCL_START */
279                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
280                 sqlite3_finalize(stmt);
281                 return CALENDAR_ERROR_DB_FAILED;
282                 /* LCOV_EXCL_STOP */
283         }
284
285         ret = CALENDAR_ERROR_PERMISSION_DENIED;
286
287         owner_label = (char*)sqlite3_column_text(stmt, 0);
288         saved_smack = cal_access_control_get_label();
289
290         if (owner_label && saved_smack && CAL_STRING_EQUAL == strcmp(owner_label, saved_smack))
291                 ret = CALENDAR_ERROR_NONE;
292
293         sqlite3_finalize(stmt);
294
295         free(saved_smack);
296         return ret;
297 }
298