2005-09-03 16:55:45 +00:00
/*
* Unix SMB / CIFS implementation .
* MS - RPC client library implementation ( WINREG pipe )
* Copyright ( C ) Chris Nicholls 2005.
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "libmsrpc.h"
# include "libmsrpc_internal.h"
int cac_RegConnect ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegConnect * op ) {
SMBCSRV * srv = NULL ;
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
POLICY_HND * key = NULL ;
WERROR err ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . root | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
srv = cac_GetServer ( hnd ) ;
if ( ! srv ) {
hnd - > status = NT_STATUS_INVALID_CONNECTION ;
return CAC_FAILURE ;
}
/*initialize for winreg pipe if we have to*/
if ( ! hnd - > _internal . pipes [ PI_WINREG ] ) {
2005-10-17 16:44:26 +00:00
if ( ! ( pipe_hnd = cli_rpc_pipe_open_noauth ( & srv - > cli , PI_WINREG , & ( hnd - > status ) ) ) ) {
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
hnd - > _internal . pipes [ PI_WINREG ] = True ;
}
2006-03-11 02:43:25 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
2005-09-03 16:55:45 +00:00
key = talloc ( mem_ctx , POLICY_HND ) ;
if ( ! key ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_connect ( pipe_hnd , mem_ctx , op - > in . root , op - > in . access , key ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
op - > out . key = key ;
return CAC_SUCCESS ;
}
int cac_RegClose ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , POLICY_HND * key ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! key | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_close ( pipe_hnd , mem_ctx , key ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
return CAC_SUCCESS ;
}
int cac_RegOpenKey ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegOpenKey * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
POLICY_HND * key_out ;
POLICY_HND * parent_key ;
char * key_name = NULL ;
uint32 reg_type = 0 ;
struct RegConnect rc ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . name | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
key_out = talloc ( mem_ctx , POLICY_HND ) ;
if ( ! key_out ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
return CAC_FAILURE ;
}
if ( ! op - > in . parent_key ) {
/*then we need to connect to the registry*/
if ( ! cac_ParseRegPath ( op - > in . name , & reg_type , & key_name ) ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
/*use cac_RegConnect because it handles the session setup*/
ZERO_STRUCT ( rc ) ;
rc . in . access = op - > in . access ;
rc . in . root = reg_type ;
if ( ! cac_RegConnect ( hnd , mem_ctx , & rc ) ) {
return CAC_FAILURE ;
}
/**if they only specified the root key, return the key we just opened*/
if ( key_name = = NULL ) {
op - > out . key = rc . out . key ;
return CAC_SUCCESS ;
}
parent_key = rc . out . key ;
}
else {
parent_key = op - > in . parent_key ;
key_name = op - > in . name ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
2005-09-03 16:55:45 +00:00
2005-10-17 16:44:26 +00:00
err = rpccli_reg_open_entry ( pipe_hnd , mem_ctx , parent_key , key_name , op - > in . access , key_out ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
if ( ! op - > in . parent_key ) {
/*then close the one that we opened above*/
2005-10-17 16:44:26 +00:00
err = rpccli_reg_close ( pipe_hnd , mem_ctx , parent_key ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
}
op - > out . key = key_out ;
return CAC_SUCCESS ;
}
int cac_RegEnumKeys ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegEnumKeys * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
2005-10-17 16:44:26 +00:00
/*buffers for rpccli_reg_enum_key call*/
2005-09-03 16:55:45 +00:00
fstring key_name_in ;
fstring class_name_in ;
/*output buffers*/
char * * key_names_out = NULL ;
char * * class_names_out = NULL ;
time_t * mod_times_out = NULL ;
uint32 num_keys_out = 0 ;
uint32 resume_idx = 0 ;
if ( ! hnd )
return CAC_FAILURE ;
/*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
if ( NT_STATUS_V ( hnd - > status ) = = NT_STATUS_V ( NT_STATUS_GUIDS_EXHAUSTED ) )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | op - > in . max_keys = = 0 | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
/**the only way to know how many keys to expect is to assume max_keys keys will be found*/
key_names_out = TALLOC_ARRAY ( mem_ctx , char * , op - > in . max_keys ) ;
if ( ! key_names_out ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
return CAC_FAILURE ;
}
class_names_out = TALLOC_ARRAY ( mem_ctx , char * , op - > in . max_keys ) ;
if ( ! class_names_out ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
2006-02-20 17:59:58 +00:00
TALLOC_FREE ( key_names_out ) ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
mod_times_out = TALLOC_ARRAY ( mem_ctx , time_t , op - > in . max_keys ) ;
if ( ! mod_times_out ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
2006-02-20 17:59:58 +00:00
TALLOC_FREE ( key_names_out ) ;
TALLOC_FREE ( class_names_out ) ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
resume_idx = op - > out . resume_idx ;
do {
2005-10-17 16:44:26 +00:00
err = rpccli_reg_enum_key ( pipe_hnd , mem_ctx , op - > in . key , resume_idx , key_name_in , class_name_in , & mod_times_out [ num_keys_out ] ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
/*don't increment any values*/
break ;
}
key_names_out [ num_keys_out ] = talloc_strdup ( mem_ctx , key_name_in ) ;
class_names_out [ num_keys_out ] = talloc_strdup ( mem_ctx , class_name_in ) ;
if ( ! key_names_out [ num_keys_out ] | | ! class_names_out [ num_keys_out ] ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
break ;
}
resume_idx + + ;
num_keys_out + + ;
} while ( num_keys_out < op - > in . max_keys ) ;
if ( CAC_OP_FAILED ( hnd - > status ) ) {
op - > out . num_keys = 0 ;
return CAC_FAILURE ;
}
op - > out . resume_idx = resume_idx ;
op - > out . num_keys = num_keys_out ;
op - > out . key_names = key_names_out ;
op - > out . class_names = class_names_out ;
op - > out . mod_times = mod_times_out ;
return CAC_SUCCESS ;
}
int cac_RegCreateKey ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegCreateKey * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
POLICY_HND * key_out ;
struct RegOpenKey rok ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . parent_key | | ! op - > in . key_name | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
/*first try to open the key - we use cac_RegOpenKey(). this doubles as a way to ensure the winreg pipe is initialized*/
ZERO_STRUCT ( rok ) ;
rok . in . name = op - > in . key_name ;
rok . in . access = op - > in . access ;
rok . in . parent_key = op - > in . parent_key ;
if ( cac_RegOpenKey ( hnd , mem_ctx , & rok ) ) {
/*then we got the key, return*/
op - > out . key = rok . out . key ;
return CAC_SUCCESS ;
}
/*just be ultra-safe*/
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
2005-09-03 16:55:45 +00:00
key_out = talloc ( mem_ctx , POLICY_HND ) ;
if ( ! key_out ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_create_key_ex ( pipe_hnd , mem_ctx , op - > in . parent_key , op - > in . key_name , op - > in . class_name , op - > in . access , key_out ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
op - > out . key = key_out ;
return CAC_SUCCESS ;
}
2005-10-17 16:44:26 +00:00
WERROR cac_delete_subkeys_recursive ( struct rpc_pipe_client * pipe_hnd , TALLOC_CTX * mem_ctx , POLICY_HND * key ) {
2005-09-03 16:55:45 +00:00
/*NOTE: using cac functions might result in a big(ger) memory bloat, and would probably be far less efficient
* so we use the cli_reg functions directly */
WERROR err = WERR_OK ;
POLICY_HND subkey ;
fstring subkey_name ;
fstring class_buf ;
time_t mod_time_buf ;
int cur_key = 0 ;
while ( W_ERROR_IS_OK ( err ) ) {
2005-10-17 16:44:26 +00:00
err = rpccli_reg_enum_key ( pipe_hnd , mem_ctx , key , cur_key , subkey_name , class_buf , & mod_time_buf ) ;
2005-09-03 16:55:45 +00:00
if ( ! W_ERROR_IS_OK ( err ) )
break ;
/*try to open the key with full access*/
2005-10-17 16:44:26 +00:00
err = rpccli_reg_open_entry ( pipe_hnd , mem_ctx , key , subkey_name , REG_KEY_ALL , & subkey ) ;
2005-09-03 16:55:45 +00:00
if ( ! W_ERROR_IS_OK ( err ) )
break ;
2005-10-17 16:44:26 +00:00
err = cac_delete_subkeys_recursive ( pipe_hnd , mem_ctx , & subkey ) ;
2005-09-03 16:55:45 +00:00
if ( ! W_ERROR_EQUAL ( err , WERR_NO_MORE_ITEMS ) & & ! W_ERROR_IS_OK ( err ) )
break ;
/*flush the key just to be safe*/
2005-10-17 16:44:26 +00:00
rpccli_reg_flush_key ( pipe_hnd , mem_ctx , key ) ;
2005-09-03 16:55:45 +00:00
/*close the key that we opened*/
2005-10-17 16:44:26 +00:00
rpccli_reg_close ( pipe_hnd , mem_ctx , & subkey ) ;
2005-09-03 16:55:45 +00:00
/*now we delete the subkey*/
2005-10-17 16:44:26 +00:00
err = rpccli_reg_delete_key ( pipe_hnd , mem_ctx , key , subkey_name ) ;
2005-09-03 16:55:45 +00:00
cur_key + + ;
}
return err ;
}
int cac_RegDeleteKey ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegDeleteKey * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . parent_key | | ! op - > in . name | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
if ( op - > in . recursive ) {
/*first open the key, and then delete all of it's subkeys recursively*/
struct RegOpenKey rok ;
ZERO_STRUCT ( rok ) ;
rok . in . parent_key = op - > in . parent_key ;
rok . in . name = op - > in . name ;
rok . in . access = REG_KEY_ALL ;
if ( ! cac_RegOpenKey ( hnd , mem_ctx , & rok ) )
return CAC_FAILURE ;
2005-10-17 16:44:26 +00:00
err = cac_delete_subkeys_recursive ( pipe_hnd , mem_ctx , rok . out . key ) ;
2005-09-03 16:55:45 +00:00
/*close the key that we opened*/
cac_RegClose ( hnd , mem_ctx , rok . out . key ) ;
hnd - > status = werror_to_ntstatus ( err ) ;
if ( NT_STATUS_V ( hnd - > status ) ! = NT_STATUS_V ( NT_STATUS_GUIDS_EXHAUSTED ) & & ! NT_STATUS_IS_OK ( hnd - > status ) )
return CAC_FAILURE ;
/*now go on to actually delete the key*/
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_delete_key ( pipe_hnd , mem_ctx , op - > in . parent_key , op - > in . name ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
return CAC_SUCCESS ;
}
int cac_RegDeleteValue ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegDeleteValue * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . parent_key | | ! op - > in . name | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_delete_val ( pipe_hnd , mem_ctx , op - > in . parent_key , op - > in . name ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
return CAC_SUCCESS ;
}
2006-03-15 02:16:14 +00:00
#if 0
/* JRA - disabled until fix. */
/* This code is currently broken so disable it - it needs to handle the ERROR_MORE_DATA
cleanly and resubmit the query . */
2005-09-03 16:55:45 +00:00
int cac_RegQueryKeyInfo ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegQueryKeyInfo * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
char * class_name_out = NULL ;
uint32 class_len = 0 ;
uint32 num_subkeys_out = 0 ;
uint32 long_subkey_out = 0 ;
uint32 long_class_out = 0 ;
uint32 num_values_out = 0 ;
uint32 long_value_out = 0 ;
uint32 long_data_out = 0 ;
uint32 secdesc_size = 0 ;
NTTIME mod_time ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_query_key ( pipe_hnd , mem_ctx , op - > in . key ,
2005-09-03 16:55:45 +00:00
class_name_out ,
& class_len ,
& num_subkeys_out ,
& long_subkey_out ,
& long_class_out ,
& num_values_out ,
& long_value_out ,
& long_data_out ,
& secdesc_size ,
& mod_time ) ;
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) )
return CAC_FAILURE ;
if ( ! class_name_out ) {
op - > out . class_name = talloc_strdup ( mem_ctx , " " ) ;
}
else if ( class_len ! = 0 & & class_name_out [ class_len - 1 ] ! = ' \0 ' ) {
/*then we need to add a '\0'*/
op - > out . class_name = talloc_size ( mem_ctx , sizeof ( char ) * ( class_len + 1 ) ) ;
memcpy ( op - > out . class_name , class_name_out , class_len ) ;
op - > out . class_name [ class_len ] = ' \0 ' ;
}
else { /*then everything worked out fine in the function*/
op - > out . class_name = talloc_strdup ( mem_ctx , class_name_out ) ;
}
if ( ! op - > out . class_name ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
return CAC_FAILURE ;
}
op - > out . num_subkeys = num_subkeys_out ;
op - > out . longest_subkey = long_subkey_out ;
op - > out . longest_class = long_class_out ;
op - > out . num_values = num_values_out ;
op - > out . longest_value_name = long_value_out ;
op - > out . longest_value_data = long_data_out ;
op - > out . security_desc_size = secdesc_size ;
op - > out . last_write_time = nt_time_to_unix ( & mod_time ) ;
return CAC_FAILURE ;
}
2006-03-15 02:16:14 +00:00
# endif
2005-09-03 16:55:45 +00:00
int cac_RegQueryValue ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegQueryValue * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
uint32 val_type ;
REGVAL_BUFFER buffer ;
REG_VALUE_DATA * data_out = NULL ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | ! op - > in . val_name | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_query_value ( pipe_hnd , mem_ctx , op - > in . key , op - > in . val_name , & val_type , & buffer ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) )
return CAC_FAILURE ;
data_out = cac_MakeRegValueData ( mem_ctx , val_type , buffer ) ;
if ( ! data_out ) {
if ( errno = = ENOMEM )
hnd - > status = NT_STATUS_NO_MEMORY ;
else
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
op - > out . type = val_type ;
op - > out . data = data_out ;
return CAC_SUCCESS ;
}
int cac_RegEnumValues ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegEnumValues * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
2005-10-17 16:44:26 +00:00
/*buffers for rpccli_reg_enum_key call*/
2005-09-03 16:55:45 +00:00
fstring val_name_buf ;
REGVAL_BUFFER val_buf ;
/*output buffers*/
uint32 * types_out = NULL ;
REG_VALUE_DATA * * values_out = NULL ;
char * * val_names_out = NULL ;
uint32 num_values_out = 0 ;
uint32 resume_idx = 0 ;
if ( ! hnd )
return CAC_FAILURE ;
/*this is to avoid useless rpc calls, if the last call exhausted all the keys, then we don't need to go through everything again*/
if ( NT_STATUS_V ( hnd - > status ) = = NT_STATUS_V ( NT_STATUS_GUIDS_EXHAUSTED ) )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | op - > in . max_values = = 0 | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
/*we need to assume that the max number of values will be enumerated*/
2005-10-18 03:24:00 +00:00
types_out = ( uint32 * ) talloc_array ( mem_ctx , int , op - > in . max_values ) ;
2005-09-03 16:55:45 +00:00
if ( ! types_out ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
return CAC_FAILURE ;
}
values_out = talloc_array ( mem_ctx , REG_VALUE_DATA * , op - > in . max_values ) ;
if ( ! values_out ) {
2006-02-20 17:59:58 +00:00
TALLOC_FREE ( types_out ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = NT_STATUS_NO_MEMORY ;
return CAC_FAILURE ;
}
val_names_out = talloc_array ( mem_ctx , char * , op - > in . max_values ) ;
if ( ! val_names_out ) {
2006-02-20 17:59:58 +00:00
TALLOC_FREE ( types_out ) ;
TALLOC_FREE ( values_out ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = NT_STATUS_NO_MEMORY ;
return CAC_FAILURE ;
}
resume_idx = op - > out . resume_idx ;
do {
ZERO_STRUCT ( val_buf ) ;
2005-10-17 16:44:26 +00:00
err = rpccli_reg_enum_val ( pipe_hnd , mem_ctx , op - > in . key , resume_idx , val_name_buf , & types_out [ num_values_out ] , & val_buf ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) )
break ;
values_out [ num_values_out ] = cac_MakeRegValueData ( mem_ctx , types_out [ num_values_out ] , val_buf ) ;
val_names_out [ num_values_out ] = talloc_strdup ( mem_ctx , val_name_buf ) ;
if ( ! val_names_out [ num_values_out ] | | ! values_out [ num_values_out ] ) {
hnd - > status = NT_STATUS_NO_MEMORY ;
break ;
}
num_values_out + + ;
resume_idx + + ;
} while ( num_values_out < op - > in . max_values ) ;
if ( CAC_OP_FAILED ( hnd - > status ) )
return CAC_FAILURE ;
op - > out . types = types_out ;
op - > out . num_values = num_values_out ;
op - > out . value_names = val_names_out ;
op - > out . values = values_out ;
op - > out . resume_idx = resume_idx ;
return CAC_SUCCESS ;
}
int cac_RegSetValue ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegSetValue * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
RPC_DATA_BLOB * buffer ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | ! op - > in . val_name | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
buffer = cac_MakeRpcDataBlob ( mem_ctx , op - > in . type , op - > in . value ) ;
if ( ! buffer ) {
if ( errno = = ENOMEM )
hnd - > status = NT_STATUS_NO_MEMORY ;
else
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_set_val ( pipe_hnd , mem_ctx , op - > in . key , op - > in . val_name , op - > in . type , buffer ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) )
return CAC_FAILURE ;
/*flush*/
2005-10-17 16:44:26 +00:00
err = rpccli_reg_flush_key ( pipe_hnd , mem_ctx , op - > in . key ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) )
return CAC_FAILURE ;
return CAC_SUCCESS ;
}
int cac_RegGetVersion ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegGetVersion * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
uint32 version_out ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_getversion ( pipe_hnd , mem_ctx , op - > in . key , & version_out ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) )
return CAC_FAILURE ;
op - > out . version = version_out ;
return CAC_SUCCESS ;
}
int cac_RegGetKeySecurity ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegGetKeySecurity * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
uint32 buf_size ;
2006-03-14 08:27:44 +00:00
SEC_DESC_BUF buf ;
2005-09-03 16:55:45 +00:00
2006-03-15 02:31:11 +00:00
ZERO_STRUCT ( buf ) ;
2005-09-03 16:55:45 +00:00
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | op - > in . info_type = = 0 | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2006-03-14 08:27:44 +00:00
err = rpccli_reg_get_key_sec ( pipe_hnd , mem_ctx , op - > in . key , op - > in . info_type , & buf_size , & buf ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
2006-03-14 08:27:44 +00:00
op - > out . size = buf . len ;
op - > out . descriptor = dup_sec_desc ( mem_ctx , buf . sec ) ;
if ( op - > out . descriptor = = NULL ) {
return CAC_FAILURE ;
}
2005-09-03 16:55:45 +00:00
return CAC_SUCCESS ;
}
int cac_RegSetKeySecurity ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegSetKeySecurity * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | op - > in . info_type = = 0 | | op - > in . size = = 0 | | ! op - > in . descriptor | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_set_key_sec ( pipe_hnd , mem_ctx , op - > in . key , op - > in . info_type , op - > in . size , op - > in . descriptor ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
return CAC_SUCCESS ;
}
int cac_RegSaveKey ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct RegSaveKey * op ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
WERROR err ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_WINREG ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! op - > in . key | | ! op - > in . filename | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_WINREG ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
err = rpccli_reg_save_key ( pipe_hnd , mem_ctx , op - > in . key , op - > in . filename ) ;
2005-09-03 16:55:45 +00:00
hnd - > status = werror_to_ntstatus ( err ) ;
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
return CAC_SUCCESS ;
}
int cac_Shutdown ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx , struct Shutdown * op ) {
SMBCSRV * srv = NULL ;
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
char * msg ;
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
if ( ! op | | ! mem_ctx ) {
hnd - > status = NT_STATUS_INVALID_PARAMETER ;
return CAC_FAILURE ;
}
srv = cac_GetServer ( hnd ) ;
if ( ! srv ) {
2005-10-17 16:44:26 +00:00
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
/*initialize for winreg pipe if we have to*/
if ( ! hnd - > _internal . pipes [ PI_SHUTDOWN ] ) {
2005-10-17 16:44:26 +00:00
if ( ! ( pipe_hnd = cli_rpc_pipe_open_noauth ( & srv - > cli , PI_SHUTDOWN , & ( hnd - > status ) ) ) ) {
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
hnd - > _internal . pipes [ PI_SHUTDOWN ] = True ;
}
2006-03-13 00:08:39 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_SHUTDOWN ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
2005-09-03 16:55:45 +00:00
msg = ( op - > in . message ! = NULL ) ? op - > in . message : talloc_strdup ( mem_ctx , " " ) ;
hnd - > status = NT_STATUS_OK ;
if ( hnd - > _internal . srv_level > SRV_WIN_NT4 ) {
2005-10-17 16:44:26 +00:00
hnd - > status = rpccli_shutdown_init_ex ( pipe_hnd , mem_ctx , msg , op - > in . timeout , op - > in . reboot , op - > in . force , op - > in . reason ) ;
2005-09-03 16:55:45 +00:00
}
if ( hnd - > _internal . srv_level < SRV_WIN_2K | | ! NT_STATUS_IS_OK ( hnd - > status ) ) {
2005-10-17 16:44:26 +00:00
hnd - > status = rpccli_shutdown_init ( pipe_hnd , mem_ctx , msg , op - > in . timeout , op - > in . reboot , op - > in . force ) ;
2005-09-03 16:55:45 +00:00
hnd - > _internal . srv_level = SRV_WIN_NT4 ;
}
if ( ! NT_STATUS_IS_OK ( hnd - > status ) ) {
return CAC_FAILURE ;
}
return CAC_SUCCESS ;
}
int cac_AbortShutdown ( CacServerHandle * hnd , TALLOC_CTX * mem_ctx ) {
2005-10-17 16:44:26 +00:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2005-09-03 16:55:45 +00:00
if ( ! hnd )
return CAC_FAILURE ;
if ( ! hnd - > _internal . ctx | | ! hnd - > _internal . pipes [ PI_SHUTDOWN ] ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
pipe_hnd = cac_GetPipe ( hnd , PI_SHUTDOWN ) ;
if ( ! pipe_hnd ) {
hnd - > status = NT_STATUS_INVALID_HANDLE ;
2005-09-03 16:55:45 +00:00
return CAC_FAILURE ;
}
2005-10-17 16:44:26 +00:00
hnd - > status = rpccli_shutdown_abort ( pipe_hnd , mem_ctx ) ;
2005-09-03 16:55:45 +00:00
if ( ! NT_STATUS_IS_OK ( hnd - > status ) )
return CAC_FAILURE ;
return CAC_SUCCESS ;
}