9f98367083fb79720bcb7649f52e66c1493e3ff6
[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                 ERR("cal_db_util_query_get_first_int_result() Fail(%d)", ret);
101                 SECURE("query[%s]", query);
102                 return;
103         }
104
105         info->write_list = calloc(count +1, sizeof(int));
106         if (NULL == info->write_list) {
107                 ERR("calloc() Fail");
108                 return;
109         }
110         info->write_list_count = 0;
111
112         sqlite3_stmt *stmt = NULL;
113         snprintf(query, sizeof(query), "SELECT id, mode, owner_label FROM %s WHERE deleted = 0 ", CAL_TABLE_CALENDAR);
114         ret = cal_db_util_query_prepare(query, &stmt);
115         if (CALENDAR_ERROR_NONE != ret) {
116                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
117                 SECURE("query[%s]", query);
118                 return;
119         }
120
121         int write_index = 0;
122         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
123                 int id = 0;
124                 int mode = 0;
125                 char *temp = NULL;
126
127                 id = sqlite3_column_int(stmt, 0);
128                 mode = sqlite3_column_int(stmt, 1);
129                 temp = (char *)sqlite3_column_text(stmt, 2);
130
131                 if (!smack_enabled) /* smack disabled */
132                         info->write_list[write_index++] = id;
133                 else if (NULL == info->ipc) /* calendar-service daemon */
134                         info->write_list[write_index++] = id;
135                 else if (info->smack_label && temp && 0 == strcmp(temp, info->smack_label)) /* owner */
136                         info->write_list[write_index++] = id;
137                 else if (CALENDAR_BOOK_MODE_NONE == mode)
138                         info->write_list[write_index++] = id;
139         }
140         info->write_list_count = write_index;
141         sqlite3_finalize(stmt);
142 }
143
144 void cal_access_control_set_client_info(void *ipc, const char *smack_label)
145 {
146         unsigned int thread_id = (unsigned int)pthread_self();
147         cal_permission_info_s *info = NULL;
148
149         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
150         info = _cal_access_control_find_permission_info(thread_id);
151         if (NULL == info) {
152                 info = calloc(1, sizeof(cal_permission_info_s));
153                 if (NULL == info) {
154                         ERR("calloc() Fail");
155                         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
156                         return;
157                 }
158                 __thread_list  = g_list_append(__thread_list, info);
159         }
160         info->thread_id = thread_id;
161         info->ipc = ipc;
162
163         free(info->smack_label);
164         info->smack_label = cal_strdup(smack_label);
165         _cal_access_control_set_permission_info(info);
166
167         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
168 }
169
170 void cal_access_control_unset_client_info(void)
171 {
172         cal_permission_info_s *find = NULL;
173
174         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
175         find = _cal_access_control_find_permission_info(pthread_self());
176         if (find) {
177                 CAL_FREE(find->smack_label);
178                 CAL_FREE(find->write_list);
179                 __thread_list = g_list_remove(__thread_list, find);
180                 free(find);
181         }
182         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
183 }
184
185 char* cal_access_control_get_label(void)
186 {
187         unsigned int thread_id = (unsigned int)pthread_self();
188         cal_permission_info_s *info = NULL;
189
190         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
191         info = _cal_access_control_find_permission_info(thread_id);
192
193         char *smack_label = NULL;
194         if (info && info->smack_label)
195                 smack_label = strdup(info->smack_label);
196
197         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
198         return smack_label;
199 }
200
201 void cal_access_control_reset(void)
202 {
203         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
204         GList *cursor;
205         for (cursor = __thread_list; cursor; cursor = cursor->next) {
206                 cal_permission_info_s *info = NULL;
207                 info = cursor->data;
208                 if (info)
209                         _cal_access_control_set_permission_info(info);
210         }
211         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
212 }
213
214 bool cal_access_control_have_write_permission(int book_id)
215 {
216         cal_permission_info_s *info = NULL;
217
218         cal_mutex_lock(CAL_MUTEX_ACCESS_CONTROL);
219         unsigned int thread_id = pthread_self();
220         info = _cal_access_control_find_permission_info(thread_id);
221         if (NULL == info) {
222                 cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
223                 ERR("_cal_access_control_find_permission_info() Fail");
224                 return false;
225         }
226
227         if (NULL == info->write_list) {
228                 cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
229                 ERR("there is no write access info");
230                 return false;
231         }
232
233         int i = 0;
234         for (i = 0; i < info->write_list_count; i++) {
235                 if (book_id == info->write_list[i]) {
236                         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
237                         return true;
238                 }
239         }
240
241         cal_mutex_unlock(CAL_MUTEX_ACCESS_CONTROL);
242         ERR("thread(0x%x), No write permission of book_id(%d)", thread_id, book_id);
243         return false;
244 }
245
246 int cal_is_owner(int book_id)
247 {
248         int ret;
249         sqlite3_stmt *stmt = NULL;
250         char query[CAL_DB_SQL_MAX_LEN] = {0};
251         char *owner_label = NULL;
252         char *saved_smack = NULL;
253
254         snprintf(query, sizeof(query), "SELECT owner_label FROM %s WHERE id = %d",
255                         CAL_TABLE_CALENDAR, book_id);
256         ret = cal_db_util_query_prepare(query, &stmt);
257         if (CALENDAR_ERROR_NONE != ret) {
258                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
259                 SECURE("query[%s]", query);
260                 return ret;
261         }
262
263         if (CAL_SQLITE_ROW != cal_db_util_stmt_step(stmt)) {
264                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
265                 sqlite3_finalize(stmt);
266                 return CALENDAR_ERROR_DB_FAILED;
267         }
268
269         ret = CALENDAR_ERROR_PERMISSION_DENIED;
270
271         owner_label = (char*)sqlite3_column_text(stmt, 0);
272         saved_smack = cal_access_control_get_label();
273
274         if (owner_label && saved_smack && CAL_STRING_EQUAL == strcmp(owner_label, saved_smack))
275                 ret = CALENDAR_ERROR_NONE;
276
277         sqlite3_finalize(stmt);
278
279         free(saved_smack);
280         return ret;
281 }
282