1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Username handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
2001-12-04 08:13:04 +03:00
Copyright ( C ) Jeremy Allison 1997 - 2001.
2010-10-20 19:16:23 +04:00
Copyright ( C ) Andrew Bartlett 2002
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2011-02-14 23:39:10 +03:00
1996-05-04 11:50:46 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2011-02-14 23:39:10 +03:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 11:50:46 +04:00
*/
# include "includes.h"
2011-02-25 19:14:22 +03:00
# include "system/passwd.h"
2010-10-20 19:16:23 +04:00
# include "memcache.h"
2011-03-02 18:06:32 +03:00
# include "../lib/util/util_pw.h"
1996-05-04 11:50:46 +04:00
1998-06-10 23:45:13 +04:00
/* internal functions */
2006-02-04 01:19:41 +03:00
static struct passwd * uname_string_combinations ( char * s , TALLOC_CTX * mem_ctx ,
struct passwd * ( * fn ) ( TALLOC_CTX * mem_ctx , const char * ) ,
int N ) ;
static struct passwd * uname_string_combinations2 ( char * s , TALLOC_CTX * mem_ctx , int offset ,
struct passwd * ( * fn ) ( TALLOC_CTX * mem_ctx , const char * ) ,
int N ) ;
1996-05-04 11:50:46 +04:00
2011-03-02 17:22:34 +03:00
static struct passwd * getpwnam_alloc_cached ( TALLOC_CTX * mem_ctx , const char * name )
2010-10-20 19:16:23 +04:00
{
struct passwd * pw , * for_cache ;
pw = ( struct passwd * ) memcache_lookup_talloc (
NULL , GETPWNAM_CACHE , data_blob_string_const_null ( name ) ) ;
if ( pw ! = NULL ) {
return tcopy_passwd ( mem_ctx , pw ) ;
}
pw = sys_getpwnam ( name ) ;
if ( pw = = NULL ) {
return NULL ;
}
for_cache = tcopy_passwd ( talloc_tos ( ) , pw ) ;
if ( for_cache = = NULL ) {
return NULL ;
}
memcache_add_talloc ( NULL , GETPWNAM_CACHE ,
data_blob_string_const_null ( name ) , & for_cache ) ;
return tcopy_passwd ( mem_ctx , pw ) ;
}
/****************************************************************************
Flush all cached passwd structs .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void flush_pwnam_cache ( void )
{
memcache_flush ( NULL , GETPWNAM_CACHE ) ;
}
1999-05-06 22:05:45 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Get a users home directory .
1999-05-06 22:05:45 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-19 17:02:59 +03:00
char * get_user_home_dir ( TALLOC_CTX * mem_ctx , const char * user )
2002-01-17 02:53:10 +03:00
{
2007-12-19 17:02:59 +03:00
struct passwd * pass ;
char * result ;
2002-01-17 02:53:10 +03:00
/* Ensure the user exists. */
2007-12-19 17:02:59 +03:00
pass = Get_Pwnam_alloc ( mem_ctx , user ) ;
2002-01-17 02:53:10 +03:00
if ( ! pass )
return ( NULL ) ;
2007-12-19 17:02:59 +03:00
2002-01-17 02:53:10 +03:00
/* Return home directory from struct passwd. */
2007-12-19 17:02:59 +03:00
result = talloc_move ( mem_ctx , & pass - > pw_dir ) ;
TALLOC_FREE ( pass ) ;
return result ;
2002-01-17 02:53:10 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-01-17 11:45:58 +03:00
* A wrapper for sys_getpwnam ( ) . The following variations are tried :
2001-01-18 01:33:07 +03:00
* - as transmitted
* - in all lower case if this differs from transmitted
* - in all upper case if this differs from transmitted
* - using lp_usernamelevel ( ) for permutations .
2001-12-04 05:58:22 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
static struct passwd * Get_Pwnam_internals ( TALLOC_CTX * mem_ctx ,
const char * user , char * user2 )
1996-05-04 11:50:46 +04:00
{
2001-01-18 01:33:07 +03:00
struct passwd * ret = NULL ;
2000-12-11 20:48:26 +03:00
2001-10-29 10:28:32 +03:00
if ( ! user2 | | ! ( * user2 ) )
2000-12-11 20:48:26 +03:00
return ( NULL ) ;
2001-10-29 10:28:32 +03:00
if ( ! user | | ! ( * user ) )
return ( NULL ) ;
2000-12-11 20:48:26 +03:00
2001-01-18 01:33:07 +03:00
/* Try in all lower case first as this is the most
2000-12-11 20:48:26 +03:00
common case on UNIX systems */
2003-07-03 23:11:31 +04:00
strlower_m ( user2 ) ;
2001-01-18 01:33:07 +03:00
DEBUG ( 5 , ( " Trying _Get_Pwnam(), username as lowercase is %s \n " , user2 ) ) ;
2011-03-02 17:22:34 +03:00
ret = getpwnam_alloc_cached ( mem_ctx , user2 ) ;
2001-01-18 01:33:07 +03:00
if ( ret )
goto done ;
/* Try as given, if username wasn't originally lowercase */
2002-03-23 11:40:15 +03:00
if ( strcmp ( user , user2 ) ! = 0 ) {
2005-12-17 19:56:24 +03:00
DEBUG ( 5 , ( " Trying _Get_Pwnam(), username as given is %s \n " ,
user ) ) ;
2011-03-02 17:22:34 +03:00
ret = getpwnam_alloc_cached ( mem_ctx , user ) ;
2001-01-18 01:33:07 +03:00
if ( ret )
goto done ;
2002-01-17 11:45:58 +03:00
}
2001-01-18 01:33:07 +03:00
/* Try as uppercase, if username wasn't originally uppercase */
2003-07-03 23:11:31 +04:00
strupper_m ( user2 ) ;
2002-03-23 11:40:15 +03:00
if ( strcmp ( user , user2 ) ! = 0 ) {
2005-12-17 19:56:24 +03:00
DEBUG ( 5 , ( " Trying _Get_Pwnam(), username as uppercase is %s \n " ,
user2 ) ) ;
2011-03-02 17:22:34 +03:00
ret = getpwnam_alloc_cached ( mem_ctx , user2 ) ;
2001-01-18 01:33:07 +03:00
if ( ret )
goto done ;
2000-12-11 20:48:26 +03:00
}
2001-01-18 01:33:07 +03:00
/* Try all combinations up to usernamelevel */
2003-07-03 23:11:31 +04:00
strlower_m ( user2 ) ;
2005-12-17 19:56:24 +03:00
DEBUG ( 5 , ( " Checking combinations of %d uppercase letters in %s \n " ,
lp_usernamelevel ( ) , user2 ) ) ;
2011-03-02 17:22:34 +03:00
ret = uname_string_combinations ( user2 , mem_ctx , getpwnam_alloc_cached ,
2005-12-17 19:56:24 +03:00
lp_usernamelevel ( ) ) ;
2000-12-11 20:48:26 +03:00
2001-01-18 01:33:07 +03:00
done :
2005-12-17 19:56:24 +03:00
DEBUG ( 5 , ( " Get_Pwnam_internals %s find user [%s]! \n " , ret ?
" did " : " didn't " , user ) ) ;
2002-07-15 14:35:28 +04:00
2001-10-29 10:28:32 +03:00
return ret ;
}
/****************************************************************************
Get_Pwnam wrapper without modification .
NOTE : This with NOT modify ' user ' !
2005-06-07 21:52:19 +04:00
This will return an allocated structure
2001-10-29 10:28:32 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
struct passwd * Get_Pwnam_alloc ( TALLOC_CTX * mem_ctx , const char * user )
2001-10-29 10:28:32 +03:00
{
fstring user2 ;
2004-03-20 01:06:54 +03:00
if ( * user = = ' \0 ' ) {
DEBUG ( 10 , ( " Get_Pwnam: empty username! \n " ) ) ;
return NULL ;
}
2001-10-29 10:28:32 +03:00
fstrcpy ( user2 , user ) ;
2002-03-23 11:40:15 +03:00
DEBUG ( 5 , ( " Finding user %s \n " , user ) ) ;
2011-02-14 23:41:00 +03:00
return Get_Pwnam_internals ( mem_ctx , user , user2 ) ;
2001-10-29 10:28:32 +03:00
}
1997-09-19 21:12:08 +04:00
/* The functions below have been taken from password.c and slightly modified */
/****************************************************************************
1999-12-13 16:27:58 +03:00
Apply a function to upper / lower case combinations
of a string and return true if one of them returns true .
Try all combinations with N uppercase letters .
offset is the first char to try and change ( start with 0 )
it assumes the string starts lowercased
1997-09-19 21:12:08 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2006-02-04 01:19:41 +03:00
static struct passwd * uname_string_combinations2 ( char * s , TALLOC_CTX * mem_ctx ,
int offset ,
struct passwd * ( * fn ) ( TALLOC_CTX * mem_ctx , const char * ) ,
int N )
1997-09-19 21:12:08 +04:00
{
2001-12-04 05:58:22 +03:00
ssize_t len = ( ssize_t ) strlen ( s ) ;
int i ;
struct passwd * ret ;
1997-09-19 21:12:08 +04:00
2001-12-04 05:58:22 +03:00
if ( N < = 0 | | offset > = len )
2006-02-04 01:19:41 +03:00
return ( fn ( mem_ctx , s ) ) ;
2001-12-04 05:58:22 +03:00
for ( i = offset ; i < ( len - ( N - 1 ) ) ; i + + ) {
char c = s [ i ] ;
2005-12-27 23:52:36 +03:00
if ( ! islower_ascii ( ( int ) c ) )
2001-12-04 05:58:22 +03:00
continue ;
2005-12-27 23:52:36 +03:00
s [ i ] = toupper_ascii ( c ) ;
2006-02-04 01:19:41 +03:00
ret = uname_string_combinations2 ( s , mem_ctx , i + 1 , fn , N - 1 ) ;
2001-12-04 05:58:22 +03:00
if ( ret )
return ( ret ) ;
s [ i ] = c ;
}
return ( NULL ) ;
1997-09-19 21:12:08 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Apply a function to upper / lower case combinations
of a string and return true if one of them returns true .
Try all combinations with up to N uppercase letters .
offset is the first char to try and change ( start with 0 )
it assumes the string starts lowercased
1997-09-19 21:12:08 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2006-02-04 01:19:41 +03:00
static struct passwd * uname_string_combinations ( char * s , TALLOC_CTX * mem_ctx ,
struct passwd * ( * fn ) ( TALLOC_CTX * mem_ctx , const char * ) ,
int N )
1997-09-19 21:12:08 +04:00
{
2001-12-04 05:58:22 +03:00
int n ;
struct passwd * ret ;
2000-05-04 20:01:47 +04:00
2001-12-04 05:58:22 +03:00
for ( n = 1 ; n < = N ; n + + ) {
2006-02-04 01:19:41 +03:00
ret = uname_string_combinations2 ( s , mem_ctx , 0 , fn , n ) ;
2001-12-04 05:58:22 +03:00
if ( ret )
return ( ret ) ;
}
return ( NULL ) ;
}
2000-05-04 20:01:47 +04:00