Code indentation.
[midnight-commander.git] / src / vfs / smbfs / helpers / lib / username.c
blobdcdcc9004c25aaa3ef187be97a52b40691a28aa0
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Username handling
6 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) 2011
9 The Free Software Foundation, Inc.
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "includes.h"
28 extern int DEBUGLEVEL;
30 /* internal functions */
31 static struct passwd *uname_string_combinations (char *s, struct passwd *(*fn) (const char *),
32 int N);
33 static struct passwd *uname_string_combinations2 (char *s, int offset,
34 struct passwd *(*fn) (const char *), int N);
36 /****************************************************************************
37 get a users home directory.
38 ****************************************************************************/
39 const char *
40 get_home_dir (char *user)
42 struct passwd *pass;
44 pass = Get_Pwnam (user);
46 if (!pass)
47 return (NULL);
48 return (pass->pw_dir);
52 #if 0 /* Fix possible buffer overflow in sscanf(unixname,"%s",user) if uncomment */
53 /*******************************************************************
54 map a username from a dos name to a unix name by looking in the username
55 map. Note that this modifies the name in place.
56 This is the main function that should be called *once* on
57 any incoming or new username - in order to canonicalize the name.
58 This is being done to de-couple the case conversions from the user mapping
59 function. Previously, the map_username was being called
60 every time Get_Pwnam was called.
61 Returns True if username was changed, false otherwise.
62 ********************************************************************/
63 BOOL
64 map_username (const char *user)
66 static BOOL initialised = False;
67 static fstring last_from, last_to;
68 FILE *f;
69 char *mapfile = lp_username_map ();
70 char *s;
71 pstring buf;
72 BOOL mapped_user = False;
74 if (!*user)
75 return False;
77 if (!*mapfile)
78 return False;
80 if (!initialised)
82 *last_from = *last_to = 0;
83 initialised = True;
86 if (strequal (user, last_to))
87 return False;
89 if (strequal (user, last_from))
91 DEBUG (3, ("Mapped user %s to %s\n", user, last_to));
92 fstrcpy (user, last_to);
93 return True;
96 f = sys_fopen (mapfile, "r");
97 if (!f)
99 DEBUG (0, ("can't open username map %s\n", mapfile));
100 return False;
103 DEBUG (4, ("Scanning username map %s\n", mapfile));
105 while ((s = fgets_slash (buf, sizeof (buf), f)) != NULL)
107 char *unixname = s;
108 char *dosname = strchr (unixname, '=');
109 BOOL return_if_mapped = False;
111 if (!dosname)
112 continue;
114 *dosname++ = 0;
116 while (isspace (*unixname))
117 unixname++;
118 if ('!' == *unixname)
120 return_if_mapped = True;
121 unixname++;
122 while (*unixname && isspace (*unixname))
123 unixname++;
126 if (!*unixname || strchr ("#;", *unixname))
127 continue;
130 int l = strlen (unixname);
131 while (l && isspace (unixname[l - 1]))
133 unixname[l - 1] = 0;
134 l--;
138 if (strchr (dosname, '*') || user_in_list (user, dosname))
140 DEBUG (3, ("Mapped user %s to %s\n", user, unixname));
141 mapped_user = True;
142 fstrcpy (last_from, user);
143 sscanf (unixname, "%s", user);
144 fstrcpy (last_to, user);
145 if (return_if_mapped)
147 fclose (f);
148 return True;
153 fclose (f);
156 * Setup the last_from and last_to as an optimization so
157 * that we don't scan the file again for the same user.
159 fstrcpy (last_from, user);
160 fstrcpy (last_to, user);
162 return mapped_user;
164 #endif /* 0 */
166 /****************************************************************************
167 Get_Pwnam wrapper
168 ****************************************************************************/
169 static struct passwd *
170 _Get_Pwnam (const char *s)
172 struct passwd *ret;
174 ret = getpwnam (s);
175 if (ret)
177 #ifdef HAVE_GETPWANAM
178 struct passwd_adjunct *pwret;
179 pwret = getpwanam (s);
180 if (pwret)
182 free (ret->pw_passwd);
183 ret->pw_passwd = pwret->pwa_passwd;
185 #endif
189 return (ret);
193 /****************************************************************************
194 a wrapper for getpwnam() that tries with all lower and all upper case
195 if the initial name fails. Also tried with first letter capitalised
196 ****************************************************************************/
197 struct passwd *
198 Get_Pwnam (const char *a_user)
200 fstring user;
201 int last_char;
202 int usernamelevel = lp_usernamelevel ();
204 struct passwd *ret;
206 if (!a_user || !(*a_user))
207 return (NULL);
209 StrnCpy (user, a_user, sizeof (user) - 1);
211 ret = _Get_Pwnam (user);
212 if (ret)
213 return (ret);
215 strlower (user);
216 ret = _Get_Pwnam (user);
217 if (ret)
218 return (ret);
220 strupper (user);
221 ret = _Get_Pwnam (user);
222 if (ret)
223 return (ret);
225 /* try with first letter capitalised */
226 if (strlen (user) > 1)
227 strlower (user + 1);
228 ret = _Get_Pwnam (user);
229 if (ret)
230 return (ret);
232 /* try with last letter capitalised */
233 strlower (user);
234 last_char = strlen (user) - 1;
235 user[last_char] = toupper (user[last_char]);
236 ret = _Get_Pwnam (user);
237 if (ret)
238 return (ret);
240 /* try all combinations up to usernamelevel */
241 strlower (user);
242 ret = uname_string_combinations (user, _Get_Pwnam, usernamelevel);
243 if (ret)
244 return (ret);
246 return (NULL);
249 #if 0
250 /****************************************************************************
251 check if a user is in a netgroup user list
252 ****************************************************************************/
253 static BOOL
254 user_in_netgroup_list (char *user, char *ngname)
256 #ifdef HAVE_NETGROUP
257 static char *mydomain = NULL;
258 if (mydomain == NULL)
259 yp_get_default_domain (&mydomain);
261 if (mydomain == NULL)
263 DEBUG (5, ("Unable to get default yp domain\n"));
265 else
267 DEBUG (5, ("looking for user %s of domain %s in netgroup %s\n", user, mydomain, ngname));
268 DEBUG (5, ("innetgr is %s\n", innetgr (ngname, NULL, user, mydomain) ? "TRUE" : "FALSE"));
270 if (innetgr (ngname, NULL, user, mydomain))
271 return (True);
273 #endif /* HAVE_NETGROUP */
274 return False;
277 /****************************************************************************
278 check if a user is in a UNIX user list
279 ****************************************************************************/
280 static BOOL
281 user_in_group_list (char *user, char *gname)
283 #ifdef HAVE_GETGRNAM
284 struct group *gptr;
285 char **member;
286 struct passwd *pass = Get_Pwnam (user, False);
288 if (pass)
290 gptr = getgrgid (pass->pw_gid);
291 if (gptr && strequal (gptr->gr_name, gname))
292 return (True);
295 gptr = (struct group *) getgrnam (gname);
297 if (gptr)
299 member = gptr->gr_mem;
300 while (member && *member)
302 if (strequal (*member, user))
303 return (True);
304 member++;
307 #endif /* HAVE_GETGRNAM */
308 return False;
311 /****************************************************************************
312 check if a user is in a user list - can check combinations of UNIX
313 and netgroup lists.
314 ****************************************************************************/
315 BOOL
316 user_in_list (char *user, char *list)
318 pstring tok;
319 char *p = list;
321 while (next_token (&p, tok, LIST_SEP, sizeof (tok)))
324 * Check raw username.
326 if (strequal (user, tok))
327 return (True);
330 * Now check to see if any combination
331 * of UNIX and netgroups has been specified.
334 if (*tok == '@')
337 * Old behaviour. Check netgroup list
338 * followed by UNIX list.
340 if (user_in_netgroup_list (user, &tok[1]))
341 return True;
342 if (user_in_group_list (user, &tok[1]))
343 return True;
345 else if (*tok == '+')
347 if (tok[1] == '&')
350 * Search UNIX list followed by netgroup.
352 if (user_in_group_list (user, &tok[2]))
353 return True;
354 if (user_in_netgroup_list (user, &tok[2]))
355 return True;
357 else
360 * Just search UNIX list.
362 if (user_in_group_list (user, &tok[1]))
363 return True;
366 else if (*tok == '&')
368 if (tok[1] == '&')
371 * Search netgroup list followed by UNIX list.
373 if (user_in_netgroup_list (user, &tok[2]))
374 return True;
375 if (user_in_group_list (user, &tok[2]))
376 return True;
378 else
381 * Just search netgroup list.
383 if (user_in_netgroup_list (user, &tok[1]))
384 return True;
388 return (False);
390 #endif /* 0 */
392 /* The functions below have been taken from password.c and slightly modified */
393 /****************************************************************************
394 apply a function to upper/lower case combinations
395 of a string and return true if one of them returns true.
396 try all combinations with N uppercase letters.
397 offset is the first char to try and change (start with 0)
398 it assumes the string starts lowercased
399 ****************************************************************************/
400 static struct passwd *
401 uname_string_combinations2 (char *s, int offset, struct passwd *(*fn) (const char *), int N)
403 int len = strlen (s);
404 int i;
405 struct passwd *ret;
407 #ifdef PASSWORD_LENGTH
408 len = MIN (len, PASSWORD_LENGTH);
409 #endif
411 if (N <= 0 || offset >= len)
412 return (fn (s));
415 for (i = offset; i < (len - (N - 1)); i++)
418 char c = s[i];
419 if (!islower (c))
420 continue;
421 s[i] = toupper (c);
422 ret = uname_string_combinations2 (s, i + 1, fn, N - 1);
423 if (ret)
424 return (ret);
425 s[i] = c;
427 return (NULL);
430 /****************************************************************************
431 apply a function to upper/lower case combinations
432 of a string and return true if one of them returns true.
433 try all combinations with up to N uppercase letters.
434 offset is the first char to try and change (start with 0)
435 it assumes the string starts lowercased
436 ****************************************************************************/
437 static struct passwd *
438 uname_string_combinations (char *s, struct passwd *(*fn) (const char *), int N)
440 int n;
441 struct passwd *ret;
443 for (n = 1; n <= N; n++)
445 ret = uname_string_combinations2 (s, 0, fn, n);
446 if (ret)
447 return (ret);
449 return (NULL);