OSDN Git Service

assign user before use
[android-x86/external-koush-Superuser.git] / Superuser / jni / su / activity.c
1 /*
2 ** Copyright 2010, Adam Shanks (@ChainsDD)
3 ** Copyright 2008, Zinx Verituse (@zinxv)
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <fcntl.h>
23 #include <paths.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #include "su.h"
28
29 /* intent actions */
30 #define ACTION_REQUEST "start", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".RequestActivity"
31 #define ACTION_NOTIFY "start", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".NotifyActivity"
32 #define ACTION_RESULT "broadcast", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".SuReceiver"
33
34 #define AM_PATH "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am"
35
36 // TODO: leverage this with exec_log?
37 int silent_run(char* const args[]) {
38     set_identity(0);
39     pid_t pid;
40     pid = fork();
41     /* Parent */
42     if (pid < 0) {
43         PLOGE("fork");
44         return -1;
45     }
46     else if (pid > 0) {
47         return 0;
48     }
49     int zero = open("/dev/zero", O_RDONLY | O_CLOEXEC);
50     dup2(zero, 0);
51     int null = open("/dev/null", O_WRONLY | O_CLOEXEC);
52     dup2(null, 1);
53     dup2(null, 2);
54     setenv("CLASSPATH", "/system/framework/am.jar", 1);
55     execv(args[0], args);
56     PLOGE("exec am");
57     _exit(EXIT_FAILURE);
58     return -1;
59 }
60
61 int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
62     int needs_owner_login_prompt = 0;
63     
64     if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
65         if (0 != ctx->user.android_user_id) {
66             needs_owner_login_prompt = 1;
67         }
68         snprintf(user, user_len, "0");
69     }
70     else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
71         snprintf(user, user_len, "%d", ctx->user.android_user_id);
72     }
73     else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
74         user[0] = '\0';
75     }
76     else {
77         snprintf(user, user_len, "0");
78     }
79     
80     return needs_owner_login_prompt;
81 }
82
83 int send_result(struct su_context *ctx, policy_t policy) {
84     char binary_version[256];
85     sprintf(binary_version, "%d", VERSION_CODE);
86
87     char uid[256];
88     sprintf(uid, "%d", ctx->from.uid);
89
90     char desired_uid[256];
91     sprintf(desired_uid, "%d", ctx->to.uid);
92
93     char user[64];
94     get_owner_login_user_args(ctx, user, sizeof(user));
95
96     if (0 != ctx->user.android_user_id) {
97         char android_user_id[256];
98         sprintf(android_user_id, "%d", ctx->user.android_user_id);
99
100         char *user_result_command[] = {
101             AM_PATH,
102             ACTION_RESULT,
103             "--ei",
104             "binary_version",
105             binary_version,
106             "--es",
107             "from_name",
108             ctx->from.name,
109             "--es",
110             "desired_name",
111             ctx->to.name,
112             "--ei",
113             "uid",
114             uid,
115             "--ei",
116             "desired_uid",
117             desired_uid,
118             "--es",
119             "command",
120             get_command(&ctx->to),
121             "--es",
122             "action",
123             policy == ALLOW ? "allow" : "deny",
124             user[0] ? "--user" : NULL,
125             android_user_id,
126             NULL
127         };
128         silent_run(user_result_command);
129     }
130
131     char *result_command[] = {
132         AM_PATH,
133         ACTION_RESULT,
134         "--ei",
135         "binary_version",
136         binary_version,
137         "--es",
138         "from_name",
139         ctx->from.name,
140         "--es",
141         "desired_name",
142         ctx->to.name,
143         "--ei",
144         "uid",
145         uid,
146         "--ei",
147         "desired_uid",
148         desired_uid,
149         "--es",
150         "command",
151         get_command(&ctx->to),
152         "--es",
153         "action",
154         policy == ALLOW ? "allow" : "deny",
155         user[0] ? "--user" : NULL,
156         user,
157         NULL
158     };
159     return silent_run(result_command);
160 }
161
162 int send_request(struct su_context *ctx) {
163     // if su is operating in MULTIUSER_MODEL_OWNER,
164     // and the user requestor is not the owner,
165     // the owner needs to be notified of the request.
166     // so there will be two activities shown.
167     char user[64];
168     int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
169
170     int ret;
171     if (needs_owner_login_prompt) {
172         char uid[256];
173         sprintf(uid, "%d", ctx->from.uid);
174
175         char android_user_id[256];
176         sprintf(android_user_id, "%d", ctx->user.android_user_id);
177
178         // in multiuser mode, the owner gets the su prompt
179         char *notify_command[] = {
180             AM_PATH,
181             ACTION_NOTIFY,
182             "--ei",
183             "caller_uid",
184             uid,
185             "--user",
186             android_user_id,
187             NULL
188         };
189
190         int ret = silent_run(notify_command);
191         if (ret) {
192             return ret;
193         }
194     }
195
196     char *request_command[] = {
197         AM_PATH,
198         ACTION_REQUEST,
199         "--es",
200         "socket",
201         ctx->sock_path,
202         user[0] ? "--user" : NULL,
203         user,
204         NULL
205     };
206
207     return silent_run(request_command);
208 }