LCOV - code coverage report
Current view: top level - source3/lib - username.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 61 90 67.8 %
Date: 2024-01-11 09:59:51 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Username handling
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Jeremy Allison 1997-2001.
       6             :    Copyright (C) Andrew Bartlett 2002
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/passwd.h"
      24             : #include "../lib/util/memcache.h"
      25             : #include "../lib/util/util_pw.h"
      26             : #include "lib/util/string_wrappers.h"
      27             : 
      28             : /* internal functions */
      29             : static struct passwd *uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
      30             :                                                 struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
      31             :                                                 int N);
      32             : static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, int offset,
      33             :                                                  struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
      34             :                                                  int N);
      35             : 
      36      135570 : static struct passwd *getpwnam_alloc_cached(TALLOC_CTX *mem_ctx, const char *name)
      37             : {
      38        1647 :         struct passwd *pw, *for_cache;
      39             : 
      40      135570 :         pw = (struct passwd *)memcache_lookup_talloc(
      41             :                 NULL, GETPWNAM_CACHE, data_blob_string_const_null(name));
      42      135570 :         if (pw != NULL) {
      43       81636 :                 return tcopy_passwd(mem_ctx, pw);
      44             :         }
      45             : 
      46       53934 :         pw = getpwnam(name);
      47       53934 :         if (pw == NULL) {
      48       11107 :                 return NULL;
      49             :         }
      50             : 
      51       41959 :         for_cache = tcopy_passwd(talloc_tos(), pw);
      52       41959 :         if (for_cache == NULL) {
      53           0 :                 return NULL;
      54             :         }
      55             : 
      56       41959 :         memcache_add_talloc(NULL, GETPWNAM_CACHE,
      57             :                         data_blob_string_const_null(name), &for_cache);
      58             : 
      59       41959 :         return tcopy_passwd(mem_ctx, pw);
      60             : }
      61             : 
      62             : /****************************************************************************
      63             :  Flush all cached passwd structs.
      64             : ****************************************************************************/
      65             : 
      66         117 : void flush_pwnam_cache(void)
      67             : {
      68         117 :         memcache_flush(NULL, GETPWNAM_CACHE);
      69         117 : }
      70             : 
      71             : /****************************************************************************
      72             :  Get a users home directory.
      73             : ****************************************************************************/
      74             : 
      75        1437 : char *get_user_home_dir(TALLOC_CTX *mem_ctx, const char *user)
      76             : {
      77          10 :         struct passwd *pass;
      78          10 :         char *result;
      79             : 
      80             :         /* Ensure the user exists. */
      81             : 
      82        1437 :         pass = Get_Pwnam_alloc(mem_ctx, user);
      83             : 
      84        1437 :         if (!pass)
      85        1419 :                 return(NULL);
      86             : 
      87             :         /* Return home directory from struct passwd. */
      88             : 
      89           8 :         result = talloc_move(mem_ctx, &pass->pw_dir);
      90             : 
      91           8 :         TALLOC_FREE(pass);
      92           8 :         return result;
      93             : }
      94             : 
      95             : /****************************************************************************
      96             :  * A wrapper for getpwnam().  The following variations are tried:
      97             :  *   - as transmitted
      98             :  *   - in all lower case if this differs from transmitted
      99             :  *   - in all upper case if this differs from transmitted
     100             :  *   - using lp_username_level() for permutations.
     101             : ****************************************************************************/
     102             : 
     103      127680 : static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx,
     104             :                                           const char *user, char *user2)
     105             : {
     106      127680 :         struct passwd *ret = NULL;
     107             : 
     108      127680 :         if (!user2 || !(*user2))
     109           0 :                 return(NULL);
     110             : 
     111      127680 :         if (!user || !(*user))
     112           0 :                 return(NULL);
     113             : 
     114             :         /* Try in all lower case first as this is the most 
     115             :            common case on UNIX systems */
     116      127680 :         if (!strlower_m(user2)) {
     117           0 :                 DEBUG(5,("strlower_m %s failed\n", user2));
     118           0 :                 goto done;
     119             :         }
     120             : 
     121      127680 :         DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2));
     122      127680 :         ret = getpwnam_alloc_cached(mem_ctx, user2);
     123      127680 :         if(ret)
     124      123595 :                 goto done;
     125             : 
     126             :         /* Try as given, if username wasn't originally lowercase */
     127        4085 :         if(strcmp(user, user2) != 0) {
     128        3877 :                 DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n",
     129             :                          user));
     130        3877 :                 ret = getpwnam_alloc_cached(mem_ctx, user);
     131        3877 :                 if(ret)
     132           0 :                         goto done;
     133             :         }
     134             : 
     135             :         /* Try as uppercase, if username wasn't originally uppercase */
     136        4085 :         if (!strupper_m(user2)) {
     137           0 :                 goto done;
     138             :         }
     139             : 
     140        4085 :         if(strcmp(user, user2) != 0) {
     141        4013 :                 DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n",
     142             :                          user2));
     143        4013 :                 ret = getpwnam_alloc_cached(mem_ctx, user2);
     144        4013 :                 if(ret)
     145           0 :                         goto done;
     146             :         }
     147             : 
     148             :         /* Try all combinations up to usernamelevel */
     149        4085 :         if (!strlower_m(user2)) {
     150           0 :                 DEBUG(5,("strlower_m %s failed\n", user2));
     151           0 :                 goto done;
     152             :         }
     153        4085 :         DEBUG(5,("Checking combinations of %d uppercase letters in %s\n",
     154             :                  lp_username_level(), user2));
     155        5158 :         ret = uname_string_combinations(user2, mem_ctx, getpwnam_alloc_cached,
     156             :                                         lp_username_level());
     157             : 
     158      127680 : done:
     159      127680 :         DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ?
     160             :                  "did":"didn't", user));
     161             : 
     162      126607 :         return ret;
     163             : }
     164             : 
     165             : /****************************************************************************
     166             :  Get_Pwnam wrapper without modification.
     167             :   NOTE: This with NOT modify 'user'! 
     168             :   This will return an allocated structure
     169             : ****************************************************************************/
     170             : 
     171      127682 : struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user)
     172             : {
     173        1073 :         fstring user2;
     174             : 
     175      127682 :         if ( *user == '\0' ) {
     176           2 :                 DEBUG(10,("Get_Pwnam: empty username!\n"));
     177           2 :                 return NULL;
     178             :         }
     179             : 
     180      127680 :         fstrcpy(user2, user);
     181             : 
     182      127680 :         DEBUG(5,("Finding user %s\n", user));
     183             : 
     184      127680 :         return Get_Pwnam_internals(mem_ctx, user, user2);
     185             : }
     186             : 
     187             : /* The functions below have been taken from password.c and slightly modified */
     188             : /****************************************************************************
     189             :  Apply a function to upper/lower case combinations
     190             :  of a string and return true if one of them returns true.
     191             :  Try all combinations with N uppercase letters.
     192             :  offset is the first char to try and change (start with 0)
     193             :  it assumes the string starts lowercased
     194             : ****************************************************************************/
     195             : 
     196           0 : static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx,
     197             :                                                  int offset,
     198             :                                                  struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *),
     199             :                                                  int N)
     200             : {
     201           0 :         ssize_t len = (ssize_t)strlen(s);
     202           0 :         int i;
     203           0 :         struct passwd *ret;
     204             : 
     205           0 :         if (N <= 0 || offset >= len)
     206           0 :                 return(fn(mem_ctx, s));
     207             : 
     208           0 :         for (i=offset;i<(len-(N-1));i++) {
     209           0 :                 char c = s[i];
     210           0 :                 if (!islower_m((int)c))
     211           0 :                         continue;
     212           0 :                 s[i] = toupper_m(c);
     213           0 :                 ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1);
     214           0 :                 if(ret)
     215           0 :                         return(ret);
     216           0 :                 s[i] = c;
     217             :         }
     218           0 :         return(NULL);
     219             : }
     220             : 
     221             : /****************************************************************************
     222             :  Apply a function to upper/lower case combinations
     223             :  of a string and return true if one of them returns true.
     224             :  Try all combinations with up to N uppercase letters.
     225             :  offset is the first char to try and change (start with 0)
     226             :  it assumes the string starts lowercased
     227             : ****************************************************************************/
     228             : 
     229        4085 : static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
     230             :                                                  struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *),
     231             :                                                  int N)
     232             : {
     233         294 :         int n;
     234         294 :         struct passwd *ret;
     235             : 
     236        4379 :         for (n=1;n<=N;n++) {
     237           0 :                 ret = uname_string_combinations2(s,mem_ctx,0,fn,n);
     238           0 :                 if(ret)
     239           0 :                         return(ret);
     240             :         }  
     241        3791 :         return(NULL);
     242             : }
     243             : 

Generated by: LCOV version 1.14