2001-02-27 21:22:39 +03:00
/*
* Unix SMB / Netbios implementation .
* Version 1.9 .
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 1997 ,
* Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1997 ,
* Copyright ( C ) Paul Ashton 1997.
* Copyright ( C ) Jeremy Allison 2001.
*
* 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 .
*/
/* This is the implementation of the srvsvc pipe. */
# include "includes.h"
extern pstring global_myname ;
/*******************************************************************
Fill in a share info level 1 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-22 20:10:28 +04:00
static void init_srv_share_info_1 ( pipes_struct * p , SRV_SHARE_INFO_1 * sh1 , int snum )
2001-02-27 21:22:39 +03:00
{
int len_net_name ;
pstring net_name ;
pstring remark ;
uint32 type ;
pstrcpy ( net_name , lp_servicename ( snum ) ) ;
pstrcpy ( remark , lp_comment ( snum ) ) ;
2001-08-22 20:10:28 +04:00
standard_sub_conn ( p - > conn , remark ) ;
2001-02-27 21:22:39 +03:00
len_net_name = strlen ( net_name ) ;
/* work out the share type */
type = STYPE_DISKTREE ;
if ( lp_print_ok ( snum ) )
type = STYPE_PRINTQ ;
2001-04-13 23:12:06 +04:00
if ( strequal ( " IPC$ " , net_name ) | | strequal ( " ADMIN$ " , net_name ) )
2001-02-27 21:22:39 +03:00
type = STYPE_IPC ;
if ( net_name [ len_net_name ] = = ' $ ' )
type | = STYPE_HIDDEN ;
init_srv_share_info1 ( & sh1 - > info_1 , net_name , type , remark ) ;
init_srv_share_info1_str ( & sh1 - > info_1_str , net_name , remark ) ;
}
/*******************************************************************
Fill in a share info level 2 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-22 20:10:28 +04:00
static void init_srv_share_info_2 ( pipes_struct * p , SRV_SHARE_INFO_2 * sh2 , int snum )
2001-02-27 21:22:39 +03:00
{
int len_net_name ;
pstring net_name ;
pstring remark ;
pstring path ;
pstring passwd ;
uint32 type ;
pstrcpy ( net_name , lp_servicename ( snum ) ) ;
pstrcpy ( remark , lp_comment ( snum ) ) ;
2001-08-22 20:10:28 +04:00
standard_sub_conn ( p - > conn , remark ) ;
2001-04-06 06:12:07 +04:00
pstrcpy ( path , " C: " ) ;
pstrcat ( path , lp_pathname ( snum ) ) ;
2001-05-01 05:01:19 +04:00
/*
* Change / to \ \ so that win2k will see it as a valid path . This was added to
* enable use of browsing in win2k add share dialog .
*/
string_replace ( path , ' / ' , ' \\ ' ) ;
2001-02-27 21:22:39 +03:00
pstrcpy ( passwd , " " ) ;
len_net_name = strlen ( net_name ) ;
/* work out the share type */
type = STYPE_DISKTREE ;
if ( lp_print_ok ( snum ) )
type = STYPE_PRINTQ ;
2001-04-13 23:12:06 +04:00
if ( strequal ( " IPC$ " , net_name ) | | strequal ( " ADMIN$ " , net_name ) )
2001-02-27 21:22:39 +03:00
type = STYPE_IPC ;
if ( net_name [ len_net_name ] = = ' $ ' )
type | = STYPE_HIDDEN ;
init_srv_share_info2 ( & sh2 - > info_2 , net_name , type , remark , 0 , 0xffffffff , 1 , path , passwd ) ;
init_srv_share_info2_str ( & sh2 - > info_2_str , net_name , remark , path , passwd ) ;
}
2001-04-10 05:44:45 +04:00
/*******************************************************************
What to do when smb . conf is updated .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void smb_conf_updated ( int msg_type , pid_t src , void * buf , size_t len )
{
DEBUG ( 10 , ( " smb_conf_updated: Got message saying smb.conf was updated. Reloading. \n " ) ) ;
reload_services ( False ) ;
}
2001-04-05 03:42:17 +04:00
/*******************************************************************
2001-04-09 00:01:51 +04:00
Create the share security tdb .
2001-04-05 03:42:17 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-04-09 00:01:51 +04:00
static TDB_CONTEXT * share_tdb ; /* used for share security descriptors */
# define SHARE_DATABASE_VERSION 1
BOOL share_info_db_init ( void )
{
static pid_t local_pid ;
char * vstring = " INFO/version " ;
if ( share_tdb & & local_pid = = sys_getpid ( ) ) return True ;
2001-09-07 02:08:19 +04:00
share_tdb = tdb_open_log ( lock_path ( " share_info.tdb " ) , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
2001-04-09 00:01:51 +04:00
if ( ! share_tdb ) {
DEBUG ( 0 , ( " Failed to open share info database %s (%s) \n " ,
lock_path ( " share_info.tdb " ) , strerror ( errno ) ) ) ;
return False ;
}
local_pid = sys_getpid ( ) ;
/* handle a Samba upgrade */
tdb_lock_bystring ( share_tdb , vstring ) ;
if ( tdb_fetch_int ( share_tdb , vstring ) ! = SHARE_DATABASE_VERSION ) {
tdb_traverse ( share_tdb , ( tdb_traverse_func ) tdb_delete , NULL ) ;
tdb_store_int ( share_tdb , vstring , SHARE_DATABASE_VERSION ) ;
}
tdb_unlock_bystring ( share_tdb , vstring ) ;
2001-04-10 05:44:45 +04:00
message_register ( MSG_SMB_CONF_UPDATED , smb_conf_updated ) ;
2001-04-09 00:01:51 +04:00
return True ;
}
/*******************************************************************
Fake up a Everyone , full access as a default .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static SEC_DESC * get_share_security_default ( TALLOC_CTX * ctx , int snum , size_t * psize )
2001-04-05 03:42:17 +04:00
{
extern DOM_SID global_sid_World ;
2001-04-09 11:03:28 +04:00
extern struct generic_mapping file_generic_mapping ;
2001-04-05 03:42:17 +04:00
SEC_ACCESS sa ;
SEC_ACE ace ;
SEC_ACL * psa = NULL ;
SEC_DESC * psd = NULL ;
2001-04-09 11:03:28 +04:00
uint32 def_access = GENERIC_ALL_ACCESS ;
2001-04-05 03:42:17 +04:00
2001-04-09 11:03:28 +04:00
se_map_generic ( & def_access , & file_generic_mapping ) ;
init_sec_access ( & sa , GENERIC_ALL_ACCESS | def_access ) ;
2001-04-05 03:42:17 +04:00
init_sec_ace ( & ace , & global_sid_World , SEC_ACE_TYPE_ACCESS_ALLOWED , sa , 0 ) ;
if ( ( psa = make_sec_acl ( ctx , NT4_ACL_REVISION , 1 , & ace ) ) ! = NULL ) {
psd = make_sec_desc ( ctx , SEC_DESC_REVISION , NULL , NULL , NULL , psa , psize ) ;
}
if ( ! psd ) {
DEBUG ( 0 , ( " get_share_security: Failed to make SEC_DESC. \n " ) ) ;
return NULL ;
}
return psd ;
}
2001-04-09 00:01:51 +04:00
/*******************************************************************
Pull a security descriptor from the share tdb .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-04-09 10:36:38 +04:00
static SEC_DESC * get_share_security ( TALLOC_CTX * ctx , int snum , size_t * psize )
2001-04-09 00:01:51 +04:00
{
prs_struct ps ;
fstring key ;
2001-04-09 21:10:06 +04:00
SEC_DESC * psd = NULL ;
* psize = 0 ;
2001-04-09 00:01:51 +04:00
/* Fetch security descriptor from tdb */
slprintf ( key , sizeof ( key ) - 1 , " SECDESC/%s " , lp_servicename ( snum ) ) ;
if ( tdb_prs_fetch ( share_tdb , key , & ps , ctx ) ! = 0 | |
! sec_io_desc ( " get_share_security " , & psd , & ps , 1 ) ) {
DEBUG ( 4 , ( " get_share_security: using default secdesc for %s \n " , lp_servicename ( snum ) ) ) ;
return get_share_security_default ( ctx , snum , psize ) ;
}
2001-04-09 21:10:06 +04:00
if ( psd )
* psize = sec_desc_size ( psd ) ;
2001-04-09 00:01:51 +04:00
prs_mem_free ( & ps ) ;
return psd ;
}
/*******************************************************************
Store a security descriptor in the share db .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-04-09 10:36:38 +04:00
static BOOL set_share_security ( TALLOC_CTX * ctx , const char * share_name , SEC_DESC * psd )
2001-04-09 00:01:51 +04:00
{
prs_struct ps ;
TALLOC_CTX * mem_ctx = NULL ;
fstring key ;
BOOL ret = False ;
mem_ctx = talloc_init ( ) ;
if ( mem_ctx = = NULL )
return False ;
prs_init ( & ps , ( uint32 ) sec_desc_size ( psd ) , mem_ctx , MARSHALL ) ;
2001-10-10 01:22:33 +04:00
if ( ! sec_io_desc ( " share_security " , & psd , & ps , 1 ) ) {
2001-04-09 00:01:51 +04:00
goto out ;
}
2001-04-09 10:36:38 +04:00
slprintf ( key , sizeof ( key ) - 1 , " SECDESC/%s " , share_name ) ;
2001-04-09 00:01:51 +04:00
if ( tdb_prs_store ( share_tdb , key , & ps ) = = 0 ) {
ret = True ;
2001-04-09 10:36:38 +04:00
DEBUG ( 5 , ( " set_share_security: stored secdesc for %s \n " , share_name ) ) ;
2001-04-09 00:01:51 +04:00
} else {
2001-04-09 10:36:38 +04:00
DEBUG ( 1 , ( " set_share_security: Failed to store secdesc for %s \n " , share_name ) ) ;
2001-04-09 00:01:51 +04:00
}
/* Free malloc'ed memory */
out :
prs_mem_free ( & ps ) ;
if ( mem_ctx )
talloc_destroy ( mem_ctx ) ;
return ret ;
}
/*******************************************************************
Delete a security descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL delete_share_security ( int snum )
{
TDB_DATA kbuf ;
fstring key ;
slprintf ( key , sizeof ( key ) - 1 , " SECDESC/%s " , lp_servicename ( snum ) ) ;
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
if ( tdb_delete ( share_tdb , kbuf ) ! = 0 ) {
DEBUG ( 0 , ( " delete_share_security: Failed to delete entry for share %s \n " ,
lp_servicename ( snum ) ) ) ;
return False ;
}
return True ;
}
2001-04-09 12:00:19 +04:00
/*******************************************************************
Map any generic bits to file specific bits .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void map_generic_share_sd_bits ( SEC_DESC * psd )
{
extern struct generic_mapping file_generic_mapping ;
int i ;
SEC_ACL * ps_dacl = NULL ;
if ( ! psd )
return ;
ps_dacl = psd - > dacl ;
if ( ! ps_dacl )
return ;
for ( i = 0 ; i < ps_dacl - > num_aces ; i + + ) {
SEC_ACE * psa = & ps_dacl - > ace [ i ] ;
uint32 orig_mask = psa - > info . mask ;
se_map_generic ( & psa - > info . mask , & file_generic_mapping ) ;
psa - > info . mask | = orig_mask ;
}
}
2001-04-09 10:36:38 +04:00
/*******************************************************************
Can this user access with share with the required permissions ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-04-12 01:19:25 +04:00
BOOL share_access_check ( connection_struct * conn , int snum , uint16 vuid , uint32 desired_access )
2001-04-09 10:36:38 +04:00
{
2001-08-27 23:46:22 +04:00
uint32 granted ;
NTSTATUS status ;
2001-04-09 10:36:38 +04:00
TALLOC_CTX * mem_ctx = NULL ;
SEC_DESC * psd = NULL ;
size_t sd_size ;
2001-09-26 04:05:03 +04:00
NT_USER_TOKEN * token = NULL ;
2001-04-09 10:36:38 +04:00
user_struct * vuser = get_valid_user_struct ( vuid ) ;
BOOL ret = True ;
mem_ctx = talloc_init ( ) ;
if ( mem_ctx = = NULL )
return False ;
psd = get_share_security ( mem_ctx , snum , & sd_size ) ;
if ( ! psd )
goto out ;
2001-10-10 23:36:53 +04:00
if ( vuser )
2001-09-26 04:05:03 +04:00
token = vuser - > nt_user_token ;
2001-10-10 23:36:53 +04:00
else
2001-09-26 04:05:03 +04:00
token = conn - > nt_user_token ;
2001-04-12 01:19:25 +04:00
2001-10-10 23:36:53 +04:00
ret = se_access_check ( psd , token , desired_access , & granted , & status ) ;
2001-04-09 10:36:38 +04:00
out :
talloc_destroy ( mem_ctx ) ;
return ret ;
}
2001-04-05 03:42:17 +04:00
/*******************************************************************
Fill in a share info level 502 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-22 20:10:28 +04:00
static void init_srv_share_info_502 ( pipes_struct * p , SRV_SHARE_INFO_502 * sh502 , int snum )
2001-04-05 03:42:17 +04:00
{
int len_net_name ;
pstring net_name ;
pstring remark ;
pstring path ;
pstring passwd ;
uint32 type ;
SEC_DESC * sd ;
size_t sd_size ;
2001-08-22 20:10:28 +04:00
TALLOC_CTX * ctx = p - > mem_ctx ;
2001-04-05 03:42:17 +04:00
ZERO_STRUCTP ( sh502 ) ;
pstrcpy ( net_name , lp_servicename ( snum ) ) ;
pstrcpy ( remark , lp_comment ( snum ) ) ;
2001-08-22 20:10:28 +04:00
standard_sub_conn ( p - > conn , remark ) ;
2001-04-06 06:12:07 +04:00
pstrcpy ( path , " C: " ) ;
pstrcat ( path , lp_pathname ( snum ) ) ;
2001-05-01 05:01:19 +04:00
/*
* Change / to \ \ so that win2k will see it as a valid path . This was added to
* enable use of browsing in win2k add share dialog .
*/
string_replace ( path , ' / ' , ' \\ ' ) ;
2001-04-05 03:42:17 +04:00
pstrcpy ( passwd , " " ) ;
len_net_name = strlen ( net_name ) ;
/* work out the share type */
type = STYPE_DISKTREE ;
if ( lp_print_ok ( snum ) )
type = STYPE_PRINTQ ;
if ( strequal ( " IPC$ " , net_name ) )
type = STYPE_IPC ;
if ( net_name [ len_net_name ] = = ' $ ' )
type | = STYPE_HIDDEN ;
sd = get_share_security ( ctx , snum , & sd_size ) ;
init_srv_share_info502 ( & sh502 - > info_502 , net_name , type , remark , 0 , 0xffffffff , 1 , path , passwd , sd , sd_size ) ;
2001-05-01 05:01:19 +04:00
init_srv_share_info502_str ( & sh502 - > info_502_str , & sh502 - > info_502 , net_name , remark , path , passwd , sd , sd_size ) ;
2001-04-05 03:42:17 +04:00
}
2001-02-27 21:22:39 +03:00
/***************************************************************************
Fill in a share info level 1005 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_share_info_1005 ( SRV_SHARE_INFO_1005 * sh1005 , int snum )
{
sh1005 - > dfs_root_flag = 0 ;
if ( lp_host_msdfs ( ) & & lp_msdfs_root ( snum ) )
sh1005 - > dfs_root_flag = 3 ;
}
2001-04-06 05:39:12 +04:00
/*******************************************************************
True if it ends in ' $ ' .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL is_admin_share ( int snum )
{
pstring net_name ;
pstrcpy ( net_name , lp_servicename ( snum ) ) ;
return ( net_name [ strlen ( net_name ) ] = = ' $ ' ) ? True : False ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
Fill in a share info structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-22 20:10:28 +04:00
static BOOL init_srv_share_info_ctr ( pipes_struct * p , SRV_SHARE_INFO_CTR * ctr ,
2001-04-06 05:39:12 +04:00
uint32 info_level , uint32 * resume_hnd , uint32 * total_entries , BOOL all_shares )
2001-02-27 21:22:39 +03:00
{
int num_entries = 0 ;
int num_services = lp_numservices ( ) ;
int snum ;
2001-08-22 20:10:28 +04:00
TALLOC_CTX * ctx = p - > mem_ctx ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " init_srv_share_info_ctr \n " ) ) ;
ZERO_STRUCTPN ( ctr ) ;
ctr - > info_level = ctr - > switch_value = info_level ;
* resume_hnd = 0 ;
/* Count the number of entries. */
for ( snum = 0 ; snum < num_services ; snum + + ) {
2001-04-06 05:39:12 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_admin_share ( snum ) ) )
2001-02-27 21:22:39 +03:00
num_entries + + ;
}
* total_entries = num_entries ;
ctr - > num_entries2 = ctr - > num_entries = num_entries ;
ctr - > ptr_share_info = ctr - > ptr_entries = 1 ;
if ( ! num_entries )
return True ;
switch ( info_level ) {
case 1 :
{
SRV_SHARE_INFO_1 * info1 ;
int i = 0 ;
info1 = talloc ( ctx , num_entries * sizeof ( SRV_SHARE_INFO_1 ) ) ;
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
2001-04-06 05:39:12 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_admin_share ( snum ) ) ) {
2001-08-22 20:10:28 +04:00
init_srv_share_info_1 ( p , & info1 [ i + + ] , snum ) ;
2001-02-27 21:22:39 +03:00
}
}
ctr - > share . info1 = info1 ;
break ;
}
case 2 :
{
SRV_SHARE_INFO_2 * info2 ;
int i = 0 ;
info2 = talloc ( ctx , num_entries * sizeof ( SRV_SHARE_INFO_2 ) ) ;
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
2001-04-06 05:39:12 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_admin_share ( snum ) ) ) {
2001-08-22 20:10:28 +04:00
init_srv_share_info_2 ( p , & info2 [ i + + ] , snum ) ;
2001-02-27 21:22:39 +03:00
}
}
ctr - > share . info2 = info2 ;
break ;
}
2001-04-05 03:42:17 +04:00
case 502 :
{
SRV_SHARE_INFO_502 * info502 ;
int i = 0 ;
info502 = talloc ( ctx , num_entries * sizeof ( SRV_SHARE_INFO_502 ) ) ;
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
2001-04-06 05:39:12 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_admin_share ( snum ) ) ) {
2001-08-22 20:10:28 +04:00
init_srv_share_info_502 ( p , & info502 [ i + + ] , snum ) ;
2001-04-05 03:42:17 +04:00
}
}
ctr - > share . info502 = info502 ;
break ;
}
2001-02-27 21:22:39 +03:00
default :
DEBUG ( 5 , ( " init_srv_share_info_ctr: unsupported switch value %d \n " , info_level ) ) ;
return False ;
}
return True ;
}
/*******************************************************************
Inits a SRV_R_NET_SHARE_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-22 20:10:28 +04:00
static void init_srv_r_net_share_enum ( pipes_struct * p , SRV_R_NET_SHARE_ENUM * r_n ,
2001-04-06 05:39:12 +04:00
uint32 info_level , uint32 resume_hnd , BOOL all )
2001-02-27 21:22:39 +03:00
{
DEBUG ( 5 , ( " init_srv_r_net_share_enum: %d \n " , __LINE__ ) ) ;
2001-08-22 20:10:28 +04:00
if ( init_srv_share_info_ctr ( p , & r_n - > ctr , info_level ,
2001-04-06 05:39:12 +04:00
& resume_hnd , & r_n - > total_entries , all ) ) {
2001-08-27 23:46:22 +04:00
r_n - > status = NT_STATUS_OK ;
2001-02-27 21:22:39 +03:00
} else {
r_n - > status = NT_STATUS_INVALID_INFO_CLASS ;
}
init_enum_hnd ( & r_n - > enum_hnd , resume_hnd ) ;
}
/*******************************************************************
Inits a SRV_R_NET_SHARE_GET_INFO structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-22 20:10:28 +04:00
static void init_srv_r_net_share_get_info ( pipes_struct * p , SRV_R_NET_SHARE_GET_INFO * r_n ,
2001-02-27 21:22:39 +03:00
char * share_name , uint32 info_level )
{
2001-08-27 23:46:22 +04:00
NTSTATUS status = NT_STATUS_OK ;
2001-02-27 21:22:39 +03:00
int snum ;
DEBUG ( 5 , ( " init_srv_r_net_share_get_info: %d \n " , __LINE__ ) ) ;
2001-04-05 03:42:17 +04:00
r_n - > info . switch_value = info_level ;
2001-02-27 21:22:39 +03:00
snum = find_service ( share_name ) ;
if ( snum > = 0 ) {
switch ( info_level ) {
case 1 :
2001-08-22 20:10:28 +04:00
init_srv_share_info_1 ( p , & r_n - > info . share . info1 , snum ) ;
2001-02-27 21:22:39 +03:00
break ;
case 2 :
2001-08-22 20:10:28 +04:00
init_srv_share_info_2 ( p , & r_n - > info . share . info2 , snum ) ;
2001-04-05 03:42:17 +04:00
break ;
case 502 :
2001-08-22 20:10:28 +04:00
init_srv_share_info_502 ( p , & r_n - > info . share . info502 , snum ) ;
2001-02-27 21:22:39 +03:00
break ;
case 1005 :
2001-04-05 03:42:17 +04:00
init_srv_share_info_1005 ( & r_n - > info . share . info1005 , snum ) ;
2001-02-27 21:22:39 +03:00
break ;
default :
DEBUG ( 5 , ( " init_srv_net_share_get_info: unsupported switch value %d \n " , info_level ) ) ;
status = NT_STATUS_INVALID_INFO_CLASS ;
break ;
}
} else {
status = NT_STATUS_BAD_NETWORK_NAME ;
}
2001-08-27 23:46:22 +04:00
r_n - > info . ptr_share_ctr = NT_STATUS_IS_OK ( status ) ? 1 : 0 ;
2001-02-27 21:22:39 +03:00
r_n - > status = status ;
}
/*******************************************************************
fill in a sess info level 1 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_sess_0_info ( SESS_INFO_0 * se0 , SESS_INFO_0_STR * str0 , char * name )
{
init_srv_sess_info0 ( se0 , name ) ;
init_srv_sess_info0_str ( str0 , name ) ;
}
/*******************************************************************
fill in a sess info level 0 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_sess_info_0 ( SRV_SESS_INFO_0 * ss0 , uint32 * snum , uint32 * stot )
{
uint32 num_entries = 0 ;
( * stot ) = 1 ;
if ( ss0 = = NULL ) {
( * snum ) = 0 ;
return ;
}
DEBUG ( 5 , ( " init_srv_sess_0_ss0 \n " ) ) ;
if ( snum ) {
for ( ; ( * snum ) < ( * stot ) & & num_entries < MAX_SESS_ENTRIES ; ( * snum ) + + ) {
init_srv_sess_0_info ( & ss0 - > info_0 [ num_entries ] ,
& ss0 - > info_0_str [ num_entries ] , " MACHINE " ) ;
/* move on to creating next session */
/* move on to creating next sess */
num_entries + + ;
}
ss0 - > num_entries_read = num_entries ;
ss0 - > ptr_sess_info = num_entries > 0 ? 1 : 0 ;
ss0 - > num_entries_read2 = num_entries ;
if ( ( * snum ) > = ( * stot ) ) {
( * snum ) = 0 ;
}
} else {
ss0 - > num_entries_read = 0 ;
ss0 - > ptr_sess_info = 0 ;
ss0 - > num_entries_read2 = 0 ;
}
}
/*******************************************************************
fill in a sess info level 1 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_sess_1_info ( SESS_INFO_1 * se1 , SESS_INFO_1_STR * str1 ,
char * name , char * user ,
uint32 num_opens ,
uint32 open_time , uint32 idle_time ,
uint32 usr_flgs )
{
init_srv_sess_info1 ( se1 , name , user , num_opens , open_time , idle_time , usr_flgs ) ;
init_srv_sess_info1_str ( str1 , name , user ) ;
}
/*******************************************************************
fill in a sess info level 1 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_sess_info_1 ( SRV_SESS_INFO_1 * ss1 , uint32 * snum , uint32 * stot )
{
uint32 num_entries = 0 ;
( * stot ) = 1 ;
if ( ss1 = = NULL ) {
( * snum ) = 0 ;
return ;
}
DEBUG ( 5 , ( " init_srv_sess_1_ss1 \n " ) ) ;
if ( snum ) {
for ( ; ( * snum ) < ( * stot ) & & num_entries < MAX_SESS_ENTRIES ; ( * snum ) + + ) {
init_srv_sess_1_info ( & ss1 - > info_1 [ num_entries ] ,
& ss1 - > info_1_str [ num_entries ] ,
" MACHINE " , " dummy_user " , 1 , 10 , 5 , 0 ) ;
/* move on to creating next session */
/* move on to creating next sess */
num_entries + + ;
}
ss1 - > num_entries_read = num_entries ;
ss1 - > ptr_sess_info = num_entries > 0 ? 1 : 0 ;
ss1 - > num_entries_read2 = num_entries ;
if ( ( * snum ) > = ( * stot ) ) {
( * snum ) = 0 ;
}
} else {
ss1 - > num_entries_read = 0 ;
ss1 - > ptr_sess_info = 0 ;
ss1 - > num_entries_read2 = 0 ;
( * stot ) = 0 ;
}
}
/*******************************************************************
makes a SRV_R_NET_SESS_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
static NTSTATUS init_srv_sess_info_ctr ( SRV_SESS_INFO_CTR * ctr ,
2001-02-27 21:22:39 +03:00
int switch_value , uint32 * resume_hnd , uint32 * total_entries )
{
2001-08-27 23:46:22 +04:00
NTSTATUS status = NT_STATUS_OK ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " init_srv_sess_info_ctr: %d \n " , __LINE__ ) ) ;
ctr - > switch_value = switch_value ;
switch ( switch_value ) {
case 0 :
init_srv_sess_info_0 ( & ( ctr - > sess . info0 ) , resume_hnd , total_entries ) ;
ctr - > ptr_sess_ctr = 1 ;
break ;
case 1 :
init_srv_sess_info_1 ( & ( ctr - > sess . info1 ) , resume_hnd , total_entries ) ;
ctr - > ptr_sess_ctr = 1 ;
break ;
default :
DEBUG ( 5 , ( " init_srv_sess_info_ctr: unsupported switch value %d \n " , switch_value ) ) ;
( * resume_hnd ) = 0 ;
( * total_entries ) = 0 ;
ctr - > ptr_sess_ctr = 0 ;
status = NT_STATUS_INVALID_INFO_CLASS ;
break ;
}
return status ;
}
/*******************************************************************
makes a SRV_R_NET_SESS_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_r_net_sess_enum ( SRV_R_NET_SESS_ENUM * r_n ,
uint32 resume_hnd , int sess_level , int switch_value )
{
DEBUG ( 5 , ( " init_srv_r_net_sess_enum: %d \n " , __LINE__ ) ) ;
r_n - > sess_level = sess_level ;
if ( sess_level = = - 1 )
r_n - > status = NT_STATUS_INVALID_INFO_CLASS ;
else
r_n - > status = init_srv_sess_info_ctr ( r_n - > ctr , switch_value , & resume_hnd , & r_n - > total_entries ) ;
2001-08-27 23:46:22 +04:00
if ( NT_STATUS_IS_ERR ( r_n - > status ) )
2001-02-27 21:22:39 +03:00
resume_hnd = 0 ;
init_enum_hnd ( & r_n - > enum_hnd , resume_hnd ) ;
}
/*******************************************************************
fill in a conn info level 0 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_conn_info_0 ( SRV_CONN_INFO_0 * ss0 , uint32 * snum , uint32 * stot )
{
uint32 num_entries = 0 ;
( * stot ) = 1 ;
if ( ss0 = = NULL ) {
( * snum ) = 0 ;
return ;
}
DEBUG ( 5 , ( " init_srv_conn_0_ss0 \n " ) ) ;
if ( snum ) {
for ( ; ( * snum ) < ( * stot ) & & num_entries < MAX_CONN_ENTRIES ; ( * snum ) + + ) {
init_srv_conn_info0 ( & ss0 - > info_0 [ num_entries ] , ( * stot ) ) ;
/* move on to creating next connection */
/* move on to creating next conn */
num_entries + + ;
}
ss0 - > num_entries_read = num_entries ;
ss0 - > ptr_conn_info = num_entries > 0 ? 1 : 0 ;
ss0 - > num_entries_read2 = num_entries ;
if ( ( * snum ) > = ( * stot ) ) {
( * snum ) = 0 ;
}
} else {
ss0 - > num_entries_read = 0 ;
ss0 - > ptr_conn_info = 0 ;
ss0 - > num_entries_read2 = 0 ;
( * stot ) = 0 ;
}
}
/*******************************************************************
fill in a conn info level 1 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_conn_1_info ( CONN_INFO_1 * se1 , CONN_INFO_1_STR * str1 ,
uint32 id , uint32 type ,
uint32 num_opens , uint32 num_users , uint32 open_time ,
char * usr_name , char * net_name )
{
init_srv_conn_info1 ( se1 , id , type , num_opens , num_users , open_time , usr_name , net_name ) ;
init_srv_conn_info1_str ( str1 , usr_name , net_name ) ;
}
/*******************************************************************
fill in a conn info level 1 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_conn_info_1 ( SRV_CONN_INFO_1 * ss1 , uint32 * snum , uint32 * stot )
{
uint32 num_entries = 0 ;
( * stot ) = 1 ;
if ( ss1 = = NULL ) {
( * snum ) = 0 ;
return ;
}
DEBUG ( 5 , ( " init_srv_conn_1_ss1 \n " ) ) ;
if ( snum ) {
for ( ; ( * snum ) < ( * stot ) & & num_entries < MAX_CONN_ENTRIES ; ( * snum ) + + ) {
init_srv_conn_1_info ( & ss1 - > info_1 [ num_entries ] ,
& ss1 - > info_1_str [ num_entries ] ,
( * stot ) , 0x3 , 1 , 1 , 3 , " dummy_user " , " IPC$ " ) ;
/* move on to creating next connection */
/* move on to creating next conn */
num_entries + + ;
}
ss1 - > num_entries_read = num_entries ;
ss1 - > ptr_conn_info = num_entries > 0 ? 1 : 0 ;
ss1 - > num_entries_read2 = num_entries ;
if ( ( * snum ) > = ( * stot ) ) {
( * snum ) = 0 ;
}
} else {
ss1 - > num_entries_read = 0 ;
ss1 - > ptr_conn_info = 0 ;
ss1 - > num_entries_read2 = 0 ;
( * stot ) = 0 ;
}
}
/*******************************************************************
makes a SRV_R_NET_CONN_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
static NTSTATUS init_srv_conn_info_ctr ( SRV_CONN_INFO_CTR * ctr ,
2001-02-27 21:22:39 +03:00
int switch_value , uint32 * resume_hnd , uint32 * total_entries )
{
2001-08-27 23:46:22 +04:00
NTSTATUS status = NT_STATUS_OK ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " init_srv_conn_info_ctr: %d \n " , __LINE__ ) ) ;
ctr - > switch_value = switch_value ;
switch ( switch_value ) {
case 0 :
init_srv_conn_info_0 ( & ctr - > conn . info0 , resume_hnd , total_entries ) ;
ctr - > ptr_conn_ctr = 1 ;
break ;
case 1 :
init_srv_conn_info_1 ( & ctr - > conn . info1 , resume_hnd , total_entries ) ;
ctr - > ptr_conn_ctr = 1 ;
break ;
default :
DEBUG ( 5 , ( " init_srv_conn_info_ctr: unsupported switch value %d \n " , switch_value ) ) ;
( * resume_hnd = 0 ) ;
( * total_entries ) = 0 ;
ctr - > ptr_conn_ctr = 0 ;
status = NT_STATUS_INVALID_INFO_CLASS ;
break ;
}
return status ;
}
/*******************************************************************
makes a SRV_R_NET_CONN_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_r_net_conn_enum ( SRV_R_NET_CONN_ENUM * r_n ,
uint32 resume_hnd , int conn_level , int switch_value )
{
DEBUG ( 5 , ( " init_srv_r_net_conn_enum: %d \n " , __LINE__ ) ) ;
r_n - > conn_level = conn_level ;
if ( conn_level = = - 1 )
r_n - > status = NT_STATUS_INVALID_INFO_CLASS ;
else
r_n - > status = init_srv_conn_info_ctr ( r_n - > ctr , switch_value , & resume_hnd , & r_n - > total_entries ) ;
2001-08-27 23:46:22 +04:00
if ( NT_STATUS_IS_ERR ( r_n - > status ) )
2001-02-27 21:22:39 +03:00
resume_hnd = 0 ;
init_enum_hnd ( & r_n - > enum_hnd , resume_hnd ) ;
}
/*******************************************************************
fill in a file info level 3 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_file_3_info ( FILE_INFO_3 * fl3 , FILE_INFO_3_STR * str3 ,
uint32 fnum , uint32 perms , uint32 num_locks ,
char * path_name , char * user_name )
{
init_srv_file_info3 ( fl3 , fnum , perms , num_locks , path_name , user_name ) ;
init_srv_file_info3_str ( str3 , path_name , user_name ) ;
}
/*******************************************************************
fill in a file info level 3 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_file_info_3 ( SRV_FILE_INFO_3 * fl3 , uint32 * fnum , uint32 * ftot )
{
uint32 num_entries = 0 ;
( * ftot ) = 1 ;
if ( fl3 = = NULL ) {
( * fnum ) = 0 ;
return ;
}
DEBUG ( 5 , ( " init_srv_file_3_fl3 \n " ) ) ;
for ( ; ( * fnum ) < ( * ftot ) & & num_entries < MAX_FILE_ENTRIES ; ( * fnum ) + + ) {
init_srv_file_3_info ( & fl3 - > info_3 [ num_entries ] ,
& fl3 - > info_3_str [ num_entries ] ,
( * fnum ) , 0x35 , 0 , " \\ PIPE \\ samr " , " dummy user " ) ;
/* move on to creating next file */
num_entries + + ;
}
fl3 - > num_entries_read = num_entries ;
fl3 - > ptr_file_info = num_entries > 0 ? 1 : 0 ;
fl3 - > num_entries_read2 = num_entries ;
if ( ( * fnum ) > = ( * ftot ) ) {
( * fnum ) = 0 ;
}
}
/*******************************************************************
makes a SRV_R_NET_FILE_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
static NTSTATUS init_srv_file_info_ctr ( SRV_FILE_INFO_CTR * ctr ,
2001-02-27 21:22:39 +03:00
int switch_value , uint32 * resume_hnd , uint32 * total_entries )
{
2001-08-27 23:46:22 +04:00
NTSTATUS status = NT_STATUS_OK ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " init_srv_file_info_ctr: %d \n " , __LINE__ ) ) ;
ctr - > switch_value = switch_value ;
switch ( switch_value ) {
case 3 :
init_srv_file_info_3 ( & ctr - > file . info3 , resume_hnd , total_entries ) ;
ctr - > ptr_file_ctr = 1 ;
break ;
default :
DEBUG ( 5 , ( " init_srv_file_info_ctr: unsupported switch value %d \n " , switch_value ) ) ;
( * resume_hnd = 0 ) ;
( * total_entries ) = 0 ;
ctr - > ptr_file_ctr = 0 ;
status = NT_STATUS_INVALID_INFO_CLASS ;
break ;
}
return status ;
}
/*******************************************************************
makes a SRV_R_NET_FILE_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_r_net_file_enum ( SRV_R_NET_FILE_ENUM * r_n ,
uint32 resume_hnd , int file_level , int switch_value )
{
DEBUG ( 5 , ( " init_srv_r_net_file_enum: %d \n " , __LINE__ ) ) ;
r_n - > file_level = file_level ;
if ( file_level = = 0 )
r_n - > status = NT_STATUS_INVALID_INFO_CLASS ;
else
r_n - > status = init_srv_file_info_ctr ( r_n - > ctr , switch_value , & resume_hnd , & ( r_n - > total_entries ) ) ;
2001-08-27 23:46:22 +04:00
if ( NT_STATUS_IS_ERR ( r_n - > status ) )
2001-02-27 21:22:39 +03:00
resume_hnd = 0 ;
init_enum_hnd ( & r_n - > enum_hnd , resume_hnd ) ;
}
/*******************************************************************
net server get info
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_srv_get_info ( pipes_struct * p , SRV_Q_NET_SRV_GET_INFO * q_u , SRV_R_NET_SRV_GET_INFO * r_u )
2001-02-27 21:22:39 +03:00
{
2001-08-27 23:46:22 +04:00
NTSTATUS status = NT_STATUS_OK ;
2001-02-27 21:22:39 +03:00
SRV_INFO_CTR * ctr = ( SRV_INFO_CTR * ) talloc ( p - > mem_ctx , sizeof ( SRV_INFO_CTR ) ) ;
if ( ! ctr )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( ctr ) ;
DEBUG ( 5 , ( " srv_net_srv_get_info: %d \n " , __LINE__ ) ) ;
switch ( q_u - > switch_value ) {
case 102 :
init_srv_info_102 ( & ctr - > srv . sv102 ,
500 , global_myname ,
string_truncate ( lp_serverstring ( ) , MAX_SERVER_STRING_LENGTH ) ,
lp_major_announce_version ( ) , lp_minor_announce_version ( ) ,
lp_default_server_announce ( ) ,
0xffffffff , /* users */
0xf , /* disc */
0 , /* hidden */
240 , /* announce */
3000 , /* announce delta */
100000 , /* licenses */
" c: \\ " ) ; /* user path */
break ;
case 101 :
init_srv_info_101 ( & ctr - > srv . sv101 ,
500 , global_myname ,
lp_major_announce_version ( ) , lp_minor_announce_version ( ) ,
lp_default_server_announce ( ) ,
string_truncate ( lp_serverstring ( ) , MAX_SERVER_STRING_LENGTH ) ) ;
break ;
2001-03-11 03:32:10 +03:00
case 100 :
init_srv_info_100 ( & ctr - > srv . sv100 , 500 , global_myname ) ;
break ;
2001-02-27 21:22:39 +03:00
default :
status = NT_STATUS_INVALID_INFO_CLASS ;
break ;
}
/* set up the net server get info structure */
init_srv_r_net_srv_get_info ( r_u , q_u - > switch_value , ctr , status ) ;
DEBUG ( 5 , ( " srv_net_srv_get_info: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
2001-06-25 10:13:27 +04:00
/*******************************************************************
net server set info
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_srv_set_info ( pipes_struct * p , SRV_Q_NET_SRV_SET_INFO * q_u , SRV_R_NET_SRV_SET_INFO * r_u )
2001-06-25 10:13:27 +04:00
{
/* NT gives "Windows NT error 0xc00000022" if we return
NT_STATUS_ACCESS_DENIED here so just pretend everything is OK . */
2001-08-27 23:46:22 +04:00
NTSTATUS status = NT_STATUS_OK ;
2001-06-25 10:13:27 +04:00
DEBUG ( 5 , ( " srv_net_srv_set_info: %d \n " , __LINE__ ) ) ;
/* Set up the net server set info structure. */
init_srv_r_net_srv_set_info ( r_u , 0x0 , status ) ;
DEBUG ( 5 , ( " srv_net_srv_set_info: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
net file enum
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_file_enum ( pipes_struct * p , SRV_Q_NET_FILE_ENUM * q_u , SRV_R_NET_FILE_ENUM * r_u )
2001-02-27 21:22:39 +03:00
{
r_u - > ctr = ( SRV_FILE_INFO_CTR * ) talloc ( p - > mem_ctx , sizeof ( SRV_FILE_INFO_CTR ) ) ;
if ( ! r_u - > ctr )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( r_u - > ctr ) ;
DEBUG ( 5 , ( " srv_net_file_enum: %d \n " , __LINE__ ) ) ;
/* set up the */
init_srv_r_net_file_enum ( r_u ,
get_enum_hnd ( & q_u - > enum_hnd ) ,
q_u - > file_level ,
q_u - > ctr - > switch_value ) ;
DEBUG ( 5 , ( " srv_net_file_enum: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
net conn enum
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_conn_enum ( pipes_struct * p , SRV_Q_NET_CONN_ENUM * q_u , SRV_R_NET_CONN_ENUM * r_u )
2001-02-27 21:22:39 +03:00
{
DEBUG ( 5 , ( " srv_net_conn_enum: %d \n " , __LINE__ ) ) ;
r_u - > ctr = ( SRV_CONN_INFO_CTR * ) talloc ( p - > mem_ctx , sizeof ( SRV_CONN_INFO_CTR ) ) ;
if ( ! r_u - > ctr )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( r_u - > ctr ) ;
/* set up the */
init_srv_r_net_conn_enum ( r_u ,
get_enum_hnd ( & q_u - > enum_hnd ) ,
q_u - > conn_level ,
q_u - > ctr - > switch_value ) ;
DEBUG ( 5 , ( " srv_net_conn_enum: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
net sess enum
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_sess_enum ( pipes_struct * p , SRV_Q_NET_SESS_ENUM * q_u , SRV_R_NET_SESS_ENUM * r_u )
2001-02-27 21:22:39 +03:00
{
DEBUG ( 5 , ( " _srv_net_sess_enum: %d \n " , __LINE__ ) ) ;
r_u - > ctr = ( SRV_SESS_INFO_CTR * ) talloc ( p - > mem_ctx , sizeof ( SRV_SESS_INFO_CTR ) ) ;
if ( ! r_u - > ctr )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( r_u - > ctr ) ;
/* set up the */
init_srv_r_net_sess_enum ( r_u ,
get_enum_hnd ( & q_u - > enum_hnd ) ,
q_u - > sess_level ,
q_u - > ctr - > switch_value ) ;
DEBUG ( 5 , ( " _srv_net_sess_enum: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
2001-04-06 05:39:12 +04:00
/*******************************************************************
Net share enum all .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_share_enum_all ( pipes_struct * p , SRV_Q_NET_SHARE_ENUM * q_u , SRV_R_NET_SHARE_ENUM * r_u )
2001-04-06 05:39:12 +04:00
{
DEBUG ( 5 , ( " _srv_net_share_enum: %d \n " , __LINE__ ) ) ;
/* Create the list of shares for the response. */
2001-08-22 20:10:28 +04:00
init_srv_r_net_share_enum ( p , r_u ,
2001-04-06 05:39:12 +04:00
q_u - > ctr . info_level ,
get_enum_hnd ( & q_u - > enum_hnd ) , True ) ;
DEBUG ( 5 , ( " _srv_net_share_enum: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
Net share enum .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_share_enum ( pipes_struct * p , SRV_Q_NET_SHARE_ENUM * q_u , SRV_R_NET_SHARE_ENUM * r_u )
2001-02-27 21:22:39 +03:00
{
DEBUG ( 5 , ( " _srv_net_share_enum: %d \n " , __LINE__ ) ) ;
/* Create the list of shares for the response. */
2001-08-22 20:10:28 +04:00
init_srv_r_net_share_enum ( p , r_u ,
2001-02-27 21:22:39 +03:00
q_u - > ctr . info_level ,
2001-04-06 05:39:12 +04:00
get_enum_hnd ( & q_u - > enum_hnd ) , False ) ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " _srv_net_share_enum: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
Net share get info .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_share_get_info ( pipes_struct * p , SRV_Q_NET_SHARE_GET_INFO * q_u , SRV_R_NET_SHARE_GET_INFO * r_u )
2001-02-27 21:22:39 +03:00
{
2001-04-07 04:36:38 +04:00
fstring share_name ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " _srv_net_share_get_info: %d \n " , __LINE__ ) ) ;
/* Create the list of shares for the response. */
2001-04-07 04:36:38 +04:00
unistr2_to_ascii ( share_name , & q_u - > uni_share_name , sizeof ( share_name ) ) ;
2001-08-22 20:10:28 +04:00
init_srv_r_net_share_get_info ( p , r_u , share_name , q_u - > info_level ) ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " _srv_net_share_get_info: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
2001-04-07 22:46:47 +04:00
/*******************************************************************
Check a given DOS pathname is valid for a share .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * valid_share_pathname ( char * dos_pathname )
{
pstring saved_pathname ;
pstring unix_pathname ;
char * ptr ;
int ret ;
/* Convert any '\' paths to '/' */
unix_format ( dos_pathname ) ;
unix_clean_name ( dos_pathname ) ;
/* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
ptr = dos_pathname ;
if ( strlen ( dos_pathname ) > 2 & & ptr [ 1 ] = = ' : ' & & ptr [ 0 ] ! = ' / ' )
ptr + = 2 ;
/* Only abolute paths allowed. */
if ( * ptr ! = ' / ' )
return NULL ;
/* Can we cd to it ? */
/* First save our current directory. */
if ( getcwd ( saved_pathname , sizeof ( saved_pathname ) ) = = NULL )
return False ;
pstrcpy ( unix_pathname , ptr ) ;
ret = chdir ( unix_pathname ) ;
/* We *MUST* be able to chdir back. Abort if we can't. */
if ( chdir ( saved_pathname ) = = - 1 )
smb_panic ( " valid_share_pathname: Unable to restore current directory. \n " ) ;
return ( ret ! = - 1 ) ? ptr : NULL ;
}
2001-04-09 00:01:51 +04:00
/*******************************************************************
Net share set info . Modify share details .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_share_set_info ( pipes_struct * p , SRV_Q_NET_SHARE_SET_INFO * q_u , SRV_R_NET_SHARE_SET_INFO * r_u )
2001-04-09 00:01:51 +04:00
{
struct current_user user ;
pstring command ;
fstring share_name ;
fstring comment ;
pstring pathname ;
int type ;
int snum ;
int ret ;
char * ptr ;
2001-04-09 10:36:38 +04:00
SEC_DESC * psd = NULL ;
2001-04-09 00:01:51 +04:00
DEBUG ( 5 , ( " _srv_net_share_set_info: %d \n " , __LINE__ ) ) ;
unistr2_to_ascii ( share_name , & q_u - > uni_share_name , sizeof ( share_name ) ) ;
r_u - > switch_value = 0 ;
2001-04-10 23:43:14 +04:00
if ( strequal ( share_name , " IPC$ " ) | | strequal ( share_name , " ADMIN$ " ) | | strequal ( share_name , " global " ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 12:00:19 +04:00
2001-04-09 00:01:51 +04:00
snum = find_service ( share_name ) ;
/* Does this share exist ? */
if ( snum < 0 )
2001-08-27 23:46:22 +04:00
return NT_STATUS_BAD_NETWORK_NAME ;
2001-04-09 22:03:02 +04:00
/* No change to printer shares. */
if ( lp_print_ok ( snum ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 00:01:51 +04:00
get_current_user ( & user , p ) ;
if ( user . uid ! = 0 )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 00:01:51 +04:00
switch ( q_u - > info_level ) {
case 1 :
2001-04-09 10:36:38 +04:00
/* Not enough info in a level 1 to do anything. */
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 00:01:51 +04:00
case 2 :
2001-04-09 10:36:38 +04:00
unistr2_to_ascii ( comment , & q_u - > info . share . info2 . info_2_str . uni_remark , sizeof ( share_name ) ) ;
unistr2_to_ascii ( pathname , & q_u - > info . share . info2 . info_2_str . uni_path , sizeof ( share_name ) ) ;
type = q_u - > info . share . info2 . info_2 . type ;
2001-04-09 12:00:19 +04:00
psd = NULL ;
2001-04-09 00:01:51 +04:00
break ;
case 502 :
2001-04-09 10:36:38 +04:00
unistr2_to_ascii ( comment , & q_u - > info . share . info502 . info_502_str . uni_remark , sizeof ( share_name ) ) ;
unistr2_to_ascii ( pathname , & q_u - > info . share . info502 . info_502_str . uni_path , sizeof ( share_name ) ) ;
type = q_u - > info . share . info502 . info_502 . type ;
psd = q_u - > info . share . info502 . info_502_str . sd ;
2001-04-09 12:00:19 +04:00
map_generic_share_sd_bits ( psd ) ;
2001-04-09 00:01:51 +04:00
break ;
case 1005 :
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 12:00:19 +04:00
case 1501 :
fstrcpy ( pathname , lp_pathname ( snum ) ) ;
fstrcpy ( comment , lp_comment ( snum ) ) ;
psd = q_u - > info . share . info1501 . sdb - > sec ;
map_generic_share_sd_bits ( psd ) ;
type = STYPE_DISKTREE ;
break ;
2001-04-09 00:01:51 +04:00
default :
DEBUG ( 5 , ( " _srv_net_share_set_info: unsupported switch value %d \n " , q_u - > info_level ) ) ;
return NT_STATUS_INVALID_INFO_CLASS ;
2001-04-09 10:36:38 +04:00
}
/* We can only modify disk shares. */
if ( type ! = STYPE_DISKTREE )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 10:36:38 +04:00
/* Check if the pathname is valid. */
if ( ! ( ptr = valid_share_pathname ( pathname ) ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_OBJECT_PATH_INVALID ;
2001-04-09 10:36:38 +04:00
/* Ensure share name, pathname and comment don't contain '"' characters. */
string_replace ( share_name , ' " ' , ' ' ) ;
string_replace ( ptr , ' " ' , ' ' ) ;
string_replace ( comment , ' " ' , ' ' ) ;
2001-04-09 21:10:06 +04:00
DEBUG ( 10 , ( " _srv_net_share_set_info: change share command = %s \n " ,
lp_change_share_cmd ( ) ? lp_change_share_cmd ( ) : " NULL " ) ) ;
2001-04-09 10:36:38 +04:00
/* Only call modify function if something changed. */
2001-04-09 21:10:06 +04:00
if ( strcmp ( ptr , lp_pathname ( snum ) ) | | strcmp ( comment , lp_comment ( snum ) ) ) {
if ( ! lp_change_share_cmd ( ) | | ! * lp_change_share_cmd ( ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 10:36:38 +04:00
2001-04-10 23:43:14 +04:00
slprintf ( command , sizeof ( command ) - 1 , " %s \" %s \" \" %s \" \" %s \" \" %s \" " ,
lp_change_share_cmd ( ) , CONFIGFILE , share_name , ptr , comment ) ;
2001-04-09 10:36:38 +04:00
DEBUG ( 10 , ( " _srv_net_share_set_info: Running [%s] \n " , command ) ) ;
2001-04-13 23:12:06 +04:00
if ( ( ret = smbrun ( command , NULL ) ) ! = 0 ) {
2001-04-09 10:36:38 +04:00
DEBUG ( 0 , ( " _srv_net_share_set_info: Running [%s] returned (%d) \n " , command , ret ) ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 10:36:38 +04:00
}
2001-04-10 05:44:45 +04:00
/* Tell everyone we updated smb.conf. */
message_send_all ( conn_tdb_ctx ( ) , MSG_SMB_CONF_UPDATED , NULL , 0 , False ) ;
2001-04-09 12:00:19 +04:00
} else {
DEBUG ( 10 , ( " _srv_net_share_set_info: No change to share name (%s) \n " , share_name ) ) ;
2001-04-09 10:36:38 +04:00
}
/* Replace SD if changed. */
if ( psd ) {
SEC_DESC * old_sd ;
size_t sd_size ;
old_sd = get_share_security ( p - > mem_ctx , snum , & sd_size ) ;
if ( old_sd & & ! sec_desc_equal ( old_sd , psd ) ) {
if ( ! set_share_security ( p - > mem_ctx , share_name , psd ) )
DEBUG ( 0 , ( " _srv_net_share_set_info: Failed to change security info in share %s. \n " ,
share_name ) ) ;
}
2001-04-09 00:01:51 +04:00
}
DEBUG ( 5 , ( " _srv_net_share_set_info: %d \n " , __LINE__ ) ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-04-09 00:01:51 +04:00
}
2001-04-06 21:41:47 +04:00
/*******************************************************************
2001-04-09 10:36:38 +04:00
Net share add . Call ' add_share_command " sharename " " pathname " " comment " " read only = xxx " '
2001-04-06 21:41:47 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_share_add ( pipes_struct * p , SRV_Q_NET_SHARE_ADD * q_u , SRV_R_NET_SHARE_ADD * r_u )
2001-04-06 21:41:47 +04:00
{
2001-04-07 04:36:38 +04:00
struct current_user user ;
pstring command ;
fstring share_name ;
fstring comment ;
pstring pathname ;
int type ;
int snum ;
2001-04-07 22:46:47 +04:00
int ret ;
char * ptr ;
2001-04-09 10:36:38 +04:00
SEC_DESC * psd = NULL ;
2001-04-06 21:41:47 +04:00
DEBUG ( 5 , ( " _srv_net_share_add: %d \n " , __LINE__ ) ) ;
2001-04-06 22:25:17 +04:00
r_u - > switch_value = 0 ;
2001-04-06 21:41:47 +04:00
2001-04-07 04:36:38 +04:00
get_current_user ( & user , p ) ;
2001-04-09 22:03:02 +04:00
if ( user . uid ! = 0 ) {
DEBUG ( 10 , ( " _srv_net_share_add: uid != 0. Access denied. \n " ) ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 22:03:02 +04:00
}
2001-04-07 04:36:38 +04:00
2001-04-09 22:03:02 +04:00
if ( ! lp_add_share_cmd ( ) | | ! * lp_add_share_cmd ( ) ) {
DEBUG ( 10 , ( " _srv_net_share_add: No add share command \n " ) ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 22:03:02 +04:00
}
2001-04-07 04:36:38 +04:00
2001-04-06 21:41:47 +04:00
switch ( q_u - > info_level ) {
case 1 :
2001-04-07 04:36:38 +04:00
/* Not enough info in a level 1 to do anything. */
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-06 21:41:47 +04:00
case 2 :
2001-04-07 04:36:38 +04:00
unistr2_to_ascii ( share_name , & q_u - > info . share . info2 . info_2_str . uni_netname , sizeof ( share_name ) ) ;
unistr2_to_ascii ( comment , & q_u - > info . share . info2 . info_2_str . uni_remark , sizeof ( share_name ) ) ;
unistr2_to_ascii ( pathname , & q_u - > info . share . info2 . info_2_str . uni_path , sizeof ( share_name ) ) ;
2001-04-07 22:46:47 +04:00
type = q_u - > info . share . info2 . info_2 . type ;
2001-04-06 21:41:47 +04:00
break ;
case 502 :
2001-04-07 04:36:38 +04:00
unistr2_to_ascii ( share_name , & q_u - > info . share . info502 . info_502_str . uni_netname , sizeof ( share_name ) ) ;
unistr2_to_ascii ( comment , & q_u - > info . share . info502 . info_502_str . uni_remark , sizeof ( share_name ) ) ;
unistr2_to_ascii ( pathname , & q_u - > info . share . info502 . info_502_str . uni_path , sizeof ( share_name ) ) ;
2001-04-07 22:46:47 +04:00
type = q_u - > info . share . info502 . info_502 . type ;
2001-04-09 10:36:38 +04:00
psd = q_u - > info . share . info502 . info_502_str . sd ;
2001-04-09 12:00:19 +04:00
map_generic_share_sd_bits ( psd ) ;
2001-04-06 21:41:47 +04:00
break ;
case 1005 :
2001-04-07 04:36:38 +04:00
/* DFS only level. */
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-06 21:41:47 +04:00
default :
DEBUG ( 5 , ( " _srv_net_share_add: unsupported switch value %d \n " , q_u - > info_level ) ) ;
2001-04-07 22:46:47 +04:00
return NT_STATUS_INVALID_INFO_CLASS ;
2001-04-06 21:41:47 +04:00
}
2001-04-10 23:43:14 +04:00
if ( strequal ( share_name , " IPC$ " ) | | strequal ( share_name , " ADMIN$ " ) | | strequal ( share_name , " global " ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-10 23:43:14 +04:00
2001-04-07 04:36:38 +04:00
snum = find_service ( share_name ) ;
/* Share already exists. */
if ( snum > = 0 )
2001-08-27 23:46:22 +04:00
return NT_STATUS_OBJECT_NAME_COLLISION ;
2001-04-07 04:36:38 +04:00
2001-04-07 22:46:47 +04:00
/* We can only add disk shares. */
if ( type ! = STYPE_DISKTREE )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-07 22:46:47 +04:00
/* Check if the pathname is valid. */
if ( ! ( ptr = valid_share_pathname ( pathname ) ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_OBJECT_PATH_INVALID ;
2001-04-07 04:36:38 +04:00
2001-04-09 00:01:51 +04:00
/* Ensure share name, pathname and comment don't contain '"' characters. */
string_replace ( share_name , ' " ' , ' ' ) ;
string_replace ( ptr , ' " ' , ' ' ) ;
string_replace ( comment , ' " ' , ' ' ) ;
2001-04-10 23:43:14 +04:00
slprintf ( command , sizeof ( command ) - 1 , " %s \" %s \" \" %s \" \" %s \" \" %s \" " ,
lp_add_share_cmd ( ) , CONFIGFILE , share_name , ptr , comment ) ;
2001-04-07 04:36:38 +04:00
2001-04-07 22:46:47 +04:00
DEBUG ( 10 , ( " _srv_net_share_add: Running [%s] \n " , command ) ) ;
2001-04-13 23:12:06 +04:00
if ( ( ret = smbrun ( command , NULL ) ) ! = 0 ) {
2001-04-07 22:46:47 +04:00
DEBUG ( 0 , ( " _srv_net_share_add: Running [%s] returned (%d) \n " , command , ret ) ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-07 22:46:47 +04:00
}
2001-04-07 04:36:38 +04:00
2001-04-09 10:36:38 +04:00
if ( psd ) {
if ( ! set_share_security ( p - > mem_ctx , share_name , psd ) )
DEBUG ( 0 , ( " _srv_net_share_add: Failed to add security info to share %s. \n " ,
share_name ) ) ;
}
2001-04-10 05:44:45 +04:00
/* Tell everyone we updated smb.conf. */
message_send_all ( conn_tdb_ctx ( ) , MSG_SMB_CONF_UPDATED , NULL , 0 , False ) ;
2001-04-07 22:46:47 +04:00
/*
2001-04-10 05:44:45 +04:00
* We don ' t call reload_services ( ) here , the message will
2001-04-07 22:46:47 +04:00
* cause this to be done before the next packet is read
* from the client . JRA .
*/
2001-04-06 21:41:47 +04:00
DEBUG ( 5 , ( " _srv_net_share_add: %d \n " , __LINE__ ) ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-04-06 21:41:47 +04:00
}
2001-04-06 22:25:17 +04:00
/*******************************************************************
2001-04-07 04:36:38 +04:00
Net share delete . Call " delete share command " with the share name as
a parameter .
2001-04-06 22:25:17 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_share_del ( pipes_struct * p , SRV_Q_NET_SHARE_DEL * q_u , SRV_R_NET_SHARE_DEL * r_u )
2001-04-06 22:25:17 +04:00
{
2001-04-07 04:36:38 +04:00
struct current_user user ;
pstring command ;
fstring share_name ;
int ret ;
2001-04-06 22:25:17 +04:00
int snum ;
DEBUG ( 5 , ( " _srv_net_share_del: %d \n " , __LINE__ ) ) ;
2001-04-07 04:36:38 +04:00
unistr2_to_ascii ( share_name , & q_u - > uni_share_name , sizeof ( share_name ) ) ;
2001-04-06 22:25:17 +04:00
2001-04-10 23:43:14 +04:00
if ( strequal ( share_name , " IPC$ " ) | | strequal ( share_name , " ADMIN$ " ) | | strequal ( share_name , " global " ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-09 22:03:02 +04:00
2001-04-06 22:25:17 +04:00
snum = find_service ( share_name ) ;
if ( snum < 0 )
2001-08-27 23:46:22 +04:00
return NT_STATUS_BAD_NETWORK_NAME ;
2001-04-09 22:03:02 +04:00
/* No change to printer shares. */
if ( lp_print_ok ( snum ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-06 22:25:17 +04:00
2001-04-07 04:36:38 +04:00
get_current_user ( & user , p ) ;
if ( user . uid ! = 0 )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-07 04:36:38 +04:00
2001-04-09 21:10:06 +04:00
if ( ! lp_delete_share_cmd ( ) | | ! * lp_delete_share_cmd ( ) )
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-07 04:36:38 +04:00
2001-04-10 23:43:14 +04:00
slprintf ( command , sizeof ( command ) - 1 , " %s \" %s \" \" %s \" " ,
lp_delete_share_cmd ( ) , CONFIGFILE , lp_servicename ( snum ) ) ;
2001-04-07 04:36:38 +04:00
DEBUG ( 10 , ( " _srv_net_share_del: Running [%s] \n " , command ) ) ;
2001-04-13 23:12:06 +04:00
if ( ( ret = smbrun ( command , NULL ) ) ! = 0 ) {
2001-04-07 04:36:38 +04:00
DEBUG ( 0 , ( " _srv_net_share_del: Running [%s] returned (%d) \n " , command , ret ) ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_ACCESS_DENIED ;
2001-04-07 04:36:38 +04:00
}
2001-04-09 00:01:51 +04:00
/* Delete the SD in the database. */
delete_share_security ( snum ) ;
2001-04-10 05:44:45 +04:00
/* Tell everyone we updated smb.conf. */
message_send_all ( conn_tdb_ctx ( ) , MSG_SMB_CONF_UPDATED , NULL , 0 , False ) ;
2001-04-07 04:36:38 +04:00
lp_killservice ( snum ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-04-06 22:25:17 +04:00
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
time of day
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_remote_tod ( pipes_struct * p , SRV_Q_NET_REMOTE_TOD * q_u , SRV_R_NET_REMOTE_TOD * r_u )
2001-02-27 21:22:39 +03:00
{
TIME_OF_DAY_INFO * tod ;
struct tm * t ;
time_t unixdate = time ( NULL ) ;
tod = ( TIME_OF_DAY_INFO * ) talloc ( p - > mem_ctx , sizeof ( TIME_OF_DAY_INFO ) ) ;
if ( ! tod )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( tod ) ;
r_u - > tod = tod ;
r_u - > ptr_srv_tod = 0x1 ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_OK ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " _srv_net_remote_tod: %d \n " , __LINE__ ) ) ;
t = gmtime ( & unixdate ) ;
/* set up the */
init_time_of_day_info ( tod ,
unixdate ,
0 ,
t - > tm_hour ,
t - > tm_min ,
t - > tm_sec ,
0 ,
TimeDiff ( unixdate ) / 60 ,
10000 ,
t - > tm_mday ,
t - > tm_mon + 1 ,
1900 + t - > tm_year ,
t - > tm_wday ) ;
DEBUG ( 5 , ( " _srv_net_remote_tod: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
2001-05-01 05:01:19 +04:00
2001-06-16 04:32:13 +04:00
/***********************************************************************************
Win9x NT tools get security descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_file_query_secdesc ( pipes_struct * p , SRV_Q_NET_FILE_QUERY_SECDESC * q_u ,
2001-06-16 04:32:13 +04:00
SRV_R_NET_FILE_QUERY_SECDESC * r_u )
{
SEC_DESC * psd = NULL ;
size_t sd_size ;
2001-10-31 13:46:25 +03:00
DATA_BLOB null_pw ;
2001-06-16 04:32:13 +04:00
pstring filename ;
pstring qualname ;
files_struct * fsp = NULL ;
SMB_STRUCT_STAT st ;
BOOL bad_path ;
int access_mode ;
int action ;
2001-09-15 16:55:59 +04:00
NTSTATUS nt_status ;
2001-06-16 04:32:13 +04:00
struct current_user user ;
connection_struct * conn = NULL ;
2001-09-19 06:28:15 +04:00
BOOL became_user = False ;
2001-06-16 04:32:13 +04:00
ZERO_STRUCT ( st ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_OK ;
2001-06-16 04:32:13 +04:00
unistr2_to_ascii ( qualname , & q_u - > uni_qual_name , sizeof ( qualname ) ) ;
/* Null password is ok - we are already an authenticated user... */
2001-10-31 13:46:25 +03:00
null_pw = data_blob ( NULL , 0 ) ;
2001-06-16 04:32:13 +04:00
2001-09-19 06:28:15 +04:00
get_current_user ( & user , p ) ;
2001-10-19 00:15:12 +04:00
become_root ( ) ;
2001-10-31 13:46:25 +03:00
conn = make_connection ( qualname , null_pw , " A: " , user . vuid , & nt_status ) ;
2001-10-19 00:15:12 +04:00
unbecome_root ( ) ;
2001-06-16 04:32:13 +04:00
if ( conn = = NULL ) {
DEBUG ( 3 , ( " _srv_net_file_query_secdesc: Unable to connect to %s \n " , qualname ) ) ;
2001-09-15 16:55:59 +04:00
r_u - > status = nt_status ;
2001-06-16 04:32:13 +04:00
goto error_exit ;
}
2001-09-19 06:28:15 +04:00
if ( ! become_user ( conn , conn - > vuid ) ) {
2001-09-19 06:53:14 +04:00
DEBUG ( 0 , ( " _srv_net_file_query_secdesc: Can't become connected user! \n " ) ) ;
2001-09-19 06:28:15 +04:00
r_u - > status = NT_STATUS_ACCESS_DENIED ;
goto error_exit ;
}
became_user = True ;
2001-06-16 04:32:13 +04:00
unistr2_to_ascii ( filename , & q_u - > uni_file_name , sizeof ( filename ) ) ;
unix_convert ( filename , conn , NULL , & bad_path , & st ) ;
2001-09-19 06:28:15 +04:00
2001-06-16 04:32:13 +04:00
fsp = open_file_shared ( conn , filename , & st , SET_OPEN_MODE ( DOS_OPEN_RDONLY ) ,
2001-09-19 06:28:15 +04:00
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) , 0 , 0 , & access_mode , & action ) ;
2001-06-16 04:32:13 +04:00
if ( ! fsp ) {
2001-06-18 21:52:58 +04:00
/* Perhaps it is a directory */
2001-06-19 22:43:17 +04:00
if ( errno = = EISDIR )
fsp = open_directory ( conn , filename , & st ,
2001-09-19 06:28:15 +04:00
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) , 0 , & action ) ;
2001-06-19 22:43:17 +04:00
2001-06-18 21:52:58 +04:00
if ( ! fsp ) {
DEBUG ( 3 , ( " _srv_net_file_query_secdesc: Unable to open file %s \n " , filename ) ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_ACCESS_DENIED ;
2001-06-18 21:52:58 +04:00
goto error_exit ;
}
2001-06-16 04:32:13 +04:00
}
sd_size = conn - > vfs_ops . get_nt_acl ( fsp , fsp - > fsp_name , & psd ) ;
if ( sd_size = = 0 ) {
DEBUG ( 3 , ( " _srv_net_file_query_secdesc: Unable to get NT ACL for file %s \n " , filename ) ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_ACCESS_DENIED ;
2001-06-16 04:32:13 +04:00
goto error_exit ;
}
r_u - > ptr_response = 1 ;
r_u - > size_response = sd_size ;
r_u - > ptr_secdesc = 1 ;
r_u - > size_secdesc = sd_size ;
r_u - > sec_desc = psd ;
psd - > dacl - > revision = ( uint16 ) NT4_ACL_REVISION ;
2001-06-22 22:58:35 +04:00
close_file ( fsp , True ) ;
2001-10-19 00:15:12 +04:00
unbecome_user ( ) ;
2001-06-16 04:32:13 +04:00
close_cnum ( conn , user . vuid ) ;
return r_u - > status ;
error_exit :
if ( fsp ) {
2001-06-22 22:58:35 +04:00
close_file ( fsp , True ) ;
2001-06-16 04:32:13 +04:00
}
2001-09-19 06:28:15 +04:00
if ( became_user )
unbecome_user ( ) ;
2001-06-16 04:32:13 +04:00
if ( conn )
close_cnum ( conn , user . vuid ) ;
return r_u - > status ;
}
/***********************************************************************************
Win9x NT tools set security descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_file_set_secdesc ( pipes_struct * p , SRV_Q_NET_FILE_SET_SECDESC * q_u ,
2001-06-16 04:32:13 +04:00
SRV_R_NET_FILE_SET_SECDESC * r_u )
{
BOOL ret ;
2001-10-31 13:46:25 +03:00
DATA_BLOB null_pw ;
2001-06-16 04:32:13 +04:00
pstring filename ;
pstring qualname ;
files_struct * fsp = NULL ;
SMB_STRUCT_STAT st ;
BOOL bad_path ;
int access_mode ;
int action ;
2001-09-15 16:55:59 +04:00
NTSTATUS nt_status ;
2001-06-16 04:32:13 +04:00
struct current_user user ;
connection_struct * conn = NULL ;
2001-08-14 03:19:16 +04:00
BOOL became_user = False ;
2001-06-16 04:32:13 +04:00
ZERO_STRUCT ( st ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_OK ;
2001-06-16 04:32:13 +04:00
unistr2_to_ascii ( qualname , & q_u - > uni_qual_name , sizeof ( qualname ) ) ;
/* Null password is ok - we are already an authenticated user... */
2001-10-31 13:46:25 +03:00
null_pw = data_blob ( NULL , 0 ) ;
2001-06-16 04:32:13 +04:00
2001-09-19 06:28:15 +04:00
get_current_user ( & user , p ) ;
2001-10-19 00:15:12 +04:00
become_root ( ) ;
2001-10-31 13:46:25 +03:00
conn = make_connection ( qualname , null_pw , " A: " , user . vuid , & nt_status ) ;
2001-10-19 00:15:12 +04:00
unbecome_root ( ) ;
2001-06-16 04:32:13 +04:00
if ( conn = = NULL ) {
DEBUG ( 3 , ( " _srv_net_file_set_secdesc: Unable to connect to %s \n " , qualname ) ) ;
2001-09-15 16:55:59 +04:00
r_u - > status = nt_status ;
2001-06-16 04:32:13 +04:00
goto error_exit ;
}
2001-08-14 03:19:16 +04:00
if ( ! become_user ( conn , conn - > vuid ) ) {
DEBUG ( 0 , ( " _srv_net_file_set_secdesc: Can't become connected user! \n " ) ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_ACCESS_DENIED ;
2001-08-14 03:19:16 +04:00
goto error_exit ;
}
became_user = True ;
2001-06-16 04:32:13 +04:00
unistr2_to_ascii ( filename , & q_u - > uni_file_name , sizeof ( filename ) ) ;
unix_convert ( filename , conn , NULL , & bad_path , & st ) ;
fsp = open_file_shared ( conn , filename , & st , SET_OPEN_MODE ( DOS_OPEN_RDWR ) ,
2001-09-19 06:28:15 +04:00
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) , 0 , 0 , & access_mode , & action ) ;
2001-06-16 04:32:13 +04:00
if ( ! fsp ) {
2001-06-18 21:52:58 +04:00
/* Perhaps it is a directory */
2001-06-19 22:43:17 +04:00
if ( errno = = EISDIR )
fsp = open_directory ( conn , filename , & st ,
2001-09-19 06:28:15 +04:00
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) , 0 , & action ) ;
2001-06-19 22:43:17 +04:00
2001-06-18 21:52:58 +04:00
if ( ! fsp ) {
DEBUG ( 3 , ( " _srv_net_file_set_secdesc: Unable to open file %s \n " , filename ) ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_ACCESS_DENIED ;
2001-06-18 21:52:58 +04:00
goto error_exit ;
}
2001-06-16 04:32:13 +04:00
}
ret = conn - > vfs_ops . set_nt_acl ( fsp , fsp - > fsp_name , q_u - > sec_info , q_u - > sec_desc ) ;
if ( ret = = False ) {
DEBUG ( 3 , ( " _srv_net_file_set_secdesc: Unable to set NT ACL on file %s \n " , filename ) ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_ACCESS_DENIED ;
2001-06-16 04:32:13 +04:00
goto error_exit ;
}
2001-06-22 22:58:35 +04:00
close_file ( fsp , True ) ;
2001-08-14 03:19:16 +04:00
unbecome_user ( ) ;
2001-06-16 04:32:13 +04:00
close_cnum ( conn , user . vuid ) ;
return r_u - > status ;
error_exit :
if ( fsp ) {
2001-06-22 22:58:35 +04:00
close_file ( fsp , True ) ;
2001-06-16 04:32:13 +04:00
}
2001-08-14 03:19:16 +04:00
if ( became_user )
unbecome_user ( ) ;
2001-06-16 04:32:13 +04:00
if ( conn )
close_cnum ( conn , user . vuid ) ;
return r_u - > status ;
}
2001-05-01 05:01:19 +04:00
/***********************************************************************************
It may be that we want to limit users to creating shares on certain areas of the UNIX file area .
We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy .
These disks would the disks listed by this function .
Users could then create shares relative to these disks . Watch out for moving these disks around .
" Nigel Williams " < nigel @ veritas . com > .
2001-05-02 12:14:00 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-01 05:01:19 +04:00
const char * server_disks [ ] = { " C: " } ;
static uint32 get_server_disk_count ( void )
{
return sizeof ( server_disks ) / sizeof ( server_disks [ 0 ] ) ;
}
static uint32 init_server_disk_enum ( uint32 * resume )
{
uint32 server_disk_count = get_server_disk_count ( ) ;
/*resume can be an offset into the list for now*/
2001-06-19 04:44:23 +04:00
if ( * resume & 0x80000000 )
2001-05-01 05:01:19 +04:00
* resume = 0 ;
if ( * resume > server_disk_count )
* resume = server_disk_count ;
return server_disk_count - * resume ;
}
static const char * next_server_disk_enum ( uint32 * resume )
{
const char * disk ;
if ( init_server_disk_enum ( resume ) = = 0 )
return NULL ;
disk = server_disks [ * resume ] ;
( * resume ) + + ;
DEBUG ( 10 , ( " next_server_disk_enum: reporting disk %s. resume handle %d. \n " , disk , * resume ) ) ;
return disk ;
}
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_disk_enum ( pipes_struct * p , SRV_Q_NET_DISK_ENUM * q_u , SRV_R_NET_DISK_ENUM * r_u )
2001-05-01 05:01:19 +04:00
{
uint32 i ;
const char * disk_name ;
uint32 resume = get_enum_hnd ( & q_u - > enum_hnd ) ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_OK ;
2001-05-01 05:01:19 +04:00
r_u - > total_entries = init_server_disk_enum ( & resume ) ;
r_u - > disk_enum_ctr . unknown = 0 ;
r_u - > disk_enum_ctr . disk_info_ptr = ( uint32 ) r_u - > disk_enum_ctr . disk_info ;
/*allow one DISK_INFO for null terminator*/
for ( i = 0 ; i < MAX_SERVER_DISK_ENTRIES - 1 & & ( disk_name = next_server_disk_enum ( & resume ) ) ; i + + ) {
r_u - > disk_enum_ctr . entries_read + + ;
/*copy disk name into a unicode string*/
init_unistr3 ( & r_u - > disk_enum_ctr . disk_info [ i ] . disk_name , disk_name ) ;
}
/*add a terminating null string. Is this there if there is more data to come?*/
r_u - > disk_enum_ctr . entries_read + + ;
init_unistr3 ( & r_u - > disk_enum_ctr . disk_info [ i ] . disk_name , " " ) ;
init_enum_hnd ( & r_u - > enum_hnd , resume ) ;
return r_u - > status ;
}
2001-08-27 23:46:22 +04:00
NTSTATUS _srv_net_name_validate ( pipes_struct * p , SRV_Q_NET_NAME_VALIDATE * q_u , SRV_R_NET_NAME_VALIDATE * r_u )
2001-05-01 05:01:19 +04:00
{
int snum ;
fstring share_name ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_OK ;
2001-05-01 05:01:19 +04:00
switch ( q_u - > type ) {
case 0x9 :
/*check if share name is ok*/
/*also check if we already have a share with this name*/
unistr2_to_ascii ( share_name , & q_u - > uni_name , sizeof ( share_name ) ) ;
snum = find_service ( share_name ) ;
/* Share already exists. */
if ( snum > = 0 )
r_u - > status = NT_STATUS_OBJECT_NAME_INVALID ;
break ;
default :
/*unsupported type*/
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_INVALID_LEVEL ;
2001-05-01 05:01:19 +04:00
break ;
}
return r_u - > status ;
}