Deleted volatile rules on boot and corrected permission format.
[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
44
45 /**
46  * Helper function. Use on INSERT or DELETE or UPDATE, when not interested in returned value
47  *
48  * @ingroup RDB: internal functions
49  *
50  * @param  p_stmt SQLite3 statement
51  * @return        PC_OPERATION_SUCCESS on success, error code otherwise
52  */
53 static int step_and_convert_returned_value(sqlite3_stmt *p_stmt)
54 {
55         if(sqlite3_step(p_stmt) == SQLITE_DONE) {
56                 return PC_OPERATION_SUCCESS;
57         } else {
58                 C_LOGE("RDB: Error during stepping: %s",
59                        sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
60                 return PC_ERR_DB_QUERY_STEP;
61         }
62 }
63
64 int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name)
65 {
66         int ret = PC_OPERATION_SUCCESS;
67         sqlite3_stmt *p_stmt = NULL;
68         ret = prepare_stmt(p_db, &p_stmt,
69                            "INSERT OR IGNORE INTO modified_label(name) VALUES(%Q)",
70                            s_label_name);
71         if(ret != PC_OPERATION_SUCCESS) goto finish;
72
73         ret = step_and_convert_returned_value(p_stmt);
74 finish:
75         if(sqlite3_finalize(p_stmt) < 0)
76                 C_LOGE("RDB: Error during finalizing statement: %s",
77                        sqlite3_errmsg(p_db));
78         return ret;
79 }
80
81
82 int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
83 {
84         int ret = PC_OPERATION_SUCCESS;
85         sqlite3_stmt *p_stmt = NULL;
86         ret = prepare_stmt(p_db, &p_stmt,
87                            "INSERT OR IGNORE INTO modified_label(name) \
88                             SELECT app_permission_view.app_name        \
89                             FROM   app_permission_view                 \
90                             WHERE  app_permission_view.permission_id = %d",
91                            i_permission_id);
92         if(ret != PC_OPERATION_SUCCESS) goto finish;
93
94         ret = step_and_convert_returned_value(p_stmt);
95 finish:
96         if(sqlite3_finalize(p_stmt) < 0)
97                 C_LOGE("RDB: Error during finalizing statement: %s",
98                        sqlite3_errmsg(p_db));
99         return ret;
100 }
101
102
103 int add_modified_apps_path_internal(sqlite3 *p_db,
104                                     const char *const s_app_label_name)
105 {
106         int ret = PC_OPERATION_SUCCESS;
107         sqlite3_stmt *p_stmt = NULL;
108         ret = prepare_stmt(p_db, &p_stmt,
109                            "INSERT OR IGNORE INTO modified_label(name) \
110                             SELECT path_view.path_label_name           \
111                             FROM   path_view                           \
112                             WHERE  path_view.owner_app_label_name = %Q",
113                            s_app_label_name);
114         if(ret != PC_OPERATION_SUCCESS) goto finish;
115
116         ret = step_and_convert_returned_value(p_stmt);
117 finish:
118         if(sqlite3_finalize(p_stmt) < 0)
119                 C_LOGE("RDB: Error during finalizing statement: %s",
120                        sqlite3_errmsg(p_db));
121         return ret;
122 }
123
124 /**
125  * Function called when the target database is busy.
126  * We attempt to access the database every
127  * RDB_TIME_BETWEEN_ATTEMPTS seconds
128  *
129  * @param  not_used  not used
130  * @param  i_attempt number of the attempt
131  * @return           0 when stops waiting
132  *                   1 when waiting
133  */
134 static int database_busy_handler(void *not_used UNUSED,
135                                  int i_attempt)
136 {
137         if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
138                 // I ain't gonna wait for you forever!
139                 C_LOGE("RDB: Database busy for too long.");
140                 return 0;
141         }
142         C_LOGW("RDB: Database busy, waiting");
143         sleep(RDB_TIME_BETWEEN_ATTEMPTS);
144         return 1;
145 }
146
147
148 int open_rdb_connection(sqlite3 **p_db)
149 {
150         RDB_LOG_ENTRY;
151
152         char *p_err_msg;
153
154         // Open connection:
155         int ret = sqlite3_open_v2(RDB_PATH,
156                                   p_db,
157                                   RDB_READWRITE_FLAG,
158                                   NULL);
159         if(*p_db == NULL) {
160                 C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
161                 return PC_ERR_DB_CONNECTION;
162         }
163         if(ret != SQLITE_OK) {
164                 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
165                 return PC_ERR_DB_CONNECTION;
166         }
167
168         //Register busy handler:
169         if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
170                 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
171                 return PC_ERR_DB_CONNECTION;
172         }
173
174         // Load extensions:
175         if(sqlite3_enable_load_extension(*p_db, 1)) {
176                 C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
177                 return PC_ERR_DB_CONNECTION;
178         }
179
180         if(sqlite3_load_extension(*p_db,
181                                   "/usr/lib/librules-db-sql-udf.so", 0,
182                                   &p_err_msg) != SQLITE_OK) {
183
184                 C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
185                        p_err_msg);
186                 sqlite3_free(p_err_msg);
187                 return PC_ERR_DB_CONNECTION;
188         }
189         sqlite3_free(p_err_msg);
190
191
192         // Create the temporary tables:
193         if(sqlite3_exec(*p_db,
194                         "PRAGMA foreign_keys = ON;                                 \
195                         CREATE TEMPORARY TABLE history_smack_rule(                 \
196                                 subject VARCHAR NOT NULL,                          \
197                                 object  VARCHAR NOT NULL,                          \
198                                 access  INTEGER NOT NULL);                         \
199                                                                                    \
200                         CREATE TEMPORARY TABLE modified_label(                     \
201                                 name VARCHAR NOT NULL,                             \
202                                 UNIQUE(name));                                     \
203                                                                                    \
204                         CREATE TEMPORARY TABLE all_smack_binary_rule_modified(     \
205                                 subject VARCHAR NOT NULL,                          \
206                                 object  VARCHAR NOT NULL,                          \
207                                 access  INTEGER NOT NULL);                         \
208                                                                                    \
209                         CREATE TEMPORARY TABLE history_smack_rule_modified(        \
210                                 subject VARCHAR NOT NULL,                          \
211                                 object  VARCHAR NOT NULL,                          \
212                                 access  INTEGER NOT NULL);                         \
213                                                                                    \
214                         CREATE TEMPORARY VIEW modified_smack_rules AS              \
215                         SELECT  subject, object,                                   \
216                                 access_to_str(access_add) AS access_add,           \
217                                 access_to_str(access_del) AS access_del            \
218                         FROM    (                                                  \
219                                 SELECT     subject, object,                        \
220                                            s1.access & ~s2.access AS access_add,   \
221                                            s2.access & ~s1.access AS access_del    \
222                                 FROM       all_smack_binary_rule_modified AS s1    \
223                                 INNER JOIN history_smack_rule_modified AS s2       \
224                                            USING (subject, object)                 \
225                                 WHERE      s1.access != s2.access                  \
226                                 UNION                                              \
227                                 SELECT     subject, object,                        \
228                                            s1.access AS access_add,                \
229                                            0 AS access_del                         \
230                                 FROM       all_smack_binary_rule_modified s1       \
231                                 LEFT JOIN  history_smack_rule_modified s2          \
232                                            USING (subject, object)                 \
233                                 WHERE      s2.subject IS NULL AND                  \
234                                            s2.object  IS NULL                      \
235                                 UNION                                              \
236                                 SELECT     subject, object,                        \
237                                            0 AS access_add,                        \
238                                            s1.access AS access_del                 \
239                                 FROM       history_smack_rule_modified s1          \
240                                 LEFT JOIN  all_smack_binary_rule_modified s2       \
241                                            USING (subject, object)                 \
242                                 WHERE      s2.subject IS NULL AND                  \
243                                            s2.object  IS NULL                      \
244                                 )                                                  \
245                         ORDER BY subject, object ASC;",
246                         0, 0, 0) != SQLITE_OK) {
247                 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
248                 return PC_ERR_DB_OPERATION;
249         }
250
251         return PC_OPERATION_SUCCESS;
252 }
253
254
255 int prepare_stmt(sqlite3 *p_db,
256                  sqlite3_stmt **pp_stmt,
257                  const char *const s_sql,
258                  ...)
259 {
260         int ret = PC_ERR_DB_QUERY_PREP;
261         char *s_query = NULL;
262         va_list args;
263         va_start(args, s_sql);
264
265         s_query = sqlite3_vmprintf(s_sql, args);
266
267         if(s_query == NULL) {
268                 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
269                 ret = PC_ERR_DB_QUERY_PREP;
270                 goto finish;
271         }
272
273         if(sqlite3_prepare_v2(p_db,
274                               s_query,
275                               strlen(s_query) + 1,
276                               pp_stmt,
277                               NULL)) {
278                 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
279                 ret = PC_ERR_DB_QUERY_PREP;
280                 goto finish;
281         }
282
283         if(*pp_stmt == NULL) {
284                 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
285                 ret = PC_ERR_DB_QUERY_PREP;
286                 goto finish;
287         }
288
289         ret = PC_OPERATION_SUCCESS;
290
291 finish:
292         va_end(args);
293         sqlite3_free(s_query);
294         return ret;
295 }
296
297
298 int check_app_label_internal(sqlite3 *p_db,
299                              const char *const s_label_name)
300 {
301         RDB_LOG_ENTRY_PARAM("%s", s_label_name);
302
303         int ret = PC_ERR_DB_OPERATION;
304         sqlite3_stmt *p_stmt = NULL;
305
306         ret = prepare_stmt(p_db, &p_stmt,
307                            "SELECT COUNT(application_view.name) \
308                            FROM application_view                \
309                            WHERE application_view.name=%Q       \
310                            LIMIT 1",
311                            s_label_name);
312         if(ret != PC_OPERATION_SUCCESS) goto finish;
313
314         ret = sqlite3_step(p_stmt);
315         if(ret == SQLITE_ROW) {
316                 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
317                 case 0: ret = PC_OPERATION_SUCCESS; break;
318                 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
319                 }
320
321         } else {
322                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
323                 ret = PC_ERR_DB_QUERY_STEP;
324         }
325 finish:
326         if(sqlite3_finalize(p_stmt) < 0)
327                 C_LOGE("RDB: Error during finalizing statement: %s",
328                        sqlite3_errmsg(p_db));
329         return ret;
330 }
331
332
333 int check_label_internal(sqlite3 *p_db,
334                          const char *const s_label_name)
335 {
336         RDB_LOG_ENTRY_PARAM("%s", s_label_name);
337
338         int ret = PC_ERR_DB_OPERATION;
339         sqlite3_stmt *p_stmt = NULL;
340
341         ret = prepare_stmt(p_db, &p_stmt,
342                            "SELECT COUNT(label.name) \
343                            FROM label WHERE name=%Q LIMIT 1",
344                            s_label_name);
345
346         if(ret != PC_OPERATION_SUCCESS) goto finish;
347
348         ret = sqlite3_step(p_stmt);
349         if(ret == SQLITE_ROW) {
350                 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
351                 case 0: ret = PC_OPERATION_SUCCESS; break;
352                 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
353                 }
354
355         } else {
356                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
357                 ret = PC_ERR_DB_QUERY_STEP;
358         }
359
360 finish:
361         if(sqlite3_finalize(p_stmt) < 0)
362                 C_LOGE("RDB: Error during finalizing statement: %s",
363                        sqlite3_errmsg(p_db));
364         return ret;
365 }
366
367
368 int add_app_internal(sqlite3 *p_db,
369                      const char *const s_label_name)
370 {
371         RDB_LOG_ENTRY_PARAM("%s", s_label_name);
372
373         int ret = PC_ERR_DB_OPERATION;
374         sqlite3_stmt *p_stmt = NULL;
375
376         ret = prepare_stmt(p_db, &p_stmt,
377                            "INSERT into application_view(name) VALUES(%Q)",
378                            s_label_name);
379         if(ret != PC_OPERATION_SUCCESS) goto finish;
380
381         ret = step_and_convert_returned_value(p_stmt);
382 finish:
383         if(sqlite3_finalize(p_stmt) < 0)
384                 C_LOGE("RDB: Error during finalizing statement: %s",
385                        sqlite3_errmsg(p_db));
386         return ret;
387 }
388
389
390 int remove_app_internal(sqlite3 *p_db,
391                         const char *const s_label_name)
392 {
393         RDB_LOG_ENTRY_PARAM("%s", s_label_name);
394
395         int ret = PC_ERR_DB_OPERATION;
396         sqlite3_stmt *p_stmt = NULL;
397
398         ret = prepare_stmt(p_db, &p_stmt,
399                            "DELETE FROM application_view \
400                              WHERE application_view.name=%Q",
401                            s_label_name);
402
403         if(ret != PC_OPERATION_SUCCESS) goto finish;
404
405         ret = step_and_convert_returned_value(p_stmt);
406 finish:
407         if(sqlite3_finalize(p_stmt) < 0)
408                 C_LOGE("RDB: Error during finalizing statement: %s",
409                        sqlite3_errmsg(p_db));
410         return ret;
411 }
412
413
414 int add_path_internal(sqlite3 *p_db,
415                       const char *const s_owner_label_name,
416                       const char *const s_path_label_name,
417                       const char *const s_path,
418                       const char *const s_access,
419                       const char *const s_type)
420 {
421         RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
422                             s_owner_label_name, s_path_label_name,
423                             s_path, s_access, s_type);
424
425         int ret = PC_ERR_DB_OPERATION;
426         sqlite3_stmt *p_stmt = NULL;
427
428         ret = prepare_stmt(p_db, &p_stmt,
429                            "INSERT INTO path_view(owner_app_label_name, \
430                                                   path,                 \
431                                                   path_label_name,      \
432                                                   access,               \
433                                                   path_type_name)       \
434                              VALUES(%Q, %Q, %Q,  %Q, %Q);",
435                            s_owner_label_name, s_path,
436                            s_path_label_name, s_access, s_type);
437         if(ret != PC_OPERATION_SUCCESS) goto finish;
438
439         ret = step_and_convert_returned_value(p_stmt);
440 finish:
441         if(sqlite3_finalize(p_stmt) < 0)
442                 C_LOGE("RDB: Error during finalizing statement: %s",
443                        sqlite3_errmsg(p_db));
444         return ret;
445 }
446
447
448 int check_permission_internal(sqlite3 *p_db,
449                               const char *const s_permission_name,
450                               const char *const s_permission_type_name)
451 {
452         RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
453
454         int ret = PC_ERR_DB_OPERATION;
455         sqlite3_stmt *p_stmt = NULL;
456
457         ret = prepare_stmt(p_db, &p_stmt,
458                            "SELECT COUNT(SELECT permission_view.permission_id \
459                                          FROM   permission_view               \
460                                          WHERE  name=%Q AND                   \
461                                                 type_name=%Q                  \
462                                          LIMIT 1)",
463                            s_permission_name, s_permission_type_name);
464
465         if(ret != PC_OPERATION_SUCCESS) goto finish;
466
467         ret = sqlite3_step(p_stmt);
468         if(ret == SQLITE_ROW) {
469                 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
470                 case 0: ret = PC_OPERATION_SUCCESS; break;  // No such permission
471                 case 1: ret = PC_PERMISSION_EXISTS; break;  // Permission exists
472                 }
473
474         } else {
475                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
476                 ret = PC_ERR_DB_QUERY_STEP;
477         }
478
479 finish:
480         if(sqlite3_finalize(p_stmt) < 0)
481                 C_LOGE("RDB: Error during finalizing statement: %s",
482                        sqlite3_errmsg(p_db));
483         return ret;
484 }
485
486
487 int add_permission_internal(sqlite3 *p_db,
488                             const char *const s_permission_name,
489                             const char *const s_permission_type_name)
490 {
491         RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
492
493         int ret = PC_ERR_DB_OPERATION;
494         sqlite3_stmt *p_stmt = NULL;
495
496         ret = prepare_stmt(p_db, &p_stmt,
497                            "INSERT INTO permission_view(name, type_name) \
498                            VALUES (%Q,%Q)",
499                            s_permission_name, s_permission_type_name);
500
501         if(ret != PC_OPERATION_SUCCESS) goto finish;
502
503         ret = step_and_convert_returned_value(p_stmt);
504 finish:
505         if(sqlite3_finalize(p_stmt) < 0)
506                 C_LOGE("RDB: Error during finalizing statement: %s",
507                        sqlite3_errmsg(p_db));
508         return ret;
509 }
510
511
512 int get_permission_id_internal(sqlite3 *p_db,
513                                const char *const s_permission_name,
514                                const char *const s_permission_type_name,
515                                sqlite3_int64 *p_permission_id)
516 {
517         RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
518
519         int ret = PC_ERR_DB_OPERATION;
520         sqlite3_stmt *p_stmt = NULL;
521
522         ret = prepare_stmt(p_db, &p_stmt,
523                            "SELECT permission_view.permission_id  \
524                             FROM   permission_view                \
525                             WHERE  permission_view.name = %Q AND  \
526                                    permission_view.type_name = %Q \
527                             LIMIT  1",
528                            s_permission_name, s_permission_type_name);
529         if(ret != PC_OPERATION_SUCCESS) goto finish;
530
531         ret = sqlite3_step(p_stmt);
532         if(ret == SQLITE_ROW) {
533                 ret = PC_OPERATION_SUCCESS;
534                 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
535         } else if(ret == SQLITE_DONE) {
536                 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
537                 ret = PC_ERR_DB_OPERATION;
538
539         } else {
540                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
541                 ret = PC_ERR_DB_QUERY_STEP;
542         }
543
544 finish:
545         if(sqlite3_finalize(p_stmt) < 0)
546                 C_LOGE("RDB: Error during finalizing statement: %s",
547                        sqlite3_errmsg(p_db));
548
549         return ret;
550 }
551
552
553 int parse_rule(const char *const s_rule,
554                char s_subject[],
555                char s_object[],
556                char s_access[])
557 {
558         int ret = PC_OPERATION_SUCCESS;
559         char *tmp_s_rule = NULL;
560         const char *tmp_s_subject = NULL;
561         const char *tmp_s_object = NULL;
562         const char *tmp_s_access = NULL;
563         char *saveptr = NULL;
564
565         // Parse subject, object and access:
566         tmp_s_rule = strdup(s_rule);
567         tmp_s_subject = strtok_r(tmp_s_rule, " \t\n", &saveptr);
568         tmp_s_object = strtok_r(NULL, " \t\n", &saveptr);
569         tmp_s_access = strtok_r(NULL, " \t\n", &saveptr);
570
571         // Check rule validity:
572         if(tmp_s_subject == NULL ||
573             tmp_s_object == NULL ||
574             tmp_s_access == NULL ||
575             strtok_r(NULL, " \t\n", &saveptr) != NULL) {
576                 C_LOGE("RDB: Incorrect rule format: %s", s_rule);
577                 ret = PC_ERR_INVALID_PARAM;
578                 goto finish;
579         }
580
581         // Copy rules
582         strcpy(s_subject, tmp_s_subject);
583         strcpy(s_object, tmp_s_object);
584         strcpy(s_access, tmp_s_access);
585 finish:
586         if(tmp_s_rule) free(tmp_s_rule);
587         return ret;
588 }
589
590
591 int add_permission_rules_internal(sqlite3 *p_db,
592                                   sqlite3_int64 permission_id,
593                                   const char *const *const pp_smack_rules)
594 {
595         RDB_LOG_ENTRY;
596
597         int i;
598         int ret = PC_OPERATION_SUCCESS;
599         sqlite3_stmt *p_stmt = NULL;
600         char s_subject[SMACK_LABEL_LEN + 1];
601         char s_object[SMACK_LABEL_LEN + 1];
602         char s_access[ACC_LEN + 1];
603
604         // Prepare statement.
605         const char *s_query = "INSERT INTO \
606                 permission_label_rule_view(permission_id,access,label_name,is_reverse) \
607                 VALUES(?,?,?,?)";
608         if(sqlite3_prepare_v2(p_db,
609                               s_query,
610                               strlen(s_query) + 1,
611                               &p_stmt,
612                               NULL)) {
613                 C_LOGE("RDB: Error during preparing statement: %s",
614                        sqlite3_errmsg(p_db));
615                 ret = PC_ERR_DB_QUERY_PREP;
616                 goto finish;
617         }
618
619         for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
620                 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
621
622                 // Ignore empty lines
623                 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
624                         continue;
625
626                 ret = parse_rule(pp_smack_rules[i], s_subject, s_object, s_access);
627                 if(ret != PC_OPERATION_SUCCESS) goto finish;
628
629                 // Bind values to the statement and run it:
630                 sqlite3_bind_int(p_stmt, 1, permission_id);
631                 sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0);
632                 if(!strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE)) {
633                         // Not reversed
634                         sqlite3_bind_text(p_stmt, 3, s_object, RDB_AUTO_DETERM_SIZE, 0);
635                         sqlite3_bind_int(p_stmt, 4, 0);
636
637                 } else if(!strcmp(s_object, SMACK_APP_LABEL_TEMPLATE)) {
638                         sqlite3_bind_text(p_stmt, 3, s_subject, RDB_AUTO_DETERM_SIZE, 0);
639                         sqlite3_bind_int(p_stmt, 4, 1);
640
641                 } else {
642                         C_LOGE("RDB: Incorrect rule format: %s", pp_smack_rules[i]);
643                         ret = PC_ERR_INVALID_PARAM;
644                         goto finish;
645                 }
646
647                 // Perform the insert
648                 ret = step_and_convert_returned_value(p_stmt);
649                 if(ret != PC_OPERATION_SUCCESS) goto finish;
650
651                 // Reset and unbind statement:
652                 if(sqlite3_reset(p_stmt) != SQLITE_OK) {
653                         C_LOGE("RDB: Error reseting statement: %s",
654                                sqlite3_errmsg(p_db));
655                         ret = PC_ERR_DB_QUERY_STEP;
656                         goto finish;
657                 }
658                 if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
659                         C_LOGE("RDB: Error reseting statement: %s",
660                                sqlite3_errmsg(p_db));
661                         ret = PC_ERR_DB_QUERY_STEP;
662                         goto finish;
663                 }
664         }
665
666 finish:
667         if(sqlite3_finalize(p_stmt) < 0)
668                 C_LOGE("RDB: Error during finalizing statement: %s",
669                        sqlite3_errmsg(p_db));
670         return ret;
671 }
672
673
674 int get_app_id_internal(sqlite3 *p_db,
675                         int *pi_app_id,
676                         const char *const s_app_label_name)
677 {
678         RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
679
680         int ret = PC_ERR_DB_OPERATION;
681         sqlite3_stmt *p_stmt = NULL;
682
683         ret = prepare_stmt(p_db, &p_stmt,
684                            "SELECT application_view.app_id \
685                              FROM application_view \
686                              WHERE application_view.name = %Q",
687                            s_app_label_name);
688
689         if(ret != PC_OPERATION_SUCCESS) goto finish;
690
691         ret = sqlite3_step(p_stmt);
692         if(ret == SQLITE_ROW) {
693                 ret = PC_OPERATION_SUCCESS;
694                 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
695
696         } else if(ret == SQLITE_DONE) {
697                 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
698                 ret = PC_ERR_DB_OPERATION;
699
700         } else {
701                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
702                 ret = PC_ERR_DB_QUERY_STEP;
703         }
704
705 finish:
706         if(sqlite3_finalize(p_stmt) < 0)
707                 C_LOGE("RDB: Error during finalizing statement: %s",
708                        sqlite3_errmsg(p_db));
709         return ret;
710 }
711
712
713 int add_app_permission_internal(sqlite3 *p_db,
714                                 int i_app_id,
715                                 const char *const s_permission_name,
716                                 const char *const s_permission_type_name,
717                                 const bool b_is_volatile_new,
718                                 const bool b_is_enabled_new)
719 {
720         RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
721                             s_permission_name, s_permission_type_name,
722                             b_is_volatile_new, b_is_enabled_new);
723
724
725         int ret = PC_ERR_DB_OPERATION;
726         sqlite3_stmt *p_stmt = NULL;
727
728         ret = prepare_stmt(p_db, &p_stmt,
729                            "INSERT INTO                                  \
730                             app_permission_view(app_id, name, type_name, \
731                             is_volatile, is_enabled)                     \
732                             VALUES(%d,%Q,%Q,%d,%d)",
733                            i_app_id, s_permission_name, s_permission_type_name,
734                            (int)b_is_volatile_new, (int)b_is_enabled_new);
735
736         if(ret != PC_OPERATION_SUCCESS) goto finish;
737
738         ret = step_and_convert_returned_value(p_stmt);
739 finish:
740         if(sqlite3_finalize(p_stmt) < 0)
741                 C_LOGE("RDB: Error during finalizing statement: %s",
742                        sqlite3_errmsg(p_db));
743         return ret;
744 }
745
746
747 int switch_app_permission_internal(sqlite3 *p_db,
748                                    const int i_app_id,
749                                    const char *const s_permission_name,
750                                    const char *const s_permission_type_name,
751                                    const bool b_is_enabled_new)
752 {
753         RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
754                             s_permission_name, s_permission_type_name,
755                             b_is_enabled_new);
756
757         int ret = PC_ERR_DB_OPERATION;
758         sqlite3_stmt *p_stmt = NULL;
759
760         ret = prepare_stmt(p_db, &p_stmt,
761                            "UPDATE app_permission_view \
762                             SET    is_enabled=%d       \
763                             WHERE  app_id = %d  AND    \
764                                    name =%Q AND        \
765                                    type_name=%Q",
766                            b_is_enabled_new, i_app_id,
767                            s_permission_name, s_permission_type_name);
768
769         if(ret != PC_OPERATION_SUCCESS) goto finish;
770         ret = step_and_convert_returned_value(p_stmt);
771 finish:
772         if(sqlite3_finalize(p_stmt) < 0)
773                 C_LOGE("RDB: Error during finalizing statement: %s",
774                        sqlite3_errmsg(p_db));
775         return ret;
776 }
777
778
779 int update_app_permission_internal(sqlite3 *p_db,
780                                    const int i_app_id,
781                                    const int i_permission_id,
782                                    const bool b_is_volatile_new,
783                                    const bool b_is_enabled_new)
784 {
785         RDB_LOG_ENTRY_PARAM("%d %d %d %d",
786                             i_app_id, i_permission_id,
787                             b_is_volatile_new, b_is_enabled_new);
788
789         int ret = PC_ERR_DB_OPERATION;
790         sqlite3_stmt *p_stmt = NULL;
791
792         ret = prepare_stmt(p_db, &p_stmt,
793                            "UPDATE app_permission \
794                              SET is_volatile = %d, is_enabled=%d \
795                              WHERE app_id = %d AND permission_id = %d",
796                            b_is_volatile_new, b_is_enabled_new,
797                            i_app_id, i_permission_id);
798
799         if(ret != PC_OPERATION_SUCCESS) goto finish;
800         ret = step_and_convert_returned_value(p_stmt);
801 finish:
802         if(sqlite3_finalize(p_stmt) < 0)
803                 C_LOGE("RDB: Error during finalizing statement: %s",
804                        sqlite3_errmsg(p_db));
805         return ret;
806 }
807
808
809 int change_app_permission_internal(sqlite3 *p_db,
810                                    int i_app_id,
811                                    const char *const s_permission_name,
812                                    const char *const s_permission_type_name,
813                                    int i_is_volatile_new,
814                                    int i_is_enabled_new)
815 {
816         RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
817                             s_permission_name, s_permission_type_name,
818                             i_is_volatile_new, i_is_enabled_new);
819
820         int ret = PC_ERR_DB_OPERATION;
821         sqlite3_stmt *p_stmt = NULL;
822         int i_is_volatile_old, i_is_enabled_old, i_permission_id;
823
824         ret = prepare_stmt(p_db, &p_stmt,
825                            "SELECT is_volatile, is_enabled, permission_id      \
826                              FROM    app_permission_list_view                   \
827                              WHERE   app_id = %d AND                            \
828                              permission_name=%Q AND                             \
829                              permission_type_name=%Q LIMIT 1",
830                            i_app_id, s_permission_name, s_permission_type_name);
831         if(ret != PC_OPERATION_SUCCESS) goto finish;
832
833         ret = sqlite3_step(p_stmt);
834         if(ret == SQLITE_ROW) {
835                 // Phi, I already have this permission...
836                 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
837                 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
838
839                 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
840                         // Confucius say, No man can down-cast volatility.
841                         C_LOGE("RDB: Down-casting volatility is forbidden.");
842                         ret = PC_ERR_DB_PERM_FORBIDDEN;
843                         goto finish;
844                 }
845
846                 if(i_is_volatile_old == i_is_volatile_new &&
847                     i_is_enabled_old == i_is_enabled_new) {
848                         // There is no change. Nice.
849                         C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
850                         ret = PC_OPERATION_SUCCESS;
851                         goto finish;
852                 }
853
854                 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
855
856                 // Finalize statement
857                 if(sqlite3_finalize(p_stmt) < 0)
858                         C_LOGE("RDB: Error during finalizing statement: %s",
859                                sqlite3_errmsg(p_db));
860                 p_stmt = NULL;
861
862                 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
863                 ret = update_app_permission_internal(p_db,
864                                                      i_app_id,
865                                                      i_permission_id,
866                                                      i_is_volatile_new,
867                                                      i_is_enabled_new);
868
869         } else if(ret == SQLITE_DONE) {
870                 // Wow! A brand new permission! Omnomnom...
871
872                 if(sqlite3_finalize(p_stmt) < 0)
873                         C_LOGE("RDB: Error during finalizing statement: %s",
874                                sqlite3_errmsg(p_db));
875                 p_stmt = NULL;
876
877                 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
878                 ret = add_app_permission_internal(p_db,
879                                                   i_app_id,
880                                                   s_permission_name,
881                                                   s_permission_type_name,
882                                                   i_is_volatile_new,
883                                                   i_is_enabled_new);
884         } else {
885                 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
886                 ret = PC_ERR_DB_QUERY_STEP;
887         }
888
889 finish:
890         if(p_stmt && sqlite3_finalize(p_stmt) < 0)
891                 C_LOGE("RDB: Error during finalizing statement: %s",
892                        sqlite3_errmsg(p_db));
893         return ret;
894 }
895
896
897 int revoke_app_permissions_internal(sqlite3 *p_db,
898                                     const char *const s_app_label_name)
899 {
900         RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
901
902         int ret = PC_ERR_DB_OPERATION;
903         sqlite3_stmt *p_stmt = NULL;
904
905         ret = prepare_stmt(p_db, &p_stmt,
906                            "DELETE FROM app_permission_view \
907                             WHERE app_permission_view.app_name=%Q;",
908                            s_app_label_name);
909
910         if(ret != PC_OPERATION_SUCCESS) goto finish;
911
912         ret = step_and_convert_returned_value(p_stmt);
913 finish:
914         if(sqlite3_finalize(p_stmt) < 0)
915                 C_LOGE("RDB: Error during finalizing statement: %s",
916                        sqlite3_errmsg(p_db));
917         return ret;
918 }
919
920
921 int reset_app_permissions_internal(sqlite3 *p_db,
922                                    const char *const s_app_label_name)
923 {
924         RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
925
926         int ret = PC_ERR_DB_OPERATION;
927         sqlite3_stmt *p_stmt = NULL;
928
929         ret = prepare_stmt(p_db, &p_stmt,
930                            "DELETE FROM app_permission_volatile_view \
931                              WHERE app_permission_volatile_view.app_name=%Q;",
932                            s_app_label_name);
933
934         if(ret != PC_OPERATION_SUCCESS) goto finish;
935
936         ret = step_and_convert_returned_value(p_stmt);
937 finish:
938         if(sqlite3_finalize(p_stmt) < 0)
939                 C_LOGE("RDB: Error during finalizing statement: %s",
940                        sqlite3_errmsg(p_db));
941         return ret;
942 }
943
944
945 int save_smack_rules(sqlite3 *p_db)
946 {
947         RDB_LOG_ENTRY;
948
949         if(sqlite3_exec(p_db,
950                         "DELETE FROM history_smack_rule;                     \
951                                                                              \
952                         INSERT INTO history_smack_rule                       \
953                         SELECT subject, object, access                       \
954                         FROM all_smack_binary_rules;                         \
955                                                                              \
956                         CREATE INDEX history_smack_rule_subject_object_index \
957                         ON history_smack_rule(subject, object);",
958                         0, 0, 0) != SQLITE_OK) {
959                 C_LOGE("RDB: Error during saving history table: %s",
960                        sqlite3_errmsg(p_db));
961                 return PC_ERR_DB_OPERATION;
962         }
963
964         return PC_OPERATION_SUCCESS;
965 }
966
967
968 int update_rules_in_db(sqlite3 *p_db)
969 {
970         RDB_LOG_ENTRY;
971
972         // All rules generated by the present state of the database
973         if(sqlite3_exec(p_db,
974                         "DELETE FROM all_smack_binary_rules;        \
975                                                                     \
976                         INSERT INTO all_smack_binary_rules          \
977                         SELECT subject, object, access, is_volatile \
978                         FROM all_smack_binary_rules_view;           \
979                                                                     \
980                         DELETE FROM all_smack_binary_rule_modified; \
981                                                                     \
982                         INSERT INTO all_smack_binary_rule_modified  \
983                         SELECT subject, object, access              \
984                         FROM   all_smack_binary_rules,              \
985                                modified_label                       \
986                         WHERE  subject IN modified_label OR         \
987                                object IN modified_label;            \
988                                                                     \
989                         DELETE FROM history_smack_rule_modified;    \
990                                                                     \
991                         INSERT INTO history_smack_rule_modified     \
992                         SELECT subject, object, access              \
993                         FROM   history_smack_rule,                  \
994                                modified_label                       \
995                         WHERE  subject IN modified_label OR         \
996                                object IN modified_label;            \
997                         ",
998                         0, 0, 0) != SQLITE_OK) {
999                 C_LOGE("RDB: Error during updating rules: %s",
1000                        sqlite3_errmsg(p_db));
1001                 return PC_ERR_DB_OPERATION;
1002         }
1003         return PC_OPERATION_SUCCESS;
1004 }
1005
1006 int update_smack_rules(sqlite3 *p_db)
1007 {
1008         RDB_LOG_ENTRY;
1009
1010         int ret = PC_OPERATION_SUCCESS;
1011         sqlite3_stmt *p_stmt = NULL;
1012         const unsigned char *s_subject    = NULL;
1013         const unsigned char *s_object     = NULL;
1014         const unsigned char *s_access_add = NULL;
1015         const unsigned char *s_access_del = NULL;
1016         struct smack_accesses *smack = NULL;
1017
1018         if(smack_accesses_new(&smack)) {
1019                 C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
1020                 ret = PC_ERR_MEM_OPERATION;
1021                 goto finish;
1022         }
1023
1024         ret = prepare_stmt(p_db, &p_stmt,
1025                            "SELECT * from modified_smack_rules;");
1026         if(ret != PC_OPERATION_SUCCESS) goto finish;
1027
1028         while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
1029                 s_subject    = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
1030                 s_object     = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
1031                 s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
1032                 s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
1033
1034                 C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
1035                        s_subject, s_object, s_access_add, s_access_del);
1036
1037                 if(smack_accesses_add_modify(smack,
1038                                              (const char *) s_subject,
1039                                              (const char *) s_object,
1040                                              (const char *) s_access_add,
1041                                              (const char *) s_access_del)) {
1042                         C_LOGE("RDB: Error during updating smack rules: %s",
1043                                sqlite3_errmsg(p_db));
1044                         ret = PC_ERR_INVALID_OPERATION;
1045                         goto finish;
1046                 }
1047         }
1048         if(ret == SQLITE_DONE) {
1049                 ret = PC_OPERATION_SUCCESS;
1050         } else {
1051                 C_LOGE("RDB: Error during updating smack rules [%d]: %s",
1052                        ret, sqlite3_errmsg(p_db));
1053                 ret = PC_ERR_DB_OPERATION;
1054         }
1055
1056         if(smack_accesses_apply(smack)) {
1057                 C_LOGE("RDB: Error in smack_accesses_apply");
1058                 ret = PC_ERR_INVALID_OPERATION;
1059         }
1060
1061 finish:
1062         if(sqlite3_finalize(p_stmt) < 0)
1063                 C_LOGE("RDB: Error during finalizing statement: %s",
1064                        sqlite3_errmsg(p_db));
1065
1066         smack_accesses_free(smack);
1067         return ret;
1068 }