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
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 .
*/
# 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"
2004-11-02 10:18:24 +03:00
2003-08-13 05:53:07 +04:00
/****************************************************************************
Add a home service . Returns the new service number or - 1 if fail .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int add_home_service ( const char * service , const char * username , const char * homedir )
{
int iHomeService ;
if ( ! service | | ! homedir )
return - 1 ;
if ( ( iHomeService = lp_servicenumber ( HOMES_NAME ) ) < 0 )
return - 1 ;
/*
* If this is a winbindd provided username , remove
* the domain component before adding the service .
* Log a warning if the " path= " parameter does not
* include any macros .
*/
{
const char * p = strchr ( service , * lp_winbind_separator ( ) ) ;
/* We only want the 'user' part of the string */
if ( p ) {
service = p + 1 ;
}
}
if ( ! lp_add_home ( service , iHomeService , username , homedir ) ) {
return - 1 ;
}
return lp_servicenumber ( service ) ;
}
/**
* Find a service entry . service is always in dos codepage .
*
* @ param service is modified ( to canonical form ? ? )
* */
static int find_service ( const char * service )
{
int iService ;
iService = lp_servicenumber ( service ) ;
2005-02-10 10:39:14 +03:00
if ( iService > = 0 & & ! lp_snum_ok ( iService ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 0 , ( " Invalid snum %d for %s \n " , iService , service ) ) ;
iService = - 1 ;
}
if ( iService = = - 1 ) {
DEBUG ( 3 , ( " find_service() failed to find service %s \n " , service ) ) ;
}
return iService ;
}
/****************************************************************************
Make a connection , given the snum to connect to , and the vuser of the
connecting user if appropriate .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
static NTSTATUS make_connection_snum ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
int snum , enum ntvfs_type type ,
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 ;
2004-09-24 07:34:55 +04:00
if ( ! socket_check_access ( req - > smb_conn - > connection - > socket ,
lp_servicename ( snum ) ,
lp_hostsallow ( snum ) ,
lp_hostsdeny ( snum ) ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
2005-01-13 21:49:10 +03:00
tcon = smbsrv_tcon_new ( req - > smb_conn ) ;
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
2004-06-28 12:27:36 +04:00
tcon - > service = snum ;
2003-08-13 05:53:07 +04:00
/* init ntvfs function pointers */
2004-09-29 17:17:09 +04:00
status = ntvfs_init_connection ( req , type ) ;
2003-08-13 05:53:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-02-10 10:39:14 +03:00
DEBUG ( 0 , ( " ntvfs_init_connection failed for service %s \n " ,
lp_servicename ( tcon - > service ) ) ) ;
2003-08-13 05:53:07 +04:00
return status ;
}
2005-01-13 21:49:10 +03:00
2003-08-13 05:53:07 +04:00
/* Invoke NTVFS connection hook */
2004-09-29 17:17:09 +04:00
status = ntvfs_connect ( req , lp_servicename ( snum ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " make_connection: NTVFS make connection failed! \n " ) ) ;
return status ;
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 ;
}
/****************************************************************************
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 ,
2004-05-25 21:24:24 +04:00
const char * dev , uint16_t vuid )
2003-08-13 05:53:07 +04:00
{
int snum ;
enum ntvfs_type type ;
const char * type_str ;
/* 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 ;
}
}
snum = find_service ( service ) ;
if ( snum = = - 1 ) {
2004-09-23 03:50:28 +04:00
DEBUG ( 0 , ( " couldn't find service %s \n " , service ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_BAD_NETWORK_NAME ;
}
/* work out what sort of connection this is */
if ( strcmp ( lp_fstype ( snum ) , " IPC " ) = = 0 ) {
type = NTVFS_IPC ;
type_str = " IPC " ;
} else if ( lp_print_ok ( snum ) ) {
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 ;
}
return make_connection_snum ( req , snum , type , password , dev ) ;
}
/*
backend for tree connect call
*/
2004-06-28 12:39:00 +04:00
NTSTATUS tcon_backend ( struct smbsrv_request * req , union smb_tcon * con )
2003-08-13 05:53:07 +04:00
{
NTSTATUS status ;
2004-07-14 16:44:31 +04:00
uint16_t vuid = UID_FIELD_INVALID ;
2003-08-13 05:53:07 +04:00
/* can only do bare tcon in share level security */
2004-07-14 16:44:31 +04:00
if ( req - > session = = NULL & & lp_security ( ) ! = SEC_SHARE ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2004-07-14 16:44:31 +04:00
if ( req - > session ) {
vuid = req - > session - > vuid ;
}
2003-08-13 05:53:07 +04:00
if ( con - > generic . level = = RAW_TCON_TCON ) {
DATA_BLOB password ;
password = data_blob ( con - > tcon . in . password , strlen ( con - > tcon . in . password ) + 1 ) ;
2004-07-14 16:44:31 +04:00
status = make_connection ( req , con - > tcon . in . service , password , con - > tcon . in . dev , vuid ) ;
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 ;
}
status = make_connection ( req , con - > tconx . in . path , con - > tconx . in . password ,
2004-07-14 16:44:31 +04:00
con - > tconx . in . device , vuid ) ;
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 ;
2004-09-08 09:39:06 +04:00
con - > tconx . out . dev_type = talloc_strdup ( req , req - > tcon - > dev_type ) ;
con - > tconx . out . fs_type = talloc_strdup ( req , req - > tcon - > fs_type ) ;
2004-06-28 12:27:36 +04:00
con - > tconx . out . options = SMB_SUPPORT_SEARCH_BITS | ( lp_csc_policy ( req - > tcon - > service ) < < 2 ) ;
if ( lp_msdfs_root ( req - > tcon - > service ) & & lp_host_msdfs ( ) ) {
2003-08-13 05:53:07 +04:00
con - > tconx . out . options | = SMB_SHARE_IN_DFS ;
}
return status ;
}