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.
31 #include "privilege-control.h"
32 #include "rules-db-internals.h"
34 static sqlite3 *p_db__ = NULL;
35 static int i_session_ret_code__ = PC_OPERATION_SUCCESS;
38 * Prepare to modify the database.
40 * @ingroup RDB internal functions
42 * @param pp_db pointer to a pointer to a SQLite3 database object
43 * @return PC_OPERATION_SUCCESS on success,
44 * error code otherwise
46 static int rdb_begin(sqlite3 **pp_db)
50 // If rdb_modification_start was called we use a global connection.
53 return PC_OPERATION_SUCCESS;
56 int ret = open_rdb_connection(pp_db);
57 if(ret != PC_OPERATION_SUCCESS) return ret;
59 if(sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0)
61 C_LOGE("RDB: Error during transaction begin: %s",
62 sqlite3_errmsg(*pp_db));
63 return PC_ERR_DB_CONNECTION;
66 ret = save_smack_rules(*pp_db);
67 if(ret != PC_OPERATION_SUCCESS) return ret;
69 return PC_OPERATION_SUCCESS;
74 * Finish database modification.
75 * If previous operation returned an error try to rollback changes.
77 * @ingroup RDB internal functions
79 * @param p_db pointer to a SQLite3 database object
80 * @param ret previous return code
82 static void rdb_end(sqlite3 *p_db, int ret)
86 if(ret == PC_OPERATION_SUCCESS &&
87 (ret = update_rules_in_db(p_db))
88 != PC_OPERATION_SUCCESS) {
89 C_LOGE("RDB: Error during updating rules in the database: %d", ret);;
93 if(ret == PC_OPERATION_SUCCESS &&
94 (ret = update_smack_rules(p_db))
95 != PC_OPERATION_SUCCESS) {
96 C_LOGE("RDB: Error updating smack rules: %d", ret);
100 // Finish transaction
101 C_LOGD("RDB: Closing connection.");
102 if(ret == PC_OPERATION_SUCCESS) {
103 if(sqlite3_exec(p_db, "COMMIT TRANSACTION", 0, 0, 0)
105 C_LOGE("RDB: Error during transaction commit: %s",
106 sqlite3_errmsg(p_db));
108 } else if(ret == PC_ERR_DB_CONNECTION) {
109 /* Life is pointless. I can't even rollback...*/
110 C_LOGE("RDB: No rollback nor commit.");
111 } else if(sqlite3_exec(p_db, "ROLLBACK TRANSACTION", 0, 0, 0)
113 C_LOGE("RDB: Error during transaction rollback: %s",
114 sqlite3_errmsg(p_db));
117 if(sqlite3_close(p_db)) {
118 C_LOGE("RDB: Error during closing the database.");
123 static void update_ret_code(int i_ret)
125 i_session_ret_code__ = i_session_ret_code__ ? i_session_ret_code__ : i_ret;
129 int rdb_modification_start(void)
132 // We have to finish the previous session:
133 C_LOGW("RDB: rdb_modification_finish was not called!");
134 rdb_modification_finish();
137 return rdb_begin(&p_db__);
141 void rdb_modification_finish(void)
144 rdb_end(p_db__, i_session_ret_code__);
146 i_session_ret_code__ = PC_OPERATION_SUCCESS;
151 int rdb_add_application(const char *const s_label_name)
153 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
155 int ret = PC_ERR_DB_OPERATION;
156 sqlite3 *p_db = NULL;
158 ret = rdb_begin(&p_db);
159 if(ret != PC_OPERATION_SUCCESS) goto finish;
161 ret = check_app_label_internal(p_db, s_label_name);
162 if(ret == PC_ERR_DB_LABEL_TAKEN) {
163 ret = PC_OPERATION_SUCCESS;
164 C_LOGW("RDB: There is an application with label: %s", s_label_name);
166 } else if(ret == PC_OPERATION_SUCCESS) {
167 // There is no such label yet.
168 ret = add_app_internal(p_db, s_label_name);
169 if(ret != PC_OPERATION_SUCCESS) goto finish;
172 ret = add_modified_label_internal(p_db, s_label_name);
174 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
179 int rdb_remove_application(const char *const s_label_name)
181 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
183 int ret = PC_ERR_DB_OPERATION;
184 sqlite3 *p_db = NULL;
186 ret = rdb_begin(&p_db);
187 if(ret != PC_OPERATION_SUCCESS) goto finish;
189 ret = remove_app_internal(p_db, s_label_name);
190 if(ret != PC_OPERATION_SUCCESS) goto finish;
192 ret = add_modified_label_internal(p_db, s_label_name);
193 if(ret != PC_OPERATION_SUCCESS) goto finish;
195 ret = add_modified_apps_path_internal(p_db, s_label_name);
197 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
202 int rdb_add_path(const char *const s_owner_label_name,
203 const char *const s_path_label_name,
204 const char *const s_path,
205 const char *const s_access,
206 const char *const s_type)
208 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
209 s_owner_label_name, s_path_label_name,
210 s_path, s_access, s_type);
212 int ret = PC_ERR_DB_OPERATION;
213 sqlite3 *p_db = NULL;
215 ret = rdb_begin(&p_db);
216 if(ret != PC_OPERATION_SUCCESS) goto finish;
218 ret = add_path_internal(p_db,
224 if(ret != PC_OPERATION_SUCCESS) goto finish;
226 ret = add_modified_label_internal(p_db, s_path_label_name);
228 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
233 int rdb_add_permission_rules(const char *const s_permission_name,
234 const char *const s_permission_type_name,
235 const char *const *const pp_smack_rules)
237 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
239 int ret = PC_ERR_DB_OPERATION;
240 sqlite3 *p_db = NULL;
241 sqlite3_int64 permission_id = -1;
243 ret = rdb_begin(&p_db);
244 if(ret != PC_OPERATION_SUCCESS) goto finish;
246 ret = add_permission_internal(p_db,
248 s_permission_type_name);
249 if(ret != PC_OPERATION_SUCCESS) goto finish;
251 ret = get_permission_id_internal(p_db,
253 s_permission_type_name,
255 if(ret != PC_OPERATION_SUCCESS) goto finish;
257 ret = add_modified_permission_internal(p_db, permission_id);
258 if(ret != PC_OPERATION_SUCCESS) goto finish;
260 if(pp_smack_rules != NULL) {
261 ret = add_permission_rules_internal(p_db,
267 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
272 int rdb_enable_app_permissions(const char *const s_app_label_name,
273 const char *const s_permission_type_name,
274 const char *const *const pp_permissions_list,
275 const bool b_is_volatile)
277 RDB_LOG_ENTRY_PARAM("%s %s %d", s_app_label_name, s_permission_type_name, b_is_volatile);
279 int ret = PC_ERR_DB_OPERATION;
280 sqlite3 *p_db = NULL;
281 char *s_permission_name = NULL;
284 C_LOGD("RDB: Enabling permissions START");
286 ret = rdb_begin(&p_db);
287 if(ret != PC_OPERATION_SUCCESS) goto finish;
289 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
290 if(ret != PC_OPERATION_SUCCESS) goto finish;
292 // Add permissions specific for the permission type:
293 ret = change_app_permission_internal(p_db,
295 s_permission_type_name,
296 s_permission_type_name,
299 if(ret != PC_OPERATION_SUCCESS) goto finish;
301 // Add permissions from the list:
302 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
303 // Ignore empty lines
304 if(strspn(pp_permissions_list[i], " \t\n")
305 == strlen(pp_permissions_list[i]))
308 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
309 if(ret != PC_OPERATION_SUCCESS) goto finish;
311 ret = change_app_permission_internal(p_db,
314 s_permission_type_name,
317 if(ret != PC_OPERATION_SUCCESS) goto finish;
318 free(s_permission_name);
321 ret = add_modified_label_internal(p_db, s_app_label_name);
323 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
328 int rdb_disable_app_permissions(const char *const s_app_label_name,
329 const char *const s_permission_type_name,
330 const char *const *const pp_permissions_list)
332 RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_permission_type_name);
334 int ret = PC_ERR_DB_OPERATION;
335 sqlite3 *p_db = NULL;
336 char *s_permission_name = NULL;
339 ret = rdb_begin(&p_db);
340 if(ret != PC_OPERATION_SUCCESS) goto finish;
342 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
343 if(ret != PC_OPERATION_SUCCESS) goto finish;
345 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
346 // Ignore empty lines
347 if(strspn(pp_permissions_list[i], " \t\n")
348 == strlen(pp_permissions_list[i]))
351 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
352 if(ret != PC_OPERATION_SUCCESS) goto finish;
354 ret = switch_app_permission_internal(p_db,
357 s_permission_type_name,
359 if(ret != PC_OPERATION_SUCCESS) goto finish;
361 free(s_permission_name);
364 ret = add_modified_label_internal(p_db, s_app_label_name);
366 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
371 int rdb_revoke_app_permissions(const char *const s_app_label_name)
373 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
375 int ret = PC_ERR_DB_OPERATION;
376 sqlite3 *p_db = NULL;
378 ret = rdb_begin(&p_db);
379 if(ret != PC_OPERATION_SUCCESS) goto finish;
381 ret = revoke_app_permissions_internal(p_db, s_app_label_name);
382 if(ret != PC_OPERATION_SUCCESS) goto finish;
384 ret = add_modified_label_internal(p_db, s_app_label_name);
385 if(ret != PC_OPERATION_SUCCESS) goto finish;
387 ret = add_modified_apps_path_internal(p_db, s_label_name);
390 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
395 int rdb_reset_app_permissions(const char *const s_app_label_name)
397 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
399 int ret = PC_ERR_DB_OPERATION;
400 sqlite3 *p_db = NULL;
402 ret = rdb_begin(&p_db);
403 if(ret != PC_OPERATION_SUCCESS) goto finish;
405 ret = reset_app_permissions_internal(p_db, s_app_label_name);
406 if(ret != PC_OPERATION_SUCCESS) goto finish;
408 ret = add_modified_label_internal(p_db, s_app_label_name);
410 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
415 int validate_all_rules(const char *const *const pp_permissions_list)
420 char s_subject[SMACK_LABEL_LEN + 1];
421 char s_object[SMACK_LABEL_LEN + 1];
422 char s_access[ACC_LEN + 1];
424 // Parse and check rules.
425 for(i = 0; pp_permissions_list[i] != NULL; ++i) {
426 // C_LOGE("RDB: Validating rules: %s", pp_permissions_list[i]);
428 // Ignore empty lines
429 if(strspn(pp_permissions_list[i], " \t\n")
430 == strlen(pp_permissions_list[i]))
433 if(parse_rule(pp_permissions_list[i], s_subject, s_object, s_access)
434 != PC_OPERATION_SUCCESS) {
435 C_LOGE("RDB: Invalid parameter");
436 return PC_ERR_INVALID_PARAM;
439 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) != 0 &&
440 strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) != 0) {
441 C_LOGE("RDB: There is no " SMACK_APP_LABEL_TEMPLATE " argument in template rule.");
442 return PC_ERR_INVALID_PARAM;
445 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
446 strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0) {
447 C_LOGE("RDB: Rule with two " SMACK_APP_LABEL_TEMPLATE " has no sense.");
448 return PC_ERR_INVALID_PARAM;
451 // Check the other label
452 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
453 !smack_label_is_valid(s_object)) {
454 C_LOGE("RDB: Incorrect object label: %s", s_object);
455 return PC_ERR_INVALID_PARAM;
456 } else if(strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0 &&
457 !smack_label_is_valid(s_subject)) {
458 C_LOGE("RDB: Incorrect subject label: %s", s_subject);
459 return PC_ERR_INVALID_PARAM;
463 return PC_OPERATION_SUCCESS;