2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1997-2001.
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.
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.
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/>.
23 /* internal functions */
24 static struct passwd *uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
25 struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
27 static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, int offset,
28 struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
31 /****************************************************************************
32 Get a users home directory.
33 ****************************************************************************/
35 char *get_user_home_dir(const char *user)
37 static struct passwd *pass;
39 /* Ensure the user exists. */
41 pass = Get_Pwnam(user);
45 /* Return home directory from struct passwd. */
50 /****************************************************************************
51 * A wrapper for sys_getpwnam(). The following variations are tried:
53 * - in all lower case if this differs from transmitted
54 * - in all upper case if this differs from transmitted
55 * - using lp_usernamelevel() for permutations.
56 ****************************************************************************/
58 static struct passwd *Get_Pwnam_ret = NULL;
60 static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx,
61 const char *user, char *user2)
63 struct passwd *ret = NULL;
65 if (!user2 || !(*user2))
68 if (!user || !(*user))
71 /* Try in all lower case first as this is the most
72 common case on UNIX systems */
74 DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2));
75 ret = getpwnam_alloc(mem_ctx, user2);
79 /* Try as given, if username wasn't originally lowercase */
80 if(strcmp(user, user2) != 0) {
81 DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n",
83 ret = getpwnam_alloc(mem_ctx, user);
88 /* Try as uppercase, if username wasn't originally uppercase */
90 if(strcmp(user, user2) != 0) {
91 DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n",
93 ret = getpwnam_alloc(mem_ctx, user2);
98 /* Try all combinations up to usernamelevel */
100 DEBUG(5,("Checking combinations of %d uppercase letters in %s\n",
101 lp_usernamelevel(), user2));
102 ret = uname_string_combinations(user2, mem_ctx, getpwnam_alloc,
106 DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ?
107 "did":"didn't", user));
112 /****************************************************************************
113 Get_Pwnam wrapper without modification.
114 NOTE: This with NOT modify 'user'!
115 This will return an allocated structure
116 ****************************************************************************/
118 struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user)
123 if ( *user == '\0' ) {
124 DEBUG(10,("Get_Pwnam: empty username!\n"));
128 fstrcpy(user2, user);
130 DEBUG(5,("Finding user %s\n", user));
132 ret = Get_Pwnam_internals(mem_ctx, user, user2);
137 /****************************************************************************
138 Get_Pwnam wrapper without modification.
139 NOTE: This with NOT modify 'user'!
140 ****************************************************************************/
142 struct passwd *Get_Pwnam(const char *user)
146 ret = Get_Pwnam_alloc(NULL, user);
148 /* This call used to just return the 'passwd' static buffer.
149 This could then have accidental reuse implications, so
150 we now malloc a copy, and free it in the next use.
152 This should cause the (ab)user to segfault if it
155 This is better than useing the wrong data in security
158 The real fix is to make the callers free the returned
163 TALLOC_FREE(Get_Pwnam_ret);
171 /* The functions below have been taken from password.c and slightly modified */
172 /****************************************************************************
173 Apply a function to upper/lower case combinations
174 of a string and return true if one of them returns true.
175 Try all combinations with N uppercase letters.
176 offset is the first char to try and change (start with 0)
177 it assumes the string starts lowercased
178 ****************************************************************************/
180 static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx,
182 struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *),
185 ssize_t len = (ssize_t)strlen(s);
189 if (N <= 0 || offset >= len)
190 return(fn(mem_ctx, s));
192 for (i=offset;i<(len-(N-1));i++) {
194 if (!islower_ascii((int)c))
196 s[i] = toupper_ascii(c);
197 ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1);
205 /****************************************************************************
206 Apply a function to upper/lower case combinations
207 of a string and return true if one of them returns true.
208 Try all combinations with up to N uppercase letters.
209 offset is the first char to try and change (start with 0)
210 it assumes the string starts lowercased
211 ****************************************************************************/
213 static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
214 struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *),
221 ret = uname_string_combinations2(s,mem_ctx,0,fn,n);