1998-01-06 01:56:29 +03:00
/*
Unix SMB / Netbios implementation .
1999-12-13 16:27:58 +03:00
Version 2.0 .
SMBFS mount program
Copyright ( C ) Andrew Tridgell 1999
1998-01-06 01:56:29 +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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
1998-07-29 07:08:05 +04:00
# define NO_SYSLOG
1998-01-06 01:56:29 +03:00
# include "includes.h"
1998-09-28 23:18:21 +04:00
1999-02-15 02:15:54 +03:00
# include <mntent.h>
1998-09-28 23:18:21 +04:00
# include <asm/types.h>
1998-01-06 01:56:29 +03:00
# include <linux/smb_fs.h>
1999-12-13 16:27:58 +03:00
extern struct in_addr ipzero ;
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
extern BOOL in_client ;
extern pstring user_socket_options ;
2001-03-10 02:48:58 +03:00
extern BOOL append_log ;
extern fstring remote_machine ;
1998-01-06 01:56:29 +03:00
2001-03-10 02:48:58 +03:00
static pstring credentials ;
1999-12-13 16:27:58 +03:00
static pstring my_netbios_name ;
static pstring password ;
static pstring username ;
static pstring workgroup ;
static pstring mpoint ;
static pstring service ;
2001-03-10 02:48:58 +03:00
static pstring options ;
1999-12-13 16:27:58 +03:00
static struct in_addr dest_ip ;
static BOOL have_ip ;
2001-08-25 00:11:09 +04:00
static int smb_port = 0 ;
1999-12-13 16:27:58 +03:00
static BOOL got_pass ;
static uid_t mount_uid ;
static gid_t mount_gid ;
static int mount_ro ;
static unsigned mount_fmask ;
static unsigned mount_dmask ;
static void usage ( void ) ;
static void exit_parent ( int sig )
1999-02-01 00:28:55 +03:00
{
/* parent simply exits when child says go... */
exit ( 0 ) ;
}
1999-12-13 16:27:58 +03:00
static void daemonize ( void )
1998-01-06 01:56:29 +03:00
{
1999-02-01 00:28:55 +03:00
int j , status ;
pid_t child_pid ;
signal ( SIGTERM , exit_parent ) ;
2000-05-02 06:23:41 +04:00
if ( ( child_pid = sys_fork ( ) ) < 0 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " could not fork \n " ) ) ;
1998-01-06 01:56:29 +03:00
}
1999-12-13 16:27:58 +03:00
if ( child_pid > 0 ) {
1999-02-01 00:28:55 +03:00
while ( 1 ) {
j = waitpid ( child_pid , & status , 0 ) ;
if ( j < 0 ) {
if ( EINTR = = errno ) {
continue ;
}
status = errno ;
}
break ;
}
/* If we get here - the child exited with some error status */
exit ( status ) ;
1998-01-06 01:56:29 +03:00
}
1999-02-01 00:28:55 +03:00
signal ( SIGTERM , SIG_DFL ) ;
1998-01-06 01:56:29 +03:00
chdir ( " / " ) ;
}
1999-12-13 16:27:58 +03:00
static void close_our_files ( int client_fd )
1998-01-06 01:56:29 +03:00
{
int i ;
2001-04-22 07:16:04 +04:00
struct rlimit limits ;
2001-04-14 22:39:32 +04:00
getrlimit ( RLIMIT_NOFILE , & limits ) ;
2001-04-22 07:16:04 +04:00
for ( i = 0 ; i < limits . rlim_max ; i + + ) {
if ( i = = client_fd )
continue ;
1998-01-06 01:56:29 +03:00
close ( i ) ;
}
}
1999-12-13 16:27:58 +03:00
static void usr1_handler ( int x )
1998-01-06 01:56:29 +03:00
{
return ;
}
1999-12-13 16:27:58 +03:00
/*****************************************************
return a connection to a server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct cli_state * do_connection ( char * service )
1998-01-06 01:56:29 +03:00
{
1999-12-13 16:27:58 +03:00
struct cli_state * c ;
struct nmb_name called , calling ;
char * server_n ;
struct in_addr ip ;
extern struct in_addr ipzero ;
pstring server ;
char * share ;
if ( service [ 0 ] ! = ' \\ ' | | service [ 1 ] ! = ' \\ ' ) {
usage ( ) ;
exit ( 1 ) ;
}
pstrcpy ( server , service + 2 ) ;
2001-07-04 11:36:09 +04:00
share = strchr_m ( server , ' \\ ' ) ;
1999-12-13 16:27:58 +03:00
if ( ! share ) {
usage ( ) ;
exit ( 1 ) ;
}
* share = 0 ;
share + + ;
server_n = server ;
2000-01-07 09:55:36 +03:00
make_nmb_name ( & calling , my_netbios_name , 0x0 ) ;
make_nmb_name ( & called , server , 0x20 ) ;
1999-12-13 16:27:58 +03:00
again :
ip = ipzero ;
if ( have_ip ) ip = dest_ip ;
/* have to open a new connection */
2001-09-10 15:08:57 +04:00
if ( ! ( c = cli_initialise ( NULL ) ) | | ( cli_set_port ( c , smb_port ) ! = smb_port ) | |
1999-12-13 16:27:58 +03:00
! cli_connect ( c , server_n , & ip ) ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Connection to %s failed \n " , getpid ( ) , server_n ) ) ;
if ( c ) {
cli_shutdown ( c ) ;
2001-09-17 04:52:47 +04:00
SAFE_FREE ( c ) ;
2001-03-10 02:48:58 +03:00
}
1999-12-13 16:27:58 +03:00
return NULL ;
}
if ( ! cli_session_request ( c , & calling , & called ) ) {
2001-03-10 02:48:58 +03:00
char * p ;
DEBUG ( 0 , ( " %d: session request to %s failed (%s) \n " ,
getpid ( ) , called . name , cli_errstr ( c ) ) ) ;
1999-12-13 16:27:58 +03:00
cli_shutdown ( c ) ;
2001-09-17 04:52:47 +04:00
SAFE_FREE ( c ) ;
2001-07-04 11:36:09 +04:00
if ( ( p = strchr_m ( called . name , ' . ' ) ) ) {
2001-03-10 02:48:58 +03:00
* p = 0 ;
goto again ;
}
1999-12-13 16:27:58 +03:00
if ( strcmp ( called . name , " *SMBSERVER " ) ) {
2000-01-07 09:55:36 +03:00
make_nmb_name ( & called , " *SMBSERVER " , 0x20 ) ;
1999-12-13 16:27:58 +03:00
goto again ;
}
return NULL ;
}
2001-03-10 02:48:58 +03:00
DEBUG ( 4 , ( " %d: session request ok \n " , getpid ( ) ) ) ;
1999-12-13 16:27:58 +03:00
if ( ! cli_negprot ( c ) ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: protocol negotiation failed \n " , getpid ( ) ) ) ;
1999-12-13 16:27:58 +03:00
cli_shutdown ( c ) ;
2001-09-17 04:52:47 +04:00
SAFE_FREE ( c ) ;
1999-12-13 16:27:58 +03:00
return NULL ;
}
if ( ! got_pass ) {
char * pass = getpass ( " Password: " ) ;
if ( pass ) {
pstrcpy ( password , pass ) ;
}
}
if ( ! cli_session_setup ( c , username ,
password , strlen ( password ) ,
password , strlen ( password ) ,
workgroup ) ) {
2001-09-21 01:06:02 +04:00
/* if a password was not supplied then try again with a
null username */
if ( password [ 0 ] | | ! username [ 0 ] | |
! cli_session_setup ( c , " " , " " , 0 , " " , 0 , workgroup ) ) {
DEBUG ( 0 , ( " %d: session setup failed: %s \n " ,
getpid ( ) , cli_errstr ( c ) ) ) ;
cli_shutdown ( c ) ;
SAFE_FREE ( c ) ;
return NULL ;
}
DEBUG ( 0 , ( " Anonymous login successful \n " ) ) ;
1999-12-13 16:27:58 +03:00
}
2001-03-10 02:48:58 +03:00
DEBUG ( 4 , ( " %d: session setup ok \n " , getpid ( ) ) ) ;
1999-12-13 16:27:58 +03:00
if ( ! cli_send_tconX ( c , share , " ????? " ,
password , strlen ( password ) + 1 ) ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: tree connect failed: %s \n " ,
getpid ( ) , cli_errstr ( c ) ) ) ;
1999-12-13 16:27:58 +03:00
cli_shutdown ( c ) ;
2001-09-17 04:52:47 +04:00
SAFE_FREE ( c ) ;
1999-12-13 16:27:58 +03:00
return NULL ;
}
2001-03-10 02:48:58 +03:00
DEBUG ( 4 , ( " %d: tconx ok \n " , getpid ( ) ) ) ;
1999-12-13 16:27:58 +03:00
got_pass = True ;
1999-02-15 02:15:54 +03:00
1999-12-13 16:27:58 +03:00
return c ;
1998-01-06 01:56:29 +03:00
}
1999-12-13 16:27:58 +03:00
1999-02-15 02:15:54 +03:00
/****************************************************************************
unmount smbfs ( this is a bailout routine to clean up if a reconnect fails )
Code blatently stolen from smbumount . c
- mhw -
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static void smb_umount ( char * mount_point )
1999-02-15 02:15:54 +03:00
{
int fd ;
struct mntent * mnt ;
FILE * mtab ;
FILE * new_mtab ;
/* Programmers Note:
This routine only gets called to the scene of a disaster
to shoot the survivors . . . A connection that was working
has now apparently failed . We have an active mount point
( presumably ) that we need to dump . If we get errors along
the way - make some noise , but we are already turning out
the lights to exit anyways . . .
*/
if ( umount ( mount_point ) ! = 0 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Could not umount %s: %s \n " ,
getpid ( ) , mount_point , strerror ( errno ) ) ) ;
1999-02-15 02:15:54 +03:00
return ;
}
1999-12-13 16:27:58 +03:00
if ( ( fd = open ( MOUNTED " ~ " , O_RDWR | O_CREAT | O_EXCL , 0600 ) ) = = - 1 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Can't get " MOUNTED " ~ lock file " , getpid ( ) ) ) ;
1999-02-15 02:15:54 +03:00
return ;
}
1999-12-13 16:27:58 +03:00
1999-02-15 02:15:54 +03:00
close ( fd ) ;
if ( ( mtab = setmntent ( MOUNTED , " r " ) ) = = NULL ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Can't open " MOUNTED " : %s \n " ,
getpid ( ) , strerror ( errno ) ) ) ;
1999-02-15 02:15:54 +03:00
return ;
}
# define MOUNTED_TMP MOUNTED".tmp"
if ( ( new_mtab = setmntent ( MOUNTED_TMP , " w " ) ) = = NULL ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Can't open " MOUNTED_TMP " : %s \n " ,
getpid ( ) , strerror ( errno ) ) ) ;
1999-02-15 02:15:54 +03:00
endmntent ( mtab ) ;
return ;
}
while ( ( mnt = getmntent ( mtab ) ) ! = NULL ) {
if ( strcmp ( mnt - > mnt_dir , mount_point ) ! = 0 ) {
addmntent ( new_mtab , mnt ) ;
}
}
endmntent ( mtab ) ;
if ( fchmod ( fileno ( new_mtab ) , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) < 0 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Error changing mode of %s: %s \n " ,
getpid ( ) , MOUNTED_TMP , strerror ( errno ) ) ) ;
1999-02-15 02:15:54 +03:00
return ;
}
endmntent ( new_mtab ) ;
if ( rename ( MOUNTED_TMP , MOUNTED ) < 0 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Cannot rename %s to %s: %s \n " ,
getpid ( ) , MOUNTED , MOUNTED_TMP , strerror ( errno ) ) ) ;
1999-02-15 02:15:54 +03:00
return ;
}
1999-12-13 16:27:58 +03:00
if ( unlink ( MOUNTED " ~ " ) = = - 1 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " %d: Can't remove " MOUNTED " ~ " , getpid ( ) ) ) ;
1999-02-15 02:15:54 +03:00
return ;
}
}
1998-01-06 01:56:29 +03:00
/*
* Call the smbfs ioctl to install a connection socket ,
* then wait for a signal to reconnect . Note that we do
* not exit after open_sockets ( ) or send_login ( ) errors ,
* as the smbfs mount would then have no way to recover .
*/
1999-12-13 16:27:58 +03:00
static void send_fs_socket ( char * service , char * mount_point , struct cli_state * c )
1998-01-06 01:56:29 +03:00
{
int fd , closed = 0 , res = 1 ;
1999-02-01 00:28:55 +03:00
pid_t parentpid = getppid ( ) ;
1999-12-13 16:27:58 +03:00
struct smb_conn_opt conn_options ;
memset ( & conn_options , 0 , sizeof ( conn_options ) ) ;
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
while ( 1 ) {
if ( ( fd = open ( mount_point , O_RDONLY ) ) < 0 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " mount.smbfs[%d]: can't open %s \n " ,
getpid ( ) , mount_point ) ) ;
1998-01-06 01:56:29 +03:00
break ;
2001-03-10 02:48:58 +03:00
}
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
conn_options . fd = c - > fd ;
conn_options . protocol = c - > protocol ;
conn_options . case_handling = SMB_CASE_DEFAULT ;
conn_options . max_xmit = c - > max_xmit ;
conn_options . server_uid = c - > vuid ;
conn_options . tid = c - > cnum ;
conn_options . secmode = c - > sec_mode ;
conn_options . rawmode = 0 ;
conn_options . sesskey = c - > sesskey ;
conn_options . maxraw = 0 ;
conn_options . capabilities = c - > capabilities ;
conn_options . serverzone = c - > serverzone / 60 ;
1998-01-06 01:56:29 +03:00
res = ioctl ( fd , SMB_IOC_NEWCONN , & conn_options ) ;
1999-12-13 16:27:58 +03:00
if ( res ! = 0 ) {
2001-03-10 02:48:58 +03:00
DEBUG ( 0 , ( " mount.smbfs[%d]: ioctl failed, res=%d \n " ,
getpid ( ) , res ) ) ;
close ( fd ) ;
1999-12-13 16:27:58 +03:00
break ;
1998-01-06 01:56:29 +03:00
}
1999-12-13 16:27:58 +03:00
if ( parentpid ) {
1999-02-01 00:28:55 +03:00
/* Ok... We are going to kill the parent. Now
is the time to break the process group . . . */
setsid ( ) ;
/* Send a signal to the parent to terminate */
1999-12-13 16:27:58 +03:00
kill ( parentpid , SIGTERM ) ;
1999-02-01 00:28:55 +03:00
parentpid = 0 ;
}
1998-01-06 01:56:29 +03:00
close ( fd ) ;
1999-12-13 16:27:58 +03:00
2001-03-10 02:48:58 +03:00
/* This looks wierd but we are only closing the userspace
side , the connection has already been passed to smbfs and
it has increased the usage count on the socket .
If we don ' t do this we will " leak " sockets and memory on
each reconnection we have to make . */
cli_shutdown ( c ) ;
2001-09-17 04:52:47 +04:00
SAFE_FREE ( c ) ;
2001-03-10 02:48:58 +03:00
1999-12-13 16:27:58 +03:00
if ( ! closed ) {
2001-03-10 02:48:58 +03:00
/* redirect stdout & stderr since we can't know that
the library functions we use are using DEBUG . */
if ( ( fd = open ( " /dev/null " , O_WRONLY ) ) < 0 )
DEBUG ( 2 , ( " mount.smbfs: can't open /dev/null \n " ) ) ;
close_our_files ( fd ) ;
if ( fd > = 0 ) {
dup2 ( fd , STDOUT_FILENO ) ;
dup2 ( fd , STDERR_FILENO ) ;
close ( fd ) ;
}
/* here we are no longer interactive */
pstrcpy ( remote_machine , " smbmount " ) ; /* sneaky ... */
setup_logging ( " mount.smbfs " , False ) ;
append_log = True ;
reopen_logs ( ) ;
DEBUG ( 0 , ( " mount.smbfs: entering daemon mode for service %s, pid=%d \n " , service , getpid ( ) ) ) ;
1998-01-06 01:56:29 +03:00
closed = 1 ;
}
2001-03-10 02:48:58 +03:00
/* Wait for a signal from smbfs ... but don't continue
until we actually get a new connection . */
while ( ! c ) {
CatchSignal ( SIGUSR1 , & usr1_handler ) ;
pause ( ) ;
DEBUG ( 2 , ( " mount.smbfs[%d]: got signal, getting new socket \n " , getpid ( ) ) ) ;
c = do_connection ( service ) ;
}
1999-12-13 16:27:58 +03:00
}
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
smb_umount ( mount_point ) ;
2001-03-10 02:48:58 +03:00
DEBUG ( 2 , ( " mount.smbfs[%d]: exit \n " , getpid ( ) ) ) ;
1999-12-13 16:27:58 +03:00
exit ( 1 ) ;
}
1998-01-22 06:47:48 +03:00
1999-12-13 16:27:58 +03:00
2001-11-19 05:49:53 +03:00
/**
* Mount a smbfs
* */
1999-12-13 16:27:58 +03:00
static void init_mount ( void )
1998-01-06 01:56:29 +03:00
{
1998-01-22 06:47:48 +03:00
char mount_point [ MAXPATHLEN + 1 ] ;
1999-12-13 16:27:58 +03:00
pstring tmp ;
pstring svc2 ;
struct cli_state * c ;
char * args [ 20 ] ;
int i , status ;
if ( realpath ( mpoint , mount_point ) = = NULL ) {
fprintf ( stderr , " Could not resolve mount point %s \n " , mpoint ) ;
1998-01-06 01:56:29 +03:00
return ;
}
1999-12-13 16:27:58 +03:00
c = do_connection ( service ) ;
if ( ! c ) {
fprintf ( stderr , " SMB connection failed \n " ) ;
exit ( 1 ) ;
1998-01-06 01:56:29 +03:00
}
1999-02-01 00:28:55 +03:00
/*
Set up to return as a daemon child and wait in the parent
until the child say it ' s ready . . .
*/
daemonize ( ) ;
1999-12-13 16:27:58 +03:00
pstrcpy ( svc2 , service ) ;
string_replace ( svc2 , ' \\ ' , ' / ' ) ;
string_replace ( svc2 , ' ' , ' _ ' ) ;
memset ( args , 0 , sizeof ( args [ 0 ] ) * 20 ) ;
i = 0 ;
args [ i + + ] = " smbmnt " ;
args [ i + + ] = mount_point ;
args [ i + + ] = " -s " ;
args [ i + + ] = svc2 ;
if ( mount_ro ) {
args [ i + + ] = " -r " ;
}
if ( mount_uid ) {
2001-04-09 00:22:39 +04:00
slprintf ( tmp , sizeof ( tmp ) - 1 , " %d " , mount_uid ) ;
1999-12-13 16:27:58 +03:00
args [ i + + ] = " -u " ;
args [ i + + ] = xstrdup ( tmp ) ;
}
if ( mount_gid ) {
2001-04-09 00:22:39 +04:00
slprintf ( tmp , sizeof ( tmp ) - 1 , " %d " , mount_gid ) ;
1999-12-13 16:27:58 +03:00
args [ i + + ] = " -g " ;
args [ i + + ] = xstrdup ( tmp ) ;
}
if ( mount_fmask ) {
2001-04-09 00:22:39 +04:00
slprintf ( tmp , sizeof ( tmp ) - 1 , " 0%o " , mount_fmask ) ;
1999-12-13 16:27:58 +03:00
args [ i + + ] = " -f " ;
args [ i + + ] = xstrdup ( tmp ) ;
}
if ( mount_dmask ) {
2001-04-09 00:22:39 +04:00
slprintf ( tmp , sizeof ( tmp ) - 1 , " 0%o " , mount_dmask ) ;
1999-12-13 16:27:58 +03:00
args [ i + + ] = " -d " ;
args [ i + + ] = xstrdup ( tmp ) ;
}
2001-03-10 02:48:58 +03:00
if ( options ) {
args [ i + + ] = " -o " ;
args [ i + + ] = options ;
}
1999-12-13 16:27:58 +03:00
2000-05-02 06:23:41 +04:00
if ( sys_fork ( ) = = 0 ) {
2001-11-19 05:49:53 +03:00
char * smbmnt_path ;
smbmnt_path = asprintf ( " %s/smbmnt " , dyn_BINDIR ) ;
if ( file_exist ( smbmnt_path , NULL ) ) {
execv ( smbmnt_path , args ) ;
fprintf ( stderr ,
" smbfs/init_mount: execv of %s failed. Error was %s. " ,
smbmnt_path , strerror ( errno ) ) ;
1999-12-13 16:27:58 +03:00
} else {
execvp ( " smbmnt " , args ) ;
2001-11-19 05:49:53 +03:00
fprintf ( stderr ,
" smbfs/init_mount: execv of %s failed. Error was %s. " ,
" smbmnt " , strerror ( errno ) ) ;
1999-12-13 16:27:58 +03:00
}
2001-11-19 05:49:53 +03:00
free ( smbmnt_path ) ;
1999-12-13 16:27:58 +03:00
exit ( 1 ) ;
}
if ( waitpid ( - 1 , & status , 0 ) = = - 1 ) {
fprintf ( stderr , " waitpid failed: Error was %s " , strerror ( errno ) ) ;
/* FIXME: do some proper error handling */
1998-01-06 01:56:29 +03:00
exit ( 1 ) ;
2001-03-10 02:48:58 +03:00
}
1999-12-13 16:27:58 +03:00
if ( WIFEXITED ( status ) & & WEXITSTATUS ( status ) ! = 0 ) {
fprintf ( stderr , " smbmnt failed: %d \n " , WEXITSTATUS ( status ) ) ;
2001-03-10 02:48:58 +03:00
/* FIXME: do some proper error handling */
exit ( 1 ) ;
1998-01-06 01:56:29 +03:00
}
1998-11-13 23:32:22 +03:00
1999-02-15 02:15:54 +03:00
/* Ok... This is the rubicon for that mount point... At any point
after this , if the connections fail and can not be reconstructed
for any reason , we will have to unmount the mount point . There
is no exit from the next call . . .
*/
1999-12-13 16:27:58 +03:00
send_fs_socket ( service , mount_point , c ) ;
1999-02-15 02:15:54 +03:00
}
1998-01-06 01:56:29 +03:00
2001-03-10 02:48:58 +03:00
/****************************************************************************
get a password from a a file or file descriptor
exit on failure ( from smbclient , move to libsmb or shared . c file ? )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void get_password_file ( void )
{
int fd = - 1 ;
char * p ;
BOOL close_it = False ;
pstring spec ;
char pass [ 128 ] ;
if ( ( p = getenv ( " PASSWD_FD " ) ) ! = NULL ) {
pstrcpy ( spec , " descriptor " ) ;
pstrcat ( spec , p ) ;
sscanf ( p , " %d " , & fd ) ;
close_it = False ;
} else if ( ( p = getenv ( " PASSWD_FILE " ) ) ! = NULL ) {
fd = sys_open ( p , O_RDONLY , 0 ) ;
pstrcpy ( spec , p ) ;
if ( fd < 0 ) {
fprintf ( stderr , " Error opening PASSWD_FILE %s: %s \n " ,
spec , strerror ( errno ) ) ;
exit ( 1 ) ;
}
close_it = True ;
}
for ( p = pass , * p = ' \0 ' ; /* ensure that pass is null-terminated */
p & & p - pass < sizeof ( pass ) ; ) {
switch ( read ( fd , p , 1 ) ) {
case 1 :
if ( * p ! = ' \n ' & & * p ! = ' \0 ' ) {
* + + p = ' \0 ' ; /* advance p, and null-terminate pass */
break ;
}
case 0 :
if ( p - pass ) {
* p = ' \0 ' ; /* null-terminate it, just in case... */
p = NULL ; /* then force the loop condition to become false */
break ;
} else {
fprintf ( stderr , " Error reading password from file %s: %s \n " ,
spec , " empty password \n " ) ;
exit ( 1 ) ;
}
default :
fprintf ( stderr , " Error reading password from file %s: %s \n " ,
spec , strerror ( errno ) ) ;
exit ( 1 ) ;
}
}
pstrcpy ( password , pass ) ;
if ( close_it )
close ( fd ) ;
}
/****************************************************************************
get username and password from a credentials file
exit on failure ( from smbclient , move to libsmb or shared . c file ? )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void read_credentials_file ( char * filename )
{
FILE * auth ;
fstring buf ;
uint16 len = 0 ;
char * ptr , * val , * param ;
if ( ( auth = sys_fopen ( filename , " r " ) ) = = NULL )
{
/* fail if we can't open the credentials file */
DEBUG ( 0 , ( " ERROR: Unable to open credentials file! \n " ) ) ;
exit ( - 1 ) ;
}
while ( ! feof ( auth ) )
{
/* get a line from the file */
if ( ! fgets ( buf , sizeof ( buf ) , auth ) )
continue ;
len = strlen ( buf ) ;
if ( ( len ) & & ( buf [ len - 1 ] = = ' \n ' ) )
{
buf [ len - 1 ] = ' \0 ' ;
len - - ;
}
if ( len = = 0 )
continue ;
/* break up the line into parameter & value.
will need to eat a little whitespace possibly */
param = buf ;
if ( ! ( ptr = strchr ( buf , ' = ' ) ) )
continue ;
val = ptr + 1 ;
* ptr = ' \0 ' ;
/* eat leading white space */
while ( ( * val ! = ' \0 ' ) & & ( ( * val = = ' ' ) | | ( * val = = ' \t ' ) ) )
val + + ;
if ( strwicmp ( " password " , param ) = = 0 )
{
pstrcpy ( password , val ) ;
got_pass = True ;
}
else if ( strwicmp ( " username " , param ) = = 0 )
pstrcpy ( username , val ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
}
fclose ( auth ) ;
}
1998-01-06 01:56:29 +03:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
usage on the program
1998-01-06 01:56:29 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static void usage ( void )
1998-01-06 01:56:29 +03:00
{
1999-12-13 16:27:58 +03:00
printf ( " Usage: mount.smbfs service mountpoint [-o options,...] \n " ) ;
printf ( " Version %s \n \n " , VERSION ) ;
printf (
" Options:
username = < arg > SMB username
password = < arg > SMB password
2001-03-10 22:50:36 +03:00
credentials = < filename > file with username / password
1999-12-13 16:27:58 +03:00
netbiosname = < arg > source NetBIOS name
uid = < arg > mount uid or username
gid = < arg > mount gid or groupname
port = < arg > remote SMB port number
fmask = < arg > file umask
dmask = < arg > directory umask
debug = < arg > debug level
ip = < arg > destination host or IP address
workgroup = < arg > workgroup on destination
sockopt = < arg > TCP socket options
scope = < arg > NetBIOS scope
2001-03-10 22:50:36 +03:00
iocharset = < arg > Linux charset ( iso8859 - 1 , utf8 )
codepage = < arg > server codepage ( cp850 )
ttl = < arg > dircache time to live
1999-12-13 16:27:58 +03:00
guest don ' t prompt for a password
ro mount read - only
rw mount read - write
This command is designed to be run from within / bin / mount by giving
the option ' - t smbfs ' . For example :
mount - t smbfs - o username = tridge , password = foobar //fjall/test /data/test
" );
1998-01-06 01:56:29 +03:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Argument parsing for mount . smbfs interface
mount will call us like this :
mount . smbfs device mountpoint - o < options >
< options > is never empty , containing at least rw or ro
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void parse_mount_smb ( int argc , char * * argv )
1998-01-06 01:56:29 +03:00
{
1999-12-13 16:27:58 +03:00
int opt ;
char * opts ;
char * opteq ;
extern char * optarg ;
int val ;
2000-01-07 09:55:36 +03:00
extern pstring global_scope ;
2001-03-10 02:48:58 +03:00
char * p ;
1999-12-13 16:27:58 +03:00
if ( argc < 2 | | argv [ 1 ] [ 0 ] = = ' - ' ) {
usage ( ) ;
exit ( 1 ) ;
}
pstrcpy ( service , argv [ 1 ] ) ;
pstrcpy ( mpoint , argv [ 2 ] ) ;
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
/* Convert any '/' characters in the service name to
' \ ' characters */
string_replace ( service , ' / ' , ' \\ ' ) ;
argc - = 2 ;
argv + = 2 ;
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
opt = getopt ( argc , argv , " o: " ) ;
if ( opt ! = ' o ' ) {
return ;
}
1998-01-06 01:56:29 +03:00
2001-03-10 02:48:58 +03:00
options [ 0 ] = 0 ;
p = options ;
1999-12-13 16:27:58 +03:00
/*
* option parsing from nfsmount . c ( util - linux - 2.9 u )
*/
for ( opts = strtok ( optarg , " , " ) ; opts ; opts = strtok ( NULL , " , " ) ) {
DEBUG ( 3 , ( " opts: %s \n " , opts ) ) ;
2001-07-04 11:36:09 +04:00
if ( ( opteq = strchr_m ( opts , ' = ' ) ) ) {
1999-12-13 16:27:58 +03:00
val = atoi ( opteq + 1 ) ;
* opteq = ' \0 ' ;
if ( ! strcmp ( opts , " username " ) | |
! strcmp ( opts , " logon " ) ) {
char * lp ;
pstrcpy ( username , opteq + 1 ) ;
2001-07-04 11:36:09 +04:00
if ( ( lp = strchr_m ( username , ' % ' ) ) ) {
1999-12-13 16:27:58 +03:00
* lp = 0 ;
pstrcpy ( password , lp + 1 ) ;
got_pass = True ;
2001-07-04 11:36:09 +04:00
memset ( strchr_m ( opteq + 1 , ' % ' ) + 1 , ' X ' , strlen ( password ) ) ;
1999-12-13 16:27:58 +03:00
}
2001-07-04 11:36:09 +04:00
if ( ( lp = strchr_m ( username , ' / ' ) ) ) {
1999-12-13 16:27:58 +03:00
* lp = 0 ;
pstrcpy ( workgroup , lp + 1 ) ;
}
} else if ( ! strcmp ( opts , " passwd " ) | |
! strcmp ( opts , " password " ) ) {
pstrcpy ( password , opteq + 1 ) ;
got_pass = True ;
memset ( opteq + 1 , ' X ' , strlen ( password ) ) ;
2001-03-10 02:48:58 +03:00
} else if ( ! strcmp ( opts , " credentials " ) ) {
pstrcpy ( credentials , opteq + 1 ) ;
1999-12-13 16:27:58 +03:00
} else if ( ! strcmp ( opts , " netbiosname " ) ) {
pstrcpy ( my_netbios_name , opteq + 1 ) ;
} else if ( ! strcmp ( opts , " uid " ) ) {
mount_uid = nametouid ( opteq + 1 ) ;
} else if ( ! strcmp ( opts , " gid " ) ) {
mount_gid = nametogid ( opteq + 1 ) ;
} else if ( ! strcmp ( opts , " port " ) ) {
smb_port = val ;
} else if ( ! strcmp ( opts , " fmask " ) ) {
mount_fmask = strtol ( opteq + 1 , NULL , 8 ) ;
} else if ( ! strcmp ( opts , " dmask " ) ) {
mount_dmask = strtol ( opteq + 1 , NULL , 8 ) ;
} else if ( ! strcmp ( opts , " debug " ) ) {
DEBUGLEVEL = val ;
} else if ( ! strcmp ( opts , " ip " ) ) {
dest_ip = * interpret_addr2 ( opteq + 1 ) ;
if ( zero_ip ( dest_ip ) ) {
fprintf ( stderr , " Can't resolve address %s \n " , opteq + 1 ) ;
exit ( 1 ) ;
}
have_ip = True ;
} else if ( ! strcmp ( opts , " workgroup " ) ) {
pstrcpy ( workgroup , opteq + 1 ) ;
} else if ( ! strcmp ( opts , " sockopt " ) ) {
pstrcpy ( user_socket_options , opteq + 1 ) ;
} else if ( ! strcmp ( opts , " scope " ) ) {
2000-01-07 09:55:36 +03:00
pstrcpy ( global_scope , opteq + 1 ) ;
1999-12-13 16:27:58 +03:00
} else {
2001-03-10 02:48:58 +03:00
slprintf ( p , sizeof ( pstring ) - ( p - options ) - 1 , " %s=%s, " , opts , opteq + 1 ) ;
p + = strlen ( p ) ;
1999-12-13 16:27:58 +03:00
}
} else {
val = 1 ;
if ( ! strcmp ( opts , " nocaps " ) ) {
fprintf ( stderr , " Unhandled option: %s \n " , opteq + 1 ) ;
exit ( 1 ) ;
} else if ( ! strcmp ( opts , " guest " ) ) {
2001-09-21 01:06:02 +04:00
* password = ' \0 ' ;
1999-12-13 16:27:58 +03:00
got_pass = True ;
} else if ( ! strcmp ( opts , " rw " ) ) {
mount_ro = 0 ;
} else if ( ! strcmp ( opts , " ro " ) ) {
mount_ro = 1 ;
2001-03-10 02:48:58 +03:00
} else {
strncpy ( p , opts , sizeof ( pstring ) - ( p - options ) - 1 ) ;
p + = strlen ( opts ) ;
* p + + = ' , ' ;
* p = 0 ;
1999-12-13 16:27:58 +03:00
}
}
}
if ( ! * service ) {
usage ( ) ;
exit ( 1 ) ;
}
2001-03-10 02:48:58 +03:00
if ( p ! = options ) {
* ( p - 1 ) = 0 ; /* remove trailing , */
DEBUG ( 3 , ( " passthrough options '%s' \n " , options ) ) ;
}
1998-01-06 01:56:29 +03:00
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main ( int argc , char * argv [ ] )
{
1999-12-13 16:27:58 +03:00
extern char * optarg ;
extern int optind ;
2001-11-19 05:49:53 +03:00
static pstring servicesf = dyn_CONFIGFILE ;
1999-12-13 16:27:58 +03:00
char * p ;
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
DEBUGLEVEL = 1 ;
2001-03-10 02:48:58 +03:00
/* here we are interactive, even if run from autofs */
1999-12-13 16:27:58 +03:00
setup_logging ( " mount.smbfs " , True ) ;
1998-01-06 01:56:29 +03:00
2001-09-21 01:06:02 +04:00
/* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default
is to not announce any unicode capabilities as current smbfs does
not support it . */
p = getenv ( " CLI_FORCE_ASCII " ) ;
if ( p & & ! strcmp ( p , " false " ) )
unsetenv ( " CLI_FORCE_ASCII " ) ;
else
setenv ( " CLI_FORCE_ASCII " , " true " , 1 ) ;
1999-12-13 16:27:58 +03:00
TimeInit ( ) ;
in_client = True ; /* Make sure that we tell lp_load we are */
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
if ( getenv ( " USER " ) ) {
pstrcpy ( username , getenv ( " USER " ) ) ;
1998-01-06 01:56:29 +03:00
2001-07-04 11:36:09 +04:00
if ( ( p = strchr_m ( username , ' % ' ) ) ) {
1999-12-13 16:27:58 +03:00
* p = 0 ;
pstrcpy ( password , p + 1 ) ;
got_pass = True ;
2001-07-04 11:36:09 +04:00
memset ( strchr_m ( getenv ( " USER " ) , ' % ' ) + 1 , ' X ' , strlen ( password ) ) ;
1999-12-13 16:27:58 +03:00
}
2001-03-10 02:48:58 +03:00
strupper ( username ) ;
1999-12-13 16:27:58 +03:00
}
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
if ( getenv ( " PASSWD " ) ) {
pstrcpy ( password , getenv ( " PASSWD " ) ) ;
2001-03-10 02:48:58 +03:00
got_pass = True ;
}
if ( getenv ( " PASSWD_FD " ) | | getenv ( " PASSWD_FILE " ) ) {
get_password_file ( ) ;
got_pass = True ;
1999-12-13 16:27:58 +03:00
}
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
if ( * username = = 0 & & getenv ( " LOGNAME " ) ) {
pstrcpy ( username , getenv ( " LOGNAME " ) ) ;
}
if ( ! lp_load ( servicesf , True , False , False ) ) {
fprintf ( stderr , " Can't load %s - run testparm to debug it \n " ,
servicesf ) ;
}
1998-01-06 01:56:29 +03:00
2001-03-10 02:48:58 +03:00
parse_mount_smb ( argc , argv ) ;
if ( * credentials ! = 0 ) {
read_credentials_file ( credentials ) ;
}
DEBUG ( 3 , ( " mount.smbfs started (version %s) \n " , VERSION ) ) ;
1999-12-13 16:27:58 +03:00
if ( * workgroup = = 0 ) {
pstrcpy ( workgroup , lp_workgroup ( ) ) ;
}
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
load_interfaces ( ) ;
if ( ! * my_netbios_name ) {
pstrcpy ( my_netbios_name , myhostname ( ) ) ;
1998-01-06 01:56:29 +03:00
}
1999-12-13 16:27:58 +03:00
strupper ( my_netbios_name ) ;
1998-01-06 01:56:29 +03:00
1999-12-13 16:27:58 +03:00
init_mount ( ) ;
return 0 ;
1998-01-06 01:56:29 +03:00
}