source: trunk/samba/source/lib/username.c@ 77

Last change on this file since 77 was 77, checked in by Paul Smedley, 18 years ago

Update trunk to 3.2.0pre1

File size: 6.7 KB
Line 
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(const char *user)
36{
37 static struct passwd *pass;
38
39 /* Ensure the user exists. */
40
41 pass = Get_Pwnam(user);
42
43 if (!pass)
44 return(NULL);
45 /* Return home directory from struct passwd. */
46
47 return(pass->pw_dir);
48}
49
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****************************************************************************/
57
58static struct passwd *Get_Pwnam_ret = NULL;
59
60static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx,
61 const char *user, char *user2)
62{
63 struct passwd *ret = NULL;
64
65 if (!user2 || !(*user2))
66 return(NULL);
67
68 if (!user || !(*user))
69 return(NULL);
70
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;
78
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;
86 }
87
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;
96 }
97
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());
104
105done:
106 DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ?
107 "did":"didn't", user));
108
109 return ret;
110}
111
112/****************************************************************************
113 Get_Pwnam wrapper without modification.
114 NOTE: This with NOT modify 'user'!
115 This will return an allocated structure
116****************************************************************************/
117
118struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user)
119{
120 fstring user2;
121 struct passwd *ret;
122
123 if ( *user == '\0' ) {
124 DEBUG(10,("Get_Pwnam: empty username!\n"));
125 return NULL;
126 }
127
128 fstrcpy(user2, user);
129
130 DEBUG(5,("Finding user %s\n", user));
131
132 ret = Get_Pwnam_internals(mem_ctx, user, user2);
133
134 return ret;
135}
136
137/****************************************************************************
138 Get_Pwnam wrapper without modification.
139 NOTE: This with NOT modify 'user'!
140****************************************************************************/
141
142struct passwd *Get_Pwnam(const char *user)
143{
144 struct passwd *ret;
145
146 ret = Get_Pwnam_alloc(NULL, user);
147
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.
151
152 This should cause the (ab)user to segfault if it
153 uses an old struct.
154
155 This is better than useing the wrong data in security
156 critical operations.
157
158 The real fix is to make the callers free the returned
159 malloc'ed data.
160 */
161
162 if (Get_Pwnam_ret) {
163 TALLOC_FREE(Get_Pwnam_ret);
164 }
165
166 Get_Pwnam_ret = ret;
167
168 return ret;
169}
170
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****************************************************************************/
179
180static 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)
184{
185 ssize_t len = (ssize_t)strlen(s);
186 int i;
187 struct passwd *ret;
188
189 if (N <= 0 || offset >= len)
190 return(fn(mem_ctx, s));
191
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;
201 }
202 return(NULL);
203}
204
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****************************************************************************/
212
213static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
214 struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *),
215 int N)
216{
217 int n;
218 struct passwd *ret;
219
220 for (n=1;n<=N;n++) {
221 ret = uname_string_combinations2(s,mem_ctx,0,fn,n);
222 if(ret)
223 return(ret);
224 }
225 return(NULL);
226}
227
Note: See TracBrowser for help on using the repository browser.