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 55 stubs_state_free( void* _s ) 56 { 57 stubs_state_t* s = _s; 58 free(s); 59 } 60 61 static stubs_state_t* 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 72 static void __stubs_key_init(void) 73 { 74 pthread_key_create( &the_key, stubs_state_free ); 75 } 76 77 static stubs_state_t* 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* 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* 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 * 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* 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* 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* 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 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 (*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* 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* 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* 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* 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 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* 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* 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* 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 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 348 void endpwent(void) 349 { 350 } 351 352 struct mntent* getmntent(FILE* f) 353 { 354 fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__); 355 return NULL; 356 } 357 358 char* ttyname(int fd) 359 { 360 fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__); 361 return NULL; 362 } 363 364 int ttyname_r(int fd, char *buf, size_t buflen) 365 { 366 fprintf(stderr, "FIX ME! implement ttyname_r() %s:%d\n", __FILE__, __LINE__); 367 return -ERANGE; 368 } 369 370 struct netent *getnetbyaddr(uint32_t net, int type) 371 { 372 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); 373 return NULL; 374 } 375 376 struct protoent *getprotobyname(const char *name) 377 { 378 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); 379 return NULL; 380 } 381 382 struct protoent *getprotobynumber(int proto) 383 { 384 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); 385 return NULL; 386 } 387 388 char* getusershell(void) 389 { 390 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); 391 return NULL; 392 } 393 394 void setusershell(void) 395 { 396 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); 397 } 398 399 void endusershell(void) 400 { 401 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); 402 } 403 404