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
do_getpw_r(int by_name,const char * name,uid_t uid,struct passwd * dst,char * buf,size_t byte_count,struct passwd ** result)40 static int do_getpw_r(int by_name, const char* name, uid_t uid,
41 struct passwd* dst, char* buf, size_t byte_count, struct passwd** result)
42 {
43 /*
44 * getpwnam_r and getpwuid_r don't modify errno, but library calls we
45 * make might.
46 */
47 int old_errno = errno;
48 int rc = 0;
49 *result = NULL;
50
51 const struct passwd* src = by_name ? getpwnam(name) : getpwuid(uid);
52
53 /*
54 * POSIX allows failure to find a match to be considered a non-error.
55 * Reporting success (0) but with *result NULL is glibc's behavior.
56 */
57 if (src == NULL) {
58 rc = (errno == ENOENT) ? 0 : errno;
59 goto failure;
60 }
61
62 /*
63 * Work out where our strings will go in 'buf', and whether we've got
64 * enough space.
65 */
66 size_t required_byte_count = 0;
67 dst->pw_name = buf;
68 required_byte_count += strlen(src->pw_name) + 1;
69 dst->pw_dir = buf + required_byte_count;
70 required_byte_count += strlen(src->pw_dir) + 1;
71 dst->pw_shell = buf + required_byte_count;
72 required_byte_count += strlen(src->pw_shell) + 1;
73 if (byte_count < required_byte_count) {
74 rc = ERANGE;
75 goto failure;
76 }
77
78 /* Copy the strings. */
79 snprintf(buf, byte_count, "%s%c%s%c%s",
80 src->pw_name, 0, src->pw_dir, 0, src->pw_shell);
81
82 /*
83 * pw_passwd is non-POSIX and unused (always NULL) in bionic.
84 * pw_gecos is non-POSIX and missing in bionic.
85 */
86 dst->pw_passwd = NULL;
87
88 /* Copy the integral fields. */
89 dst->pw_gid = src->pw_gid;
90 dst->pw_uid = src->pw_uid;
91
92 success:
93 rc = 0;
94 *result = dst;
95 failure:
96 errno = old_errno;
97 return rc;
98 }
99
getpwnam_r(const char * name,struct passwd * pwd,char * buf,size_t byte_count,struct passwd ** result)100 int getpwnam_r(const char* name, struct passwd* pwd,
101 char* buf, size_t byte_count, struct passwd** result)
102 {
103 return do_getpw_r(1, name, -1, pwd, buf, byte_count, result);
104 }
105
getpwuid_r(uid_t uid,struct passwd * pwd,char * buf,size_t byte_count,struct passwd ** result)106 int getpwuid_r(uid_t uid, struct passwd* pwd,
107 char* buf, size_t byte_count, struct passwd** result)
108 {
109 return do_getpw_r(0, NULL, uid, pwd, buf, byte_count, result);
110 }
111
112 /** Thread-specific state for the stubs functions
113 **/
114
115 static pthread_once_t the_once = PTHREAD_ONCE_INIT;
116 static pthread_key_t the_key;
117
118 typedef struct {
119 struct passwd passwd;
120 struct group group;
121 char* group_members[2];
122 char app_name_buffer[32];
123 char group_name_buffer[32];
124 } stubs_state_t;
125
126 static void
stubs_state_free(void * _s)127 stubs_state_free( void* _s )
128 {
129 stubs_state_t* s = _s;
130 free(s);
131 }
132
133 static stubs_state_t*
stubs_state_alloc(void)134 stubs_state_alloc( void )
135 {
136 stubs_state_t* s = calloc(1, sizeof *s);
137
138 if (s != NULL) {
139 s->group.gr_mem = s->group_members;
140 }
141 return s;
142 }
143
__stubs_key_init(void)144 static void __stubs_key_init(void)
145 {
146 pthread_key_create( &the_key, stubs_state_free );
147 }
148
149 static stubs_state_t*
__stubs_state(void)150 __stubs_state(void)
151 {
152 stubs_state_t* s;
153
154 pthread_once(&the_once, __stubs_key_init);
155 s = pthread_getspecific(the_key);
156 if (s == NULL) {
157 s = stubs_state_alloc();
158 if (s == NULL) {
159 errno = ENOMEM; /* just in case */
160 } else {
161 if ( pthread_setspecific(the_key, s) != 0 ) {
162 stubs_state_free(s);
163 errno = ENOMEM;
164 s = NULL;
165 }
166 }
167 }
168 return s;
169 }
170
171 static struct passwd*
android_iinfo_to_passwd(struct passwd * pw,struct android_id_info * iinfo)172 android_iinfo_to_passwd( struct passwd *pw,
173 struct android_id_info *iinfo )
174 {
175 pw->pw_name = (char*)iinfo->name;
176 pw->pw_uid = iinfo->aid;
177 pw->pw_gid = iinfo->aid;
178 pw->pw_dir = "/";
179 pw->pw_shell = "/system/bin/sh";
180 return pw;
181 }
182
183 static struct group*
android_iinfo_to_group(struct group * gr,struct android_id_info * iinfo)184 android_iinfo_to_group( struct group *gr,
185 struct android_id_info *iinfo )
186 {
187 gr->gr_name = (char*) iinfo->name;
188 gr->gr_gid = iinfo->aid;
189 gr->gr_mem[0] = gr->gr_name;
190 gr->gr_mem[1] = NULL;
191 return gr;
192 }
193
194 static struct passwd *
android_id_to_passwd(struct passwd * pw,unsigned id)195 android_id_to_passwd( struct passwd *pw, unsigned id)
196 {
197 struct android_id_info *iinfo = android_ids;
198 unsigned n;
199 for (n = 0; n < android_id_count; n++) {
200 if (iinfo[n].aid == id) {
201 return android_iinfo_to_passwd(pw, iinfo + n);
202 }
203 }
204 return NULL;
205 }
206
207 static struct passwd*
android_name_to_passwd(struct passwd * pw,const char * name)208 android_name_to_passwd(struct passwd *pw, const char *name)
209 {
210 struct android_id_info *iinfo = android_ids;
211 unsigned n;
212 for (n = 0; n < android_id_count; n++) {
213 if (!strcmp(iinfo[n].name, name)) {
214 return android_iinfo_to_passwd(pw, iinfo + n);
215 }
216 }
217 return NULL;
218 }
219
220 static struct group*
android_id_to_group(struct group * gr,unsigned id)221 android_id_to_group( struct group *gr, unsigned id )
222 {
223 struct android_id_info *iinfo = android_ids;
224 unsigned n;
225 for (n = 0; n < android_id_count; n++) {
226 if (iinfo[n].aid == id) {
227 return android_iinfo_to_group(gr, iinfo + n);
228 }
229 }
230 return NULL;
231 }
232
233 static struct group*
android_name_to_group(struct group * gr,const char * name)234 android_name_to_group( struct group *gr, const char *name )
235 {
236 struct android_id_info *iinfo = android_ids;
237 unsigned n;
238 for (n = 0; n < android_id_count; n++) {
239 if (!strcmp(iinfo[n].name, name)) {
240 return android_iinfo_to_group(gr, iinfo + n);
241 }
242 }
243 return NULL;
244 }
245
246 /* translate a user/group name like app_1234 into the
247 * corresponding user/group id (AID_APP + 1234)
248 * returns 0 and sets errno to ENOENT in case of error
249 */
250 static unsigned
app_id_from_name(const char * name)251 app_id_from_name( const char* name )
252 {
253 unsigned long id;
254 char* end;
255
256 if (memcmp(name, "app_", 4) != 0 || !isdigit(name[4]))
257 goto FAIL;
258
259 id = strtoul(name+4, &end, 10);
260 if (*end != '\0')
261 goto FAIL;
262
263 id += AID_APP;
264
265 /* check for overflow and that the value can be
266 * stored in our 32-bit uid_t/gid_t */
267 if (id < AID_APP || (unsigned)id != id)
268 goto FAIL;
269
270 return (unsigned)id;
271
272 FAIL:
273 errno = ENOENT;
274 return 0;
275 }
276
277 /* translate a uid into the corresponding app_<uid>
278 * passwd structure (sets errno to ENOENT on failure)
279 */
280 static struct passwd*
app_id_to_passwd(uid_t uid,stubs_state_t * state)281 app_id_to_passwd(uid_t uid, stubs_state_t* state)
282 {
283 struct passwd* pw = &state->passwd;
284
285 if (uid < AID_APP) {
286 errno = ENOENT;
287 return NULL;
288 }
289
290 snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
291 "app_%u", uid - AID_APP );
292
293 pw->pw_name = state->app_name_buffer;
294 pw->pw_dir = "/data";
295 pw->pw_shell = "/system/bin/sh";
296 pw->pw_uid = uid;
297 pw->pw_gid = uid;
298
299 return pw;
300 }
301
302 /* translate a gid into the corresponding app_<gid>
303 * group structure (sets errno to ENOENT on failure)
304 */
305 static struct group*
app_id_to_group(gid_t gid,stubs_state_t * state)306 app_id_to_group(gid_t gid, stubs_state_t* state)
307 {
308 struct group* gr = &state->group;
309
310 if (gid < AID_APP) {
311 errno = ENOENT;
312 return NULL;
313 }
314
315 snprintf(state->group_name_buffer, sizeof state->group_name_buffer,
316 "app_%u", gid - AID_APP);
317
318 gr->gr_name = state->group_name_buffer;
319 gr->gr_gid = gid;
320 gr->gr_mem[0] = gr->gr_name;
321 gr->gr_mem[1] = NULL;
322
323 return gr;
324 }
325
326
327 struct passwd*
getpwuid(uid_t uid)328 getpwuid(uid_t uid)
329 {
330 stubs_state_t* state = __stubs_state();
331 struct passwd* pw;
332
333 if (state == NULL)
334 return NULL;
335
336 pw = &state->passwd;
337
338 if ( android_id_to_passwd(pw, uid) != NULL )
339 return pw;
340
341 return app_id_to_passwd(uid, state);
342 }
343
344 struct passwd*
getpwnam(const char * login)345 getpwnam(const char *login)
346 {
347 stubs_state_t* state = __stubs_state();
348
349 if (state == NULL)
350 return NULL;
351
352 if (android_name_to_passwd(&state->passwd, login) != NULL)
353 return &state->passwd;
354
355 return app_id_to_passwd( app_id_from_name(login), state );
356 }
357
358 int
getgrouplist(const char * user,gid_t group,gid_t * groups,int * ngroups)359 getgrouplist (const char *user, gid_t group,
360 gid_t *groups, int *ngroups)
361 {
362 if (*ngroups < 1) {
363 *ngroups = 1;
364 return -1;
365 }
366 groups[0] = group;
367 return (*ngroups = 1);
368 }
369
370 char*
getlogin(void)371 getlogin(void)
372 {
373 struct passwd *pw = getpwuid(getuid());
374
375 if(pw) {
376 return pw->pw_name;
377 } else {
378 return NULL;
379 }
380 }
381
382 struct group*
getgrgid(gid_t gid)383 getgrgid(gid_t gid)
384 {
385 stubs_state_t* state = __stubs_state();
386 struct group* gr;
387
388 if (state == NULL)
389 return NULL;
390
391 gr = android_id_to_group(&state->group, gid);
392 if (gr != NULL)
393 return gr;
394
395 return app_id_to_group(gid, state);
396 }
397
398 struct group*
getgrnam(const char * name)399 getgrnam(const char *name)
400 {
401 stubs_state_t* state = __stubs_state();
402 unsigned id;
403
404 if (state == NULL)
405 return NULL;
406
407 if (android_name_to_group(&state->group, name) != 0)
408 return &state->group;
409
410 return app_id_to_group( app_id_from_name(name), state );
411 }
412
413
getnetbyname(const char * name)414 struct netent* getnetbyname(const char *name)
415 {
416 fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__);
417 return NULL;
418 }
419
endpwent(void)420 void endpwent(void)
421 {
422 }
423
getmntent(FILE * f)424 struct mntent* getmntent(FILE* f)
425 {
426 fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
427 return NULL;
428 }
429
ttyname(int fd)430 char* ttyname(int fd)
431 {
432 fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
433 return NULL;
434 }
435
ttyname_r(int fd,char * buf,size_t buflen)436 int ttyname_r(int fd, char *buf, size_t buflen)
437 {
438 fprintf(stderr, "FIX ME! implement ttyname_r() %s:%d\n", __FILE__, __LINE__);
439 return -ERANGE;
440 }
441
getnetbyaddr(uint32_t net,int type)442 struct netent *getnetbyaddr(uint32_t net, int type)
443 {
444 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
445 return NULL;
446 }
447
getprotobyname(const char * name)448 struct protoent *getprotobyname(const char *name)
449 {
450 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
451 return NULL;
452 }
453
getprotobynumber(int proto)454 struct protoent *getprotobynumber(int proto)
455 {
456 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
457 return NULL;
458 }
459
getusershell(void)460 char* getusershell(void)
461 {
462 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
463 return NULL;
464 }
465
setusershell(void)466 void setusershell(void)
467 {
468 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
469 }
470
endusershell(void)471 void endusershell(void)
472 {
473 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
474 }
475