1/* 2 Unix SMB/CIFS implementation. 3 Username handling 4 Copyright (C) Andrew Tridgell 1992-1998 5 Copyright (C) Jeremy Allison 1997-2001. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22 23/* internal functions */ 24static struct passwd *uname_string_combinations(char *s, TALLOC_CTX *mem_ctx, 25 struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *), 26 int N); 27static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, int offset, 28 struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *), 29 int N); 30 31/**************************************************************************** 32 Get a users home directory. 33****************************************************************************/ 34 35char *get_user_home_dir(TALLOC_CTX *mem_ctx, const char *user) 36{ 37 struct passwd *pass; 38 char *result; 39 40 /* Ensure the user exists. */ 41 42 pass = Get_Pwnam_alloc(mem_ctx, user); 43 44 if (!pass) 45 return(NULL); 46 47 /* Return home directory from struct passwd. */ 48 49 result = talloc_move(mem_ctx, &pass->pw_dir); 50 51 TALLOC_FREE(pass); 52 return result; 53} 54 55/**************************************************************************** 56 * A wrapper for sys_getpwnam(). The following variations are tried: 57 * - as transmitted 58 * - in all lower case if this differs from transmitted 59 * - in all upper case if this differs from transmitted 60 * - using lp_usernamelevel() for permutations. 61****************************************************************************/ 62 63static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx, 64 const char *user, char *user2) 65{ 66 struct passwd *ret = NULL; 67 68 if (!user2 || !(*user2)) 69 return(NULL); 70 71 if (!user || !(*user)) 72 return(NULL); 73 74 /* Try in all lower case first as this is the most 75 common case on UNIX systems */ 76 strlower_m(user2); 77 DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2)); 78 ret = getpwnam_alloc(mem_ctx, user2); 79 if(ret) 80 goto done; 81 82 /* Try as given, if username wasn't originally lowercase */ 83 if(strcmp(user, user2) != 0) { 84 DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n", 85 user)); 86 ret = getpwnam_alloc(mem_ctx, user); 87 if(ret) 88 goto done; 89 } 90 91 /* Try as uppercase, if username wasn't originally uppercase */ 92 strupper_m(user2); 93 if(strcmp(user, user2) != 0) { 94 DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n", 95 user2)); 96 ret = getpwnam_alloc(mem_ctx, user2); 97 if(ret) 98 goto done; 99 } 100 101 /* Try all combinations up to usernamelevel */ 102 strlower_m(user2); 103 DEBUG(5,("Checking combinations of %d uppercase letters in %s\n", 104 lp_usernamelevel(), user2)); 105 ret = uname_string_combinations(user2, mem_ctx, getpwnam_alloc, 106 lp_usernamelevel()); 107 108done: 109 DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ? 110 "did":"didn't", user)); 111 112 return ret; 113} 114 115/**************************************************************************** 116 Get_Pwnam wrapper without modification. 117 NOTE: This with NOT modify 'user'! 118 This will return an allocated structure 119****************************************************************************/ 120 121struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user) 122{ 123 fstring user2; 124 struct passwd *ret; 125 126 if ( *user == '\0' ) { 127 DEBUG(10,("Get_Pwnam: empty username!\n")); 128 return NULL; 129 } 130 131 fstrcpy(user2, user); 132 133 DEBUG(5,("Finding user %s\n", user)); 134 135 ret = Get_Pwnam_internals(mem_ctx, user, user2); 136 137 return ret; 138} 139 140/* The functions below have been taken from password.c and slightly modified */ 141/**************************************************************************** 142 Apply a function to upper/lower case combinations 143 of a string and return true if one of them returns true. 144 Try all combinations with N uppercase letters. 145 offset is the first char to try and change (start with 0) 146 it assumes the string starts lowercased 147****************************************************************************/ 148 149static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, 150 int offset, 151 struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *), 152 int N) 153{ 154 ssize_t len = (ssize_t)strlen(s); 155 int i; 156 struct passwd *ret; 157 158 if (N <= 0 || offset >= len) 159 return(fn(mem_ctx, s)); 160 161 for (i=offset;i<(len-(N-1));i++) { 162 char c = s[i]; 163 if (!islower_ascii((int)c)) 164 continue; 165 s[i] = toupper_ascii(c); 166 ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1); 167 if(ret) 168 return(ret); 169 s[i] = c; 170 } 171 return(NULL); 172} 173 174/**************************************************************************** 175 Apply a function to upper/lower case combinations 176 of a string and return true if one of them returns true. 177 Try all combinations with up to N uppercase letters. 178 offset is the first char to try and change (start with 0) 179 it assumes the string starts lowercased 180****************************************************************************/ 181 182static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx, 183 struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *), 184 int N) 185{ 186 int n; 187 struct passwd *ret; 188 189 for (n=1;n<=N;n++) { 190 ret = uname_string_combinations2(s,mem_ctx,0,fn,n); 191 if(ret) 192 return(ret); 193 } 194 return(NULL); 195} 196 197