Home | History | Annotate | Download | only in bionic
      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 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 
    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 
    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
    127 stubs_state_free( void*  _s )
    128 {
    129     stubs_state_t*  s = _s;
    130     free(s);
    131 }
    132 
    133 static stubs_state_t*
    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 
    144 static void __stubs_key_init(void)
    145 {
    146     pthread_key_create( &the_key, stubs_state_free );
    147 }
    148 
    149 static stubs_state_t*
    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*
    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*
    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 *
    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*
    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*
    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*
    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
    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*
    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*
    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*
    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*
    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
    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*
    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*
    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*
    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 
    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 
    420 void endpwent(void)
    421 {
    422 }
    423 
    424 struct mntent* getmntent(FILE* f)
    425 {
    426     fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
    427     return NULL;
    428 }
    429 
    430 char* ttyname(int fd)
    431 {
    432     fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
    433     return NULL;
    434 }
    435 
    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 
    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 
    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 
    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 
    460 char* getusershell(void)
    461 {
    462     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    463     return NULL;
    464 }
    465 
    466 void setusershell(void)
    467 {
    468     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    469 }
    470 
    471 void endusershell(void)
    472 {
    473     fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    474 }
    475