2 Unix SMB/Netbios implementation.
6 Copyright (C) Andrew Tridgell 1992-1998
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/>.
28 extern int DEBUGLEVEL
;
30 /* internal functions */
31 static struct passwd
*uname_string_combinations (char *s
, struct passwd
*(*fn
) (const char *),
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 ****************************************************************************/
40 get_home_dir (char *user
)
44 pass
= Get_Pwnam (user
);
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 ********************************************************************/
64 map_username (const char *user
)
66 static BOOL initialised
= False
;
67 static fstring last_from
, last_to
;
69 char *mapfile
= lp_username_map ();
72 BOOL mapped_user
= False
;
82 *last_from
= *last_to
= 0;
86 if (strequal (user
, last_to
))
89 if (strequal (user
, last_from
))
91 DEBUG (3, ("Mapped user %s to %s\n", user
, last_to
));
92 fstrcpy (user
, last_to
);
96 f
= sys_fopen (mapfile
, "r");
99 DEBUG (0, ("can't open username map %s\n", mapfile
));
103 DEBUG (4, ("Scanning username map %s\n", mapfile
));
105 while ((s
= fgets_slash (buf
, sizeof (buf
), f
)) != NULL
)
108 char *dosname
= strchr (unixname
, '=');
109 BOOL return_if_mapped
= False
;
116 while (isspace (*unixname
))
118 if ('!' == *unixname
)
120 return_if_mapped
= True
;
122 while (*unixname
&& isspace (*unixname
))
126 if (!*unixname
|| strchr ("#;", *unixname
))
130 int l
= strlen (unixname
);
131 while (l
&& isspace (unixname
[l
- 1]))
138 if (strchr (dosname
, '*') || user_in_list (user
, dosname
))
140 DEBUG (3, ("Mapped user %s to %s\n", user
, unixname
));
142 fstrcpy (last_from
, user
);
143 sscanf (unixname
, "%s", user
);
144 fstrcpy (last_to
, user
);
145 if (return_if_mapped
)
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
);
166 /****************************************************************************
168 ****************************************************************************/
169 static struct passwd
*
170 _Get_Pwnam (const char *s
)
177 #ifdef HAVE_GETPWANAM
178 struct passwd_adjunct
*pwret
;
179 pwret
= getpwanam (s
);
182 free (ret
->pw_passwd
);
183 ret
->pw_passwd
= pwret
->pwa_passwd
;
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 ****************************************************************************/
198 Get_Pwnam (const char *a_user
)
202 int usernamelevel
= lp_usernamelevel ();
206 if (!a_user
|| !(*a_user
))
209 StrnCpy (user
, a_user
, sizeof (user
) - 1);
211 ret
= _Get_Pwnam (user
);
216 ret
= _Get_Pwnam (user
);
221 ret
= _Get_Pwnam (user
);
225 /* try with first letter capitalised */
226 if (strlen (user
) > 1)
228 ret
= _Get_Pwnam (user
);
232 /* try with last letter capitalised */
234 last_char
= strlen (user
) - 1;
235 user
[last_char
] = toupper (user
[last_char
]);
236 ret
= _Get_Pwnam (user
);
240 /* try all combinations up to usernamelevel */
242 ret
= uname_string_combinations (user
, _Get_Pwnam
, usernamelevel
);
250 /****************************************************************************
251 check if a user is in a netgroup user list
252 ****************************************************************************/
254 user_in_netgroup_list (char *user
, char *ngname
)
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"));
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
))
273 #endif /* HAVE_NETGROUP */
277 /****************************************************************************
278 check if a user is in a UNIX user list
279 ****************************************************************************/
281 user_in_group_list (char *user
, char *gname
)
286 struct passwd
*pass
= Get_Pwnam (user
, False
);
290 gptr
= getgrgid (pass
->pw_gid
);
291 if (gptr
&& strequal (gptr
->gr_name
, gname
))
295 gptr
= (struct group
*) getgrnam (gname
);
299 member
= gptr
->gr_mem
;
300 while (member
&& *member
)
302 if (strequal (*member
, user
))
307 #endif /* HAVE_GETGRNAM */
311 /****************************************************************************
312 check if a user is in a user list - can check combinations of UNIX
314 ****************************************************************************/
316 user_in_list (char *user
, char *list
)
321 while (next_token (&p
, tok
, LIST_SEP
, sizeof (tok
)))
324 * Check raw username.
326 if (strequal (user
, tok
))
330 * Now check to see if any combination
331 * of UNIX and netgroups has been specified.
337 * Old behaviour. Check netgroup list
338 * followed by UNIX list.
340 if (user_in_netgroup_list (user
, &tok
[1]))
342 if (user_in_group_list (user
, &tok
[1]))
345 else if (*tok
== '+')
350 * Search UNIX list followed by netgroup.
352 if (user_in_group_list (user
, &tok
[2]))
354 if (user_in_netgroup_list (user
, &tok
[2]))
360 * Just search UNIX list.
362 if (user_in_group_list (user
, &tok
[1]))
366 else if (*tok
== '&')
371 * Search netgroup list followed by UNIX list.
373 if (user_in_netgroup_list (user
, &tok
[2]))
375 if (user_in_group_list (user
, &tok
[2]))
381 * Just search netgroup list.
383 if (user_in_netgroup_list (user
, &tok
[1]))
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
);
407 #ifdef PASSWORD_LENGTH
408 len
= MIN (len
, PASSWORD_LENGTH
);
411 if (N
<= 0 || offset
>= len
)
415 for (i
= offset
; i
< (len
- (N
- 1)); i
++)
422 ret
= uname_string_combinations2 (s
, i
+ 1, fn
, N
- 1);
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
)
443 for (n
= 1; n
<= N
; n
++)
445 ret
= uname_string_combinations2 (s
, 0, fn
, n
);