2005-11-05 07:21:55 +03:00
/*
* Unix SMB / CIFS implementation .
2001-02-27 21:22:39 +03:00
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 1997 ,
* Copyright ( C ) Jeremy Allison 2001.
2002-08-17 19:34:15 +04:00
* Copyright ( C ) Nigel Williams 2001.
2001-02-27 21:22:39 +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 .
*/
/* This is the implementation of the srvsvc pipe. */
# include "includes.h"
2005-04-06 20:28:04 +04:00
extern struct generic_mapping file_generic_mapping ;
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_RPC_SRV
2005-12-14 04:09:46 +03:00
# define INVALID_SHARENAME_CHARS "<>*?| / \\+=;:\","
2005-12-11 08:06:35 +03:00
/********************************************************************
Check a string for any occurrences of a specified list of invalid
characters .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL validate_net_name ( const char * name , const char * invalid_chars , int max_len )
{
int i ;
for ( i = 0 ; i < max_len & & name [ i ] ; i + + ) {
/* fail if strchr_m() finds one of the invalid characters */
if ( name [ i ] & & strchr_m ( invalid_chars , name [ i ] ) )
return False ;
}
return True ;
}
2002-08-17 19:34:15 +04:00
/*******************************************************************
Utility function to get the ' type ' of a share from an snum .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint32 get_share_type ( int snum )
{
char * net_name = lp_servicename ( snum ) ;
int len_net_name = strlen ( net_name ) ;
/* work out the share type */
uint32 type = STYPE_DISKTREE ;
if ( lp_print_ok ( snum ) )
type = STYPE_PRINTQ ;
if ( strequal ( lp_fstype ( snum ) , " IPC " ) )
type = STYPE_IPC ;
if ( net_name [ len_net_name ] = = ' $ ' )
type | = STYPE_HIDDEN ;
return type ;
}
/*******************************************************************
Fill in a share info level 0 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_share_info_0 ( pipes_struct * p , SRV_SHARE_INFO_0 * sh0 , int snum )
{
pstring net_name ;
pstrcpy ( net_name , lp_servicename ( snum ) ) ;
init_srv_share_info0 ( & sh0 - > info_0 , net_name ) ;
init_srv_share_info0_str ( & sh0 - > info_0_str , net_name ) ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
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
{
pstring remark ;
2002-08-17 19:34:15 +04:00
char * net_name = lp_servicename ( snum ) ;
2001-02-27 21:22:39 +03:00
pstrcpy ( remark , lp_comment ( snum ) ) ;
2002-07-15 14:35:28 +04:00
standard_sub_conn ( p - > conn , remark , sizeof ( remark ) ) ;
2001-02-27 21:22:39 +03:00
2002-08-17 19:34:15 +04:00
init_srv_share_info1 ( & sh1 - > info_1 , net_name , get_share_type ( snum ) , remark ) ;
2001-02-27 21:22:39 +03:00
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
{
pstring remark ;
pstring path ;
pstring passwd ;
2002-08-17 19:34:15 +04:00
char * net_name = lp_servicename ( snum ) ;
2001-02-27 21:22:39 +03:00
pstrcpy ( remark , lp_comment ( snum ) ) ;
2002-07-15 14:35:28 +04:00
standard_sub_conn ( p - > conn , remark , sizeof ( 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 , " " ) ;
2002-08-17 19:34:15 +04:00
init_srv_share_info2 ( & sh2 - > info_2 , net_name , get_share_type ( snum ) , remark , 0 , 0xffffffff , 1 , path , passwd ) ;
2001-02-27 21:22:39 +03:00
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
static void smb_conf_updated ( int msg_type , struct process_id src ,
void * buf , size_t len )
2001-04-10 05:44:45 +04:00
{
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 */
2002-01-09 08:24:07 +03:00
# define SHARE_DATABASE_VERSION_V1 1
# define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */
2001-04-09 00:01:51 +04:00
BOOL share_info_db_init ( void )
{
2002-01-09 07:13:30 +03:00
static pid_t local_pid ;
2003-01-03 11:28:12 +03:00
const char * vstring = " INFO/version " ;
2002-01-09 07:13:30 +03:00
int32 vers_id ;
2001-04-09 00:01:51 +04:00
2002-01-09 07:13:30 +03:00
if ( share_tdb & & local_pid = = sys_getpid ( ) )
return True ;
share_tdb = tdb_open_log ( lock_path ( " share_info.tdb " ) , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
if ( ! share_tdb ) {
DEBUG ( 0 , ( " Failed to open share info database %s (%s) \n " ,
lock_path ( " share_info.tdb " ) , strerror ( errno ) ) ) ;
return False ;
}
2001-04-09 00:01:51 +04:00
2002-01-09 07:13:30 +03:00
local_pid = sys_getpid ( ) ;
2001-04-09 00:01:51 +04:00
2002-01-09 07:13:30 +03:00
/* handle a Samba upgrade */
2002-10-05 02:53:18 +04:00
tdb_lock_bystring ( share_tdb , vstring , 0 ) ;
2002-01-09 07:13:30 +03:00
/* Cope with byte-reversed older versions of the db. */
vers_id = tdb_fetch_int32 ( share_tdb , vstring ) ;
2002-01-09 08:24:07 +03:00
if ( ( vers_id = = SHARE_DATABASE_VERSION_V1 ) | | ( IREV ( vers_id ) = = SHARE_DATABASE_VERSION_V1 ) ) {
2002-01-09 07:13:30 +03:00
/* Written on a bigendian machine with old fetch_int code. Save as le. */
2002-01-09 08:24:07 +03:00
tdb_store_int32 ( share_tdb , vstring , SHARE_DATABASE_VERSION_V2 ) ;
vers_id = SHARE_DATABASE_VERSION_V2 ;
2002-01-09 07:13:30 +03:00
}
2002-01-09 08:24:07 +03:00
if ( vers_id ! = SHARE_DATABASE_VERSION_V2 ) {
2002-01-09 07:13:30 +03:00
tdb_traverse ( share_tdb , tdb_traverse_delete_fn , NULL ) ;
2002-01-09 08:24:07 +03:00
tdb_store_int32 ( share_tdb , vstring , SHARE_DATABASE_VERSION_V2 ) ;
2002-01-09 07:13:30 +03:00
}
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
2002-01-09 07:13:30 +03:00
return True ;
2001-04-09 00:01:51 +04:00
}
/*******************************************************************
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
{
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 ) ;
2002-03-05 05:12:00 +03:00
init_sec_access ( & sa , GENERIC_ALL_ACCESS | def_access ) ;
init_sec_ace ( & ace , & global_sid_World , SEC_ACE_TYPE_ACCESS_ALLOWED , sa , 0 ) ;
2001-04-05 03:42:17 +04:00
if ( ( psa = make_sec_acl ( ctx , NT4_ACL_REVISION , 1 , & ace ) ) ! = NULL ) {
2003-09-20 01:57:43 +04:00
psd = make_sec_desc ( ctx , SEC_DESC_REVISION , SEC_DESC_SELF_RELATIVE , NULL , NULL , NULL , psa , psize ) ;
2001-04-05 03:42:17 +04:00
}
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 ) ) ;
2002-03-05 05:12:00 +03:00
if ( tdb_prs_fetch ( share_tdb , key , & ps , ctx ) ! = 0 | |
! sec_io_desc ( " get_share_security " , & psd , & ps , 1 ) ) {
2001-04-09 00:01:51 +04:00
2002-03-05 05:12:00 +03:00
DEBUG ( 4 , ( " get_share_security: using default secdesc for %s \n " , lp_servicename ( snum ) ) ) ;
2001-04-09 00:01:51 +04:00
2002-03-05 05:12:00 +03:00
return get_share_security_default ( ctx , snum , psize ) ;
}
2001-04-09 00:01:51 +04:00
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 ;
2002-12-20 23:21:31 +03:00
mem_ctx = talloc_init ( " set_share_security " ) ;
2001-04-09 00:01:51 +04:00
if ( mem_ctx = = NULL )
return False ;
prs_init ( & ps , ( uint32 ) sec_desc_size ( psd ) , mem_ctx , MARSHALL ) ;
2002-03-05 05:12:00 +03:00
if ( ! sec_io_desc ( " share_security " , & psd , & ps , 1 ) )
goto out ;
2001-04-09 00:01:51 +04:00
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
2002-03-05 05:12:00 +03:00
if ( tdb_prs_store ( share_tdb , key , & ps ) = = 0 ) {
ret = True ;
DEBUG ( 5 , ( " set_share_security: stored secdesc for %s \n " , share_name ) ) ;
} else {
DEBUG ( 1 , ( " set_share_security: Failed to store secdesc for %s \n " , share_name ) ) ;
}
/* Free malloc'ed memory */
2001-04-09 00:01:51 +04:00
2002-08-17 19:34:15 +04:00
out :
2001-04-09 00:01:51 +04:00
2002-03-05 05:12:00 +03:00
prs_mem_free ( & ps ) ;
if ( mem_ctx )
talloc_destroy ( mem_ctx ) ;
return ret ;
2001-04-09 00:01:51 +04:00
}
/*******************************************************************
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 )
{
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 ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
BOOL share_access_check ( connection_struct * conn , int snum , user_struct * vuser , 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
BOOL ret = True ;
2002-12-20 23:21:31 +03:00
mem_ctx = talloc_init ( " share_access_check " ) ;
2001-04-09 10:36:38 +04:00
if ( mem_ctx = = NULL )
return False ;
psd = get_share_security ( mem_ctx , snum , & sd_size ) ;
if ( ! psd )
goto out ;
2002-09-25 19:19:00 +04:00
if ( conn - > nt_user_token )
2001-09-26 04:05:03 +04:00
token = conn - > nt_user_token ;
2002-09-25 19:19:00 +04:00
else
token = vuser - > 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
2002-08-17 19:34:15 +04:00
out :
2001-04-09 10:36:38 +04:00
talloc_destroy ( mem_ctx ) ;
return ret ;
}
2002-04-10 05:04:13 +04:00
/*******************************************************************
Fill in a share info level 501 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_share_info_501 ( pipes_struct * p , SRV_SHARE_INFO_501 * sh501 , int snum )
{
pstring remark ;
2004-11-24 02:13:48 +03:00
const char * net_name = lp_servicename ( snum ) ;
2002-04-10 05:04:13 +04:00
pstrcpy ( remark , lp_comment ( snum ) ) ;
2002-07-15 14:35:28 +04:00
standard_sub_conn ( p - > conn , remark , sizeof ( remark ) ) ;
2002-04-10 05:04:13 +04:00
2002-08-17 19:34:15 +04:00
init_srv_share_info501 ( & sh501 - > info_501 , net_name , get_share_type ( snum ) , remark , ( lp_csc_policy ( snum ) < < 4 ) ) ;
2002-04-10 05:04:13 +04:00
init_srv_share_info501_str ( & sh501 - > info_501_str , net_name , remark ) ;
}
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
{
pstring net_name ;
pstring remark ;
pstring path ;
pstring passwd ;
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 ) ) ;
2002-07-15 14:35:28 +04:00
standard_sub_conn ( p - > conn , remark , sizeof ( 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 , " " ) ;
sd = get_share_security ( ctx , snum , & sd_size ) ;
2002-08-17 19:34:15 +04:00
init_srv_share_info502 ( & sh502 - > info_502 , net_name , get_share_type ( snum ) , remark , 0 , 0xffffffff , 1 , path , passwd , sd , sd_size ) ;
init_srv_share_info502_str ( & sh502 - > info_502_str , net_name , remark , path , passwd , sd , sd_size ) ;
}
/***************************************************************************
Fill in a share info level 1004 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_share_info_1004 ( pipes_struct * p , SRV_SHARE_INFO_1004 * sh1004 , int snum )
{
pstring remark ;
pstrcpy ( remark , lp_comment ( snum ) ) ;
standard_sub_conn ( p - > conn , remark , sizeof ( remark ) ) ;
ZERO_STRUCTP ( sh1004 ) ;
init_srv_share_info1004 ( & sh1004 - > info_1004 , remark ) ;
init_srv_share_info1004_str ( & sh1004 - > info_1004_str , remark ) ;
2001-04-05 03:42:17 +04:00
}
2001-02-27 21:22:39 +03:00
/***************************************************************************
Fill in a share info level 1005 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 19:34:15 +04:00
static void init_srv_share_info_1005 ( pipes_struct * p , SRV_SHARE_INFO_1005 * sh1005 , int snum )
2001-02-27 21:22:39 +03:00
{
2003-07-02 01:47:13 +04:00
sh1005 - > share_info_flags = 0 ;
2001-02-27 21:22:39 +03:00
if ( lp_host_msdfs ( ) & & lp_msdfs_root ( snum ) )
2003-07-02 01:47:13 +04:00
sh1005 - > share_info_flags | =
SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT ;
sh1005 - > share_info_flags | =
lp_csc_policy ( snum ) < < SHARE_1005_CSC_POLICY_SHIFT ;
2001-02-27 21:22:39 +03:00
}
2002-08-17 19:34:15 +04:00
/***************************************************************************
Fill in a share info level 1006 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_share_info_1006 ( pipes_struct * p , SRV_SHARE_INFO_1006 * sh1006 , int snum )
{
sh1006 - > max_uses = - 1 ;
}
/***************************************************************************
Fill in a share info level 1007 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_share_info_1007 ( pipes_struct * p , SRV_SHARE_INFO_1007 * sh1007 , int snum )
{
pstring alternate_directory_name = " " ;
uint32 flags = 0 ;
ZERO_STRUCTP ( sh1007 ) ;
init_srv_share_info1007 ( & sh1007 - > info_1007 , flags , alternate_directory_name ) ;
init_srv_share_info1007_str ( & sh1007 - > info_1007_str , alternate_directory_name ) ;
}
/*******************************************************************
Fill in a share info level 1501 structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_srv_share_info_1501 ( pipes_struct * p , SRV_SHARE_INFO_1501 * sh1501 , int snum )
{
SEC_DESC * sd ;
size_t sd_size ;
TALLOC_CTX * ctx = p - > mem_ctx ;
ZERO_STRUCTP ( sh1501 ) ;
sd = get_share_security ( ctx , snum , & sd_size ) ;
sh1501 - > sdb = make_sec_desc_buf ( p - > mem_ctx , sd_size , sd ) ;
}
2001-02-27 21:22:39 +03:00
2001-04-06 05:39:12 +04:00
/*******************************************************************
True if it ends in ' $ ' .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 19:34:15 +04:00
static BOOL is_hidden_share ( int snum )
2001-04-06 05:39:12 +04:00
{
2003-11-19 03:18:45 +03:00
const char * net_name = lp_servicename ( snum ) ;
2001-04-06 05:39:12 +04:00
2003-11-19 03:18:45 +03:00
return ( net_name [ strlen ( net_name ) - 1 ] = = ' $ ' ) ? True : False ;
2001-04-06 05:39:12 +04:00
}
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 + + ) {
2002-08-17 19:34:15 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_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 ) {
2002-08-17 19:34:15 +04:00
case 0 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_0 * info0 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_0 , num_entries ) ;
2002-08-17 19:34:15 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info0 ) {
return False ;
}
2002-08-17 19:34:15 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_share ( snum ) ) ) {
init_srv_share_info_0 ( p , & info0 [ i + + ] , snum ) ;
}
}
ctr - > share . info0 = info0 ;
break ;
}
2001-02-27 21:22:39 +03:00
case 1 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_1 * info1 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_1 , num_entries ) ;
2001-02-27 21:22:39 +03:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info1 ) {
return False ;
}
2001-02-27 21:22:39 +03:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
2002-08-17 19:34:15 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_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 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_2 * info2 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_2 , num_entries ) ;
2001-02-27 21:22:39 +03:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info2 ) {
return False ;
}
2001-02-27 21:22:39 +03:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
2002-08-17 19:34:15 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_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 ;
}
2002-04-10 05:04:13 +04:00
case 501 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_501 * info501 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_501 , num_entries ) ;
2002-04-10 05:04:13 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info501 ) {
return False ;
}
2002-04-10 05:04:13 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
2002-08-17 19:34:15 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_share ( snum ) ) ) {
2002-04-10 05:04:13 +04:00
init_srv_share_info_501 ( p , & info501 [ i + + ] , snum ) ;
}
}
ctr - > share . info501 = info501 ;
break ;
}
2001-04-05 03:42:17 +04:00
case 502 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_502 * info502 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_502 , num_entries ) ;
2001-04-05 03:42:17 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info502 ) {
return False ;
}
2001-04-05 03:42:17 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
2002-08-17 19:34:15 +04:00
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_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 ;
}
2002-08-17 19:34:15 +04:00
/* here for completeness but not currently used with enum (1004 - 1501)*/
case 1004 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_1004 * info1004 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_1004 , num_entries ) ;
2002-08-17 19:34:15 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info1004 ) {
return False ;
}
2002-08-17 19:34:15 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_share ( snum ) ) ) {
init_srv_share_info_1004 ( p , & info1004 [ i + + ] , snum ) ;
}
}
ctr - > share . info1004 = info1004 ;
break ;
}
case 1005 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_1005 * info1005 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_1005 , num_entries ) ;
2002-08-17 19:34:15 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info1005 ) {
return False ;
}
2002-08-17 19:34:15 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_share ( snum ) ) ) {
init_srv_share_info_1005 ( p , & info1005 [ i + + ] , snum ) ;
}
}
ctr - > share . info1005 = info1005 ;
break ;
}
case 1006 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_1006 * info1006 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_1006 , num_entries ) ;
2002-08-17 19:34:15 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info1006 ) {
return False ;
}
2002-08-17 19:34:15 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_share ( snum ) ) ) {
init_srv_share_info_1006 ( p , & info1006 [ i + + ] , snum ) ;
}
}
ctr - > share . info1006 = info1006 ;
break ;
}
case 1007 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_1007 * info1007 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_1007 , num_entries ) ;
2002-08-17 19:34:15 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info1007 ) {
return False ;
}
2002-08-17 19:34:15 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_share ( snum ) ) ) {
init_srv_share_info_1007 ( p , & info1007 [ i + + ] , snum ) ;
}
}
ctr - > share . info1007 = info1007 ;
break ;
}
case 1501 :
{
2004-12-07 21:25:53 +03:00
SRV_SHARE_INFO_1501 * info1501 = TALLOC_ARRAY ( ctx , SRV_SHARE_INFO_1501 , num_entries ) ;
2002-08-17 19:34:15 +04:00
int i = 0 ;
2004-12-07 21:25:53 +03:00
if ( ! info1501 ) {
return False ;
}
2002-08-17 19:34:15 +04:00
for ( snum = * resume_hnd ; snum < num_services ; snum + + ) {
if ( lp_browseable ( snum ) & & lp_snum_ok ( snum ) & & ( all_shares | | ! is_hidden_share ( snum ) ) ) {
init_srv_share_info_1501 ( p , & info1501 [ i + + ] , snum ) ;
}
}
ctr - > share . info1501 = info1501 ;
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 ) ) {
2002-03-05 05:12:00 +03:00
r_n - > status = WERR_OK ;
2001-02-27 21:22:39 +03:00
} else {
2002-03-05 05:12:00 +03:00
r_n - > status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
}
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 )
{
2002-03-05 05:12:00 +03:00
WERROR status = WERR_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 ) {
2002-08-17 19:34:15 +04:00
case 0 :
init_srv_share_info_0 ( p , & r_n - > info . share . info0 , snum ) ;
break ;
2001-02-27 21:22:39 +03:00
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 ;
2002-04-10 05:04:13 +04:00
case 501 :
init_srv_share_info_501 ( p , & r_n - > info . share . info501 , snum ) ;
break ;
2001-04-05 03:42:17 +04:00
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 ;
2002-08-17 19:34:15 +04:00
/* here for completeness */
case 1004 :
init_srv_share_info_1004 ( p , & r_n - > info . share . info1004 , snum ) ;
break ;
2001-02-27 21:22:39 +03:00
case 1005 :
2002-08-17 19:34:15 +04:00
init_srv_share_info_1005 ( p , & r_n - > info . share . info1005 , snum ) ;
break ;
/* here for completeness 1006 - 1501 */
case 1006 :
init_srv_share_info_1006 ( p , & r_n - > info . share . info1006 , snum ) ;
break ;
case 1007 :
init_srv_share_info_1007 ( p , & r_n - > info . share . info1007 , snum ) ;
break ;
case 1501 :
init_srv_share_info_1501 ( p , & r_n - > info . share . info1501 , 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 ) ) ;
2002-03-05 05:12:00 +03:00
status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
break ;
}
} else {
2002-03-05 05:12:00 +03:00
status = WERR_INVALID_NAME ;
2001-02-27 21:22:39 +03:00
}
2002-03-05 05:12:00 +03:00
r_n - > info . ptr_share_ctr = W_ERROR_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 )
{
2002-07-15 14:35:28 +04:00
struct sessionid * session_list ;
2001-02-27 21:22:39 +03:00
uint32 num_entries = 0 ;
2002-07-15 14:35:28 +04:00
( * stot ) = list_sessions ( & session_list ) ;
2001-02-27 21:22:39 +03:00
if ( ss0 = = NULL ) {
( * snum ) = 0 ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( session_list ) ;
2001-02-27 21:22:39 +03:00
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 ] ,
2002-07-15 14:35:28 +04:00
& ss0 - > info_0_str [ num_entries ] , session_list [ ( * snum ) ] . remote_machine ) ;
2001-02-27 21:22:39 +03:00
/* 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 ;
}
2002-07-15 14:35:28 +04:00
SAFE_FREE ( session_list ) ;
2001-02-27 21:22:39 +03:00
}
/*******************************************************************
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 )
{
2002-07-15 14:35:28 +04:00
struct sessionid * session_list ;
2001-02-27 21:22:39 +03:00
uint32 num_entries = 0 ;
2002-07-15 14:35:28 +04:00
( * stot ) = list_sessions ( & session_list ) ;
2001-02-27 21:22:39 +03:00
if ( ss1 = = NULL ) {
( * snum ) = 0 ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( session_list ) ;
2001-02-27 21:22:39 +03:00
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 ] ,
2002-07-15 14:35:28 +04:00
& ss1 - > info_1_str [ num_entries ] ,
session_list [ * snum ] . remote_machine ,
session_list [ * snum ] . username ,
1 , 10 , 5 , 0 ) ;
2001-02-27 21:22:39 +03:00
/* 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
static WERROR 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 )
{
2002-03-05 05:12:00 +03:00
WERROR status = WERR_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 ;
2002-03-05 05:12:00 +03:00
status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
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 )
2002-03-05 05:12:00 +03:00
r_n - > status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
else
r_n - > status = init_srv_sess_info_ctr ( r_n - > ctr , switch_value , & resume_hnd , & r_n - > total_entries ) ;
2002-03-05 05:12:00 +03:00
if ( ! W_ERROR_IS_OK ( 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 ,
2003-01-03 11:28:12 +03:00
const char * usr_name , const char * net_name )
2001-02-27 21:22:39 +03:00
{
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
static WERROR 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 )
{
2002-03-05 05:12:00 +03:00
WERROR status = WERR_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 ;
2002-03-05 05:12:00 +03:00
status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
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 )
2002-03-05 05:12:00 +03:00
r_n - > status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
else
r_n - > status = init_srv_conn_info_ctr ( r_n - > ctr , switch_value , & resume_hnd , & r_n - > total_entries ) ;
2002-03-05 05:12:00 +03:00
if ( ! W_ERROR_IS_OK ( r_n - > status ) )
2001-02-27 21:22:39 +03:00
resume_hnd = 0 ;
init_enum_hnd ( & r_n - > enum_hnd , resume_hnd ) ;
}
/*******************************************************************
makes a SRV_R_NET_FILE_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
static WERROR init_srv_file_info_ctr ( pipes_struct * p , SRV_FILE_INFO_CTR * ctr ,
2002-08-17 19:34:15 +04:00
int switch_value , uint32 * resume_hnd ,
uint32 * total_entries )
2001-02-27 21:22:39 +03:00
{
2002-03-05 05:12:00 +03:00
WERROR status = WERR_OK ;
2002-07-15 14:35:28 +04:00
TALLOC_CTX * ctx = p - > mem_ctx ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " init_srv_file_info_ctr: %d \n " , __LINE__ ) ) ;
2002-07-15 14:35:28 +04:00
* total_entries = 1 ; /* dummy entries only, for */
2001-02-27 21:22:39 +03:00
ctr - > switch_value = switch_value ;
2002-07-15 14:35:28 +04:00
ctr - > num_entries = * total_entries - * resume_hnd ;
ctr - > num_entries2 = ctr - > num_entries ;
2001-02-27 21:22:39 +03:00
switch ( switch_value ) {
2002-07-15 14:35:28 +04:00
case 3 : {
int i ;
if ( * total_entries > 0 ) {
ctr - > ptr_entries = 1 ;
2004-12-07 21:25:53 +03:00
ctr - > file . info3 = TALLOC_ARRAY ( ctx , SRV_FILE_INFO_3 , ctr - > num_entries ) ;
2002-07-15 14:35:28 +04:00
}
for ( i = 0 ; i < ctr - > num_entries ; i + + ) {
init_srv_file_info3 ( & ctr - > file . info3 [ i ] . info_3 , i + * resume_hnd , 0x35 , 0 , " \\ PIPE \\ samr " , " dummy user " ) ;
init_srv_file_info3_str ( & ctr - > file . info3 [ i ] . info_3_str , " \\ PIPE \\ samr " , " dummy user " ) ;
}
ctr - > ptr_file_info = 1 ;
* resume_hnd = 0 ;
2001-02-27 21:22:39 +03:00
break ;
2002-07-15 14:35:28 +04:00
}
2001-02-27 21:22:39 +03:00
default :
DEBUG ( 5 , ( " init_srv_file_info_ctr: unsupported switch value %d \n " , switch_value ) ) ;
( * resume_hnd = 0 ) ;
( * total_entries ) = 0 ;
2002-07-15 14:35:28 +04:00
ctr - > ptr_entries = 0 ;
2002-03-05 05:12:00 +03:00
status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
break ;
}
return status ;
}
/*******************************************************************
makes a SRV_R_NET_FILE_ENUM structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
static void init_srv_r_net_file_enum ( pipes_struct * p , SRV_R_NET_FILE_ENUM * r_n ,
2001-02-27 21:22:39 +03:00
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 )
2002-03-05 05:12:00 +03:00
r_n - > status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
else
2002-07-15 14:35:28 +04:00
r_n - > status = init_srv_file_info_ctr ( p , & r_n - > ctr , switch_value , & resume_hnd , & ( r_n - > total_entries ) ) ;
2001-02-27 21:22:39 +03:00
2002-03-05 05:12:00 +03:00
if ( ! W_ERROR_IS_OK ( 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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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
{
2002-03-05 05:12:00 +03:00
WERROR status = WERR_OK ;
2004-12-07 21:25:53 +03:00
SRV_INFO_CTR * ctr = TALLOC_P ( p - > mem_ctx , SRV_INFO_CTR ) ;
2001-02-27 21:22:39 +03:00
if ( ! ctr )
2002-03-05 05:12:00 +03:00
return WERR_NOMEM ;
2001-02-27 21:22:39 +03:00
ZERO_STRUCTP ( ctr ) ;
DEBUG ( 5 , ( " srv_net_srv_get_info: %d \n " , __LINE__ ) ) ;
2002-07-15 14:35:28 +04:00
if ( ! pipe_access_check ( p ) ) {
DEBUG ( 3 , ( " access denied to srv_net_srv_get_info \n " ) ) ;
return WERR_ACCESS_DENIED ;
}
2001-02-27 21:22:39 +03:00
switch ( q_u - > switch_value ) {
2002-07-15 14:35:28 +04:00
/* Technically level 102 should only be available to
Administrators but there isn ' t anything super - secret
here , as most of it is made up . */
2001-02-27 21:22:39 +03:00
case 102 :
init_srv_info_102 ( & ctr - > srv . sv102 ,
2002-11-13 02:20:50 +03:00
500 , global_myname ( ) ,
2002-07-15 14:35:28 +04:00
string_truncate ( lp_serverstring ( ) , MAX_SERVER_STRING_LENGTH ) ,
2001-02-27 21:22:39 +03:00
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 ,
2002-11-13 02:20:50 +03:00
500 , global_myname ( ) ,
2001-02-27 21:22:39 +03:00
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 :
2002-11-13 02:20:50 +03:00
init_srv_info_100 ( & ctr - > srv . sv100 , 500 , global_myname ( ) ) ;
2001-03-11 03:32:10 +03:00
break ;
2001-02-27 21:22:39 +03:00
default :
2002-03-05 05:12:00 +03:00
status = WERR_UNKNOWN_LEVEL ;
2001-02-27 21:22:39 +03:00
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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
{
2002-03-05 05:12:00 +03:00
WERROR status = WERR_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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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
{
DEBUG ( 5 , ( " srv_net_file_enum: %d \n " , __LINE__ ) ) ;
/* set up the */
2002-07-15 14:35:28 +04:00
init_srv_r_net_file_enum ( p , r_u ,
2001-02-27 21:22:39 +03:00
get_enum_hnd ( & q_u - > enum_hnd ) ,
q_u - > file_level ,
2002-07-15 14:35:28 +04:00
q_u - > ctr . switch_value ) ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " srv_net_file_enum: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
net conn enum
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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__ ) ) ;
2004-12-07 21:25:53 +03:00
r_u - > ctr = TALLOC_P ( p - > mem_ctx , SRV_CONN_INFO_CTR ) ;
2001-02-27 21:22:39 +03:00
if ( ! r_u - > ctr )
2002-03-05 05:12:00 +03:00
return WERR_NOMEM ;
2001-02-27 21:22:39 +03:00
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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__ ) ) ;
2004-12-07 21:25:53 +03:00
r_u - > ctr = TALLOC_P ( p - > mem_ctx , SRV_SESS_INFO_CTR ) ;
2001-02-27 21:22:39 +03:00
if ( ! r_u - > ctr )
2002-03-05 05:12:00 +03:00
return WERR_NOMEM ;
2001-02-27 21:22:39 +03:00
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__ ) ) ;
2005-03-23 23:57:03 +03:00
return r_u - > status ;
}
/*******************************************************************
net sess del
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR _srv_net_sess_del ( pipes_struct * p , SRV_Q_NET_SESS_DEL * q_u , SRV_R_NET_SESS_DEL * r_u )
{
struct sessionid * session_list ;
2005-03-24 03:01:56 +03:00
struct current_user user ;
2005-07-19 07:54:01 +04:00
int num_sessions , snum ;
2005-03-23 23:57:03 +03:00
fstring username ;
fstring machine ;
2005-03-24 11:36:00 +03:00
BOOL not_root = False ;
2005-03-23 23:57:03 +03:00
rpcstr_pull_unistr2_fstring ( username , & q_u - > uni_user_name ) ;
rpcstr_pull_unistr2_fstring ( machine , & q_u - > uni_cli_name ) ;
/* strip leading backslashes if any */
while ( machine [ 0 ] = = ' \\ ' ) {
memmove ( machine , & machine [ 1 ] , strlen ( machine ) ) ;
}
num_sessions = list_sessions ( & session_list ) ;
DEBUG ( 5 , ( " _srv_net_sess_del: %d \n " , __LINE__ ) ) ;
r_u - > status = WERR_ACCESS_DENIED ;
2005-03-24 03:01:56 +03:00
get_current_user ( & user , p ) ;
2005-03-24 17:40:35 +03:00
/* fail out now if you are not root or not a domain admin */
2005-03-24 03:01:56 +03:00
if ( ( user . uid ! = sec_initial_uid ( ) ) & &
( ! nt_token_check_domain_rid ( p - > pipe_user . nt_user_token , DOMAIN_GROUP_RID_ADMINS ) ) ) {
goto done ;
}
2005-03-23 23:57:03 +03:00
for ( snum = 0 ; snum < num_sessions ; snum + + ) {
2005-03-24 00:46:09 +03:00
if ( ( strequal ( session_list [ snum ] . username , username ) | | username [ 0 ] = = ' \0 ' ) & &
strequal ( session_list [ snum ] . remote_machine , machine ) ) {
2005-03-23 23:57:03 +03:00
2005-03-24 03:01:56 +03:00
if ( user . uid ! = sec_initial_uid ( ) ) {
2005-03-24 11:36:00 +03:00
not_root = True ;
2005-03-24 03:01:56 +03:00
become_root ( ) ;
}
2005-03-24 17:40:35 +03:00
2005-09-30 21:13:37 +04:00
if ( message_send_pid ( pid_to_procid ( session_list [ snum ] . pid ) , MSG_SHUTDOWN , NULL , 0 , False ) )
2005-03-23 23:57:03 +03:00
r_u - > status = WERR_OK ;
2005-03-24 17:40:35 +03:00
if ( not_root )
2005-03-24 03:01:56 +03:00
unbecome_root ( ) ;
2005-03-23 23:57:03 +03:00
}
}
DEBUG ( 5 , ( " _srv_net_sess_del: %d \n " , __LINE__ ) ) ;
2005-03-24 03:01:56 +03:00
done :
SAFE_FREE ( session_list ) ;
2001-02-27 21:22:39 +03:00
return r_u - > status ;
}
2001-04-06 05:39:12 +04:00
/*******************************************************************
Net share enum all .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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__ ) ) ;
2002-07-15 14:35:28 +04:00
if ( ! pipe_access_check ( p ) ) {
DEBUG ( 3 , ( " access denied to srv_net_share_enum_all \n " ) ) ;
return WERR_ACCESS_DENIED ;
}
2001-04-06 05:39:12 +04:00
/* 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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__ ) ) ;
2002-07-15 14:35:28 +04:00
if ( ! pipe_access_check ( p ) ) {
DEBUG ( 3 , ( " access denied to srv_net_share_enum \n " ) ) ;
return WERR_ACCESS_DENIED ;
}
2001-02-27 21:22:39 +03:00
/* 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 ,
2002-08-17 19:34:15 +04:00
q_u - > ctr . info_level ,
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-23 20:25:31 +04:00
char * valid_share_pathname ( char * dos_pathname )
2001-04-07 22:46:47 +04:00
{
char * ptr ;
/* 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 ;
2005-05-23 20:25:31 +04:00
/* Only absolute paths allowed. */
2001-04-07 22:46:47 +04:00
if ( * ptr ! = ' / ' )
return NULL ;
2005-01-19 21:28:55 +03:00
return ptr ;
2001-04-07 22:46:47 +04:00
}
2001-04-09 00:01:51 +04:00
/*******************************************************************
Net share set info . Modify share details .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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 ;
2005-01-19 21:28:55 +03:00
char * path ;
2001-04-09 10:36:38 +04:00
SEC_DESC * psd = NULL ;
2005-01-18 22:51:36 +03:00
SE_PRIV se_diskop = SE_DISK_OPERATOR ;
2005-03-24 00:46:09 +03:00
BOOL is_disk_op = False ;
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 ) ) ;
2002-08-17 19:34:15 +04:00
r_u - > parm_error = 0 ;
2001-04-09 00:01:51 +04:00
2005-05-23 20:25:31 +04:00
if ( strequal ( share_name , " IPC$ " )
| | ( lp_enable_asu_support ( ) & & strequal ( share_name , " ADMIN$ " ) )
| | strequal ( share_name , " global " ) )
{
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2005-05-23 20:25:31 +04:00
}
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 )
2005-06-15 16:43:36 +04:00
return WERR_NET_NAME_NOT_FOUND ;
2001-04-09 22:03:02 +04:00
/* No change to printer shares. */
if ( lp_print_ok ( snum ) )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-09 00:01:51 +04:00
get_current_user ( & user , p ) ;
2005-01-18 22:51:36 +03:00
is_disk_op = user_has_privileges ( p - > pipe_user . nt_user_token , & se_diskop ) ;
/* fail out now if you are not root and not a disk op */
if ( user . uid ! = sec_initial_uid ( ) & & ! is_disk_op )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-09 00:01:51 +04:00
switch ( q_u - > info_level ) {
case 1 :
2003-01-14 11:53:59 +03:00
pstrcpy ( pathname , lp_pathname ( snum ) ) ;
2002-08-17 19:34:15 +04:00
unistr2_to_ascii ( comment , & q_u - > info . share . info2 . info_2_str . uni_remark , sizeof ( comment ) ) ;
type = q_u - > info . share . info2 . info_2 . type ;
psd = NULL ;
break ;
2001-04-09 00:01:51 +04:00
case 2 :
2002-08-17 19:34:15 +04:00
unistr2_to_ascii ( comment , & q_u - > info . share . info2 . info_2_str . uni_remark , sizeof ( comment ) ) ;
unistr2_to_ascii ( pathname , & q_u - > info . share . info2 . info_2_str . uni_path , sizeof ( pathname ) ) ;
2001-04-09 10:36:38 +04:00
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 ;
2002-08-17 19:34:15 +04:00
#if 0
/* not supported on set but here for completeness */
case 501 :
unistr2_to_ascii ( comment , & q_u - > info . share . info501 . info_501_str . uni_remark , sizeof ( comment ) ) ;
type = q_u - > info . share . info501 . info_501 . type ;
psd = NULL ;
break ;
# endif
2001-04-09 00:01:51 +04:00
case 502 :
2002-08-17 19:34:15 +04:00
unistr2_to_ascii ( comment , & q_u - > info . share . info502 . info_502_str . uni_remark , sizeof ( comment ) ) ;
unistr2_to_ascii ( pathname , & q_u - > info . share . info502 . info_502_str . uni_path , sizeof ( pathname ) ) ;
2001-04-09 10:36:38 +04:00
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 ;
2002-08-17 19:34:15 +04:00
case 1004 :
2003-01-14 11:53:59 +03:00
pstrcpy ( pathname , lp_pathname ( snum ) ) ;
2002-08-17 19:34:15 +04:00
unistr2_to_ascii ( comment , & q_u - > info . share . info1004 . info_1004_str . uni_remark , sizeof ( comment ) ) ;
type = STYPE_DISKTREE ;
break ;
2001-04-09 00:01:51 +04:00
case 1005 :
2003-07-02 01:47:13 +04:00
/* XP re-sets the csc policy even if it wasn't changed by the
user , so we must compare it to see if it ' s what is set in
smb . conf , so that we can contine other ops like setting
ACLs on a share */
if ( ( ( q_u - > info . share . info1005 . share_info_flags &
SHARE_1005_CSC_POLICY_MASK ) > >
SHARE_1005_CSC_POLICY_SHIFT ) = = lp_csc_policy ( snum ) )
return WERR_OK ;
else {
DEBUG ( 3 , ( " _srv_net_share_set_info: client is trying to change csc policy from the network; must be done with smb.conf \n " ) ) ;
return WERR_ACCESS_DENIED ;
}
2002-08-17 19:34:15 +04:00
case 1006 :
case 1007 :
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-09 12:00:19 +04:00
case 1501 :
2003-01-14 11:53:59 +03:00
pstrcpy ( pathname , lp_pathname ( snum ) ) ;
2001-04-09 12:00:19 +04:00
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 ) ) ;
2002-03-05 05:12:00 +03:00
return WERR_UNKNOWN_LEVEL ;
2001-04-09 10:36:38 +04:00
}
/* We can only modify disk shares. */
if ( type ! = STYPE_DISKTREE )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-09 10:36:38 +04:00
/* Check if the pathname is valid. */
2005-01-19 21:28:55 +03:00
if ( ! ( path = valid_share_pathname ( pathname ) ) )
2002-03-05 05:12:00 +03:00
return WERR_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 , ' " ' , ' ' ) ;
2005-01-19 21:28:55 +03:00
string_replace ( path , ' " ' , ' ' ) ;
2001-04-09 10:36:38 +04:00
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. */
2005-01-18 22:51:36 +03:00
2005-01-19 21:28:55 +03:00
if ( strcmp ( path , lp_pathname ( snum ) ) | | strcmp ( comment , lp_comment ( snum ) ) )
2005-01-18 22:51:36 +03:00
{
2005-06-30 19:19:54 +04:00
if ( ! lp_change_share_cmd ( ) | | ! * lp_change_share_cmd ( ) ) {
DEBUG ( 10 , ( " _srv_net_share_set_info: No change share command \n " ) ) ;
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2005-06-30 19:19:54 +04:00
}
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 \" " ,
2005-01-19 21:28:55 +03:00
lp_change_share_cmd ( ) , dyn_CONFIGFILE , share_name , path , comment ) ;
2001-04-09 10:36:38 +04:00
DEBUG ( 10 , ( " _srv_net_share_set_info: Running [%s] \n " , command ) ) ;
2005-01-18 22:51:36 +03:00
/********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
if ( is_disk_op )
become_root ( ) ;
2005-01-20 00:10:56 +03:00
if ( ( ret = smbrun ( command , NULL ) ) = = 0 ) {
/* Tell everyone we updated smb.conf. */
message_send_all ( conn_tdb_ctx ( ) , MSG_SMB_CONF_UPDATED , NULL , 0 , False , NULL ) ;
}
2005-01-18 22:51:36 +03:00
if ( is_disk_op )
unbecome_root ( ) ;
/********* END SeDiskOperatorPrivilege BLOCK *********/
DEBUG ( 3 , ( " _srv_net_share_set_info: Running [%s] returned (%d) \n " , command , ret ) ) ;
if ( ret ! = 0 )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
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
}
2005-01-18 22:51:36 +03:00
2001-04-09 00:01:51 +04:00
DEBUG ( 5 , ( " _srv_net_share_set_info: %d \n " , __LINE__ ) ) ;
2002-03-05 05:12:00 +03:00
return WERR_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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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 ;
2005-01-19 21:28:55 +03:00
char * path ;
2001-04-09 10:36:38 +04:00
SEC_DESC * psd = NULL ;
2005-01-18 22:51:36 +03:00
SE_PRIV se_diskop = SE_DISK_OPERATOR ;
BOOL is_disk_op ;
2001-04-06 21:41:47 +04:00
DEBUG ( 5 , ( " _srv_net_share_add: %d \n " , __LINE__ ) ) ;
2002-08-17 19:34:15 +04:00
r_u - > parm_error = 0 ;
2001-04-06 21:41:47 +04:00
2001-04-07 04:36:38 +04:00
get_current_user ( & user , p ) ;
2005-01-18 22:51:36 +03:00
is_disk_op = user_has_privileges ( p - > pipe_user . nt_user_token , & se_diskop ) ;
if ( user . uid ! = sec_initial_uid ( ) & & ! is_disk_op )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
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 " ) ) ;
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-09 22:03:02 +04:00
}
2005-01-18 22:51:36 +03:00
2001-04-06 21:41:47 +04:00
switch ( q_u - > info_level ) {
2002-08-17 19:34:15 +04:00
case 0 :
/* No path. Not enough info in a level 0 to do anything. */
return WERR_ACCESS_DENIED ;
2001-04-06 21:41:47 +04:00
case 1 :
2001-04-07 04:36:38 +04:00
/* Not enough info in a level 1 to do anything. */
2002-03-05 05:12:00 +03:00
return WERR_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 ;
2002-08-17 19:34:15 +04:00
case 501 :
/* No path. Not enough info in a level 501 to do anything. */
return WERR_ACCESS_DENIED ;
2001-04-06 21:41:47 +04:00
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 ;
2002-08-17 19:34:15 +04:00
/* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
case 1004 :
2001-04-06 21:41:47 +04:00
case 1005 :
2002-08-17 19:34:15 +04:00
case 1006 :
case 1007 :
return WERR_ACCESS_DENIED ;
case 1501 :
2001-04-07 04:36:38 +04:00
/* DFS only level. */
2002-03-05 05:12:00 +03:00
return WERR_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 ) ) ;
2002-03-05 05:12:00 +03:00
return WERR_UNKNOWN_LEVEL ;
2001-04-06 21:41:47 +04:00
}
2005-12-11 08:06:35 +03:00
/* check for invalid share names */
if ( ! validate_net_name ( share_name , INVALID_SHARENAME_CHARS , sizeof ( share_name ) ) ) {
DEBUG ( 5 , ( " _srv_net_name_validate: Bad sharename \" %s \" \n " , share_name ) ) ;
return WERR_INVALID_NAME ;
}
2005-05-23 20:25:31 +04:00
if ( strequal ( share_name , " IPC$ " )
| | ( lp_enable_asu_support ( ) & & strequal ( share_name , " ADMIN$ " ) )
| | strequal ( share_name , " global " ) )
{
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2005-05-23 20:25:31 +04:00
}
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 )
2002-03-05 05:12:00 +03:00
return WERR_ALREADY_EXISTS ;
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 )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-07 22:46:47 +04:00
/* Check if the pathname is valid. */
2005-01-19 21:28:55 +03:00
if ( ! ( path = valid_share_pathname ( pathname ) ) )
2002-03-05 05:12:00 +03:00
return WERR_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 , ' " ' , ' ' ) ;
2005-01-19 21:28:55 +03:00
string_replace ( path , ' " ' , ' ' ) ;
2001-04-09 00:01:51 +04:00
string_replace ( comment , ' " ' , ' ' ) ;
2001-04-10 23:43:14 +04:00
slprintf ( command , sizeof ( command ) - 1 , " %s \" %s \" \" %s \" \" %s \" \" %s \" " ,
2005-01-19 21:28:55 +03:00
lp_add_share_cmd ( ) , dyn_CONFIGFILE , share_name , path , comment ) ;
2005-01-18 22:51:36 +03:00
2001-04-07 22:46:47 +04:00
DEBUG ( 10 , ( " _srv_net_share_add: Running [%s] \n " , command ) ) ;
2005-01-18 22:51:36 +03:00
/********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
if ( is_disk_op )
become_root ( ) ;
2005-01-20 00:10:56 +03:00
if ( ( ret = smbrun ( command , NULL ) ) = = 0 ) {
/* Tell everyone we updated smb.conf. */
message_send_all ( conn_tdb_ctx ( ) , MSG_SMB_CONF_UPDATED , NULL , 0 , False , NULL ) ;
}
2005-01-18 22:51:36 +03:00
if ( is_disk_op )
unbecome_root ( ) ;
/********* END SeDiskOperatorPrivilege BLOCK *********/
DEBUG ( 3 , ( " _srv_net_share_add: Running [%s] returned (%d) \n " , command , ret ) ) ;
if ( ret ! = 0 )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2005-01-18 22:51:36 +03:00
2001-04-09 10:36:38 +04:00
if ( psd ) {
2005-01-19 21:28:55 +03:00
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-09 10:36:38 +04:00
}
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__ ) ) ;
2002-03-05 05:12:00 +03:00
return WERR_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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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 ;
2005-01-18 22:51:36 +03:00
SE_PRIV se_diskop = SE_DISK_OPERATOR ;
BOOL is_disk_op ;
2001-04-06 22:25:17 +04:00
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
2005-05-23 20:25:31 +04:00
if ( strequal ( share_name , " IPC$ " )
| | ( lp_enable_asu_support ( ) & & strequal ( share_name , " ADMIN$ " ) )
| | strequal ( share_name , " global " ) )
{
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2005-05-23 20:25:31 +04:00
}
2001-04-09 22:03:02 +04:00
2001-04-06 22:25:17 +04:00
snum = find_service ( share_name ) ;
if ( snum < 0 )
2002-03-05 05:12:00 +03:00
return WERR_NO_SUCH_SHARE ;
2001-04-09 22:03:02 +04:00
/* No change to printer shares. */
if ( lp_print_ok ( snum ) )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-06 22:25:17 +04:00
2001-04-07 04:36:38 +04:00
get_current_user ( & user , p ) ;
2005-01-18 22:51:36 +03:00
is_disk_op = user_has_privileges ( p - > pipe_user . nt_user_token , & se_diskop ) ;
if ( user . uid ! = sec_initial_uid ( ) & & ! is_disk_op )
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2001-04-07 04:36:38 +04:00
2005-06-30 19:19:54 +04:00
if ( ! lp_delete_share_cmd ( ) | | ! * lp_delete_share_cmd ( ) ) {
DEBUG ( 10 , ( " _srv_net_share_del: No delete share command \n " ) ) ;
2002-03-05 05:12:00 +03:00
return WERR_ACCESS_DENIED ;
2005-06-30 19:19:54 +04:00
}
2005-01-18 22:51:36 +03:00
2001-04-10 23:43:14 +04:00
slprintf ( command , sizeof ( command ) - 1 , " %s \" %s \" \" %s \" " ,
2001-11-19 05:49:53 +03:00
lp_delete_share_cmd ( ) , dyn_CONFIGFILE , lp_servicename ( snum ) ) ;
2001-04-07 04:36:38 +04:00
DEBUG ( 10 , ( " _srv_net_share_del: Running [%s] \n " , command ) ) ;
2005-01-18 22:51:36 +03:00
/********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
if ( is_disk_op )
become_root ( ) ;
2005-01-20 00:10:56 +03:00
if ( ( ret = smbrun ( command , NULL ) ) = = 0 ) {
/* Tell everyone we updated smb.conf. */
message_send_all ( conn_tdb_ctx ( ) , MSG_SMB_CONF_UPDATED , NULL , 0 , False , NULL ) ;
}
2005-01-18 22:51:36 +03:00
if ( is_disk_op )
unbecome_root ( ) ;
/********* END SeDiskOperatorPrivilege BLOCK *********/
DEBUG ( 3 , ( " _srv_net_share_del: Running [%s] returned (%d) \n " , command , ret ) ) ;
if ( ret ! = 0 )
return WERR_ACCESS_DENIED ;
2001-04-09 00:01:51 +04:00
2005-01-18 22:51:36 +03:00
/* Delete the SD in the database. */
delete_share_security ( snum ) ;
2001-04-07 04:36:38 +04:00
lp_killservice ( snum ) ;
2002-03-05 05:12:00 +03:00
return WERR_OK ;
2001-04-06 22:25:17 +04:00
}
2002-08-17 19:34:15 +04:00
WERROR _srv_net_share_del_sticky ( pipes_struct * p , SRV_Q_NET_SHARE_DEL * q_u , SRV_R_NET_SHARE_DEL * r_u )
{
DEBUG ( 5 , ( " _srv_net_share_del_stick: %d \n " , __LINE__ ) ) ;
return _srv_net_share_del ( p , q_u , r_u ) ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
time of day
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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 ) ;
2005-11-28 00:51:46 +03:00
/* We do this call first as if we do it *after* the gmtime call
it overwrites the pointed - to values . JRA */
uint32 zone = get_time_zone ( unixdate ) / 60 ;
2001-02-27 21:22:39 +03:00
2004-12-07 21:25:53 +03:00
tod = TALLOC_P ( p - > mem_ctx , TIME_OF_DAY_INFO ) ;
2001-02-27 21:22:39 +03:00
if ( ! tod )
2002-03-05 05:12:00 +03:00
return WERR_NOMEM ;
2001-02-27 21:22:39 +03:00
ZERO_STRUCTP ( tod ) ;
r_u - > tod = tod ;
r_u - > ptr_srv_tod = 0x1 ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_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 ,
2005-11-28 00:51:46 +03:00
zone ,
2001-02-27 21:22:39 +03:00
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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 ;
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 ;
2002-03-05 05:12:00 +03:00
BOOL became_user = False ;
2001-06-16 04:32:13 +04:00
ZERO_STRUCT ( st ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_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
2002-03-05 05:12:00 +03: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 ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = ntstatus_to_werror ( 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 " ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_ACCESS_DENIED ;
2001-09-19 06:28:15 +04:00
goto error_exit ;
}
2003-03-19 02:49:03 +03:00
became_user = True ;
2001-09-19 06:28:15 +04:00
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 ) ;
2004-06-11 21:54:23 +04:00
if ( bad_path ) {
DEBUG ( 3 , ( " _srv_net_file_query_secdesc: bad pathname %s \n " , filename ) ) ;
r_u - > status = WERR_ACCESS_DENIED ;
goto error_exit ;
}
if ( ! check_name ( filename , conn ) ) {
DEBUG ( 3 , ( " _srv_net_file_query_secdesc: can't access %s \n " , filename ) ) ;
r_u - > status = WERR_ACCESS_DENIED ;
goto error_exit ;
}
2005-07-08 08:51:27 +04:00
fsp = open_file_stat ( conn , filename , & st ) ;
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 )
2005-07-08 08:51:27 +04:00
fsp = open_directory ( conn , filename , & st ,
READ_CONTROL_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN ,
0 ,
NULL ) ;
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 ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_ACCESS_DENIED ;
2001-06-18 21:52:58 +04:00
goto error_exit ;
}
2001-06-16 04:32:13 +04:00
}
2003-05-30 03:49:31 +04:00
sd_size = SMB_VFS_GET_NT_ACL ( fsp , fsp - > fsp_name , ( OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION ) , & psd ) ;
2001-06-16 04:32:13 +04:00
if ( sd_size = = 0 ) {
DEBUG ( 3 , ( " _srv_net_file_query_secdesc: Unable to get NT ACL for file %s \n " , filename ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_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 ;
2002-08-17 19:34:15 +04:00
error_exit :
2001-06-16 04:32:13 +04:00
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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 ;
pstring filename ;
pstring qualname ;
2002-03-05 05:12:00 +03:00
DATA_BLOB null_pw ;
2001-06-16 04:32:13 +04:00
files_struct * fsp = NULL ;
SMB_STRUCT_STAT st ;
BOOL bad_path ;
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 ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_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
2002-03-05 05:12:00 +03: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 ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = ntstatus_to_werror ( 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 " ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_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 ) ;
2004-06-11 21:54:23 +04:00
if ( bad_path ) {
DEBUG ( 3 , ( " _srv_net_file_set_secdesc: bad pathname %s \n " , filename ) ) ;
r_u - > status = WERR_ACCESS_DENIED ;
goto error_exit ;
}
if ( ! check_name ( filename , conn ) ) {
DEBUG ( 3 , ( " _srv_net_file_set_secdesc: can't access %s \n " , filename ) ) ;
r_u - > status = WERR_ACCESS_DENIED ;
goto error_exit ;
}
2001-06-16 04:32:13 +04:00
2005-07-08 08:51:27 +04:00
fsp = open_file_stat ( conn , filename , & st ) ;
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 )
2005-07-08 08:51:27 +04:00
fsp = open_directory ( conn , filename , & st ,
FILE_READ_ATTRIBUTES ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN ,
0 ,
NULL ) ;
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 ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_ACCESS_DENIED ;
2001-06-18 21:52:58 +04:00
goto error_exit ;
}
2001-06-16 04:32:13 +04:00
}
2003-05-14 14:59:01 +04:00
ret = SMB_VFS_SET_NT_ACL ( fsp , fsp - > fsp_name , q_u - > sec_info , q_u - > sec_desc ) ;
2001-06-16 04:32:13 +04:00
if ( ret = = False ) {
DEBUG ( 3 , ( " _srv_net_file_set_secdesc: Unable to set NT ACL on file %s \n " , filename ) ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_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 ;
2002-08-17 19:34:15 +04:00
error_exit :
2001-06-16 04:32:13 +04:00
if ( fsp ) {
2001-06-22 22:58:35 +04:00
close_file ( fsp , True ) ;
2001-06-16 04:32:13 +04:00
}
2005-07-08 08:51:27 +04:00
if ( became_user ) {
2001-08-14 03:19:16 +04:00
unbecome_user ( ) ;
2005-07-08 08:51:27 +04:00
}
2001-08-14 03:19:16 +04:00
2005-07-08 08:51:27 +04:00
if ( conn ) {
2001-06-16 04:32:13 +04:00
close_cnum ( conn , user . vuid ) ;
2005-07-08 08:51:27 +04:00
}
2001-06-16 04:32:13 +04:00
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
2002-07-15 14:35:28 +04:00
static const char * server_disks [ ] = { " C: " } ;
2001-05-01 05:01:19 +04:00
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 ;
}
2002-03-05 05:12:00 +03:00
WERROR _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 ;
2002-08-17 19:34:15 +04:00
TALLOC_CTX * ctx = p - > mem_ctx ;
2001-05-01 05:01:19 +04:00
uint32 resume = get_enum_hnd ( & q_u - > enum_hnd ) ;
2002-03-05 05:12:00 +03:00
r_u - > status = WERR_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 ;
2004-12-07 21:25:53 +03:00
if ( ! ( r_u - > disk_enum_ctr . disk_info = TALLOC_ARRAY ( ctx , DISK_INFO , MAX_SERVER_DISK_ENTRIES ) ) ) {
return WERR_NOMEM ;
2002-08-17 19:34:15 +04:00
}
2002-03-05 05:12:00 +03:00
r_u - > disk_enum_ctr . disk_info_ptr = r_u - > disk_enum_ctr . disk_info ? 1 : 0 ;
2001-05-01 05:01:19 +04:00
/*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 ) ;
}
2002-08-17 19:34:15 +04:00
/* add a terminating null string. Is this there if there is more data to come? */
2001-05-01 05:01:19 +04:00
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 ;
}
2005-12-11 08:06:35 +03:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-05 05:12:00 +03:00
WERROR _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
{
2005-12-11 08:06:35 +03:00
fstring sharename ;
2001-05-01 05:01:19 +04:00
2005-10-14 18:51:48 +04:00
switch ( q_u - > type ) {
2001-05-01 05:01:19 +04:00
case 0x9 :
2005-12-11 08:06:35 +03:00
/* Run the name through alpha_strcpy() to remove any unsafe
shell characters . Compare the copied string with the original
and fail if the strings don ' t match */
unistr2_to_ascii ( sharename , & q_u - > uni_name , sizeof ( sharename ) ) ;
if ( ! validate_net_name ( sharename , INVALID_SHARENAME_CHARS , sizeof ( sharename ) ) ) {
DEBUG ( 5 , ( " _srv_net_name_validate: Bad sharename \" %s \" \n " , sharename ) ) ;
return WERR_INVALID_NAME ;
}
2001-05-01 05:01:19 +04:00
break ;
2005-12-11 08:06:35 +03:00
2001-05-01 05:01:19 +04:00
default :
2005-10-14 18:51:48 +04:00
return WERR_UNKNOWN_LEVEL ;
2001-05-01 05:01:19 +04:00
}
2005-10-14 18:51:48 +04:00
return WERR_OK ;
2001-05-01 05:01:19 +04:00
}