2010-09-17 15:17:12 +04:00
/*
Unix SMB / CIFS implementation .
RPC pipe client
Copyright ( C ) Guenther Deschner 2009
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "rpcclient.h"
2011-01-12 23:11:17 +03:00
# include "../librpc/gen_ndr/ndr_winreg_c.h"
2010-09-17 15:17:12 +04:00
# include "../librpc/gen_ndr/ndr_misc.h"
static WERROR cmd_winreg_enumkeys ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx , int argc ,
const char * * argv )
{
NTSTATUS status ;
WERROR werr ;
struct policy_handle handle ;
uint32_t enum_index = 0 ;
struct winreg_StringBuf name ;
2011-01-12 23:11:17 +03:00
struct dcerpc_binding_handle * b = cli - > binding_handle ;
2010-09-17 15:17:12 +04:00
if ( argc < 2 ) {
printf ( " usage: %s [name] \n " , argv [ 0 ] ) ;
return WERR_OK ;
}
2011-01-12 23:11:17 +03:00
status = dcerpc_winreg_OpenHKLM ( b , mem_ctx ,
2010-09-17 15:17:12 +04:00
NULL ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
ZERO_STRUCT ( name ) ;
name . name = argv [ 1 ] ;
name . length = strlen_m_term_null ( name . name ) * 2 ;
name . size = name . length ;
2011-01-12 23:11:17 +03:00
status = dcerpc_winreg_EnumKey ( b , mem_ctx ,
2010-09-17 15:17:12 +04:00
& handle ,
enum_index ,
& name ,
NULL ,
NULL ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
return WERR_OK ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR pull_winreg_Data ( TALLOC_CTX * mem_ctx ,
const DATA_BLOB * blob ,
union winreg_Data * data ,
enum winreg_Type type )
{
enum ndr_err_code ndr_err ;
ndr_err = ndr_pull_union_blob ( blob , mem_ctx , data , type ,
( ndr_pull_flags_fn_t ) ndr_pull_winreg_Data ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2015-12-03 17:24:21 +03:00
return WERR_GEN_FAILURE ;
2010-09-17 15:17:12 +04:00
}
return WERR_OK ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void display_winreg_data ( const char * v ,
enum winreg_Type type ,
uint8_t * data ,
uint32_t length )
{
2021-07-21 09:28:20 +03:00
size_t i ;
2010-09-17 15:17:12 +04:00
union winreg_Data r ;
DATA_BLOB blob = data_blob_const ( data , length ) ;
WERROR result ;
result = pull_winreg_Data ( talloc_tos ( ) , & blob , & r , type ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
return ;
}
switch ( type ) {
case REG_DWORD :
2023-11-13 18:49:32 +03:00
printf ( " %-20s: REG_DWORD: 0x%08x \n " , v , r . value ) ;
2010-09-17 15:17:12 +04:00
break ;
case REG_SZ :
2023-11-13 18:49:32 +03:00
printf ( " %-20s: REG_SZ: %s \n " , v , r . string ) ;
2010-09-17 15:17:12 +04:00
break ;
case REG_BINARY : {
char * hex = hex_encode_talloc ( NULL ,
r . binary . data , r . binary . length ) ;
size_t len ;
2023-11-13 18:49:32 +03:00
printf ( " %-20s: REG_BINARY: " , v ) ;
2010-09-17 15:17:12 +04:00
len = strlen ( hex ) ;
for ( i = 0 ; i < len ; i + + ) {
if ( hex [ i ] = = ' \0 ' ) {
break ;
}
if ( i % 40 = = 0 ) {
putchar ( ' \n ' ) ;
}
putchar ( hex [ i ] ) ;
}
TALLOC_FREE ( hex ) ;
putchar ( ' \n ' ) ;
break ;
}
case REG_MULTI_SZ :
2023-11-13 18:49:32 +03:00
printf ( " %-20s: REG_MULTI_SZ: " , v ) ;
2010-09-17 15:17:12 +04:00
for ( i = 0 ; r . string_array [ i ] ! = NULL ; i + + ) {
printf ( " %s " , r . string_array [ i ] ) ;
}
printf ( " \n " ) ;
break ;
default :
2023-11-13 18:49:32 +03:00
printf ( " %-20ss: unknown type 0x%02x: \n " , v , type ) ;
2010-09-17 15:17:12 +04:00
break ;
}
}
static WERROR cmd_winreg_querymultiplevalues_ex ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx , int argc ,
const char * * argv , bool multiplevalues2 )
{
NTSTATUS status ;
WERROR werr ;
struct policy_handle handle , key_handle ;
2011-03-15 12:49:00 +03:00
struct winreg_String key_name = { 0 , } ;
2011-01-12 23:11:17 +03:00
struct dcerpc_binding_handle * b = cli - > binding_handle ;
2010-09-17 15:17:12 +04:00
struct QueryMultipleValue * values_in , * values_out ;
uint32_t num_values ;
uint8_t * buffer = NULL ;
2021-07-21 09:28:20 +03:00
uint32_t i ;
2010-09-17 15:17:12 +04:00
if ( argc < 2 ) {
printf ( " usage: %s [key] [value1] [value2] ... \n " , argv [ 0 ] ) ;
return WERR_OK ;
}
2011-01-12 23:11:17 +03:00
status = dcerpc_winreg_OpenHKLM ( b , mem_ctx ,
2010-09-17 15:17:12 +04:00
NULL ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
key_name . name = argv [ 1 ] ;
2011-01-12 23:11:17 +03:00
status = dcerpc_winreg_OpenKey ( b , mem_ctx ,
2010-09-17 15:17:12 +04:00
& handle ,
key_name ,
0 , /* options */
SEC_FLAG_MAXIMUM_ALLOWED ,
& key_handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
num_values = argc - 2 ;
values_in = talloc_zero_array ( mem_ctx , struct QueryMultipleValue , num_values ) ;
if ( values_in = = NULL ) {
2015-12-03 17:24:16 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-09-17 15:17:12 +04:00
}
values_out = talloc_zero_array ( mem_ctx , struct QueryMultipleValue , num_values ) ;
if ( values_out = = NULL ) {
2015-12-03 17:24:16 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-09-17 15:17:12 +04:00
}
for ( i = 0 ; i < num_values ; i + + ) {
values_in [ i ] . ve_valuename = talloc_zero ( values_in , struct winreg_ValNameBuf ) ;
if ( values_in [ i ] . ve_valuename = = NULL ) {
2015-12-03 17:24:16 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-09-17 15:17:12 +04:00
}
values_in [ i ] . ve_valuename - > name = talloc_strdup ( values_in [ i ] . ve_valuename , argv [ i + 2 ] ) ;
values_in [ i ] . ve_valuename - > length = strlen_m_term_null ( values_in [ i ] . ve_valuename - > name ) * 2 ;
values_in [ i ] . ve_valuename - > size = values_in [ i ] . ve_valuename - > length ;
}
if ( multiplevalues2 ) {
uint32_t offered = 0 , needed = 0 ;
2011-01-12 23:11:17 +03:00
status = dcerpc_winreg_QueryMultipleValues2 ( b , mem_ctx ,
2010-09-17 15:17:12 +04:00
& key_handle ,
values_in ,
values_out ,
num_values ,
buffer ,
& offered ,
& needed ,
& werr ) ;
2011-01-12 23:11:17 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
2010-09-17 15:17:12 +04:00
if ( W_ERROR_EQUAL ( werr , WERR_MORE_DATA ) ) {
offered = needed ;
buffer = talloc_zero_array ( mem_ctx , uint8_t , needed ) ;
if ( buffer = = NULL ) {
2015-12-03 17:24:16 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-09-17 15:17:12 +04:00
}
2011-01-12 23:11:17 +03:00
status = dcerpc_winreg_QueryMultipleValues2 ( b , mem_ctx ,
2010-09-17 15:17:12 +04:00
& key_handle ,
values_in ,
values_out ,
num_values ,
buffer ,
& offered ,
& needed ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
}
} else {
uint32_t buffer_size = 0xff ;
buffer = talloc_zero_array ( mem_ctx , uint8_t , buffer_size ) ;
if ( buffer = = NULL ) {
2015-12-03 17:24:16 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2010-09-17 15:17:12 +04:00
}
2011-01-12 23:11:17 +03:00
status = dcerpc_winreg_QueryMultipleValues ( b , mem_ctx ,
2010-09-17 15:17:12 +04:00
& key_handle ,
values_in ,
values_out ,
num_values ,
buffer ,
& buffer_size ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
}
for ( i = 0 ; i < num_values ; i + + ) {
if ( buffer ) {
display_winreg_data ( values_in [ i ] . ve_valuename - > name ,
values_out [ i ] . ve_type ,
buffer + values_out [ i ] . ve_valueptr ,
values_out [ i ] . ve_valuelen ) ;
}
}
return WERR_OK ;
}
static WERROR cmd_winreg_querymultiplevalues ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx , int argc ,
const char * * argv )
{
return cmd_winreg_querymultiplevalues_ex ( cli , mem_ctx , argc , argv , false ) ;
}
static WERROR cmd_winreg_querymultiplevalues2 ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx , int argc ,
const char * * argv )
{
return cmd_winreg_querymultiplevalues_ex ( cli , mem_ctx , argc , argv , true ) ;
}
2023-11-13 18:49:32 +03:00
static WERROR cmd_winreg_enumval ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx , int argc ,
const char * * argv )
{
NTSTATUS status ;
WERROR werr , ignore ;
struct dcerpc_binding_handle * b = cli - > binding_handle ;
struct policy_handle parent_handle , handle ;
uint32_t enum_index = 0 ;
if ( argc < 1 | | argc > 3 ) {
printf ( " usage: %s [name] \n " , argv [ 0 ] ) ;
return WERR_OK ;
}
status = dcerpc_winreg_OpenHKLM ( b , mem_ctx ,
NULL ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& parent_handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
if ( argc > = 2 ) {
struct winreg_String keyname ;
ZERO_STRUCT ( keyname ) ;
keyname . name = argv [ 1 ] ;
status = dcerpc_winreg_OpenKey ( b , mem_ctx ,
& parent_handle ,
keyname ,
0 ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ntstatus_to_werror ( status ) ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
} else {
handle = parent_handle ;
}
do {
struct winreg_ValNameBuf name ;
enum winreg_Type type = REG_NONE ;
uint32_t size = 0 , length = 0 ;
struct winreg_EnumValue r ;
name . name = " " ;
name . size = 1024 ;
r . in . handle = & handle ;
r . in . enum_index = enum_index ;
r . in . name = & name ;
r . in . type = & type ;
r . in . size = & size ;
r . in . length = & length ;
r . in . value = talloc_array ( mem_ctx , uint8_t , size ) ;
if ( r . in . value = = NULL ) {
werr = WERR_NOT_ENOUGH_MEMORY ;
goto done ;
}
r . out . name = & name ;
r . out . type = & type ;
r . out . size = & size ;
r . out . length = & length ;
r . out . value = r . in . value ;
status = dcerpc_winreg_EnumValue_r ( b , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
werr = ntstatus_to_werror ( status ) ;
goto done ;
}
werr = r . out . result ;
if ( W_ERROR_EQUAL ( werr , WERR_MORE_DATA ) ) {
* r . in . size = * r . out . size ;
r . in . value = talloc_zero_array ( mem_ctx , uint8_t , * r . in . size ) ;
if ( r . in . value = = NULL ) {
werr = WERR_NOT_ENOUGH_MEMORY ;
goto done ;
}
status = dcerpc_winreg_EnumValue_r ( b , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
werr = ntstatus_to_werror ( status ) ;
goto done ;
}
werr = r . out . result ;
}
if ( ! W_ERROR_IS_OK ( r . out . result ) ) {
goto done ;
}
printf ( " %02d: " , enum_index + + ) ;
display_winreg_data ( r . out . name - > name ,
* r . out . type ,
r . out . value ,
* r . out . size ) ;
} while ( W_ERROR_IS_OK ( werr ) ) ;
done :
if ( argc > = 2 ) {
dcerpc_winreg_CloseKey ( b , mem_ctx , & handle , & ignore ) ;
}
dcerpc_winreg_CloseKey ( b , mem_ctx , & parent_handle , & ignore ) ;
return werr ;
}
2010-09-17 15:17:12 +04:00
/* List of commands exported by this module */
struct cmd_set winreg_commands [ ] = {
2019-01-09 17:16:35 +03:00
{
. name = " WINREG " ,
} ,
{
. name = " winreg_enumkey " ,
. returntype = RPC_RTYPE_WERROR ,
. ntfn = NULL ,
. wfn = cmd_winreg_enumkeys ,
. table = & ndr_table_winreg ,
. rpc_pipe = NULL ,
. description = " Enumerate Keys " ,
. usage = " " ,
} ,
{
. name = " querymultiplevalues " ,
. returntype = RPC_RTYPE_WERROR ,
. ntfn = NULL ,
. wfn = cmd_winreg_querymultiplevalues ,
. table = & ndr_table_winreg ,
. rpc_pipe = NULL ,
. description = " Query multiple values " ,
. usage = " " ,
} ,
{
. name = " querymultiplevalues2 " ,
. returntype = RPC_RTYPE_WERROR ,
. ntfn = NULL ,
. wfn = cmd_winreg_querymultiplevalues2 ,
. table = & ndr_table_winreg ,
. rpc_pipe = NULL ,
. description = " Query multiple values " ,
. usage = " " ,
} ,
2023-11-13 18:49:32 +03:00
{
. name = " winreg_enumval " ,
. returntype = RPC_RTYPE_WERROR ,
. ntfn = NULL ,
. wfn = cmd_winreg_enumval ,
. table = & ndr_table_winreg ,
. rpc_pipe = NULL ,
. description = " Enumerate Values " ,
. usage = " " ,
} ,
2019-01-09 17:16:35 +03:00
{
. name = NULL ,
} ,
2010-09-17 15:17:12 +04:00
} ;