• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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