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"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2006-12-12 20:38:42 +03:00
extern userdom_struct current_user_info ;
2004-03-27 01:26:33 +03:00
/**********************************************************
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-17 04:07:11 +03:00
static char * read_target_host ( TALLOC_CTX * ctx , const char * mapfile )
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 ) {
2007-11-04 04:15:45 +03:00
char addr [ INET6_ADDRSTRLEN ] ;
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 ' ;
2007-11-04 09:20:10 +03:00
if ( strncmp ( client_addr ( get_client_fd ( ) , addr , sizeof ( addr ) ) ,
2007-11-04 04:41:26 +03:00
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 ) ) ;
2007-11-17 04:07:11 +03:00
if ( ( targethost = read_target_host ( ctx , mapfilename ) ) = = 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 ) ) ,
conn - > user ,
conn - > connectpath ,
conn - > gid ,
get_current_username ( ) ,
current_user_info . domain ,
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 ) ;
2004-03-27 01:26:33 +03:00
2007-11-17 04:07:11 +03:00
if ( ! target ) {
errno = ENOMEM ;
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
if ( result < 0 )
return result ;
target [ result ] = ' \0 ' ;
2004-03-29 15:40:43 +04:00
if ( ( strncmp ( target , " msdfs: " , strlen ( " msdfs: " ) ) = = 0 ) & &
( 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 ;
}
}
safe_strcpy ( buf , target , bufsiz - 1 ) ;
return strlen ( buf ) ;
}
/* VFS operations structure */
2007-11-17 04:07:11 +03:00
static vfs_op_tuple expand_msdfs_ops [ ] = {
2004-03-27 01:26:33 +03:00
{ SMB_VFS_OP ( expand_msdfs_readlink ) , SMB_VFS_OP_READLINK ,
SMB_VFS_LAYER_TRANSPARENT } ,
{ SMB_VFS_OP ( NULL ) , SMB_VFS_OP_NOOP , SMB_VFS_LAYER_NOOP }
} ;
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 " ,
expand_msdfs_ops ) ;
}