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"
2018-10-18 22:53:36 +03:00
# include "lib/gencache.h"
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
/****************************************************************************
2021-04-20 18:59:34 +03:00
Check if a user is in a user list
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
We removed NIS support in 2021 , but need to keep configs working .
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
TOOD FIXME : Remove this funciton
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
bool user_in_list ( TALLOC_CTX * ctx , const char * user , const char * const * list )
{
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
if ( list = = NULL | | * list = = NULL ) {
2010-06-02 21:39:18 +04:00
return false ;
}
2021-04-20 18:59:34 +03:00
DBG_DEBUG ( " Checking user %s in list \n " , user ) ;
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
while ( * list ) {
const char * p = * list ;
bool ok ;
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
/* Check raw username */
if ( strequal ( user , p ) ) {
return true ;
}
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
while ( * p = = ' @ ' | | * p = = ' & ' | | * p = = ' + ' ) {
p + + ;
}
2010-06-02 21:39:18 +04:00
2021-04-20 18:59:34 +03:00
ok = user_in_group ( user , p ) ;
if ( ok ) {
return true ;
2010-06-02 21:39:18 +04:00
}
list + + ;
}
2021-04-20 18:59:34 +03:00
return false ;
2010-06-02 21:39:18 +04:00
}
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
{
2019-11-05 14:11:54 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2016-11-22 03:38:16 +03:00
FILE * f ;
2019-11-05 14:11:54 +03:00
char * mapfile = lp_username_map ( talloc_tos ( ) , lp_sub ) ;
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 ;
2019-11-05 14:12:51 +03:00
char * cmd = lp_username_map_script ( talloc_tos ( ) , lp_sub ) ;
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 ;
}