#include <stdio.h>
#include <limits.h>
#include <sqlite3.h>
+#include <time.h>
#include "su.h"
-static int database_callback(void *NotUsed, int argc, char **argv, char **azColName){
+struct callback_data_t {
+ struct su_context *ctx;
+ policy_t policy;
+};
+
+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;
- for(i=0; i<argc; i++){
- printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
+ 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]);
+ }
+ }
+ }
+
+ // 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;
+ }
+
+ data->policy = ALLOW;
+ // even though we allow, continue, so we can see if there's another policy
+ // that denies...
+ }
}
- printf("\n");
+
return 0;
}
-int database_check(struct su_context *ctx) {
+policy_t database_check(struct su_context *ctx) {
sqlite3 *db = NULL;
char query[512];
- snprintf(query, sizeof(query), "select allow_type, until, command from access where uid=%d", ctx->from.uid);
- int ret = sqlite3_open(query, &db);
+ 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 failure");
- return 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;
+ }
- return -1;
+ return data.policy;
}