68b0b5c117c703d8329eacc8e010c3ae7aa31f81
[platform/core/security/libprivilege-control.git] / src / rules-db-internals.c
1 /*
2  * libprivilege control, rules database
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Jan Olszak <j.olszak@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 /*
23 * @file        rules-db-internals.c
24 * @author      Jan Olszak (j.olszak@samsung.com)
25 * @version     1.0
26 * @brief       Definition of internal functions of the rules-db API.
27 */
28
29 #include <errno.h>      // For error logging
30 #include <stdarg.h>     // For handling multiple arguments
31 #include <stdlib.h>     // For free
32 #include <stdio.h>      // For file manipulation
33 #include "common.h"     // For smack_label_is_valid
34 #include <unistd.h>     // For sleep
35
36 #include "rules-db-internals.h"
37 #include "rules-db.h"
38
39 #define RDB_MAX_QUERY_ATTEMPTS    50
40 #define RDB_TIME_BETWEEN_ATTEMPTS 1 // sec
41
42 /**
43  * Reset and unbind statement. Used in functions that use bindings.
44  * @param  p_stmt SQLite3 statement
45  * @return        PC_OPERATION_SUCCESS on success, error code otherwise
46  */
47 static int reset_and_unbind_stmt(sqlite3_stmt *p_stmt)
48 {
49         if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
50                 C_LOGE("RDB: Error unbinding statement: %s",
51                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
52                 return PC_ERR_DB_QUERY_STEP;
53         }
54
55         if(sqlite3_reset(p_stmt) != SQLITE_OK) {
56                 C_LOGE("RDB: Error reseting statement: %s",
57                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
58                 return PC_ERR_DB_QUERY_STEP;
59         }
60         return PC_OPERATION_SUCCESS;
61 }
62
63
64
65 /**
66  * Helper function. Use on INSERT or DELETE or UPDATE, when not interested in returned value
67  *
68  * @ingroup RDB: internal functions
69  *
70  * @param  p_stmt SQLite3 statement
71  * @return        PC_OPERATION_SUCCESS on success, error code otherwise
72  */
73 static int step_and_convert_returned_value(sqlite3_stmt *p_stmt)
74 {
75         if(sqlite3_step(p_stmt) == SQLITE_DONE) {
76                 return PC_OPERATION_SUCCESS;
77         } else {
78                 C_LOGE("RDB: Error during stepping: %s",
79                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
80                 return PC_ERR_DB_QUERY_STEP;
81         }
82 }
83
84 int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name)
85 {
86         int ret = PC_OPERATION_SUCCESS;
87         sqlite3_stmt *p_stmt = NULL;
88         ret = prepare_stmt(p_db, &p_stmt,
89                            "INSERT OR IGNORE INTO modified_label(name) VALUES(%Q)",
90                            s_label_name);
91         if(ret != PC_OPERATION_SUCCESS) goto finish;
92
93         ret = step_and_convert_returned_value(p_stmt);
94 finish:
95         if(sqlite3_finalize(p_stmt) < 0)
96                 C_LOGE("RDB: Error during finalizing statement: %s",
97                        sqlite3_errmsg(p_db));
98         return ret;
99 }
100
101
102 int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
103 {
104         int ret = PC_OPERATION_SUCCESS;
105         sqlite3_stmt *p_stmt = NULL;
106         ret = prepare_stmt(p_db, &p_stmt,
107                            "INSERT OR IGNORE INTO modified_label(name) \
108                             SELECT app_permission_view.app_name        \
109                             FROM   app_permission_view                 \
110                             WHERE  app_permission_view.permission_id = %d",
111                            i_permission_id);
112         if(ret != PC_OPERATION_SUCCESS) goto finish;
113
114         ret = step_and_convert_returned_value(p_stmt);
115 finish:
116         if(sqlite3_finalize(p_stmt) < 0)
117                 C_LOGE("RDB: Error during finalizing statement: %s",
118                        sqlite3_errmsg(p_db));
119         return ret;
120 }
121
122
123 int add_modified_apps_path_internal(sqlite3 *p_db,
124                                     const char *const s_app_label_name)
125 {
126         int ret = PC_OPERATION_SUCCESS;
127         sqlite3_stmt *p_stmt = NULL;
128         ret = prepare_stmt(p_db, &p_stmt,
129                            "INSERT OR IGNORE INTO modified_label(name) \
130                             SELECT path_view.path_label_name           \
131                             FROM   path_view                           \
132                             WHERE  path_view.owner_app_label_name = %Q",
133                            s_app_label_name);
134         if(ret != PC_OPERATION_SUCCESS) goto finish;
135
136         ret = step_and_convert_returned_value(p_stmt);
137 finish:
138         if(sqlite3_finalize(p_stmt) < 0)
139                 C_LOGE("RDB: Error during finalizing statement: %s",
140                        sqlite3_errmsg(p_db));
141         return ret;
142 }
143
144 /**
145  * Function called when the target database is busy.
146  * We attempt to access the database every
147  * RDB_TIME_BETWEEN_ATTEMPTS seconds
148  *
149  * @param  not_used  not used
150  * @param  i_attempt number of the attempt
151  * @return           0 when stops waiting
152  *                   1 when waiting
153  */
154 static int database_busy_handler(void *not_used UNUSED,
155                                  int i_attempt)
156 {
157         if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
158                 // I ain't gonna wait for you forever!
159                 C_LOGE("RDB: Database busy for too long.");
160                 return 0;
161         }
162         C_LOGW("RDB: Database busy, waiting");
163         sleep(RDB_TIME_BETWEEN_ATTEMPTS);
164         return 1;
165 }
166
167
168 int open_rdb_connection(sqlite3 **p_db)
169 {
170         RDB_LOG_ENTRY;
171
172         char *p_err_msg;
173
174         // Open connection:
175         int ret = sqlite3_open_v2(RDB_PATH,
176                                   p_db,
177                                   RDB_READWRITE_FLAG,
178                                   NULL);
179         if(*p_db == NULL) {
180                 C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
181                 return PC_ERR_DB_CONNECTION;
182         }
183         if(ret != SQLITE_OK) {
184                 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
185                 return PC_ERR_DB_CONNECTION;
186         }
187
188         //Register busy handler:
189         if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
190                 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
191                 return PC_ERR_DB_CONNECTION;
192         }
193
194         // Load extensions:
195         if(sqlite3_enable_load_extension(*p_db, 1)) {
196                 C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
197                 return PC_ERR_DB_CONNECTION;
198         }
199
200         if(sqlite3_load_extension(*p_db,
201                                   "/usr/lib/librules-db-sql-udf.so", 0,
202                                   &p_err_msg) != SQLITE_OK) {
203
204                 C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
205                        p_err_msg);
206                 sqlite3_free(p_err_msg);
207                 return PC_ERR_DB_CONNECTION;
208         }
209         sqlite3_free(p_err_msg);
210
211
212         // Create the temporary tables:
213         if(sqlite3_exec(*p_db,
214                         "PRAGMA foreign_keys = ON;                                 \
215                         CREATE TEMPORARY TABLE history_smack_rule(                 \
216                                 subject VARCHAR NOT NULL,                          \
217                                 object  VARCHAR NOT NULL,                          \
218                                 access  INTEGER NOT NULL);                         \
219                                                                                    \
220                         CREATE TEMPORARY TABLE modified_label(                     \
221                                 name VARCHAR NOT NULL,                             \
222                                 UNIQUE(name));                                     \
223                                                                                    \
224                         CREATE TEMPORARY TABLE all_smack_binary_rule_modified(     \
225                                 subject VARCHAR NOT NULL,                          \
226                                 object  VARCHAR NOT NULL,                          \
227                                 access  INTEGER NOT NULL);                         \
228                                                                                    \
229                         CREATE TEMPORARY TABLE history_smack_rule_modified(        \
230                                 subject VARCHAR NOT NULL,                          \
231                                 object  VARCHAR NOT NULL,                          \
232                                 access  INTEGER NOT NULL);                         \
233                                                                                    \
234                         CREATE TEMPORARY VIEW modified_smack_rules AS              \
235                         SELECT  subject, object,                                   \
236                                 access_to_str(access_add) AS access_add,           \
237                                 access_to_str(access_del) AS access_del            \
238                         FROM    (                                                  \
239                                 SELECT     subject, object,                        \
240                                            s1.access & ~s2.access AS access_add,   \
241                                            s2.access & ~s1.access AS access_del    \
242                                 FROM       all_smack_binary_rule_modified AS s1    \
243                                 INNER JOIN history_smack_rule_modified AS s2       \
244                                            USING (subject, object)                 \
245                                 WHERE      s1.access != s2.access                  \
246                                 UNION                                              \
247                                 SELECT     subject, object,                        \
248                                            s1.access AS access_add,                \
249                                            0 AS access_del                         \
250                                 FROM       all_smack_binary_rule_modified s1       \
251                                 LEFT JOIN  history_smack_rule_modified s2          \
252                                            USING (subject, object)                 \
253                                 WHERE      s2.subject IS NULL AND                  \
254                                            s2.object  IS NULL                      \
255                                 UNION                                              \
256                                 SELECT     subject, object,                        \
257                                            0 AS access_add,                        \
258                                            s1.access AS access_del                 \
259                                 FROM       history_smack_rule_modified s1          \
260                                 LEFT JOIN  all_smack_binary_rule_modified s2       \
261                                            USING (subject, object)                 \
262                                 WHERE      s2.subject IS NULL AND                  \
263                                            s2.object  IS NULL                      \
264                                 )                                                  \
265                         ORDER BY subject, object ASC;",
266                         0, 0, 0) != SQLITE_OK) {
267                 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
268                 return PC_ERR_DB_OPERATION;
269         }
270
271         return PC_OPERATION_SUCCESS;
272 }
273
274
275 int prepare_stmt(sqlite3 *p_db,
276                  sqlite3_stmt **pp_stmt,
277                  const char *const s_sql,
278                  ...)
279 {
280         int ret = PC_ERR_DB_QUERY_PREP;
281         char *s_query = NULL;
282         va_list args;
283         va_start(args, s_sql);
284
285         s_query = sqlite3_vmprintf(s_sql, args);
286
287         if(s_query == NULL) {
288                 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
289                 ret = PC_ERR_DB_QUERY_PREP;
290                 goto finish;
291         }
292
293         if(sqlite3_prepare_v2(p_db,
294                               s_query,
295                               strlen(s_query) + 1,
296                               pp_stmt,
297                               NULL)) {
298                 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
299                 ret = PC_ERR_DB_QUERY_PREP;
300                 goto finish;
301         }
302
303         if(*pp_stmt == NULL) {
304                 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
305                 ret = PC_ERR_DB_QUERY_PREP;
306                 goto finish;
307         }
308
309         ret = PC_OPERATION_SUCCESS;
310
311 finish:
312         va_end(args);
313         sqlite3_free(s_query);
314         return ret;
315 }
316
317
318 int check_app_label_internal(sqlite3 *p_db,
319                              const char *const s_label_name)
320 {
321         RDB_LOG_ENTRY_PARAM("%s", s_label_name);
322
323         int ret = PC_ERR_DB_OPERATION;
324         sqlite3_stmt *p_stmt = NULL;
325
326         ret = prepare_stmt(p_db, &p_stmt,
327                            "SELECT 1                      \
328                             FROM application_view          \
329                             WHERE application_view.name=%Q \
330                             LIMIT 1",
331                            s_label_name);
332         if(ret != PC_OPERATION_SUCCESS) goto finish;
333
334         ret = sqlite3_step(p_stmt);
335         if(ret == SQLITE_ROW) {
336                 // There is such application label
337                 ret = PC_ERR_DB_LABEL_TAKEN;
338         } else if(ret == SQLITE_DONE) {
339                 // No such application label
340                 ret = PC_OPERATION_SUCCESS;
341         } else {
342                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
343                 ret = PC_ERR_DB_QUERY_STEP;
344         }
345 finish:
346         if(sqlite3_finalize(p_stmt) < 0)
347                 C_LOGE("RDB: Error during finalizing statement: %s",
348                        sqlite3_errmsg(p_db));
349         return ret;
350 }
351
352
353 int add_app_internal(sqlite3 *p_db,
354                      const char *const s_label_name)
355 {
356         RDB_LOG_ENTRY_PARAM("%s", s_label_name);
357
358         int ret = PC_ERR_DB_OPERATION;
359         sqlite3_stmt *p_stmt = NULL;
360
361         ret = prepare_stmt(p_db, &p_stmt,
362                            "INSERT into application_view(name) VALUES(%Q)",
363                            s_label_name);
364         if(ret != PC_OPERATION_SUCCESS) goto finish;
365
366         ret = step_and_convert_returned_value(p_stmt);
367 finish:
368         if(sqlite3_finalize(p_stmt) < 0)
369                 C_LOGE("RDB: Error during finalizing statement: %s",
370                        sqlite3_errmsg(p_db));
371         return ret;
372 }
373
374
375 int remove_app_internal(sqlite3 *p_db,
376                         const char *const s_label_name)
377 {
378         RDB_LOG_ENTRY_PARAM("%s", s_label_name);
379
380         int ret = PC_ERR_DB_OPERATION;
381         sqlite3_stmt *p_stmt = NULL;
382
383         ret = prepare_stmt(p_db, &p_stmt,
384                            "DELETE FROM application_view \
385                              WHERE application_view.name=%Q",
386                            s_label_name);
387
388         if(ret != PC_OPERATION_SUCCESS) goto finish;
389
390         ret = step_and_convert_returned_value(p_stmt);
391 finish:
392         if(sqlite3_finalize(p_stmt) < 0)
393                 C_LOGE("RDB: Error during finalizing statement: %s",
394                        sqlite3_errmsg(p_db));
395         return ret;
396 }
397
398
399 int add_path_internal(sqlite3 *p_db,
400                       const char *const s_owner_label_name,
401                       const char *const s_path_label_name,
402                       const char *const s_path,
403                       const char *const s_access,
404                       const char *const s_access_reverse,
405                       const char *const s_type)
406 {
407         RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
408                             s_owner_label_name, s_path_label_name,
409                             s_path, s_access, s_access_reverse, s_type);
410
411         int ret = PC_ERR_DB_OPERATION;
412         sqlite3_stmt *p_stmt = NULL;
413
414         ret = prepare_stmt(p_db, &p_stmt,
415                            "INSERT INTO path_view(owner_app_label_name, \
416                                                   path,                 \
417                                                   path_label_name,      \
418                                                   access,               \
419                                                   access_reverse,       \
420                                                   path_type_name)       \
421                              VALUES(%Q, %Q, %Q, %Q, %Q, %Q);",
422                            s_owner_label_name, s_path, s_path_label_name,
423                            s_access, s_access_reverse, s_type);
424         if(ret != PC_OPERATION_SUCCESS) goto finish;
425
426         ret = step_and_convert_returned_value(p_stmt);
427 finish:
428         if(sqlite3_finalize(p_stmt) < 0)
429                 C_LOGE("RDB: Error during finalizing statement: %s",
430                        sqlite3_errmsg(p_db));
431         return ret;
432 }
433
434
435 int add_permission_internal(sqlite3 *p_db,
436                             const char *const s_permission_name,
437                             const char *const s_permission_type_name)
438 {
439         RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
440
441         int ret = PC_ERR_DB_OPERATION;
442         sqlite3_stmt *p_stmt = NULL;
443
444         ret = prepare_stmt(p_db, &p_stmt,
445                            "INSERT INTO permission_view(name, type_name) \
446                            VALUES (%Q,%Q)",
447                            s_permission_name, s_permission_type_name);
448
449         if(ret != PC_OPERATION_SUCCESS) goto finish;
450
451         ret = step_and_convert_returned_value(p_stmt);
452 finish:
453         if(sqlite3_finalize(p_stmt) < 0)
454                 C_LOGE("RDB: Error during finalizing statement: %s",
455                        sqlite3_errmsg(p_db));
456         return ret;
457 }
458
459
460 int get_permission_id_internal(sqlite3 *p_db,
461                                const char *const s_permission_name,
462                                const char *const s_permission_type_name,
463                                sqlite3_int64 *p_permission_id)
464 {
465         RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
466
467         int ret = PC_ERR_DB_OPERATION;
468         sqlite3_stmt *p_stmt = NULL;
469
470         ret = prepare_stmt(p_db, &p_stmt,
471                            "SELECT permission_view.permission_id  \
472                             FROM   permission_view                \
473                             WHERE  permission_view.name = %Q AND  \
474                                    permission_view.type_name = %Q \
475                             LIMIT  1",
476                            s_permission_name, s_permission_type_name);
477         if(ret != PC_OPERATION_SUCCESS) goto finish;
478
479         ret = sqlite3_step(p_stmt);
480         if(ret == SQLITE_ROW) {
481                 ret = PC_OPERATION_SUCCESS;
482                 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
483         } else if(ret == SQLITE_DONE) {
484                 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
485                 ret = PC_ERR_DB_OPERATION;
486
487         } else {
488                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
489                 ret = PC_ERR_DB_QUERY_STEP;
490         }
491
492 finish:
493         if(sqlite3_finalize(p_stmt) < 0)
494                 C_LOGE("RDB: Error during finalizing statement: %s",
495                        sqlite3_errmsg(p_db));
496
497         return ret;
498 }
499
500
501 int prepare_stmts_for_bind(sqlite3 *p_db,
502                            sqlite3_stmt **pp_stmt,
503                            const char *const s_query)
504 {
505         if(sqlite3_prepare_v2(p_db,
506                               s_query,
507                               strlen(s_query) + 1,
508                               pp_stmt,
509                               NULL)) {
510                 C_LOGE("RDB: Error during preparing statement: %s",
511                        sqlite3_errmsg(p_db));
512                 return PC_ERR_DB_QUERY_PREP;
513         }
514         return PC_OPERATION_SUCCESS;
515 }
516
517
518 static int add_permission_label_rule(sqlite3_stmt *p_stmt,
519                                      const sqlite3_int64 i_permission_id,
520                                      const char *const s_label_name,
521                                      const char *const s_access,
522                                      const int i_is_reverse)
523 {
524         int ret = PC_OPERATION_SUCCESS;
525
526         // Bind values to the statement and run it:
527         // Bind returns SQLITE_OK == 0 on success
528         if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
529             sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
530             sqlite3_bind_text(p_stmt, 3, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
531             sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
532                 C_LOGE("RDB: Error during binding to statement: %s",
533                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
534                 ret = PC_ERR_DB_QUERY_BIND;
535                 goto finish;
536         }
537
538         // Perform the insert
539         ret = step_and_convert_returned_value(p_stmt);
540
541 finish:
542         reset_and_unbind_stmt(p_stmt);
543         return ret;
544 }
545
546
547 static int add_permission_permission_rule(sqlite3_stmt *p_stmt,
548                 const sqlite3_int64 i_permission_id,
549                 const sqlite3_int64 i_target_permission_id,
550                 const char *const s_access,
551                 const int i_is_reverse)
552 {
553         int ret = PC_OPERATION_SUCCESS;
554
555         if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
556             sqlite3_bind_int(p_stmt, 2, i_target_permission_id)  ||
557             sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
558             sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
559                 C_LOGE("RDB: Error during binding to statement: %s",
560                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
561                 ret = PC_ERR_DB_QUERY_BIND;
562                 goto finish;
563         }
564
565         ret = step_and_convert_returned_value(p_stmt);
566
567 finish:
568         reset_and_unbind_stmt(p_stmt);
569         return ret;
570 }
571
572
573 static int add_permission_app_path_type_rule(sqlite3_stmt *p_stmt,
574                 const sqlite3_int64 i_permission_id,
575                 const char *const s_path_type_name,
576                 const char *const s_access,
577                 const int i_is_reverse)
578 {
579         int ret = PC_OPERATION_SUCCESS;
580
581         if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
582             sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0)  ||
583             sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
584             sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
585                 C_LOGE("RDB: Error during binding to statement: %s",
586                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
587                 ret = PC_ERR_DB_QUERY_BIND;
588                 goto finish;
589         }
590
591         ret = step_and_convert_returned_value(p_stmt);
592
593 finish:
594         reset_and_unbind_stmt(p_stmt);
595         return ret;
596 }
597
598 int add_permission_rules_internal(sqlite3 *p_db,
599                                   const sqlite3_int64 i_permission_id,
600                                   const char *const *const pp_smack_rules)
601 {
602         RDB_LOG_ENTRY;
603
604         int ret = PC_OPERATION_SUCCESS;
605         char s_label[SMACK_LABEL_LEN + 1];
606         char s_access[ACC_LEN + 1];
607         sqlite3_int64 i_all_apps_permission_id = 1;
608         int i_is_reverse = 0;
609         int i;
610         sqlite3_stmt *p_perm_to_label_stmt = NULL;
611         sqlite3_stmt *p_perm_to_perm_stmt = NULL;
612         sqlite3_stmt *p_perm_to_app_path_type_stmt = NULL;
613
614         // Prepare stmts. They are static, so we parse SQL only once per process and reuse it.
615         ret = prepare_stmts_for_bind(p_db, &p_perm_to_label_stmt,
616                                      "INSERT INTO permission_label_rule_view(        \
617                                       permission_id, access, label_name, is_reverse) \
618                                       VALUES(?,?,?,?)");
619         if(ret != PC_OPERATION_SUCCESS) goto finish;
620
621         ret = prepare_stmts_for_bind(p_db, &p_perm_to_perm_stmt,
622                                      "INSERT OR REPLACE INTO permission_permission_rule( \
623                                       permission_id, target_permission_id,               \
624                                       access, is_reverse)                                \
625                                       VALUES(?,?,str_to_access(?),?)");
626         if(ret != PC_OPERATION_SUCCESS) goto finish;
627
628
629         ret = prepare_stmts_for_bind(p_db, &p_perm_to_app_path_type_stmt,
630                                      "INSERT INTO permission_app_path_type_rule_view(        \
631                                       permission_id, app_path_type_name, access, is_reverse) \
632                                       VALUES(?,?,?,?)");
633         if(ret != PC_OPERATION_SUCCESS) goto finish;
634
635
636         for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
637                 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
638
639                 // Ignore empty lines
640                 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
641                         continue;
642
643                 ret = parse_rule(pp_smack_rules[i], s_label, s_access, &i_is_reverse);
644                 if(ret != PC_OPERATION_SUCCESS) goto finish;
645
646                 // Interpret wildcards
647                 if(s_label[0] != '~' &&
648                     s_label[strlen(s_label) - 1] != '~') {
649                         // It's not a wildcard!
650                         ret = add_permission_label_rule(p_perm_to_label_stmt,
651                                                         i_permission_id,
652                                                         s_label,
653                                                         s_access,
654                                                         i_is_reverse);
655                         if(ret != PC_OPERATION_SUCCESS) goto finish;
656
657                 } else if(!strcmp(s_label, "~ALL_APPS~")) {
658                         ret = get_permission_id_internal(p_db,
659                                                          "ALL_APPS",
660                                                          "ALL_APPS",
661                                                          &i_all_apps_permission_id);
662                         if(ret != PC_OPERATION_SUCCESS) goto finish;
663
664                         ret = add_permission_permission_rule(p_perm_to_perm_stmt,
665                                                              i_permission_id,
666                                                              i_all_apps_permission_id,
667                                                              s_access,
668                                                              i_is_reverse);
669                         if(ret != PC_OPERATION_SUCCESS) goto finish;
670
671                 } else if(!strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~")) {
672                         ret = add_permission_permission_rule(p_perm_to_perm_stmt,
673                                                              i_permission_id,
674                                                              i_permission_id,
675                                                              s_access,
676                                                              i_is_reverse);
677                         if(ret != PC_OPERATION_SUCCESS) goto finish;
678
679                 } else if(!strcmp(s_label, "~PUBLIC_PATH~")) {
680                         ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
681                                                                 i_permission_id,
682                                                                 "PUBLIC_PATH",
683                                                                 s_access,
684                                                                 i_is_reverse);
685                         if(ret != PC_OPERATION_SUCCESS) goto finish;
686
687                 } else if(!strcmp(s_label, "~GROUP_PATH~")) {
688                         ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
689                                                                 i_permission_id,
690                                                                 "GROUP_PATH",
691                                                                 s_access,
692                                                                 i_is_reverse);
693                         if(ret != PC_OPERATION_SUCCESS) goto finish;
694
695                 } else if(!strcmp(s_label, "~SETTINGS_PATH~")) {
696                         ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
697                                                                 i_permission_id,
698                                                                 "SETTINGS_PATH",
699                                                                 s_access,
700                                                                 i_is_reverse);
701                         if(ret != PC_OPERATION_SUCCESS) goto finish;
702                 }
703         }
704
705         ret = PC_OPERATION_SUCCESS;
706
707 finish:
708         if(p_perm_to_label_stmt &&
709             sqlite3_finalize(p_perm_to_label_stmt) < 0) {
710                 C_LOGE("RDB: Error during finalizing statement: %s",
711                        sqlite3_errmsg(p_db));
712         }
713
714         if(p_perm_to_perm_stmt &&
715             sqlite3_finalize(p_perm_to_perm_stmt) < 0) {
716                 C_LOGE("RDB: Error during finalizing statement: %s",
717                        sqlite3_errmsg(p_db));
718         }
719
720         if(p_perm_to_app_path_type_stmt &&
721             sqlite3_finalize(p_perm_to_app_path_type_stmt) < 0) {
722                 C_LOGE("RDB: Error during finalizing statement: %s",
723                        sqlite3_errmsg(p_db));
724         }
725         return ret;
726 }
727
728 static int add_label_app_path_type_rule(sqlite3_stmt *p_stmt,
729                                         const char *const s_label_name,
730                                         const char *const s_path_type_name,
731                                         const char *const s_access,
732                                         const int i_is_reverse)
733 {
734         int ret = PC_OPERATION_SUCCESS;
735
736         if(sqlite3_bind_text(p_stmt, 1, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
737             sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0)  ||
738             sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
739             sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
740                 C_LOGE("RDB: Error during binding to statement: %s",
741                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
742                 ret = PC_ERR_DB_QUERY_BIND;
743                 goto finish;
744         }
745
746         ret = step_and_convert_returned_value(p_stmt);
747
748 finish:
749         reset_and_unbind_stmt(p_stmt);
750         return ret;
751 }
752
753
754 int add_additional_rules_internal(sqlite3 *p_db, const char *const *const pp_smack_rules)
755 {
756         RDB_LOG_ENTRY;
757         int ret = PC_OPERATION_SUCCESS;
758         size_t i;
759         char s_subject[SMACK_LABEL_LEN + 1];
760         char s_object[SMACK_LABEL_LEN + 1];
761         char s_access[ACC_LEN + 1];
762         sqlite3_stmt *p_label_to_app_path_type_stmt = NULL;
763         int is_reverse = 0;
764         char *ps_subject, *ps_object;
765
766         // Clear the label_app_path_type_rule table
767         if(sqlite3_exec(p_db, "DELETE FROM label_app_path_type_rule_view;", 0, 0, 0) != SQLITE_OK) {
768                 C_LOGE("RDB: Error during clearing additional rules: %s", sqlite3_errmsg(p_db));
769                 ret = PC_ERR_DB_OPERATION;
770                 goto finish;
771         }
772
773         ret = prepare_stmts_for_bind(p_db, &p_label_to_app_path_type_stmt,
774                                      "INSERT INTO label_app_path_type_rule_view(          \
775                                       label_name, app_path_type_name, access, is_reverse) \
776                                       VALUES(?,?,?,?)");
777         if(ret != PC_OPERATION_SUCCESS) goto finish;
778
779         // Add rules to the database
780         for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
781
782                 // Ignore empty lines
783                 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
784                         continue;
785
786                 // Tokenize
787                 ret = tokenize_rule(pp_smack_rules[i], s_subject , s_object, s_access);
788                 if(ret != PC_OPERATION_SUCCESS) goto finish;
789
790                 if(is_wildcard(s_subject)) {
791                         ps_subject = s_object;
792                         ps_object = s_subject;
793                         is_reverse = 1;
794                 } else {
795                         ps_subject = s_subject;
796                         ps_object = s_object;
797                         is_reverse = 0;
798                 }
799
800                 // Check validity
801                 if(!smack_label_is_valid(ps_subject)) {
802                         C_LOGE("Subject is not a valid label");
803                         ret = PC_ERR_INVALID_PARAM;
804                         goto finish;
805                 }
806
807                 // Add access to paths
808                 if(!strcmp(ps_object, "~PUBLIC_PATH~")) {
809                         ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
810                                                            ps_subject,
811                                                            "PUBLIC_PATH",
812                                                            s_access,
813                                                            is_reverse);
814                         if(ret != PC_OPERATION_SUCCESS) goto finish;
815
816                 } else if(!strcmp(ps_object, "~GROUP_PATH~")) {
817                         ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
818                                                            ps_subject,
819                                                            "GROUP_PATH",
820                                                            s_access,
821                                                            is_reverse);
822                         if(ret != PC_OPERATION_SUCCESS) goto finish;
823
824                 } else if(!strcmp(ps_object, "~SETTINGS_PATH~")) {
825                         ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
826                                                            ps_subject,
827                                                            "SETTINGS_PATH",
828                                                            s_access,
829                                                            is_reverse);
830                         if(ret != PC_OPERATION_SUCCESS) goto finish;
831                 } else if(!strcmp(ps_object, "~NPRUNTIME_PATH~")) {
832                         ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
833                                                            ps_subject,
834                                                            "NPRUNTIME_PATH",
835                                                            s_access,
836                                                            is_reverse);
837                         if(ret != PC_OPERATION_SUCCESS) goto finish;
838                 }
839
840
841                 // Mark label as modified
842                 ret = add_modified_label_internal(p_db, ps_subject);
843                 if(ret != PC_OPERATION_SUCCESS) goto finish;
844         }
845
846 finish:
847         if(p_label_to_app_path_type_stmt &&
848             sqlite3_finalize(p_label_to_app_path_type_stmt) < 0)
849                 C_LOGE("RDB: Error during finalizing statement: %s",
850                        sqlite3_errmsg(p_db));
851         return ret;
852 }
853
854 int check_app_has_permission_internal(sqlite3 *p_db,
855                                       const char *const s_app_label_name,
856                                       const char *const s_permission_name,
857                                       const char *const s_permission_type_name,
858                                       bool *const p_is_enabled)
859 {
860         RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
861                             s_permission_name, s_permission_type_name);
862
863         int ret = PC_ERR_DB_OPERATION;
864         sqlite3_stmt *p_stmt = NULL;
865
866         ret = prepare_stmt(p_db, &p_stmt,
867                            "SELECT is_enabled              \
868                             FROM   app_permission_view     \
869                             WHERE  app_name = %Q AND       \
870                                    name = %Q AND           \
871                                    type_name = %Q          \
872                             LIMIT  1",
873                            s_app_label_name, s_permission_name, s_permission_type_name);
874         if(ret != PC_OPERATION_SUCCESS) goto finish;
875
876         ret = sqlite3_step(p_stmt);
877         if(ret == SQLITE_ROW) {
878                 ret = PC_OPERATION_SUCCESS;
879                 //store the result
880                 *p_is_enabled = (bool)sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
881         } else if(ret == SQLITE_DONE) {
882                 //no entry == permission not assigned
883                 C_LOGD("RDB: Permission: %s of type: %s is not assigned to app: %s",
884                        s_permission_name, s_permission_type_name, s_app_label_name);
885                 ret = PC_OPERATION_SUCCESS;
886                 *p_is_enabled = false;
887         } else if(ret == SQLITE_BUSY) {
888                 //base locked in exclusive mode for too long
889                 C_LOGE("RDB: Database is busy. RDB Connection Error returned.");
890                 ret = PC_ERR_DB_CONNECTION;
891         } else {
892                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
893                 ret = PC_ERR_DB_QUERY_STEP;
894         }
895
896 finish:
897         if(sqlite3_finalize(p_stmt) < 0)
898                 C_LOGE("RDB: Error during finalizing statement: %s",
899                        sqlite3_errmsg(p_db));
900         return ret;
901 }
902
903 int get_app_id_internal(sqlite3 *p_db,
904                         int *pi_app_id,
905                         const char *const s_app_label_name)
906 {
907         RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
908
909         int ret = PC_ERR_DB_OPERATION;
910         sqlite3_stmt *p_stmt = NULL;
911
912         ret = prepare_stmt(p_db, &p_stmt,
913                            "SELECT application_view.app_id \
914                              FROM application_view \
915                              WHERE application_view.name = %Q",
916                            s_app_label_name);
917
918         if(ret != PC_OPERATION_SUCCESS) goto finish;
919
920         ret = sqlite3_step(p_stmt);
921         if(ret == SQLITE_ROW) {
922                 ret = PC_OPERATION_SUCCESS;
923                 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
924
925         } else if(ret == SQLITE_DONE) {
926                 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
927                 ret = PC_ERR_DB_OPERATION;
928
929         } else {
930                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
931                 ret = PC_ERR_DB_QUERY_STEP;
932         }
933
934 finish:
935         if(sqlite3_finalize(p_stmt) < 0)
936                 C_LOGE("RDB: Error during finalizing statement: %s",
937                        sqlite3_errmsg(p_db));
938         return ret;
939 }
940
941
942 int add_app_permission_internal(sqlite3 *p_db,
943                                 int i_app_id,
944                                 const char *const s_permission_name,
945                                 const char *const s_permission_type_name,
946                                 const bool b_is_volatile_new,
947                                 const bool b_is_enabled_new)
948 {
949         RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
950                             s_permission_name, s_permission_type_name,
951                             b_is_volatile_new, b_is_enabled_new);
952
953
954         int ret = PC_ERR_DB_OPERATION;
955         sqlite3_stmt *p_stmt = NULL;
956
957         ret = prepare_stmt(p_db, &p_stmt,
958                            "INSERT INTO                                  \
959                             app_permission_view(app_id, name, type_name, \
960                             is_volatile, is_enabled)                     \
961                             VALUES(%d,%Q,%Q,%d,%d)",
962                            i_app_id, s_permission_name, s_permission_type_name,
963                            (int)b_is_volatile_new, (int)b_is_enabled_new);
964
965         if(ret != PC_OPERATION_SUCCESS) goto finish;
966
967         ret = step_and_convert_returned_value(p_stmt);
968 finish:
969         if(sqlite3_finalize(p_stmt) < 0)
970                 C_LOGE("RDB: Error during finalizing statement: %s",
971                        sqlite3_errmsg(p_db));
972         return ret;
973 }
974
975
976 int switch_app_permission_internal(sqlite3 *p_db,
977                                    const int i_app_id,
978                                    const char *const s_permission_name,
979                                    const char *const s_permission_type_name,
980                                    const bool b_is_enabled_new)
981 {
982         RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
983                             s_permission_name, s_permission_type_name,
984                             b_is_enabled_new);
985
986         int ret = PC_ERR_DB_OPERATION;
987         sqlite3_stmt *p_stmt = NULL;
988
989         ret = prepare_stmt(p_db, &p_stmt,
990                            "UPDATE app_permission_view \
991                             SET    is_enabled=%d       \
992                             WHERE  app_id = %d  AND    \
993                                    name =%Q AND        \
994                                    type_name=%Q",
995                            b_is_enabled_new, i_app_id,
996                            s_permission_name, s_permission_type_name);
997
998         if(ret != PC_OPERATION_SUCCESS) goto finish;
999         ret = step_and_convert_returned_value(p_stmt);
1000 finish:
1001         if(sqlite3_finalize(p_stmt) < 0)
1002                 C_LOGE("RDB: Error during finalizing statement: %s",
1003                        sqlite3_errmsg(p_db));
1004         return ret;
1005 }
1006
1007
1008 int update_app_permission_internal(sqlite3 *p_db,
1009                                    const int i_app_id,
1010                                    const int i_permission_id,
1011                                    const bool b_is_volatile_new,
1012                                    const bool b_is_enabled_new)
1013 {
1014         RDB_LOG_ENTRY_PARAM("%d %d %d %d",
1015                             i_app_id, i_permission_id,
1016                             b_is_volatile_new, b_is_enabled_new);
1017
1018         int ret = PC_ERR_DB_OPERATION;
1019         sqlite3_stmt *p_stmt = NULL;
1020
1021         ret = prepare_stmt(p_db, &p_stmt,
1022                            "UPDATE app_permission \
1023                              SET is_volatile = %d, is_enabled=%d \
1024                              WHERE app_id = %d AND permission_id = %d",
1025                            b_is_volatile_new, b_is_enabled_new,
1026                            i_app_id, i_permission_id);
1027
1028         if(ret != PC_OPERATION_SUCCESS) goto finish;
1029         ret = step_and_convert_returned_value(p_stmt);
1030 finish:
1031         if(sqlite3_finalize(p_stmt) < 0)
1032                 C_LOGE("RDB: Error during finalizing statement: %s",
1033                        sqlite3_errmsg(p_db));
1034         return ret;
1035 }
1036
1037
1038 int change_app_permission_internal(sqlite3 *p_db,
1039                                    int i_app_id,
1040                                    const char *const s_permission_name,
1041                                    const char *const s_permission_type_name,
1042                                    int i_is_volatile_new,
1043                                    int i_is_enabled_new)
1044 {
1045         RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
1046                             s_permission_name, s_permission_type_name,
1047                             i_is_volatile_new, i_is_enabled_new);
1048
1049         int ret = PC_ERR_DB_OPERATION;
1050         sqlite3_stmt *p_stmt = NULL;
1051         int i_is_volatile_old, i_is_enabled_old, i_permission_id;
1052
1053         ret = prepare_stmt(p_db, &p_stmt,
1054                            "SELECT is_volatile, is_enabled, permission_id      \
1055                              FROM    app_permission_list_view                   \
1056                              WHERE   app_id = %d AND                            \
1057                              permission_name=%Q AND                             \
1058                              permission_type_name=%Q LIMIT 1",
1059                            i_app_id, s_permission_name, s_permission_type_name);
1060         if(ret != PC_OPERATION_SUCCESS) goto finish;
1061
1062         ret = sqlite3_step(p_stmt);
1063         if(ret == SQLITE_ROW) {
1064                 // Phi, I already have this permission...
1065                 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
1066                 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
1067
1068                 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
1069                         // Confucius say, No man can down-cast volatility.
1070                         C_LOGE("RDB: Down-casting volatility is forbidden.");
1071                         ret = PC_ERR_DB_PERM_FORBIDDEN;
1072                         goto finish;
1073                 }
1074
1075                 if(i_is_volatile_old == i_is_volatile_new &&
1076                     i_is_enabled_old == i_is_enabled_new) {
1077                         // There is no change. Nice.
1078                         C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
1079                         ret = PC_OPERATION_SUCCESS;
1080                         goto finish;
1081                 }
1082
1083                 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
1084
1085                 // Finalize statement
1086                 if(sqlite3_finalize(p_stmt) < 0)
1087                         C_LOGE("RDB: Error during finalizing statement: %s",
1088                                sqlite3_errmsg(p_db));
1089                 p_stmt = NULL;
1090
1091                 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
1092                 ret = update_app_permission_internal(p_db,
1093                                                      i_app_id,
1094                                                      i_permission_id,
1095                                                      i_is_volatile_new,
1096                                                      i_is_enabled_new);
1097
1098         } else if(ret == SQLITE_DONE) {
1099                 // Wow! A brand new permission! Omnomnom...
1100
1101                 if(sqlite3_finalize(p_stmt) < 0)
1102                         C_LOGE("RDB: Error during finalizing statement: %s",
1103                                sqlite3_errmsg(p_db));
1104                 p_stmt = NULL;
1105
1106                 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
1107                 ret = add_app_permission_internal(p_db,
1108                                                   i_app_id,
1109                                                   s_permission_name,
1110                                                   s_permission_type_name,
1111                                                   i_is_volatile_new,
1112                                                   i_is_enabled_new);
1113         } else {
1114                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
1115                 ret = PC_ERR_DB_QUERY_STEP;
1116         }
1117
1118 finish:
1119         if(p_stmt && sqlite3_finalize(p_stmt) < 0)
1120                 C_LOGE("RDB: Error during finalizing statement: %s",
1121                        sqlite3_errmsg(p_db));
1122         return ret;
1123 }
1124
1125
1126 int revoke_app_permissions_internal(sqlite3 *p_db,
1127                                     const char *const s_app_label_name)
1128 {
1129         RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
1130
1131         int ret = PC_ERR_DB_OPERATION;
1132         sqlite3_stmt *p_stmt = NULL;
1133
1134         ret = prepare_stmt(p_db, &p_stmt,
1135                            "DELETE FROM app_permission_view \
1136                             WHERE app_permission_view.app_name=%Q;",
1137                            s_app_label_name);
1138
1139         if(ret != PC_OPERATION_SUCCESS) goto finish;
1140
1141         ret = step_and_convert_returned_value(p_stmt);
1142 finish:
1143         if(sqlite3_finalize(p_stmt) < 0)
1144                 C_LOGE("RDB: Error during finalizing statement: %s",
1145                        sqlite3_errmsg(p_db));
1146         return ret;
1147 }
1148
1149
1150 int reset_app_permissions_internal(sqlite3 *p_db,
1151                                    const char *const s_app_label_name)
1152 {
1153         RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
1154
1155         int ret = PC_ERR_DB_OPERATION;
1156         sqlite3_stmt *p_stmt = NULL;
1157
1158         ret = prepare_stmt(p_db, &p_stmt,
1159                            "DELETE FROM app_permission_volatile_view \
1160                              WHERE app_permission_volatile_view.app_name=%Q;",
1161                            s_app_label_name);
1162
1163         if(ret != PC_OPERATION_SUCCESS) goto finish;
1164
1165         ret = step_and_convert_returned_value(p_stmt);
1166 finish:
1167         if(sqlite3_finalize(p_stmt) < 0)
1168                 C_LOGE("RDB: Error during finalizing statement: %s",
1169                        sqlite3_errmsg(p_db));
1170         return ret;
1171 }
1172
1173
1174 int save_smack_rules(sqlite3 *p_db)
1175 {
1176         RDB_LOG_ENTRY;
1177
1178         if(sqlite3_exec(p_db,
1179                         "DELETE FROM history_smack_rule;                     \
1180                                                                              \
1181                         INSERT INTO history_smack_rule                       \
1182                         SELECT subject, object, access                       \
1183                         FROM all_smack_binary_rules;                         \
1184                                                                              \
1185                         CREATE INDEX history_smack_rule_subject_object_index \
1186                         ON history_smack_rule(subject, object);",
1187                         0, 0, 0) != SQLITE_OK) {
1188                 C_LOGE("RDB: Error during saving history table: %s",
1189                        sqlite3_errmsg(p_db));
1190                 return PC_ERR_DB_OPERATION;
1191         }
1192
1193         return PC_OPERATION_SUCCESS;
1194 }
1195
1196
1197 int update_rules_in_db(sqlite3 *p_db)
1198 {
1199         RDB_LOG_ENTRY;
1200
1201         // All rules generated by the present state of the database
1202         if(sqlite3_exec(p_db,
1203                         "DELETE FROM all_smack_binary_rules;        \
1204                                                                     \
1205                         INSERT INTO all_smack_binary_rules          \
1206                         SELECT subject, object, access, is_volatile \
1207                         FROM all_smack_binary_rules_view;           \
1208                                                                     \
1209                         DELETE FROM all_smack_binary_rule_modified; \
1210                                                                     \
1211                         INSERT INTO all_smack_binary_rule_modified  \
1212                         SELECT subject, object, access              \
1213                         FROM   all_smack_binary_rules,              \
1214                                modified_label                       \
1215                         WHERE  subject IN modified_label OR         \
1216                                object IN modified_label;            \
1217                                                                     \
1218                         DELETE FROM history_smack_rule_modified;    \
1219                                                                     \
1220                         INSERT INTO history_smack_rule_modified     \
1221                         SELECT subject, object, access              \
1222                         FROM   history_smack_rule,                  \
1223                                modified_label                       \
1224                         WHERE  subject IN modified_label OR         \
1225                                object IN modified_label;            \
1226                         ",
1227                         0, 0, 0) != SQLITE_OK) {
1228                 C_LOGE("RDB: Error during updating rules: %s",
1229                        sqlite3_errmsg(p_db));
1230                 return PC_ERR_DB_OPERATION;
1231         }
1232         return PC_OPERATION_SUCCESS;
1233 }
1234
1235 int update_smack_rules(sqlite3 *p_db)
1236 {
1237         RDB_LOG_ENTRY;
1238
1239         int ret = PC_OPERATION_SUCCESS;
1240         sqlite3_stmt *p_stmt = NULL;
1241         const unsigned char *s_subject    = NULL;
1242         const unsigned char *s_object     = NULL;
1243         const unsigned char *s_access_add = NULL;
1244         const unsigned char *s_access_del = NULL;
1245         struct smack_accesses *smack = NULL;
1246
1247         if(smack_accesses_new(&smack)) {
1248                 C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
1249                 ret = PC_ERR_MEM_OPERATION;
1250                 goto finish;
1251         }
1252
1253         ret = prepare_stmt(p_db, &p_stmt,
1254                            "SELECT * from modified_smack_rules;");
1255         if(ret != PC_OPERATION_SUCCESS) goto finish;
1256
1257         while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
1258                 s_subject    = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
1259                 s_object     = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
1260                 s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
1261                 s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
1262
1263                 C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
1264                        s_subject, s_object, s_access_add, s_access_del);
1265
1266                 if(smack_accesses_add_modify(smack,
1267                                              (const char *) s_subject,
1268                                              (const char *) s_object,
1269                                              (const char *) s_access_add,
1270                                              (const char *) s_access_del)) {
1271                         C_LOGE("RDB: Error during updating smack rules: %s",
1272                                sqlite3_errmsg(p_db));
1273                         ret = PC_ERR_INVALID_OPERATION;
1274                         goto finish;
1275                 }
1276         }
1277         if(ret == SQLITE_DONE) {
1278                 ret = PC_OPERATION_SUCCESS;
1279         } else {
1280                 C_LOGE("RDB: Error during updating smack rules [%d]: %s",
1281                        ret, sqlite3_errmsg(p_db));
1282                 ret = PC_ERR_DB_OPERATION;
1283         }
1284
1285         if(smack_accesses_apply(smack)) {
1286                 C_LOGE("RDB: Error in smack_accesses_apply");
1287                 ret = PC_ERR_INVALID_OPERATION;
1288         }
1289
1290 finish:
1291         if(sqlite3_finalize(p_stmt) < 0)
1292                 C_LOGE("RDB: Error during finalizing statement: %s",
1293                        sqlite3_errmsg(p_db));
1294
1295         smack_accesses_free(smack);
1296         return ret;
1297 }