OSDN Git Service

Fix building issues with pie-x86
[android-x86/external-koush-Superuser.git] / Superuser / jni / su / db.c
index fad5371..dd47197 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** Copyright 2010, Adam Shanks (@ChainsDD)
+** Copyright 2013, Koushik Dutta (@koush)
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 #include <stdlib.h>
 #include <stdio.h>
 #include <limits.h>
+#include <sqlite3.h>
+#include <time.h>
 
 #include "su.h"
 
-int database_check(struct su_context *ctx)
-{
-    FILE *fp;
-    char filename[PATH_MAX];
-    char allow[7];
-    int last = 0;
-    int from_uid = ctx->from.uid;
-    
-    if (ctx->user.owner_mode) {
-        from_uid = from_uid % 100000;
-    }
+struct callback_data_t {
+    struct su_context *ctx;
+    policy_t policy;
+};
 
-    snprintf(filename, sizeof(filename),
-                "%s/%u-%u", ctx->user.store_path, from_uid, ctx->to.uid);
-    if ((fp = fopen(filename, "r"))) {
-        LOGD("Found file %s", filename);
-        
-        while (fgets(allow, sizeof(allow), fp)) {
-            last = strlen(allow) - 1;
-            if (last >= 0)
-                   allow[last] = 0;
-               
-            char cmd[ARG_MAX];
-            fgets(cmd, sizeof(cmd), fp);
-            /* skip trailing '\n' */
-            last = strlen(cmd) - 1;
-            if (last >= 0)
-                cmd[last] = 0;
+static int database_callback(void *v, int argc, char **argv, char **azColName){
+    struct callback_data_t *data = (struct callback_data_t *)v;
+    int command_match = 0;
+    policy_t policy = DENY;
+    int i;
+    time_t until = 0;
+    for(i = 0; i < argc; i++) {
+        if (strcmp(azColName[i], "policy") == 0) {
+            if (argv[i] == NULL) {
+                policy = DENY;
+            }
+            if (strcmp(argv[i], "allow") == 0) {
+                policy = ALLOW;
+            }
+            else if (strcmp(argv[i], "interactive") == 0) {
+                policy = INTERACTIVE;
+            }
+            else {
+                policy = DENY;
+            }
+        }
+        else if (strcmp(azColName[i], "command") == 0) {
+            // null or empty command means to match all commands (whitelist all from uid)
+            command_match = argv[i] == NULL || strlen(argv[i]) == 0 || strcmp(argv[i], get_command(&(data->ctx->to))) == 0;
+        }
+        else if (strcmp(azColName[i], "until") == 0) {
+            if (argv[i] != NULL) {
+                until = atoi(argv[i]);
+            }
+        }
+    }
 
-            LOGD("Comparing '%s' to '%s'", cmd, get_command(&ctx->to));
-            if (strcmp(cmd, get_command(&ctx->to)) == 0)
-                break;
-            else if (strcmp(cmd, "any") == 0) {
-                ctx->to.all = 1;
-                break;
+    // check for command match
+    if (command_match) {
+        // also make sure this policy has not expired
+        if (until == 0 || until > time(NULL)) {
+            if (policy == DENY) {
+                data->policy = DENY;
+                return -1;
             }
-            else
-                strcpy(allow, "prompt");
+
+            data->policy = ALLOW;
+            // even though we allow, continue, so we can see if there's another policy
+            // that denies...
         }
-        fclose(fp);
-    } else if ((fp = fopen(ctx->user.store_default, "r"))) {
-        LOGD("Using default file %s", ctx->user.store_default);
-        fgets(allow, sizeof(allow), fp);
-        last = strlen(allow) - 1;
-        if (last >=0)
-            allow[last] = 0;
-        
-        fclose(fp);
     }
+    
+    return 0;
+}
 
-    if (strcmp(allow, "allow") == 0) {
-        return ALLOW;
-    } else if (strcmp(allow, "deny") == 0) {
+policy_t database_check(struct su_context *ctx) {
+    sqlite3 *db = NULL;
+    
+    char query[512];
+    snprintf(query, sizeof(query), "select policy, until, command from uid_policy where uid=%d", ctx->from.uid);
+    int ret = sqlite3_open_v2(ctx->user.database_path, &db, SQLITE_OPEN_READONLY, NULL);
+    if (ret) {
+        LOGE("sqlite3 open %s failure: %d", ctx->user.database_path, ret);
+        sqlite3_close(db);
+        return INTERACTIVE;
+    }
+    
+    char *err = NULL;
+    struct callback_data_t data;
+    data.ctx = ctx;
+    data.policy = INTERACTIVE;
+    ret = sqlite3_exec(db, query, database_callback, &data, &err);
+    sqlite3_close(db);
+    if (err != NULL) {
+        LOGE("sqlite3_exec: %s", err);
         return DENY;
-    } else {
-        if (ctx->user.userid != 0 && ctx->user.owner_mode) {
-            return DENY;
-        } else {
-            return INTERACTIVE;
-        }
     }
+
+    return data.policy;
 }