Ejemplo n.º 1
0
static void allow(char *shell, mode_t mask)
{
    struct su_initiator *from = &su_from;
    struct su_request *to = &su_to;
    char *exe = NULL;

    umask(mask);
    send_intent(&su_from, &su_to, "", 1, 1);

    if (!strcmp(shell, "")) {
        strcpy(shell , "/system/bin/sh");
    }
    exe = strrchr (shell, '/') + 1;
    setresgid(to->uid, to->uid, to->uid);
    setresuid(to->uid, to->uid, to->uid);
    LOGD("%u %s executing %u %s using shell %s : %s", from->uid, from->bin,
            to->uid, to->command, shell, exe);
    if (strcmp(to->command, DEFAULT_COMMAND)) {
        execl(shell, exe, "-c", to->command, (char*)NULL);
    } else {
        execl(shell, exe, "-", (char*)NULL);
    }
    PLOGE("exec");
    exit(EXIT_SUCCESS);
}
Ejemplo n.º 2
0
static __attribute__ ((noreturn)) void deny(const struct su_context *ctx)
{
    char *cmd = get_command(&ctx->to);

    send_intent(ctx, "", 0, ACTION_RESULT);
    LOGW("request rejected (%u->%u %s)", ctx->from.uid, ctx->to.uid, cmd);
    fprintf(stderr, "%s\n", strerror(EACCES));
    exit(EXIT_FAILURE);
}
Ejemplo n.º 3
0
static void deny(void)
{
    struct su_initiator *from = &su_from;
    struct su_request *to = &su_to;

    send_intent(&su_from, &su_to, "", 0, 1);
    LOGW("request rejected (%u->%u %s)", from->uid, to->uid, to->command);
    fprintf(stderr, "%s\n", strerror(EACCES));
    exit(EXIT_FAILURE);
}
Ejemplo n.º 4
0
int main (int argc, char *argv[])
{
  printf("Welcome to pinentry-android\n");
  printf("starting java activity...\n");
  send_intent();
  sleep(3);
  pid_t child_pid;
  int child_status;
//   pinentry_init ("pinentry-android");

  /* Consumes all arguments.  */
//   if (pinentry_parse_opts (argc, argv))
//     {
//       printf ("pinentry-android (pinentry) " VERSION "\n");
//       exit (EXIT_SUCCESS);
//     }

  struct sockaddr_un addr;
  int fd;

  if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    perror("socket error");
    exit(-1);
  }

  memset(&addr, 0, sizeof(addr));
  addr.sun_family = AF_UNIX;
  addr.sun_path[0] = '\0';
  strncpy( &addr.sun_path[1], SOCKET_NAME, sizeof(addr.sun_path)-1 );
  /* calculate the length of our addrlen, for some reason this isn't simply
   * sizeof(addr), TODO: learn why, i suspect it has something to do with sun_path
   * being a char[108]
   */
  int len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&addr.sun_path[1]);

  printf("connecting to Java socket server...\n");
  if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
    perror("connect error");
    exit(-1);
  }

  printf("connection succeeded\n");
  /* remember Java doesn't understand \0 terminated strings*/
  int bytes_written = write(fd, "hello!", 6);
  printf("wrote %d bytes \n", bytes_written);
  close(fd);

  child_pid = fork();
  if( child_pid < 0 ) {
    /* unsuccessful fork */
    perror("fork:");
    exit(-1);
  }
  if( child_pid == 0 ) { /* child process */
    printf("child! bye\n");
    /* TODO: we actually don't want to pass the socket here..*/
//     if (pinentry_loop2 (fd, fd))
//       exit(1);
    exit(0);
  } else { /* parent process */
    wait(&child_status);
    exit(0);
  }

  return 0;
}
Ejemplo n.º 5
0
static __attribute__ ((noreturn)) void allow(const struct su_context *ctx)
{
    char *arg0;
    int argc, err;

    umask(ctx->umask);
    send_intent(ctx, "", 1, ACTION_RESULT);

    arg0 = strrchr (ctx->to.shell, '/');
    arg0 = (arg0) ? arg0 + 1 : ctx->to.shell;
    if (ctx->to.login) {
        int s = strlen(arg0) + 2;
        char *p = malloc(s);

        if (!p)
            exit(EXIT_FAILURE);

        *p = '-';
        strcpy(p + 1, arg0);
        arg0 = p;
    }

    /*
     * Set effective uid back to root, otherwise setres[ug]id will fail
     * if ctx->to.uid isn't root.
     */
    if (seteuid(0)) {
        PLOGE("seteuid (root)");
        exit(EXIT_FAILURE);
    }

    populate_environment(ctx);

    if (setresgid(ctx->to.uid, ctx->to.uid, ctx->to.uid)) {
        PLOGE("setresgid (%u)", ctx->to.uid);
        exit(EXIT_FAILURE);
    }
    if (setresuid(ctx->to.uid, ctx->to.uid, ctx->to.uid)) {
        PLOGE("setresuid (%u)", ctx->to.uid);
        exit(EXIT_FAILURE);
    }

#define PARG(arg)									\
    (ctx->to.optind + (arg) < ctx->to.argc) ? " " : "",					\
    (ctx->to.optind + (arg) < ctx->to.argc) ? ctx->to.argv[ctx->to.optind + (arg)] : ""

    LOGD("%u %s executing %u %s using shell %s : %s%s%s%s%s%s%s%s%s%s%s%s%s%s",
            ctx->from.uid, ctx->from.bin,
            ctx->to.uid, get_command(&ctx->to), ctx->to.shell,
            arg0, PARG(0), PARG(1), PARG(2), PARG(3), PARG(4), PARG(5),
            (ctx->to.optind + 6 < ctx->to.argc) ? " ..." : "");

    argc = ctx->to.optind;
    if (ctx->to.command) {
        ctx->to.argv[--argc] = ctx->to.command;
        ctx->to.argv[--argc] = "-c";
    }
    ctx->to.argv[--argc] = arg0;
    execv(ctx->to.shell, ctx->to.argv + argc);
    err = errno;
    PLOGE("exec");
    fprintf(stderr, "Cannot execute %s: %s\n", ctx->to.shell, strerror(err));
    exit(EXIT_FAILURE);
}
Ejemplo n.º 6
0
int main(int argc, char *argv[])
{
    struct stat st;
    static int socket_serv_fd = -1;
    char buf[64], shell[PATH_MAX], *result, debuggable[PROPERTY_VALUE_MAX];
    char enabled[PROPERTY_VALUE_MAX], build_type[PROPERTY_VALUE_MAX];
    char root_settings[PROPERTY_VALUE_MAX];
    int i, dballow;
    mode_t orig_umask;

    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) {
            if (++i < argc) {
                su_to.command = argv[i];
            } else {
                usage();
            }
        } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--shell")) {
            if (++i < argc) {
                strncpy(shell, argv[i], sizeof(shell));
                shell[sizeof(shell) - 1] = 0;
            } else {
                usage();
            }
        } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
            printf("%s\n", VERSION);
            exit(EXIT_SUCCESS);
        } else if (!strcmp(argv[i], "-V")) {
            printf("%d\n", VERSION_CODE);
            exit(EXIT_SUCCESS);
        } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
            usage();
        } else if (!strcmp(argv[i], "-") || !strcmp(argv[i], "-l") ||
                !strcmp(argv[i], "--login")) {
            ++i;
            break;
        } else {
            break;
        }
    }
    if (i < argc-1) {
        usage();
    }
    if (i == argc-1) {
        struct passwd *pw;
        pw = getpwnam(argv[i]);
        if (!pw) {
            su_to.uid = atoi(argv[i]);
        } else {
            su_to.uid = pw->pw_uid;
        }
    }

    if (from_init(&su_from) < 0) {
        deny();
    }

    property_get("ro.debuggable", debuggable, "0");
    property_get(ROOT_ACCESS_PROPERTY, enabled, ROOT_ACCESS_DEFAULT);
    property_get("ro.build.type", build_type, "");
    property_get(ROOT_SETTINGS_PROPERTY, root_settings, "");

    orig_umask = umask(027);

    // Root Settings-specific behavior
    if (strcmp("1", root_settings) == 0) {
        // only allow su on debuggable builds
        if (strcmp("1", debuggable) != 0) {
            LOGE("Root access is disabled on non-debug builds");
            deny();
        }

        // enforce persist.sys.root_access on non-eng builds
        if (strcmp("eng", build_type) != 0 &&
               (atoi(enabled) & 1) != 1 ) {
            LOGE("Root access is disabled by system setting - enable it under settings -> developer options");
            deny();
        }

        // disallow su in a shell if appropriate
        if (su_from.uid == AID_SHELL && (atoi(enabled) == 1)) {
            LOGE("Root access is disabled by a system setting - enable it under settings -> developer options");
            deny();
        }
    }

    if (su_from.uid == AID_ROOT || su_from.uid == AID_SHELL)
        allow(shell, orig_umask);

    if (stat(REQUESTOR_DATA_PATH, &st) < 0) {
        PLOGE("stat");
        deny();
    }

    if (st.st_gid != st.st_uid)
    {
        LOGE("Bad uid/gid %d/%d for Superuser Requestor application",
                (int)st.st_uid, (int)st.st_gid);
        deny();
    }

    if (mkdir(REQUESTOR_CACHE_PATH, 0770) >= 0) {
        chown(REQUESTOR_CACHE_PATH, st.st_uid, st.st_gid);
    }

    setgroups(0, NULL);
    setegid(st.st_gid);
    seteuid(st.st_uid);

    LOGE("sudb - Opening database");
    db = database_init();
    if (!db) {
        LOGE("sudb - Could not open database, prompt user");
        // if the database could not be opened, we can assume we need to
        // prompt the user
        dballow = DB_INTERACTIVE;
    } else {
        LOGE("sudb - Database opened");
        dballow = database_check(db, &su_from, &su_to);
        // Close the database, we're done with it. If it stays open,
        // it will cause problems
        sqlite3_close(db);
        db = NULL;
        LOGE("sudb - Database closed");
    }

    switch (dballow) {
        case DB_DENY: deny();
        case DB_ALLOW: allow(shell, orig_umask);
        case DB_INTERACTIVE: break;
        default: deny();
    }
    
    socket_serv_fd = socket_create_temp();
    if (socket_serv_fd < 0) {
        deny();
    }

    signal(SIGHUP, cleanup_signal);
    signal(SIGPIPE, cleanup_signal);
    signal(SIGTERM, cleanup_signal);
    signal(SIGABRT, cleanup_signal);
    atexit(cleanup);

    if (send_intent(&su_from, &su_to, socket_path, -1, 0) < 0) {
        deny();
    }

    if (socket_receive_result(socket_serv_fd, buf, sizeof(buf)) < 0) {
        deny();
    }

    close(socket_serv_fd);
    socket_cleanup();

    result = buf;

    if (!strcmp(result, "DENY")) {
        deny();
    } else if (!strcmp(result, "ALLOW")) {
        allow(shell, orig_umask);
    } else {
        LOGE("unknown response from Superuser Requestor: %s", result);
        deny();
    }

    deny();
    return -1;
}