Add define guards around FSTRING_LEN.
[Samba/vl.git] / source3 / lib / username.c
blob21eed9f5fc3cd2c5e7be5fe0e0846e155d34eb46
1 /*
2 Unix SMB/CIFS implementation.
3 Username handling
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/>.
21 #include "includes.h"
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 *),
26 int N);
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 *),
29 int N);
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);
43 if (!pass)
44 return(NULL);
45 /* Return home directory from struct passwd. */
47 return(pass->pw_dir);
50 /****************************************************************************
51 * A wrapper for sys_getpwnam(). The following variations are tried:
52 * - as transmitted
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))
66 return(NULL);
68 if (!user || !(*user))
69 return(NULL);
71 /* Try in all lower case first as this is the most
72 common case on UNIX systems */
73 strlower_m(user2);
74 DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2));
75 ret = getpwnam_alloc(mem_ctx, user2);
76 if(ret)
77 goto done;
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",
82 user));
83 ret = getpwnam_alloc(mem_ctx, user);
84 if(ret)
85 goto done;
88 /* Try as uppercase, if username wasn't originally uppercase */
89 strupper_m(user2);
90 if(strcmp(user, user2) != 0) {
91 DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n",
92 user2));
93 ret = getpwnam_alloc(mem_ctx, user2);
94 if(ret)
95 goto done;
98 /* Try all combinations up to usernamelevel */
99 strlower_m(user2);
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,
103 lp_usernamelevel());
105 done:
106 DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ?
107 "did":"didn't", user));
109 return ret;
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)
120 fstring user2;
121 struct passwd *ret;
123 if ( *user == '\0' ) {
124 DEBUG(10,("Get_Pwnam: empty username!\n"));
125 return NULL;
128 fstrcpy(user2, user);
130 DEBUG(5,("Finding user %s\n", user));
132 ret = Get_Pwnam_internals(mem_ctx, user, user2);
134 return ret;
137 /****************************************************************************
138 Get_Pwnam wrapper without modification.
139 NOTE: This with NOT modify 'user'!
140 ****************************************************************************/
142 struct passwd *Get_Pwnam(const char *user)
144 struct passwd *ret;
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
153 uses an old struct.
155 This is better than useing the wrong data in security
156 critical operations.
158 The real fix is to make the callers free the returned
159 malloc'ed data.
162 if (Get_Pwnam_ret) {
163 TALLOC_FREE(Get_Pwnam_ret);
166 Get_Pwnam_ret = ret;
168 return 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,
181 int offset,
182 struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *),
183 int N)
185 ssize_t len = (ssize_t)strlen(s);
186 int i;
187 struct passwd *ret;
189 if (N <= 0 || offset >= len)
190 return(fn(mem_ctx, s));
192 for (i=offset;i<(len-(N-1));i++) {
193 char c = s[i];
194 if (!islower_ascii((int)c))
195 continue;
196 s[i] = toupper_ascii(c);
197 ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1);
198 if(ret)
199 return(ret);
200 s[i] = c;
202 return(NULL);
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 *),
215 int N)
217 int n;
218 struct passwd *ret;
220 for (n=1;n<=N;n++) {
221 ret = uname_string_combinations2(s,mem_ctx,0,fn,n);
222 if(ret)
223 return(ret);
225 return(NULL);