• 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 
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