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"
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"
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
{
XFILE * 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 ;
2004-03-27 01:26:33 +03:00
f = x_fopen ( mapfile , O_RDONLY , 0 ) ;
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 ) ) ;
2005-01-20 04:19:57 +03:00
while ( x_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 ;
}
}
x_fclose ( f ) ;
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
{
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 ;
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 ) ) ;
2010-08-14 14:11:07 +04:00
targethost = read_target_host (
2010-08-18 21:57:21 +04:00
ctx , conn - > sconn - > client_id . addr , mapfilename ) ;
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
}
2007-11-17 04:07:11 +03:00
targethost = talloc_sub_advanced ( ctx ,
lp_servicename ( SNUM ( conn ) ) ,
2008-05-08 18:06:42 +04:00
conn - > server_info - > unix_name ,
2007-11-17 04:07:11 +03:00
conn - > connectpath ,
2008-06-19 18:54:12 +04:00
conn - > server_info - > utok . gid ,
2008-05-11 13:26:33 +04:00
conn - > server_info - > sanitized_username ,
2010-05-27 11:41:56 +04:00
conn - > server_info - > info3 - > base . domain . string ,
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
}
static int expand_msdfs_readlink ( struct vfs_handle_struct * handle ,
const char * path , char * buf , size_t bufsiz )
{
2007-11-17 04:07:11 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2004-03-27 01:26:33 +03:00
int result ;
2007-11-17 04:07:11 +03:00
char * target = TALLOC_ARRAY ( ctx , char , PATH_MAX + 1 ) ;
2010-02-03 03:43:41 +03:00
size_t len ;
2004-03-27 01:26:33 +03:00
2007-11-17 04:07:11 +03:00
if ( ! target ) {
errno = ENOMEM ;
return - 1 ;
}
2010-02-03 03:43:41 +03:00
if ( bufsiz = = 0 ) {
errno = EINVAL ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
result = SMB_VFS_NEXT_READLINK ( handle , path , target ,
2007-11-17 04:07:11 +03:00
PATH_MAX ) ;
2004-03-27 01:26:33 +03:00
2010-02-03 09:37:29 +03:00
if ( result < = 0 )
2004-03-27 01:26:33 +03:00
return result ;
target [ result ] = ' \0 ' ;
2010-02-03 03:43:41 +03:00
if ( ( strncmp ( target , " msdfs: " , 6 ) = = 0 ) & &
2004-03-29 15:40:43 +04:00
( strchr_m ( target , ' @ ' ) ! = NULL ) ) {
2007-11-17 04:07:11 +03:00
target = expand_msdfs_target ( ctx , handle - > conn , target ) ;
if ( ! target ) {
2004-03-27 01:26:33 +03:00
errno = ENOENT ;
return - 1 ;
}
}
2010-02-03 03:43:41 +03:00
len = MIN ( bufsiz , strlen ( target ) ) ;
2010-02-03 09:37:29 +03:00
memcpy ( buf , target , len ) ;
2010-02-03 03:43:41 +03:00
TALLOC_FREE ( target ) ;
return len ;
2004-03-27 01:26:33 +03:00
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_expand_msdfs_fns = {
. vfs_readlink = expand_msdfs_readlink
2004-03-27 01:26:33 +03:00
} ;
2006-12-19 23:16:52 +03:00
NTSTATUS vfs_expand_msdfs_init ( void ) ;
2004-03-27 01:26:33 +03:00
NTSTATUS vfs_expand_msdfs_init ( void )
{
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
}