2 * libprivilege control, rules database
4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
6 * Contact: Jan Olszak <j.olszak@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
24 * @author Jan Olszak (j.olszak@samsung.com)
26 * @brief This file contains declaration of the API to rules database.
29 #include "rules-db-internals.h"
31 static sqlite3 *p_db__ = NULL;
32 static int i_session_ret_code__ = PC_OPERATION_SUCCESS;
35 * Prepare to modify the database.
37 * @ingroup RDB internal functions
39 * @param pp_db pointer to a pointer to a SQLite3 database object
40 * @return PC_OPERATION_SUCCESS on success,
41 * error code otherwise
43 static int rdb_begin(sqlite3 **pp_db)
47 // If rdb_modification_start was called we use a global connection.
50 return PC_OPERATION_SUCCESS;
53 int ret = open_rdb_connection(pp_db);
54 if(ret != PC_OPERATION_SUCCESS) return ret;
56 if(sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0)
58 C_LOGE("RDB: Error during transaction begin: %s",
59 sqlite3_errmsg(*pp_db));
60 return PC_ERR_DB_CONNECTION;
64 ret = save_smack_rules(*pp_db);
65 if(ret != PC_OPERATION_SUCCESS) return ret;
68 return PC_OPERATION_SUCCESS;
73 * Finish database modification.
74 * If previous operation returned an error try to rollback changes.
76 * @ingroup RDB internal functions
78 * @param p_db pointer to a SQLite3 database object
79 * @param ret previous return code
81 static void rdb_end(sqlite3 *p_db, int ret)
86 if(ret == PC_OPERATION_SUCCESS &&
87 (ret = update_smack_rules(p_db))
88 != PC_OPERATION_SUCCESS) {
89 C_LOGE("RDB: Error updating smack rules");
94 C_LOGD("RDB: Closing connection.");
95 if(ret == PC_OPERATION_SUCCESS) {
96 if(sqlite3_exec(p_db, "COMMIT TRANSACTION", 0, 0, 0)
98 C_LOGE("RDB: Error during transaction commit: %s",
99 sqlite3_errmsg(p_db));
101 } else if(ret == PC_ERR_DB_CONNECTION) {
102 /* Life is pointless. I can't even rollback...*/
103 C_LOGE("RDB: No rollback nor commit.");
104 } else if(sqlite3_exec(p_db, "ROLLBACK TRANSACTION", 0, 0, 0)
106 C_LOGE("RDB: Error during transaction rollback: %s",
107 sqlite3_errmsg(p_db));
110 if(sqlite3_close(p_db)) {
111 C_LOGE("RDB: Error during closing the database.");
116 static void update_ret_code(int i_ret)
118 i_session_ret_code__ = i_session_ret_code__ ? i_session_ret_code__ : i_ret;
122 int rdb_modification_start(void)
125 // We have to finish the previous session:
126 C_LOGW("RDB: rdb_modification_finish was not called!");
127 rdb_modification_finish();
130 return rdb_begin(&p_db__);
134 void rdb_modification_finish(void)
137 rdb_end(p_db__, i_session_ret_code__);
139 i_session_ret_code__ = PC_OPERATION_SUCCESS;
144 int rdb_add_application(const char *const s_label_name)
146 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
148 int ret = PC_ERR_DB_OPERATION;
149 sqlite3 *p_db = NULL;
151 ret = rdb_begin(&p_db);
152 if(ret != PC_OPERATION_SUCCESS) goto finish;
154 ret = check_app_label_internal(p_db, s_label_name);
155 if(ret == PC_ERR_DB_LABEL_TAKEN) {
156 ret = PC_OPERATION_SUCCESS;
157 C_LOGW("RDB: There is an application with label: %s", s_label_name);
159 } else if(ret == PC_OPERATION_SUCCESS) {
160 // There is no such label yet.
161 ret = add_app_internal(p_db, s_label_name);
162 if(ret != PC_OPERATION_SUCCESS) goto finish;
165 ret = add_modified_label_internal(p_db, s_label_name);
167 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
172 int rdb_remove_application(const char *const s_label_name)
174 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
176 int ret = PC_ERR_DB_OPERATION;
177 sqlite3 *p_db = NULL;
179 ret = rdb_begin(&p_db);
180 if(ret != PC_OPERATION_SUCCESS) goto finish;
182 ret = remove_app_internal(p_db, s_label_name);
183 if(ret != PC_OPERATION_SUCCESS) goto finish;
185 ret = add_modified_label_internal(p_db, s_label_name);
186 if(ret != PC_OPERATION_SUCCESS) goto finish;
188 ret = add_modified_apps_path_internal(p_db, s_label_name);
190 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
195 int rdb_add_path(const char *const s_owner_label_name,
196 const char *const s_path_label_name,
197 const char *const s_path,
198 const char *const s_access,
199 const char *const s_type)
201 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
202 s_owner_label_name, s_path_label_name,
203 s_path, s_access, s_type);
205 int ret = PC_ERR_DB_OPERATION;
206 sqlite3 *p_db = NULL;
208 ret = rdb_begin(&p_db);
209 if(ret != PC_OPERATION_SUCCESS) goto finish;
211 ret = add_path_internal(p_db,
217 if(ret != PC_OPERATION_SUCCESS) goto finish;
219 ret = add_modified_label_internal(p_db, s_path_label_name);
221 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
226 int rdb_add_permission_rules(const char *const s_permission_name,
227 const char *const s_permission_type_name,
228 const char *const *const pp_smack_rules)
230 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
232 int ret = PC_ERR_DB_OPERATION;
233 sqlite3 *p_db = NULL;
234 sqlite3_int64 permission_id = -1;
236 ret = rdb_begin(&p_db);
237 if(ret != PC_OPERATION_SUCCESS) goto finish;
239 ret = add_permission_internal(p_db,
241 s_permission_type_name);
242 if(ret != PC_OPERATION_SUCCESS) goto finish;
244 ret = get_permission_id_internal(p_db,
246 s_permission_type_name,
248 if(ret != PC_OPERATION_SUCCESS) goto finish;
250 ret = add_modified_permission_internal(p_db, permission_id);
251 if(ret != PC_OPERATION_SUCCESS) goto finish;
253 if(pp_smack_rules != NULL) {
254 ret = add_permission_rules_internal(p_db,
260 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
265 int rdb_enable_app_permissions(const char *const s_app_label_name,
266 const char *const s_permission_type_name,
267 const char *const *const pp_permissions_list,
268 const bool b_is_volatile)
270 RDB_LOG_ENTRY_PARAM("%s %s %d", s_app_label_name, s_permission_type_name, b_is_volatile);
272 int ret = PC_ERR_DB_OPERATION;
273 sqlite3 *p_db = NULL;
276 C_LOGD("RDB: Enabling permissions START");
278 ret = rdb_begin(&p_db);
279 if(ret != PC_OPERATION_SUCCESS) goto finish;
281 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
282 if(ret != PC_OPERATION_SUCCESS) goto finish;
284 // Add permissions specific for the permission type:
285 ret = change_app_permission_internal(p_db,
287 s_permission_type_name,
288 s_permission_type_name,
291 if(ret != PC_OPERATION_SUCCESS) goto finish;
293 // Add permissions from the list:
294 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
295 // Ignore empty lines
296 if(strspn(pp_permissions_list[i], " \t\n")
297 == strlen(pp_permissions_list[i]))
300 ret = change_app_permission_internal(p_db,
302 pp_permissions_list[i],
303 s_permission_type_name,
306 if(ret != PC_OPERATION_SUCCESS) goto finish;
309 ret = add_modified_label_internal(p_db, s_app_label_name);
311 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
316 int rdb_disable_app_permissions(const char *const s_app_label_name,
317 const char *const s_permission_type_name,
318 const char *const *const pp_permissions_list)
320 RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_permission_type_name);
322 int ret = PC_ERR_DB_OPERATION;
323 sqlite3 *p_db = NULL;
326 ret = rdb_begin(&p_db);
327 if(ret != PC_OPERATION_SUCCESS) goto finish;
329 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
330 if(ret != PC_OPERATION_SUCCESS) goto finish;
332 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
333 // Ignore empty lines
334 if(strspn(pp_permissions_list[i], " \t\n")
335 == strlen(pp_permissions_list[i]))
338 ret = switch_app_permission_internal(p_db,
340 pp_permissions_list[i],
341 s_permission_type_name,
343 if(ret != PC_OPERATION_SUCCESS) goto finish;
346 ret = add_modified_label_internal(p_db, s_app_label_name);
348 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
353 int rdb_revoke_app_permissions(const char *const s_app_label_name)
355 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
357 int ret = PC_ERR_DB_OPERATION;
358 sqlite3 *p_db = NULL;
360 ret = rdb_begin(&p_db);
361 if(ret != PC_OPERATION_SUCCESS) goto finish;
363 ret = revoke_app_permissions_internal(p_db, s_app_label_name);
364 if(ret != PC_OPERATION_SUCCESS) goto finish;
366 ret = add_modified_label_internal(p_db, s_app_label_name);
368 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
373 int rdb_reset_app_permissions(const char *const s_app_label_name)
375 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
377 int ret = PC_ERR_DB_OPERATION;
378 sqlite3 *p_db = NULL;
380 ret = rdb_begin(&p_db);
381 if(ret != PC_OPERATION_SUCCESS) goto finish;
383 ret = reset_app_permissions_internal(p_db, s_app_label_name);
384 if(ret != PC_OPERATION_SUCCESS) goto finish;
386 ret = add_modified_label_internal(p_db, s_app_label_name);
388 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
393 int validate_all_rules(const char *const *const pp_permissions_list)
398 char s_subject[SMACK_LABEL_LEN + 1];
399 char s_object[SMACK_LABEL_LEN + 1];
400 char s_access[ACC_LEN + 1];
402 // Parse and check rules.
403 for(i = 0; pp_permissions_list[i] != NULL; ++i) {
404 // C_LOGE("RDB: Validating rules: %s", pp_permissions_list[i]);
406 // Ignore empty lines
407 if(strspn(pp_permissions_list[i], " \t\n")
408 == strlen(pp_permissions_list[i]))
411 if(parse_rule(pp_permissions_list[i], s_subject, s_object, s_access)
412 != PC_OPERATION_SUCCESS) {
413 C_LOGE("RDB: Invalid parameter");
414 return PC_ERR_INVALID_PARAM;
417 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) != 0 &&
418 strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) != 0) {
419 C_LOGE("RDB: There is no " SMACK_APP_LABEL_TEMPLATE " argument in template rule.");
420 return PC_ERR_INVALID_PARAM;
423 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
424 strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0) {
425 C_LOGE("RDB: Rule with two " SMACK_APP_LABEL_TEMPLATE " has no sense.");
426 return PC_ERR_INVALID_PARAM;
429 // Check the other label
430 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
431 !smack_label_is_valid(s_object)) {
432 C_LOGE("RDB: Incorrect object label: %s", s_object);
433 return PC_ERR_INVALID_PARAM;
434 } else if(strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0 &&
435 !smack_label_is_valid(s_subject)) {
436 C_LOGE("RDB: Incorrect subject label: %s", s_subject);
437 return PC_ERR_INVALID_PARAM;
441 return PC_OPERATION_SUCCESS;