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;
166 ret = add_modified_label_internal(p_db, s_label_name);
168 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
173 int rdb_remove_application(const char *const s_label_name)
175 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
177 int ret = PC_ERR_DB_OPERATION;
178 sqlite3 *p_db = NULL;
180 ret = rdb_begin(&p_db);
181 if(ret != PC_OPERATION_SUCCESS) goto finish;
183 ret = remove_app_internal(p_db, s_label_name);
184 if(ret != PC_OPERATION_SUCCESS) goto finish;
186 ret = add_modified_label_internal(p_db, s_label_name);
188 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
193 int rdb_add_path(const char *const s_owner_label_name,
194 const char *const s_path_label_name,
195 const char *const s_path,
196 const char *const s_access,
197 const char *const s_type)
199 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
200 s_owner_label_name, s_path_label_name,
201 s_path, s_access, s_type);
203 int ret = PC_ERR_DB_OPERATION;
204 sqlite3 *p_db = NULL;
206 ret = rdb_begin(&p_db);
207 if(ret != PC_OPERATION_SUCCESS) goto finish;
209 ret = add_path_internal(p_db,
215 if(ret != PC_OPERATION_SUCCESS) goto finish;
217 ret = add_modified_label_internal(p_db, s_path_label_name);
219 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
224 int rdb_add_permission_rules(const char *const s_permission_name,
225 const char *const s_permission_type_name,
226 const char *const *const pp_smack_rules)
228 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
230 int ret = PC_ERR_DB_OPERATION;
231 sqlite3 *p_db = NULL;
232 sqlite3_int64 permission_id = -1;
234 ret = rdb_begin(&p_db);
235 if(ret != PC_OPERATION_SUCCESS) goto finish;
237 ret = add_permission_internal(p_db,
239 s_permission_type_name);
240 if(ret != PC_OPERATION_SUCCESS) goto finish;
242 ret = get_permission_id_internal(p_db,
244 s_permission_type_name,
246 if(ret != PC_OPERATION_SUCCESS) goto finish;
248 ret = add_modified_permission_internal(p_db, permission_id);
249 if(ret != PC_OPERATION_SUCCESS) goto finish;
251 if(pp_smack_rules != NULL) {
252 ret = add_permission_rules_internal(p_db,
258 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
263 int rdb_enable_app_permissions(const char *const s_app_label_name,
264 const char *const s_permission_type_name,
265 const char *const *const pp_permissions_list,
266 const bool b_is_volatile)
268 RDB_LOG_ENTRY_PARAM("%s %s %d", s_app_label_name, s_permission_type_name, b_is_volatile);
270 int ret = PC_ERR_DB_OPERATION;
271 sqlite3 *p_db = NULL;
274 C_LOGD("RDB: Enabling permissions START");
276 ret = rdb_begin(&p_db);
277 if(ret != PC_OPERATION_SUCCESS) goto finish;
279 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
280 if(ret != PC_OPERATION_SUCCESS) goto finish;
282 // Add permissions specific for the permission type:
283 ret = change_app_permission_internal(p_db,
285 s_permission_type_name,
286 s_permission_type_name,
289 if(ret != PC_OPERATION_SUCCESS) goto finish;
291 // Add permissions from the list:
292 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
293 // Ignore empty lines
294 if(strspn(pp_permissions_list[i], " \t\n")
295 == strlen(pp_permissions_list[i]))
298 ret = change_app_permission_internal(p_db,
300 pp_permissions_list[i],
301 s_permission_type_name,
304 if(ret != PC_OPERATION_SUCCESS) goto finish;
307 ret = add_modified_label_internal(p_db, s_app_label_name);
309 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
314 int rdb_disable_app_permissions(const char *const s_app_label_name,
315 const char *const s_permission_type_name,
316 const char *const *const pp_permissions_list)
318 RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_permission_type_name);
320 int ret = PC_ERR_DB_OPERATION;
321 sqlite3 *p_db = NULL;
324 ret = rdb_begin(&p_db);
325 if(ret != PC_OPERATION_SUCCESS) goto finish;
327 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
328 if(ret != PC_OPERATION_SUCCESS) goto finish;
330 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
331 // Ignore empty lines
332 if(strspn(pp_permissions_list[i], " \t\n")
333 == strlen(pp_permissions_list[i]))
336 ret = switch_app_permission_internal(p_db,
338 pp_permissions_list[i],
339 s_permission_type_name,
341 if(ret != PC_OPERATION_SUCCESS) goto finish;
344 ret = add_modified_label_internal(p_db, s_app_label_name);
346 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
351 int rdb_revoke_app_permissions(const char *const s_app_label_name)
353 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
355 int ret = PC_ERR_DB_OPERATION;
356 sqlite3 *p_db = NULL;
358 ret = rdb_begin(&p_db);
359 if(ret != PC_OPERATION_SUCCESS) goto finish;
361 ret = revoke_app_permissions_internal(p_db, s_app_label_name);
362 if(ret != PC_OPERATION_SUCCESS) goto finish;
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_reset_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 = reset_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);
386 if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
391 int validate_all_rules(const char *const *const pp_permissions_list)
396 char s_subject[SMACK_LABEL_LEN + 1];
397 char s_object[SMACK_LABEL_LEN + 1];
398 char s_access[ACC_LEN + 1];
400 // Parse and check rules.
401 for(i = 0; pp_permissions_list[i] != NULL; ++i) {
402 // C_LOGE("RDB: Validating rules: %s", pp_permissions_list[i]);
404 // Ignore empty lines
405 if(strspn(pp_permissions_list[i], " \t\n")
406 == strlen(pp_permissions_list[i]))
409 if(parse_rule(pp_permissions_list[i], s_subject, s_object, s_access)
410 != PC_OPERATION_SUCCESS) {
411 C_LOGE("RDB: Invalid parameter");
412 return PC_ERR_INVALID_PARAM;
415 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) != 0 &&
416 strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) != 0) {
417 C_LOGE("RDB: There is no " SMACK_APP_LABEL_TEMPLATE " argument in template rule.");
418 return PC_ERR_INVALID_PARAM;
421 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
422 strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0) {
423 C_LOGE("RDB: Rule with two " SMACK_APP_LABEL_TEMPLATE " has no sense.");
424 return PC_ERR_INVALID_PARAM;
427 // Check the other label
428 if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
429 !smack_label_is_valid(s_object)) {
430 C_LOGE("RDB: Incorrect object label: %s", s_object);
431 return PC_ERR_INVALID_PARAM;
432 } else if(strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0 &&
433 !smack_label_is_valid(s_subject)) {
434 C_LOGE("RDB: Incorrect subject label: %s", s_subject);
435 return PC_ERR_INVALID_PARAM;
439 return PC_OPERATION_SUCCESS;