2004-03-27 01:26:33 +03:00
/*
* Expand msdfs targets based on client IP
*
* Copyright ( C ) Volker Lendecke , 2004
*
* 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
2004-03-27 01:26:33 +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 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2004-03-27 01:26:33 +03:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2010-08-05 17:14:04 +04:00
# include "../librpc/gen_ndr/ndr_netlogon.h"
2010-08-18 21:57:21 +04:00
# include "smbd/globals.h"
2011-03-24 16:15:54 +03:00
# include "auth.h"
2011-06-16 16:23:54 +04:00
# include "../lib/tsocket/tsocket.h"
2004-03-27 01:26:33 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
/**********************************************************
Under mapfile we expect a table of the following format :
IP - Prefix whitespace expansion
For example :
192.168 .234 local . samba . org
192.168 remote . samba . org
default . samba . org
This is to redirect a DFS client to a host close to it .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-08-14 14:11:07 +04:00
static char * read_target_host ( TALLOC_CTX * ctx , const char * mapfile ,
const char * clientaddr )
2004-03-27 01:26:33 +03:00
{
2016-11-22 03:42:36 +03:00
FILE * f ;
2007-11-17 04:07:11 +03:00
char buf [ 1024 ] ;
2005-01-20 04:19:57 +03:00
char * space = buf ;
2007-11-17 04:07:11 +03:00
bool found = false ;
2016-11-22 03:42:36 +03:00
f = fopen ( mapfile , " r " ) ;
2004-03-27 01:26:33 +03:00
if ( f = = NULL ) {
DEBUG ( 0 , ( " can't open IP map %s. Error %s \n " ,
mapfile , strerror ( errno ) ) ) ;
2007-11-17 04:07:11 +03:00
return NULL ;
2004-03-27 01:26:33 +03:00
}
DEBUG ( 10 , ( " Scanning mapfile [%s] \n " , mapfile ) ) ;
2016-11-22 03:42:36 +03:00
while ( fgets ( buf , sizeof ( buf ) , f ) ! = NULL ) {
2004-03-29 15:40:43 +04:00
2004-03-29 15:54:34 +04:00
if ( ( strlen ( buf ) > 0 ) & & ( buf [ strlen ( buf ) - 1 ] = = ' \n ' ) )
2004-03-29 15:40:43 +04:00
buf [ strlen ( buf ) - 1 ] = ' \0 ' ;
DEBUG ( 10 , ( " Scanning line [%s] \n " , buf ) ) ;
2004-03-27 01:26:33 +03:00
space = strchr_m ( buf , ' ' ) ;
if ( space = = NULL ) {
DEBUG ( 0 , ( " Ignoring invalid line %s \n " , buf ) ) ;
continue ;
}
* space = ' \0 ' ;
2010-08-14 14:11:07 +04:00
if ( strncmp ( clientaddr , buf , strlen ( buf ) ) = = 0 ) {
2007-11-17 04:07:11 +03:00
found = true ;
2004-03-27 01:26:33 +03:00
break ;
}
}
2016-11-22 03:42:36 +03:00
fclose ( f ) ;
2004-03-27 01:26:33 +03:00
2007-11-17 04:07:11 +03:00
if ( ! found ) {
return NULL ;
}
2004-03-27 01:26:33 +03:00
space + = 1 ;
while ( isspace ( * space ) )
space + = 1 ;
2007-11-17 04:07:11 +03:00
return talloc_strdup ( ctx , space ) ;
2004-03-27 01:26:33 +03:00
}
/**********************************************************
Expand the msdfs target host using read_target_host
explained above . The syntax used in the msdfs link is
msdfs : @ table - filename @ / share
Everything between and including the two @ - signs is
replaced by the substitution string found in the table
described above .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-17 04:07:11 +03:00
static char * expand_msdfs_target ( TALLOC_CTX * ctx ,
connection_struct * conn ,
char * target )
2004-03-27 01:26:33 +03:00
{
2019-11-07 13:01:05 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2007-11-17 04:07:11 +03:00
char * mapfilename = NULL ;
2004-03-27 01:26:33 +03:00
char * filename_start = strchr_m ( target , ' @ ' ) ;
2007-11-17 04:07:11 +03:00
char * filename_end = NULL ;
int filename_len = 0 ;
char * targethost = NULL ;
char * new_target = NULL ;
2011-06-16 16:23:54 +04:00
char * raddr ;
2004-03-27 01:26:33 +03:00
if ( filename_start = = NULL ) {
DEBUG ( 10 , ( " No filename start in %s \n " , target ) ) ;
2007-11-17 04:07:11 +03:00
return NULL ;
2004-03-27 01:26:33 +03:00
}
filename_end = strchr_m ( filename_start + 1 , ' @ ' ) ;
if ( filename_end = = NULL ) {
DEBUG ( 10 , ( " No filename end in %s \n " , target ) ) ;
2007-11-17 04:07:11 +03:00
return NULL ;
2004-03-27 01:26:33 +03:00
}
filename_len = PTR_DIFF ( filename_end , filename_start + 1 ) ;
2007-11-17 04:07:11 +03:00
mapfilename = talloc_strdup ( ctx , filename_start + 1 ) ;
if ( ! mapfilename ) {
return NULL ;
}
2004-03-27 01:26:33 +03:00
mapfilename [ filename_len ] = ' \0 ' ;
DEBUG ( 10 , ( " Expanding from table [%s] \n " , mapfilename ) ) ;
2011-06-16 16:23:54 +04:00
raddr = tsocket_address_inet_addr_string ( conn - > sconn - > remote_address ,
ctx ) ;
if ( raddr = = NULL ) {
return NULL ;
}
2017-03-14 18:12:20 +03:00
targethost = read_target_host ( ctx , mapfilename , raddr ) ;
2010-08-14 14:11:07 +04:00
if ( targethost = = NULL ) {
2004-03-27 01:26:33 +03:00
DEBUG ( 1 , ( " Could not expand target host from file %s \n " ,
mapfilename ) ) ;
2007-11-17 04:07:11 +03:00
return NULL ;
2004-03-27 01:26:33 +03:00
}
2019-10-31 14:45:44 +03:00
targethost = talloc_sub_full ( ctx ,
2019-11-07 13:01:05 +03:00
lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( conn ) ) ,
2011-07-15 09:55:31 +04:00
conn - > session_info - > unix_info - > unix_name ,
2007-11-17 04:07:11 +03:00
conn - > connectpath ,
2011-07-15 08:59:14 +04:00
conn - > session_info - > unix_token - > gid ,
2011-07-15 09:55:31 +04:00
conn - > session_info - > unix_info - > sanitized_username ,
2011-07-18 06:58:25 +04:00
conn - > session_info - > info - > domain_name ,
2007-11-17 04:07:11 +03:00
targethost ) ;
2004-03-27 01:26:33 +03:00
DEBUG ( 10 , ( " Expanded targethost to %s \n " , targethost ) ) ;
2007-11-17 04:07:11 +03:00
/* Replace the part between '@...@' */
2004-03-27 01:26:33 +03:00
* filename_start = ' \0 ' ;
2007-11-17 04:07:11 +03:00
new_target = talloc_asprintf ( ctx ,
" %s%s%s " ,
target ,
targethost ,
filename_end + 1 ) ;
if ( ! new_target ) {
return NULL ;
}
2004-03-27 01:26:33 +03:00
DEBUG ( 10 , ( " New DFS target: %s \n " , new_target ) ) ;
2007-11-17 04:07:11 +03:00
return new_target ;
2004-03-27 01:26:33 +03:00
}
2019-08-23 00:18:16 +03:00
static int expand_msdfs_readlinkat ( struct vfs_handle_struct * handle ,
2020-10-13 16:19:30 +03:00
const struct files_struct * dirfsp ,
2019-08-23 00:18:16 +03:00
const struct smb_filename * smb_fname ,
char * buf ,
size_t bufsiz )
{
TALLOC_CTX * ctx = talloc_tos ( ) ;
int result ;
char * target = talloc_array ( ctx , char , PATH_MAX + 1 ) ;
size_t len ;
if ( ! target ) {
errno = ENOMEM ;
return - 1 ;
}
if ( bufsiz = = 0 ) {
errno = EINVAL ;
return - 1 ;
}
result = SMB_VFS_NEXT_READLINKAT ( handle ,
dirfsp ,
smb_fname ,
target ,
PATH_MAX ) ;
if ( result < = 0 )
return result ;
target [ result ] = ' \0 ' ;
if ( ( strncmp ( target , " msdfs: " , 6 ) = = 0 ) & &
( strchr_m ( target , ' @ ' ) ! = NULL ) ) {
target = expand_msdfs_target ( ctx , handle - > conn , target ) ;
if ( ! target ) {
errno = ENOENT ;
return - 1 ;
}
}
len = MIN ( bufsiz , strlen ( target ) ) ;
memcpy ( buf , target , len ) ;
TALLOC_FREE ( target ) ;
return len ;
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_expand_msdfs_fns = {
2019-08-23 00:18:16 +03:00
. readlinkat_fn = expand_msdfs_readlinkat
2004-03-27 01:26:33 +03:00
} ;
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_expand_msdfs_init ( TALLOC_CTX * ctx )
2004-03-27 01:26:33 +03:00
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " expand_msdfs " ,
2009-07-24 04:28:58 +04:00
& vfs_expand_msdfs_fns ) ;
2004-03-27 01:26:33 +03:00
}