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
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 .
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 .
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"
2009-01-08 14:03:45 +03:00
# include "smbd/globals.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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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-04-09 19:19:13 +04:00
static bool fetch_map_from_gencache ( fstring user )
{
char * key , * value ;
bool found ;
if ( lp_username_map_cache_time ( ) = = 0 ) {
return false ;
}
key = talloc_asprintf_strupper_m ( talloc_tos ( ) , " USERNAME_MAP/%s " ,
user ) ;
if ( key = = NULL ) {
return false ;
}
found = gencache_get ( key , & value , NULL ) ;
TALLOC_FREE ( key ) ;
if ( ! found ) {
return false ;
}
fstrcpy ( user , value ) ;
SAFE_FREE ( value ) ;
return true ;
}
static void store_map_in_gencache ( const char * from , const char * to )
{
char * key ;
int cache_time = lp_username_map_cache_time ( ) ;
if ( cache_time = = 0 ) {
return ;
}
key = talloc_asprintf_strupper_m ( talloc_tos ( ) , " USERNAME_MAP/%s " ,
from ) ;
if ( key = = NULL ) {
return ;
}
gencache_set ( key , to , cache_time + time ( NULL ) ) ;
TALLOC_FREE ( key ) ;
}
2009-05-26 18:38:45 +04:00
bool map_username ( struct smbd_server_connection * sconn , fstring user )
2006-02-13 20:08:25 +03:00
{
XFILE * f ;
char * mapfile = lp_username_map ( ) ;
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 ;
2006-02-13 20:08:25 +03:00
char * cmd = lp_username_map_script ( ) ;
2007-11-13 05:12:26 +03:00
2006-02-13 20:08:25 +03:00
if ( ! * user )
2007-11-13 05:12:26 +03:00
return false ;
2007-12-18 04:27:29 +03:00
if ( strequal ( user , get_last_to ( ) ) )
2007-11-13 05:12:26 +03:00
return false ;
2006-02-13 20:08:25 +03:00
2007-12-18 04:27:29 +03:00
if ( strequal ( user , get_last_from ( ) ) ) {
DEBUG ( 3 , ( " Mapped user %s to %s \n " , user , get_last_to ( ) ) ) ;
fstrcpy ( user , 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-04-09 19:19:13 +04:00
if ( fetch_map_from_gencache ( user ) ) {
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 ;
2007-11-13 05:12:26 +03:00
command = talloc_asprintf ( talloc_tos ( ) ,
" %s \" %s \" " ,
cmd ,
user ) ;
if ( ! command ) {
return false ;
}
2006-02-13 20:08:25 +03:00
DEBUG ( 10 , ( " Running [%s] \n " , command ) ) ;
ret = smbrun ( command , & fd ) ;
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-04-09 16:09:20 +04:00
qlines = fd_lines_load ( fd , & numlines , 0 , talloc_tos ( ) ) ;
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 ) {
2006-02-13 20:08:25 +03:00
DEBUG ( 3 , ( " Mapped user %s to %s \n " , user , qlines [ 0 ] ) ) ;
2010-04-12 12:34:29 +04:00
set_last_from_to ( user , qlines [ 0 ] ) ;
2010-04-09 19:19:13 +04:00
store_map_in_gencache ( user , qlines [ 0 ] ) ;
2006-02-13 20:08:25 +03:00
fstrcpy ( user , qlines [ 0 ] ) ;
}
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 ;
f = x_fopen ( mapfile , O_RDONLY , 0 ) ;
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 ) ) ;
while ( ( s = fgets_slash ( buf , sizeof ( buf ) , f ) ) ! = NULL ) {
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 = ' */
2008-11-07 05:53:00 +03:00
dosuserlist = str_list_make_v3 ( talloc_tos ( ) , 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 , ' * ' ) | |
2009-05-26 18:38:45 +04:00
user_in_list ( sconn , user , ( const char * * ) dosuserlist ) ) {
2006-02-13 20:08:25 +03:00
DEBUG ( 3 , ( " Mapped user %s to %s \n " , user , unixname ) ) ;
mapped_user = True ;
2007-12-18 04:27:29 +03:00
set_last_from_to ( user , unixname ) ;
2010-04-09 19:19:13 +04:00
store_map_in_gencache ( user , unixname ) ;
2006-02-13 20:08:25 +03:00
fstrcpy ( user , unixname ) ;
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 ) ;
2006-02-13 20:08:25 +03:00
x_fclose ( f ) ;
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
}
x_fclose ( f ) ;
/*
2007-12-18 04:27:29 +03:00
* 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 .
*/
2007-12-18 04:27:29 +03:00
set_last_from_to ( user , user ) ;
2010-04-09 19:19:13 +04:00
store_map_in_gencache ( user , user ) ;
2006-02-13 20:08:25 +03:00
return mapped_user ;
}