2010-06-02 21:39:18 +04:00
/*
2006-02-13 20:08:25 +03:00
Unix SMB / CIFS implementation .
Username handling
Copyright ( C ) Andrew Tridgell 1992 - 1998
Copyright ( C ) Jeremy Allison 1997 - 2001.
Copyright ( C ) Volker Lendecke 2006
2010-06-02 21:39:18 +04:00
2006-02-13 20:08:25 +03: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
2006-02-13 20:08:25 +03:00
( at your option ) any later version .
2010-06-02 21:39:18 +04:00
2006-02-13 20:08:25 +03: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 .
2010-06-02 21:39:18 +04:00
2006-02-13 20:08:25 +03: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/>.
2006-02-13 20:08:25 +03:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-25 04:28:05 +03:00
# include "auth.h"
2006-02-13 20:08:25 +03:00
2018-01-19 11:33:21 +03:00
# ifdef HAVE_NETGROUP
/* rpc/xdr.h uses TRUE and FALSE */
# ifdef TRUE
# undef TRUE
# endif
# ifdef FALSE
# undef FALSE
# endif
# include "system/nis.h"
# endif
2006-02-13 20:08:25 +03:00
/*******************************************************************
Map a username from a dos name to a unix name by looking in the username
map . Note that this modifies the name in place .
This is the main function that should be called * once * on
any incoming or new username - in order to canonicalize the name .
This is being done to de - couple the case conversions from the user mapping
function . Previously , the map_username was being called
2007-12-19 17:02:59 +03:00
every time Get_Pwnam_alloc was called .
2006-02-13 20:08:25 +03:00
Returns True if username was changed , false otherwise .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-31 20:33:38 +04:00
static char * last_from = NULL ;
static char * last_to = NULL ;
2007-12-18 04:27:29 +03:00
static const char * get_last_from ( void )
{
if ( ! last_from ) {
return " " ;
}
return last_from ;
}
static const char * get_last_to ( void )
{
if ( ! last_to ) {
return " " ;
}
return last_to ;
}
static bool set_last_from_to ( const char * from , const char * to )
{
char * orig_from = last_from ;
char * orig_to = last_to ;
last_from = SMB_STRDUP ( from ) ;
last_to = SMB_STRDUP ( to ) ;
SAFE_FREE ( orig_from ) ;
SAFE_FREE ( orig_to ) ;
if ( ! last_from | | ! last_to ) {
SAFE_FREE ( last_from ) ;
SAFE_FREE ( last_to ) ;
return false ;
}
return true ;
}
2010-04-09 16:30:54 +04:00
static char * skip_space ( char * s )
{
while ( isspace ( ( int ) ( * s ) ) ) {
s + = 1 ;
}
return s ;
}
2010-11-09 23:07:25 +03:00
static bool fetch_map_from_gencache ( TALLOC_CTX * ctx ,
const char * user_in ,
char * * p_user_out )
2010-04-09 19:19:13 +04:00
{
char * key , * value ;
bool found ;
if ( lp_username_map_cache_time ( ) = = 0 ) {
return false ;
}
2010-11-09 23:07:25 +03:00
key = talloc_asprintf_strupper_m ( ctx , " USERNAME_MAP/%s " ,
user_in ) ;
2010-04-09 19:19:13 +04:00
if ( key = = NULL ) {
return false ;
}
2013-09-04 10:57:59 +04:00
found = gencache_get ( key , ctx , & value , NULL ) ;
2010-04-09 19:19:13 +04:00
TALLOC_FREE ( key ) ;
if ( ! found ) {
return false ;
}
2010-11-09 23:07:25 +03:00
TALLOC_FREE ( * p_user_out ) ;
2013-09-04 10:57:59 +04:00
* p_user_out = value ;
2010-11-09 23:07:25 +03:00
if ( ! * p_user_out ) {
return false ;
}
2010-04-09 19:19:13 +04:00
return true ;
}
2010-11-09 23:07:25 +03:00
static void store_map_in_gencache ( TALLOC_CTX * ctx , const char * from , const char * to )
2010-04-09 19:19:13 +04:00
{
char * key ;
int cache_time = lp_username_map_cache_time ( ) ;
if ( cache_time = = 0 ) {
return ;
}
2010-11-09 23:07:25 +03:00
key = talloc_asprintf_strupper_m ( ctx , " USERNAME_MAP/%s " ,
2010-04-09 19:19:13 +04:00
from ) ;
if ( key = = NULL ) {
return ;
}
gencache_set ( key , to , cache_time + time ( NULL ) ) ;
TALLOC_FREE ( key ) ;
}
2010-06-02 21:39:18 +04:00
/****************************************************************************
Check if a user is in a netgroup user list . If at first we don ' t succeed ,
try lower case .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-11-09 23:07:25 +03:00
bool user_in_netgroup ( TALLOC_CTX * ctx , const char * user , const char * ngname )
2010-06-02 21:39:18 +04:00
{
# ifdef HAVE_NETGROUP
static char * my_yp_domain = NULL ;
2010-11-09 23:07:25 +03:00
char * lowercase_user = NULL ;
2010-06-02 21:39:18 +04:00
if ( my_yp_domain = = NULL ) {
yp_get_default_domain ( & my_yp_domain ) ;
}
if ( my_yp_domain = = NULL ) {
DEBUG ( 5 , ( " Unable to get default yp domain, "
" let's try without specifying it \n " ) ) ;
}
DEBUG ( 5 , ( " looking for user %s of domain %s in netgroup %s \n " ,
user , my_yp_domain ? my_yp_domain : " (ANY) " , ngname ) ) ;
if ( innetgr ( ngname , NULL , user , my_yp_domain ) ) {
DEBUG ( 5 , ( " user_in_netgroup: Found \n " ) ) ;
return true ;
}
/*
* Ok , innetgr is case sensitive . Try once more with lowercase
* just in case . Attempt to fix # 703. JRA .
*/
2010-11-09 23:07:25 +03:00
lowercase_user = talloc_strdup ( ctx , user ) ;
if ( ! lowercase_user ) {
return false ;
}
2012-08-09 04:01:00 +04:00
if ( ! strlower_m ( lowercase_user ) ) {
return false ;
}
2010-06-02 21:39:18 +04:00
if ( strcmp ( user , lowercase_user ) = = 0 ) {
/* user name was already lower case! */
return false ;
}
DEBUG ( 5 , ( " looking for user %s of domain %s in netgroup %s \n " ,
lowercase_user , my_yp_domain ? my_yp_domain : " (ANY) " , ngname ) ) ;
if ( innetgr ( ngname , NULL , lowercase_user , my_yp_domain ) ) {
DEBUG ( 5 , ( " user_in_netgroup: Found \n " ) ) ;
return true ;
}
# endif /* HAVE_NETGROUP */
return false ;
}
/****************************************************************************
Check if a user is in a user list - can check combinations of UNIX
and netgroup lists .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-02-26 23:16:26 +04:00
bool user_in_list ( TALLOC_CTX * ctx , const char * user , const char * const * list )
2010-06-02 21:39:18 +04:00
{
if ( ! list | | ! * list )
return False ;
DEBUG ( 10 , ( " user_in_list: checking user %s in list \n " , user ) ) ;
while ( * list ) {
DEBUG ( 10 , ( " user_in_list: checking user |%s| against |%s| \n " ,
user , * list ) ) ;
/*
* Check raw username .
*/
if ( strequal ( user , * list ) )
return ( True ) ;
/*
* Now check to see if any combination
* of UNIX and netgroups has been specified .
*/
if ( * * list = = ' @ ' ) {
/*
* Old behaviour . Check netgroup list
* followed by UNIX list .
*/
2010-11-09 23:07:25 +03:00
if ( user_in_netgroup ( ctx , user , * list + 1 ) )
2010-06-02 21:39:18 +04:00
return True ;
if ( user_in_group ( user , * list + 1 ) )
return True ;
} else if ( * * list = = ' + ' ) {
if ( ( * ( * list + 1 ) ) = = ' & ' ) {
/*
* Search UNIX list followed by netgroup .
*/
if ( user_in_group ( user , * list + 2 ) )
return True ;
2010-11-09 23:07:25 +03:00
if ( user_in_netgroup ( ctx , user , * list + 2 ) )
2010-06-02 21:39:18 +04:00
return True ;
} else {
/*
* Just search UNIX list .
*/
if ( user_in_group ( user , * list + 1 ) )
return True ;
}
} else if ( * * list = = ' & ' ) {
if ( * ( * list + 1 ) = = ' + ' ) {
/*
* Search netgroup list followed by UNIX list .
*/
2010-11-09 23:07:25 +03:00
if ( user_in_netgroup ( ctx , user , * list + 2 ) )
2010-06-02 21:39:18 +04:00
return True ;
if ( user_in_group ( user , * list + 2 ) )
return True ;
} else {
/*
* Just search netgroup list .
*/
2010-11-09 23:07:25 +03:00
if ( user_in_netgroup ( ctx , user , * list + 1 ) )
2010-06-02 21:39:18 +04:00
return True ;
}
}
list + + ;
}
return ( False ) ;
}
2010-11-09 23:07:25 +03:00
bool map_username ( TALLOC_CTX * ctx , const char * user_in , char * * p_user_out )
2006-02-13 20:08:25 +03:00
{
2016-11-22 03:38:16 +03:00
FILE * f ;
2012-07-18 09:37:23 +04:00
char * mapfile = lp_username_map ( talloc_tos ( ) ) ;
2006-02-13 20:08:25 +03:00
char * s ;
2007-11-13 05:12:26 +03:00
char buf [ 512 ] ;
2007-10-19 04:40:25 +04:00
bool mapped_user = False ;
2012-07-18 09:37:23 +04:00
char * cmd = lp_username_map_script ( talloc_tos ( ) ) ;
2007-11-13 05:12:26 +03:00
2010-11-09 23:07:25 +03:00
* p_user_out = NULL ;
if ( ! user_in )
return false ;
/* Initially make a copy of the incoming name. */
* p_user_out = talloc_strdup ( ctx , user_in ) ;
if ( ! * p_user_out ) {
2007-11-13 05:12:26 +03:00
return false ;
2010-11-09 23:07:25 +03:00
}
2007-11-13 05:12:26 +03:00
2010-11-09 23:07:25 +03:00
if ( strequal ( user_in , get_last_to ( ) ) )
2007-11-13 05:12:26 +03:00
return false ;
2006-02-13 20:08:25 +03:00
2010-11-09 23:07:25 +03:00
if ( strequal ( user_in , get_last_from ( ) ) ) {
DEBUG ( 3 , ( " Mapped user %s to %s \n " , user_in , get_last_to ( ) ) ) ;
TALLOC_FREE ( * p_user_out ) ;
* p_user_out = talloc_strdup ( ctx , get_last_to ( ) ) ;
2007-11-13 05:12:26 +03:00
return true ;
2006-02-13 20:08:25 +03:00
}
2007-11-13 05:12:26 +03:00
2010-11-09 23:07:25 +03:00
if ( fetch_map_from_gencache ( ctx , user_in , p_user_out ) ) {
2010-04-09 19:19:13 +04:00
return true ;
}
2006-02-13 20:08:25 +03:00
/* first try the username map script */
2007-11-13 05:12:26 +03:00
2006-02-13 20:08:25 +03:00
if ( * cmd ) {
char * * qlines ;
2007-11-13 05:12:26 +03:00
char * command = NULL ;
2006-02-13 20:08:25 +03:00
int numlines , ret , fd ;
2010-11-09 23:07:25 +03:00
command = talloc_asprintf ( ctx ,
2007-11-13 05:12:26 +03:00
" %s \" %s \" " ,
cmd ,
2010-11-09 23:07:25 +03:00
user_in ) ;
2007-11-13 05:12:26 +03:00
if ( ! command ) {
return false ;
}
2006-02-13 20:08:25 +03:00
DEBUG ( 10 , ( " Running [%s] \n " , command ) ) ;
2016-10-12 18:55:15 +03:00
ret = smbrun ( command , & fd , NULL ) ;
2006-02-13 20:08:25 +03:00
DEBUGADD ( 10 , ( " returned [%d] \n " , ret ) ) ;
2010-04-09 16:05:09 +04:00
TALLOC_FREE ( command ) ;
2006-02-13 20:08:25 +03:00
if ( ret ! = 0 ) {
if ( fd ! = - 1 )
close ( fd ) ;
return False ;
}
numlines = 0 ;
2010-11-09 23:07:25 +03:00
qlines = fd_lines_load ( fd , & numlines , 0 , ctx ) ;
2006-02-13 20:08:25 +03:00
DEBUGADD ( 10 , ( " Lines returned = [%d] \n " , numlines ) ) ;
close ( fd ) ;
/* should be either no lines or a single line with the mapped username */
2006-06-28 05:25:29 +04:00
if ( numlines & & qlines ) {
2010-11-09 23:07:25 +03:00
DEBUG ( 3 , ( " Mapped user %s to %s \n " , user_in , qlines [ 0 ] ) ) ;
set_last_from_to ( user_in , qlines [ 0 ] ) ;
store_map_in_gencache ( ctx , user_in , qlines [ 0 ] ) ;
TALLOC_FREE ( * p_user_out ) ;
* p_user_out = talloc_strdup ( ctx , qlines [ 0 ] ) ;
if ( ! * p_user_out ) {
return false ;
}
2006-02-13 20:08:25 +03:00
}
2008-10-12 19:34:43 +04:00
TALLOC_FREE ( qlines ) ;
2007-11-13 05:12:26 +03:00
2006-02-13 20:08:25 +03:00
return numlines ! = 0 ;
}
/* ok. let's try the mapfile */
if ( ! * mapfile )
return False ;
2016-11-22 03:38:16 +03:00
f = fopen ( mapfile , " r " ) ;
2006-02-13 20:08:25 +03:00
if ( ! f ) {
DEBUG ( 0 , ( " can't open username map %s. Error %s \n " , mapfile , strerror ( errno ) ) ) ;
return False ;
}
DEBUG ( 4 , ( " Scanning username map %s \n " , mapfile ) ) ;
2016-11-22 03:38:16 +03:00
while ( ( s = fgets_slash ( NULL , buf , sizeof ( buf ) , f ) ) ! = NULL ) {
2006-02-13 20:08:25 +03:00
char * unixname = s ;
char * dosname = strchr_m ( unixname , ' = ' ) ;
char * * dosuserlist ;
2007-10-19 04:40:25 +04:00
bool return_if_mapped = False ;
2006-02-13 20:08:25 +03:00
if ( ! dosname )
continue ;
* dosname + + = 0 ;
2010-04-09 16:30:54 +04:00
unixname = skip_space ( unixname ) ;
2006-02-13 20:08:25 +03:00
if ( ' ! ' = = * unixname ) {
return_if_mapped = True ;
2010-04-09 16:30:54 +04:00
unixname = skip_space ( unixname + 1 ) ;
2006-02-13 20:08:25 +03:00
}
2007-12-18 04:27:29 +03:00
2006-02-13 20:08:25 +03:00
if ( ! * unixname | | strchr_m ( " #; " , * unixname ) )
continue ;
{
int l = strlen ( unixname ) ;
while ( l & & isspace ( ( int ) unixname [ l - 1 ] ) ) {
unixname [ l - 1 ] = 0 ;
l - - ;
}
}
2006-03-01 18:11:56 +03:00
/* skip lines like 'user = ' */
2010-11-09 23:07:25 +03:00
dosuserlist = str_list_make_v3 ( ctx , dosname , NULL ) ;
2006-02-13 20:08:25 +03:00
if ( ! dosuserlist ) {
2006-03-01 18:11:56 +03:00
DEBUG ( 0 , ( " Bad username map entry. Unable to build user list. Ignoring. \n " ) ) ;
continue ;
2006-02-13 20:08:25 +03:00
}
if ( strchr_m ( dosname , ' * ' ) | |
2014-02-26 23:16:26 +04:00
user_in_list ( ctx , user_in , ( const char * const * ) dosuserlist ) ) {
2010-11-09 23:07:25 +03:00
DEBUG ( 3 , ( " Mapped user %s to %s \n " , user_in , unixname ) ) ;
2006-02-13 20:08:25 +03:00
mapped_user = True ;
2007-12-18 04:27:29 +03:00
2010-11-09 23:07:25 +03:00
set_last_from_to ( user_in , unixname ) ;
store_map_in_gencache ( ctx , user_in , unixname ) ;
TALLOC_FREE ( * p_user_out ) ;
* p_user_out = talloc_strdup ( ctx , unixname ) ;
if ( ! * p_user_out ) {
TALLOC_FREE ( dosuserlist ) ;
2016-11-22 03:38:16 +03:00
fclose ( f ) ;
2010-11-09 23:07:25 +03:00
return false ;
}
2007-12-18 04:27:29 +03:00
2006-02-13 20:08:25 +03:00
if ( return_if_mapped ) {
2008-02-04 22:57:35 +03:00
TALLOC_FREE ( dosuserlist ) ;
2016-11-22 03:38:16 +03:00
fclose ( f ) ;
2006-02-13 20:08:25 +03:00
return True ;
}
}
2007-12-18 04:27:29 +03:00
2008-02-04 22:57:35 +03:00
TALLOC_FREE ( dosuserlist ) ;
2006-02-13 20:08:25 +03:00
}
2016-11-22 03:38:16 +03:00
fclose ( f ) ;
2006-02-13 20:08:25 +03:00
/*
2013-04-05 16:07:37 +04:00
* If we didn ' t successfully map a user in the loop above ,
* setup the last_from and last_to as an optimization so
2006-02-13 20:08:25 +03:00
* that we don ' t scan the file again for the same user .
*/
2013-04-05 16:07:37 +04:00
if ( ! mapped_user ) {
DEBUG ( 8 , ( " The user '%s' has no mapping. "
" Skip it next time. \n " , user_in ) ) ;
set_last_from_to ( user_in , user_in ) ;
store_map_in_gencache ( ctx , user_in , user_in ) ;
}
2006-02-13 20:08:25 +03:00
return mapped_user ;
}