1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28 #include <grp.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <pwd.h>
32 #include <netdb.h>
33 #include <mntent.h>
34 #include <private/android_filesystem_config.h>
35 #include <pthread.h>
36 #include <stdlib.h>
37 #include <errno.h>
38 #include <ctype.h>
39
40 /** Thread-specific state for the stubs functions
41 **/
42
43 pthread_once_t the_once = PTHREAD_ONCE_INIT;
44 pthread_key_t the_key;
45
46 typedef struct {
47 struct passwd passwd;
48 struct group group;
49 char* group_members[2];
50 char app_name_buffer[32];
51 char group_name_buffer[32];
52 } stubs_state_t;
53
54 static void
stubs_state_free(void * _s)55 stubs_state_free( void* _s )
56 {
57 stubs_state_t* s = _s;
58 free(s);
59 }
60
61 static stubs_state_t*
stubs_state_alloc(void)62 stubs_state_alloc( void )
63 {
64 stubs_state_t* s = calloc(1, sizeof *s);
65
66 if (s != NULL) {
67 s->group.gr_mem = s->group_members;
68 }
69 return s;
70 }
71
__stubs_key_init(void)72 static void __stubs_key_init(void)
73 {
74 pthread_key_create( &the_key, stubs_state_free );
75 }
76
77 static stubs_state_t*
__stubs_state(void)78 __stubs_state(void)
79 {
80 stubs_state_t* s;
81
82 pthread_once(&the_once, __stubs_key_init);
83 s = pthread_getspecific(the_key);
84 if (s == NULL) {
85 s = stubs_state_alloc();
86 if (s == NULL) {
87 errno = ENOMEM; /* just in case */
88 } else {
89 if ( pthread_setspecific(the_key, s) != 0 ) {
90 stubs_state_free(s);
91 errno = ENOMEM;
92 s = NULL;
93 }
94 }
95 }
96 return s;
97 }
98
99 static struct passwd*
android_iinfo_to_passwd(struct passwd * pw,struct android_id_info * iinfo)100 android_iinfo_to_passwd( struct passwd *pw,
101 struct android_id_info *iinfo )
102 {
103 pw->pw_name = (char*)iinfo->name;
104 pw->pw_uid = iinfo->aid;
105 pw->pw_gid = iinfo->aid;
106 pw->pw_dir = "/";
107 pw->pw_shell = "/system/bin/sh";
108 return pw;
109 }
110
111 static struct group*
android_iinfo_to_group(struct group * gr,struct android_id_info * iinfo)112 android_iinfo_to_group( struct group *gr,
113 struct android_id_info *iinfo )
114 {
115 gr->gr_name = (char*) iinfo->name;
116 gr->gr_gid = iinfo->aid;
117 gr->gr_mem[0] = gr->gr_name;
118 gr->gr_mem[1] = NULL;
119 return gr;
120 }
121
122 static struct passwd *
android_id_to_passwd(struct passwd * pw,unsigned id)123 android_id_to_passwd( struct passwd *pw, unsigned id)
124 {
125 struct android_id_info *iinfo = android_ids;
126 unsigned n;
127 for (n = 0; n < android_id_count; n++) {
128 if (iinfo[n].aid == id) {
129 return android_iinfo_to_passwd(pw, iinfo + n);
130 }
131 }
132 return NULL;
133 }
134
135 static struct passwd*
android_name_to_passwd(struct passwd * pw,const char * name)136 android_name_to_passwd(struct passwd *pw, const char *name)
137 {
138 struct android_id_info *iinfo = android_ids;
139 unsigned n;
140 for (n = 0; n < android_id_count; n++) {
141 if (!strcmp(iinfo[n].name, name)) {
142 return android_iinfo_to_passwd(pw, iinfo + n);
143 }
144 }
145 return NULL;
146 }
147
148 static struct group*
android_id_to_group(struct group * gr,unsigned id)149 android_id_to_group( struct group *gr, unsigned id )
150 {
151 struct android_id_info *iinfo = android_ids;
152 unsigned n;
153 for (n = 0; n < android_id_count; n++) {
154 if (iinfo[n].aid == id) {
155 return android_iinfo_to_group(gr, iinfo + n);
156 }
157 }
158 return NULL;
159 }
160
161 static struct group*
android_name_to_group(struct group * gr,const char * name)162 android_name_to_group( struct group *gr, const char *name )
163 {
164 struct android_id_info *iinfo = android_ids;
165 unsigned n;
166 for (n = 0; n < android_id_count; n++) {
167 if (!strcmp(iinfo[n].name, name)) {
168 return android_iinfo_to_group(gr, iinfo + n);
169 }
170 }
171 return NULL;
172 }
173
174 /* translate a user/group name like app_1234 into the
175 * corresponding user/group id (AID_APP + 1234)
176 * returns 0 and sets errno to ENOENT in case of error
177 */
178 static unsigned
app_id_from_name(const char * name)179 app_id_from_name( const char* name )
180 {
181 unsigned long id;
182 char* end;
183
184 if (memcmp(name, "app_", 4) != 0 || !isdigit(name[4]))
185 goto FAIL;
186
187 id = strtoul(name+4, &end, 10);
188 if (id == 0 || *end != '\0')
189 goto FAIL;
190
191 id += AID_APP;
192
193 /* check for overflow and that the value can be
194 * stored in our 32-bit uid_t/gid_t */
195 if (id < AID_APP || (unsigned)id != id)
196 goto FAIL;
197
198 return (unsigned)id;
199
200 FAIL:
201 errno = ENOENT;
202 return 0;
203 }
204
205 /* translate a uid into the corresponding app_<uid>
206 * passwd structure (sets errno to ENOENT on failure)
207 */
208 static struct passwd*
app_id_to_passwd(uid_t uid,stubs_state_t * state)209 app_id_to_passwd(uid_t uid, stubs_state_t* state)
210 {
211 struct passwd* pw = &state->passwd;
212
213 if (uid < AID_APP) {
214 errno = ENOENT;
215 return NULL;
216 }
217
218 snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
219 "app_%u", uid - AID_APP );
220
221 pw->pw_name = state->app_name_buffer;
222 pw->pw_dir = "/data";
223 pw->pw_shell = "/system/bin/sh";
224 pw->pw_uid = uid;
225 pw->pw_gid = uid;
226
227 return pw;
228 }
229
230 /* translate a gid into the corresponding app_<gid>
231 * group structure (sets errno to ENOENT on failure)
232 */
233 static struct group*
app_id_to_group(gid_t gid,stubs_state_t * state)234 app_id_to_group(gid_t gid, stubs_state_t* state)
235 {
236 struct group* gr = &state->group;
237
238 if (gid < AID_APP) {
239 errno = ENOENT;
240 return NULL;
241 }
242
243 snprintf(state->group_name_buffer, sizeof state->group_name_buffer,
244 "app_%u", gid - AID_APP);
245
246 gr->gr_name = state->group_name_buffer;
247 gr->gr_gid = gid;
248 gr->gr_mem[0] = gr->gr_name;
249 gr->gr_mem[1] = NULL;
250
251 return gr;
252 }
253
254
255 struct passwd*
getpwuid(uid_t uid)256 getpwuid(uid_t uid)
257 {
258 stubs_state_t* state = __stubs_state();
259 struct passwd* pw;
260
261 if (state == NULL)
262 return NULL;
263
264 pw = &state->passwd;
265
266 if ( android_id_to_passwd(pw, uid) != NULL )
267 return pw;
268
269 return app_id_to_passwd(uid, state);
270 }
271
272 struct passwd*
getpwnam(const char * login)273 getpwnam(const char *login)
274 {
275 stubs_state_t* state = __stubs_state();
276
277 if (state == NULL)
278 return NULL;
279
280 if (android_name_to_passwd(&state->passwd, login) != NULL)
281 return &state->passwd;
282
283 return app_id_to_passwd( app_id_from_name(login), state );
284 }
285
286 int
getgrouplist(const char * user,gid_t group,gid_t * groups,int * ngroups)287 getgrouplist (const char *user, gid_t group,
288 gid_t *groups, int *ngroups)
289 {
290 if (*ngroups < 1) {
291 *ngroups = 1;
292 return -1;
293 }
294 groups[0] = group;
295 return (*ngroups = 1);
296 }
297
298 char*
getlogin(void)299 getlogin(void)
300 {
301 struct passwd *pw = getpwuid(getuid());
302
303 if(pw) {
304 return pw->pw_name;
305 } else {
306 return NULL;
307 }
308 }
309
310 struct group*
getgrgid(gid_t gid)311 getgrgid(gid_t gid)
312 {
313 stubs_state_t* state = __stubs_state();
314 struct group* gr;
315
316 if (state == NULL)
317 return NULL;
318
319 gr = android_id_to_group(&state->group, gid);
320 if (gr != NULL)
321 return gr;
322
323 return app_id_to_group(gid, state);
324 }
325
326 struct group*
getgrnam(const char * name)327 getgrnam(const char *name)
328 {
329 stubs_state_t* state = __stubs_state();
330 unsigned id;
331
332 if (state == NULL)
333 return NULL;
334
335 if (android_name_to_group(&state->group, name) != 0)
336 return &state->group;
337
338 return app_id_to_group( app_id_from_name(name), state );
339 }
340
341
getnetbyname(const char * name)342 struct netent* getnetbyname(const char *name)
343 {
344 fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__);
345 return NULL;
346 }
347
endpwent(void)348 void endpwent(void)
349 {
350 }
351
getmntent(FILE * f)352 struct mntent* getmntent(FILE* f)
353 {
354 fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
355 return NULL;
356 }
357
ttyname(int fd)358 char* ttyname(int fd)
359 {
360 fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
361 return NULL;
362 }
363
getnetbyaddr(uint32_t net,int type)364 struct netent *getnetbyaddr(uint32_t net, int type)
365 {
366 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
367 return NULL;
368 }
369
getprotobyname(const char * name)370 struct protoent *getprotobyname(const char *name)
371 {
372 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
373 return NULL;
374 }
375
getprotobynumber(int proto)376 struct protoent *getprotobynumber(int proto)
377 {
378 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
379 return NULL;
380 }
381