root/src/vfs/smbfs/helpers/lib/username.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. get_home_dir
  2. map_username
  3. _Get_Pwnam
  4. Get_Pwnam
  5. user_in_netgroup_list
  6. user_in_group_list
  7. user_in_list
  8. uname_string_combinations2
  9. uname_string_combinations

   1 /*
   2    Unix SMB/Netbios implementation.
   3    Version 1.9.
   4    Username handling
   5 
   6    Copyright (C) Andrew Tridgell 1992-1998
   7 
   8    Copyright (C) 2011-2019
   9    Free Software Foundation, Inc.
  10 
  11    This file is part of the Midnight Commander.
  12 
  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.
  17 
  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.
  22 
  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/>.
  25  */
  26 
  27 #include "includes.h"
  28 extern int DEBUGLEVEL;
  29 
  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);
  35 
  36 /****************************************************************************
  37 get a users home directory.
  38 ****************************************************************************/
  39 const char *
  40 get_home_dir (char *user)
     /* [previous][next][first][last][top][bottom][index][help]  */
  41 {
  42     struct passwd *pass;
  43 
  44     pass = Get_Pwnam (user);
  45 
  46     if (!pass)
  47         return (NULL);
  48     return (pass->pw_dir);
  49 }
  50 
  51 
  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)
     /* [previous][next][first][last][top][bottom][index][help]  */
  65 {
  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;
  73 
  74     if (!*user)
  75         return False;
  76 
  77     if (!*mapfile)
  78         return False;
  79 
  80     if (!initialised)
  81     {
  82         *last_from = *last_to = 0;
  83         initialised = True;
  84     }
  85 
  86     if (strequal (user, last_to))
  87         return False;
  88 
  89     if (strequal (user, last_from))
  90     {
  91         DEBUG (3, ("Mapped user %s to %s\n", user, last_to));
  92         fstrcpy (user, last_to);
  93         return True;
  94     }
  95 
  96     f = sys_fopen (mapfile, "r");
  97     if (!f)
  98     {
  99         DEBUG (0, ("can't open username map %s\n", mapfile));
 100         return False;
 101     }
 102 
 103     DEBUG (4, ("Scanning username map %s\n", mapfile));
 104 
 105     while ((s = fgets_slash (buf, sizeof (buf), f)) != NULL)
 106     {
 107         char *unixname = s;
 108         char *dosname = strchr (unixname, '=');
 109         BOOL return_if_mapped = False;
 110 
 111         if (!dosname)
 112             continue;
 113 
 114         *dosname++ = 0;
 115 
 116         while (isspace (*unixname))
 117             unixname++;
 118         if ('!' == *unixname)
 119         {
 120             return_if_mapped = True;
 121             unixname++;
 122             while (*unixname && isspace (*unixname))
 123                 unixname++;
 124         }
 125 
 126         if (!*unixname || strchr ("#;", *unixname))
 127             continue;
 128 
 129         {
 130             int l = strlen (unixname);
 131             while (l && isspace (unixname[l - 1]))
 132             {
 133                 unixname[l - 1] = 0;
 134                 l--;
 135             }
 136         }
 137 
 138         if (strchr (dosname, '*') || user_in_list (user, dosname))
 139         {
 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)
 146             {
 147                 fclose (f);
 148                 return True;
 149             }
 150         }
 151     }
 152 
 153     fclose (f);
 154 
 155     /*
 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.
 158      */
 159     fstrcpy (last_from, user);
 160     fstrcpy (last_to, user);
 161 
 162     return mapped_user;
 163 }
 164 #endif /* 0 */
 165 
 166 /****************************************************************************
 167 Get_Pwnam wrapper
 168 ****************************************************************************/
 169 static struct passwd *
 170 _Get_Pwnam (const char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 171 {
 172     struct passwd *ret;
 173 
 174     ret = getpwnam (s);
 175     if (ret)
 176     {
 177 #ifdef HAVE_GETPWANAM
 178         struct passwd_adjunct *pwret;
 179         pwret = getpwanam (s);
 180         if (pwret)
 181         {
 182             free (ret->pw_passwd);
 183             ret->pw_passwd = pwret->pwa_passwd;
 184         }
 185 #endif
 186 
 187     }
 188 
 189     return (ret);
 190 }
 191 
 192 
 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)
     /* [previous][next][first][last][top][bottom][index][help]  */
 199 {
 200     fstring user;
 201     int last_char;
 202     int usernamelevel = lp_usernamelevel ();
 203 
 204     struct passwd *ret;
 205 
 206     if (!a_user || !(*a_user))
 207         return (NULL);
 208 
 209     StrnCpy (user, a_user, sizeof (user) - 1);
 210 
 211     ret = _Get_Pwnam (user);
 212     if (ret)
 213         return (ret);
 214 
 215     strlower (user);
 216     ret = _Get_Pwnam (user);
 217     if (ret)
 218         return (ret);
 219 
 220     strupper (user);
 221     ret = _Get_Pwnam (user);
 222     if (ret)
 223         return (ret);
 224 
 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);
 231 
 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);
 239 
 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);
 245 
 246     return (NULL);
 247 }
 248 
 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)
     /* [previous][next][first][last][top][bottom][index][help]  */
 255 {
 256 #ifdef HAVE_NETGROUP
 257     static char *mydomain = NULL;
 258     if (mydomain == NULL)
 259         yp_get_default_domain (&mydomain);
 260 
 261     if (mydomain == NULL)
 262     {
 263         DEBUG (5, ("Unable to get default yp domain\n"));
 264     }
 265     else
 266     {
 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"));
 269 
 270         if (innetgr (ngname, NULL, user, mydomain))
 271             return (True);
 272     }
 273 #endif /* HAVE_NETGROUP */
 274     return False;
 275 }
 276 
 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)
     /* [previous][next][first][last][top][bottom][index][help]  */
 282 {
 283 #ifdef HAVE_GETGRNAM
 284     struct group *gptr;
 285     char **member;
 286     struct passwd *pass = Get_Pwnam (user, False);
 287 
 288     if (pass)
 289     {
 290         gptr = getgrgid (pass->pw_gid);
 291         if (gptr && strequal (gptr->gr_name, gname))
 292             return (True);
 293     }
 294 
 295     gptr = (struct group *) getgrnam (gname);
 296 
 297     if (gptr)
 298     {
 299         member = gptr->gr_mem;
 300         while (member && *member)
 301         {
 302             if (strequal (*member, user))
 303                 return (True);
 304             member++;
 305         }
 306     }
 307 #endif /* HAVE_GETGRNAM */
 308     return False;
 309 }
 310 
 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)
     /* [previous][next][first][last][top][bottom][index][help]  */
 317 {
 318     pstring tok;
 319     char *p = list;
 320 
 321     while (next_token (&p, tok, LIST_SEP, sizeof (tok)))
 322     {
 323         /*
 324          * Check raw username.
 325          */
 326         if (strequal (user, tok))
 327             return (True);
 328 
 329         /*
 330          * Now check to see if any combination
 331          * of UNIX and netgroups has been specified.
 332          */
 333 
 334         if (*tok == '@')
 335         {
 336             /*
 337              * Old behaviour. Check netgroup list
 338              * followed by UNIX list.
 339              */
 340             if (user_in_netgroup_list (user, &tok[1]))
 341                 return True;
 342             if (user_in_group_list (user, &tok[1]))
 343                 return True;
 344         }
 345         else if (*tok == '+')
 346         {
 347             if (tok[1] == '&')
 348             {
 349                 /*
 350                  * Search UNIX list followed by netgroup.
 351                  */
 352                 if (user_in_group_list (user, &tok[2]))
 353                     return True;
 354                 if (user_in_netgroup_list (user, &tok[2]))
 355                     return True;
 356             }
 357             else
 358             {
 359                 /*
 360                  * Just search UNIX list.
 361                  */
 362                 if (user_in_group_list (user, &tok[1]))
 363                     return True;
 364             }
 365         }
 366         else if (*tok == '&')
 367         {
 368             if (tok[1] == '&')
 369             {
 370                 /*
 371                  * Search netgroup list followed by UNIX list.
 372                  */
 373                 if (user_in_netgroup_list (user, &tok[2]))
 374                     return True;
 375                 if (user_in_group_list (user, &tok[2]))
 376                     return True;
 377             }
 378             else
 379             {
 380                 /*
 381                  * Just search netgroup list.
 382                  */
 383                 if (user_in_netgroup_list (user, &tok[1]))
 384                     return True;
 385             }
 386         }
 387     }
 388     return (False);
 389 }
 390 #endif /* 0 */
 391 
 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)
     /* [previous][next][first][last][top][bottom][index][help]  */
 402 {
 403     int len = strlen (s);
 404     int i;
 405     struct passwd *ret;
 406 
 407 #ifdef PASSWORD_LENGTH
 408     len = MIN (len, PASSWORD_LENGTH);
 409 #endif
 410 
 411     if (N <= 0 || offset >= len)
 412         return (fn (s));
 413 
 414 
 415     for (i = offset; i < (len - (N - 1)); i++)
 416 
 417     {
 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;
 426     }
 427     return (NULL);
 428 }
 429 
 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)
     /* [previous][next][first][last][top][bottom][index][help]  */
 439 {
 440     int n;
 441     struct passwd *ret;
 442 
 443     for (n = 1; n <= N; n++)
 444     {
 445         ret = uname_string_combinations2 (s, 0, fn, n);
 446         if (ret)
 447             return (ret);
 448     }
 449     return (NULL);
 450 }

/* [previous][next][first][last][top][bottom][index][help]  */