2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
service ( connection ) handling
Copyright ( C ) Andrew Tridgell 1992 - 2003
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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2004-11-02 10:18:24 +03:00
# include "smb_server/smb_server.h"
2005-01-30 03:54:57 +03:00
# include "smbd/service_stream.h"
2005-12-28 01:51:30 +03:00
# include "ntvfs/ntvfs.h"
2007-09-08 16:42:09 +04:00
# include "param/share.h"
# include "param/param.h"
2004-11-02 10:18:24 +03:00
2003-08-13 05:53:07 +04:00
/****************************************************************************
Make a connection , given the snum to connect to , and the vuser of the
connecting user if appropriate .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-23 22:43:07 +04:00
static NTSTATUS make_connection_scfg ( struct smbsrv_request * req ,
struct share_config * scfg ,
enum ntvfs_type type ,
2003-08-13 05:53:07 +04:00
DATA_BLOB password ,
const char * dev )
{
2004-06-28 12:27:36 +04:00
struct smbsrv_tcon * tcon ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
2006-07-23 22:43:07 +04:00
tcon = smbsrv_smb_tcon_new ( req - > smb_conn , scfg - > name ) ;
2004-06-28 12:27:36 +04:00
if ( ! tcon ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 0 , ( " Couldn't find free connection. \n " ) ) ;
return NT_STATUS_INSUFFICIENT_RESOURCES ;
}
2004-06-28 12:27:36 +04:00
req - > tcon = tcon ;
2003-08-13 05:53:07 +04:00
/* init ntvfs function pointers */
2006-07-23 22:43:07 +04:00
status = ntvfs_init_connection ( tcon , scfg , type ,
2006-03-15 20:28:46 +03:00
req - > smb_conn - > negotiate . protocol ,
req - > smb_conn - > connection - > event . ctx ,
req - > smb_conn - > connection - > msg_ctx ,
2007-12-10 06:33:16 +03:00
req - > smb_conn - > lp_ctx ,
2006-03-15 20:28:46 +03:00
req - > smb_conn - > connection - > server_id ,
& tcon - > ntvfs ) ;
2003-08-13 05:53:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-23 22:43:07 +04:00
DEBUG ( 0 , ( " make_connection_scfg: connection failed for service %s \n " ,
scfg - > name ) ) ;
2006-03-15 20:28:46 +03:00
goto failed ;
}
status = ntvfs_set_oplock_handler ( tcon - > ntvfs , smbsrv_send_oplock_break , tcon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " make_connection: NTVFS failed to set the oplock handler! \n " ) ) ;
goto failed ;
2003-08-13 05:53:07 +04:00
}
2005-01-13 21:49:10 +03:00
2006-03-16 21:54:19 +03:00
status = ntvfs_set_addr_callbacks ( tcon - > ntvfs , smbsrv_get_my_addr , smbsrv_get_peer_addr , req - > smb_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-05-20 12:15:22 +04:00
DEBUG ( 0 , ( " make_connection: NTVFS failed to set the addr callbacks! \n " ) ) ;
goto failed ;
}
status = ntvfs_set_handle_callbacks ( tcon - > ntvfs ,
smbsrv_handle_create_new ,
smbsrv_handle_make_valid ,
smbsrv_handle_destroy ,
smbsrv_handle_search_by_wire_key ,
smbsrv_handle_get_wire_key ,
tcon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " make_connection: NTVFS failed to set the handle callbacks! \n " ) ) ;
2006-03-16 21:54:19 +03:00
goto failed ;
}
2006-03-18 14:10:21 +03:00
req - > ntvfs = ntvfs_request_create ( req - > tcon - > ntvfs , req ,
req - > session - > session_info ,
SVAL ( req - > in . hdr , HDR_PID ) ,
req - > request_time ,
req , NULL , 0 ) ;
if ( ! req - > ntvfs ) {
status = NT_STATUS_NO_MEMORY ;
goto failed ;
}
2006-03-16 21:54:19 +03:00
2003-08-13 05:53:07 +04:00
/* Invoke NTVFS connection hook */
2006-07-23 22:43:07 +04:00
status = ntvfs_connect ( req - > ntvfs , scfg - > name ) ;
2004-09-29 17:17:09 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " make_connection: NTVFS make connection failed! \n " ) ) ;
2006-03-15 20:28:46 +03:00
goto failed ;
2003-08-13 05:53:07 +04:00
}
2005-01-13 21:49:10 +03:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
2006-03-15 20:28:46 +03:00
failed :
req - > tcon = NULL ;
talloc_free ( tcon ) ;
return status ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
Make a connection to a service .
*
* @ param service
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
static NTSTATUS make_connection ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
const char * service , DATA_BLOB password ,
2005-11-10 16:02:56 +03:00
const char * dev )
2003-08-13 05:53:07 +04:00
{
2006-07-23 22:43:07 +04:00
NTSTATUS status ;
2003-08-13 05:53:07 +04:00
enum ntvfs_type type ;
const char * type_str ;
2006-07-23 22:43:07 +04:00
struct share_config * scfg ;
const char * sharetype ;
2005-06-16 12:40:10 +04:00
2003-08-13 05:53:07 +04:00
/* the service might be of the form \\SERVER\SHARE. Should we put
the server name we get from this somewhere ? */
if ( strncmp ( service , " \\ \\ " , 2 ) = = 0 ) {
char * p = strchr ( service + 2 , ' \\ ' ) ;
if ( p ) {
service = p + 1 ;
}
}
2006-07-23 22:43:07 +04:00
status = share_get_config ( req , req - > smb_conn - > share_context , service , & scfg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " make_connection: couldn't find service %s \n " , service ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_BAD_NETWORK_NAME ;
}
2006-07-23 22:43:07 +04:00
/* TODO: check the password, when it's share level security! */
if ( ! socket_check_access ( req - > smb_conn - > connection - > socket ,
scfg - > name ,
share_string_list_option ( req , scfg , SHARE_HOSTS_ALLOW ) ,
share_string_list_option ( req , scfg , SHARE_HOSTS_DENY ) ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
2003-08-13 05:53:07 +04:00
/* work out what sort of connection this is */
2006-07-23 22:43:07 +04:00
sharetype = share_string_option ( scfg , " type " , " DISK " ) ;
if ( sharetype & & strcmp ( sharetype , " IPC " ) = = 0 ) {
2003-08-13 05:53:07 +04:00
type = NTVFS_IPC ;
type_str = " IPC " ;
2006-07-23 22:43:07 +04:00
} else if ( sharetype & & strcmp ( sharetype , " PRINTER " ) = = 0 ) {
2003-08-13 05:53:07 +04:00
type = NTVFS_PRINT ;
type_str = " LPT: " ;
} else {
type = NTVFS_DISK ;
type_str = " A: " ;
}
if ( strcmp ( dev , " ????? " ) ! = 0 & & strcasecmp ( type_str , dev ) ! = 0 ) {
/* the client gave us the wrong device type */
return NT_STATUS_BAD_DEVICE_TYPE ;
}
2006-07-23 22:43:07 +04:00
return make_connection_scfg ( req , scfg , type , password , dev ) ;
2003-08-13 05:53:07 +04:00
}
/*
backend for tree connect call
*/
2006-03-06 18:33:25 +03:00
NTSTATUS smbsrv_tcon_backend ( struct smbsrv_request * req , union smb_tcon * con )
2003-08-13 05:53:07 +04:00
{
NTSTATUS status ;
if ( con - > generic . level = = RAW_TCON_TCON ) {
DATA_BLOB password ;
2007-04-19 20:50:16 +04:00
password = data_blob_string_const ( con - > tcon . in . password ) ;
2003-08-13 05:53:07 +04:00
2005-11-10 16:02:56 +03:00
status = make_connection ( req , con - > tcon . in . service , password , con - > tcon . in . dev ) ;
2003-08-13 05:53:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-06-29 11:40:14 +04:00
con - > tcon . out . max_xmit = req - > smb_conn - > negotiate . max_recv ;
2005-01-13 21:49:10 +03:00
con - > tcon . out . tid = req - > tcon - > tid ;
2003-08-13 05:53:07 +04:00
return status ;
}
2007-08-16 18:45:46 +04:00
/* TODO: take a look at tconx.in.flags! */
2003-08-13 05:53:07 +04:00
status = make_connection ( req , con - > tconx . in . path , con - > tconx . in . password ,
2005-11-10 16:02:56 +03:00
con - > tconx . in . device ) ;
2003-08-13 05:53:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2005-01-13 21:49:10 +03:00
con - > tconx . out . tid = req - > tcon - > tid ;
2006-03-15 20:28:46 +03:00
con - > tconx . out . dev_type = talloc_strdup ( req , req - > tcon - > ntvfs - > dev_type ) ;
con - > tconx . out . fs_type = talloc_strdup ( req , req - > tcon - > ntvfs - > fs_type ) ;
2006-07-23 22:43:07 +04:00
con - > tconx . out . options = SMB_SUPPORT_SEARCH_BITS | ( share_int_option ( req - > tcon - > ntvfs - > config , SHARE_CSC_POLICY , SHARE_CSC_POLICY_DEFAULT ) < < 2 ) ;
2007-12-03 23:25:17 +03:00
if ( share_bool_option ( req - > tcon - > ntvfs - > config , SHARE_MSDFS_ROOT , SHARE_MSDFS_ROOT_DEFAULT ) & & lp_host_msdfs ( req - > smb_conn - > lp_ctx ) ) {
2003-08-13 05:53:07 +04:00
con - > tconx . out . options | = SMB_SHARE_IN_DFS ;
}
return status ;
}