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