1/* 2 Unix SMB/CIFS implementation. 3 4 Safe versions of getpw* calls 5 6 Copyright (C) Andrew Bartlett 2002 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*/ 22 23#include "includes.h" 24 25struct passwd *tcopy_passwd(TALLOC_CTX *mem_ctx, const struct passwd *from) 26{ 27 struct passwd *ret = TALLOC_P(mem_ctx, struct passwd); 28 if (!ret) { 29 return NULL; 30 } 31 ret->pw_name = talloc_strdup(ret, from->pw_name); 32 ret->pw_passwd = talloc_strdup(ret, from->pw_passwd); 33 ret->pw_uid = from->pw_uid; 34 ret->pw_gid = from->pw_gid; 35 ret->pw_gecos = talloc_strdup(ret, from->pw_gecos); 36 ret->pw_dir = talloc_strdup(ret, from->pw_dir); 37 ret->pw_shell = talloc_strdup(ret, from->pw_shell); 38 return ret; 39} 40 41#define PWNAMCACHE_SIZE 4 42static struct passwd **pwnam_cache = NULL; 43 44static void init_pwnam_cache(void) 45{ 46 if (pwnam_cache != NULL) 47 return; 48 49 pwnam_cache = TALLOC_ZERO_ARRAY(NULL, struct passwd *, 50 PWNAMCACHE_SIZE); 51 if (pwnam_cache == NULL) { 52 smb_panic("Could not init pwnam_cache\n"); 53 } 54 55 return; 56} 57 58void flush_pwnam_cache(void) 59{ 60 TALLOC_FREE(pwnam_cache); 61 pwnam_cache = NULL; 62 init_pwnam_cache(); 63} 64 65struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) 66{ 67 int i; 68 69 struct passwd *temp; 70 71 init_pwnam_cache(); 72 73 for (i=0; i<PWNAMCACHE_SIZE; i++) { 74 if ((pwnam_cache[i] != NULL) && 75 (strcmp(name, pwnam_cache[i]->pw_name) == 0)) { 76 DEBUG(10, ("Got %s from pwnam_cache\n", name)); 77 return (struct passwd *)talloc_reference(mem_ctx, pwnam_cache[i]); 78 } 79 } 80 81 temp = sys_getpwnam(name); 82 83 if (!temp) { 84#if 0 85 if (errno == ENOMEM) { 86 /* what now? */ 87 } 88#endif 89 return NULL; 90 } 91 92 for (i=0; i<PWNAMCACHE_SIZE; i++) { 93 if (pwnam_cache[i] == NULL) 94 break; 95 } 96 97 if (i == PWNAMCACHE_SIZE) 98 i = rand() % PWNAMCACHE_SIZE; 99 100 if (pwnam_cache[i] != NULL) { 101 TALLOC_FREE(pwnam_cache[i]); 102 } 103 104 pwnam_cache[i] = tcopy_passwd(pwnam_cache, temp); 105 if (pwnam_cache[i]!= NULL && mem_ctx != NULL) { 106 return (struct passwd *)talloc_reference(mem_ctx, pwnam_cache[i]); 107 } 108 109 return tcopy_passwd(NULL, pwnam_cache[i]); 110} 111 112struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) 113{ 114 struct passwd *temp; 115 116 temp = sys_getpwuid(uid); 117 118 if (!temp) { 119#if 0 120 if (errno == ENOMEM) { 121 /* what now? */ 122 } 123#endif 124 return NULL; 125 } 126 127 return tcopy_passwd(mem_ctx, temp); 128} 129