2005-05-23 20:25:31 +04:00
/*
Samba Unix / Linux SMB client library
Distributed SMB / CIFS Server Management Utility
2006-09-28 01:37:43 +04:00
Copyright ( C ) Gerald ( Jerry ) Carter 2005 - 2006
2005-05-23 20:25:31 +04: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 . */
# include "includes.h"
# include "utils/net.h"
# include "regfio.h"
# include "reg_objects.h"
2006-11-21 13:32:08 +03:00
static BOOL reg_hive_key ( const char * fullname , uint32 * reg_type ,
const char * * key_name )
{
const char * sep ;
ptrdiff_t len ;
sep = strchr_m ( fullname , ' \\ ' ) ;
if ( sep ! = NULL ) {
len = sep - fullname ;
* key_name = sep + 1 ;
}
else {
len = strlen ( fullname ) ;
* key_name = " " ;
}
if ( strnequal ( fullname , " HKLM " , len ) | |
strnequal ( fullname , " HKEY_LOCAL_MACHINE " , len ) )
( * reg_type ) = HKEY_LOCAL_MACHINE ;
else if ( strnequal ( fullname , " HKCR " , len ) | |
strnequal ( fullname , " HKEY_CLASSES_ROOT " , len ) )
( * reg_type ) = HKEY_CLASSES_ROOT ;
else if ( strnequal ( fullname , " HKU " , len ) | |
strnequal ( fullname , " HKEY_USERS " , len ) )
( * reg_type ) = HKEY_USERS ;
else if ( strnequal ( fullname , " HKPD " , len ) | |
strnequal ( fullname , " HKEY_PERFORMANCE_DATA " , len ) )
( * reg_type ) = HKEY_PERFORMANCE_DATA ;
else {
DEBUG ( 10 , ( " reg_hive_key: unrecognised hive key %s \n " ,
fullname ) ) ;
return False ;
}
return True ;
}
static NTSTATUS registry_openkey ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * pipe_hnd ,
const char * name , uint32 access_mask ,
struct policy_handle * hive_hnd ,
struct policy_handle * key_hnd )
{
uint32 hive ;
NTSTATUS status ;
struct winreg_String key ;
if ( ! reg_hive_key ( name , & hive , & key . name ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
status = rpccli_winreg_Connect ( pipe_hnd , mem_ctx , hive , access_mask ,
hive_hnd ) ;
if ( ! ( NT_STATUS_IS_OK ( status ) ) ) {
return status ;
}
status = rpccli_winreg_OpenKey ( pipe_hnd , mem_ctx , hive_hnd , key , 0 ,
access_mask , key_hnd ) ;
if ( ! ( NT_STATUS_IS_OK ( status ) ) ) {
rpccli_winreg_CloseKey ( pipe_hnd , mem_ctx , hive_hnd ) ;
return status ;
}
return NT_STATUS_OK ;
}
2006-11-21 02:20:07 +03:00
static NTSTATUS registry_enumkeys ( TALLOC_CTX * ctx ,
struct rpc_pipe_client * pipe_hnd ,
struct policy_handle * key_hnd ,
uint32 * pnum_keys , char * * * pnames ,
char * * * pclasses , NTTIME * * * pmodtimes )
{
TALLOC_CTX * mem_ctx ;
NTSTATUS status ;
uint32 num_subkeys , max_subkeylen , max_classlen ;
uint32 num_values , max_valnamelen , max_valbufsize ;
uint32 i ;
NTTIME last_changed_time ;
uint32 secdescsize ;
struct winreg_String classname ;
char * * names , * * classes ;
NTTIME * * modtimes ;
if ( ! ( mem_ctx = talloc_new ( ctx ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCT ( classname ) ;
status = rpccli_winreg_QueryInfoKey (
pipe_hnd , mem_ctx , key_hnd , & classname , & num_subkeys ,
& max_subkeylen , & max_classlen , & num_values , & max_valnamelen ,
& max_valbufsize , & secdescsize , & last_changed_time ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
if ( num_subkeys = = 0 ) {
* pnum_keys = 0 ;
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_OK ;
}
if ( ( ! ( names = TALLOC_ZERO_ARRAY ( mem_ctx , char * , num_subkeys ) ) ) | |
( ! ( classes = TALLOC_ZERO_ARRAY ( mem_ctx , char * , num_subkeys ) ) ) | |
( ! ( modtimes = TALLOC_ZERO_ARRAY ( mem_ctx , NTTIME * ,
num_subkeys ) ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
}
for ( i = 0 ; i < num_subkeys ; i + + ) {
char c , n ;
struct winreg_StringBuf class_buf ;
struct winreg_StringBuf * pclass_buf = & class_buf ;
struct winreg_StringBuf name_buf ;
NTTIME modtime ;
NTTIME * pmodtime = & modtime ;
c = ' \0 ' ;
class_buf . name = & c ;
class_buf . size = max_classlen + 2 ;
n = ' \0 ' ;
name_buf . name = & n ;
name_buf . size = max_subkeylen + 2 ;
ZERO_STRUCT ( modtime ) ;
status = rpccli_winreg_EnumKey ( pipe_hnd , mem_ctx , key_hnd ,
i , & name_buf , & pclass_buf ,
& pmodtime ) ;
if ( W_ERROR_EQUAL ( ntstatus_to_werror ( status ) ,
WERR_NO_MORE_ITEMS ) ) {
status = NT_STATUS_OK ;
break ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
classes [ i ] = NULL ;
if ( ( pclass_buf ) & &
( ! ( classes [ i ] = talloc_strdup ( classes ,
pclass_buf - > name ) ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
}
if ( ! ( names [ i ] = talloc_strdup ( names , name_buf . name ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
}
if ( ( pmodtime ) & &
( ! ( modtimes [ i ] = ( NTTIME * ) talloc_memdup (
modtimes , pmodtime , sizeof ( * pmodtime ) ) ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
}
}
* pnum_keys = num_subkeys ;
if ( pnames ) {
* pnames = talloc_move ( ctx , & names ) ;
}
if ( pclasses ) {
* pclasses = talloc_move ( ctx , & classes ) ;
}
if ( pmodtimes ) {
* pmodtimes = talloc_move ( ctx , & modtimes ) ;
}
status = NT_STATUS_OK ;
error :
TALLOC_FREE ( mem_ctx ) ;
return status ;
}
static NTSTATUS registry_pull_value ( TALLOC_CTX * mem_ctx ,
struct registry_value * * pvalue ,
enum winreg_Type type , uint8 * data ,
uint32 size , uint32 length )
{
struct registry_value * value ;
NTSTATUS status ;
2006-11-21 05:21:45 +03:00
if ( ! ( value = TALLOC_ZERO_P ( mem_ctx , struct registry_value ) ) ) {
2006-11-21 02:20:07 +03:00
return NT_STATUS_NO_MEMORY ;
}
value - > type = type ;
switch ( type ) {
case REG_DWORD :
if ( ( size ! = 4 ) | | ( length ! = 4 ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
value - > v . dword = IVAL ( data , 0 ) ;
break ;
case REG_SZ :
case REG_EXPAND_SZ :
{
/*
* Make sure we get a NULL terminated string for
* convert_string_talloc ( ) .
*/
smb_ucs2_t * tmp ;
uint32 num_ucs2 = length / 2 ;
if ( ( length % 2 ) ! = 0 ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
if ( ! ( tmp = SMB_MALLOC_ARRAY ( smb_ucs2_t , num_ucs2 + 1 ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
}
memcpy ( ( void * ) tmp , ( const void * ) data , length ) ;
tmp [ num_ucs2 ] = 0 ;
value - > v . sz . len = convert_string_talloc (
value , CH_UTF16LE , CH_UNIX , tmp , length + 2 ,
& value - > v . sz . str , False ) ;
SAFE_FREE ( tmp ) ;
if ( value - > v . sz . len = = ( size_t ) - 1 ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
break ;
}
2006-11-21 05:21:45 +03:00
case REG_MULTI_SZ :
status = reg_pull_multi_sz ( value , ( void * ) data , length ,
& value - > v . multi_sz . num_strings ,
& value - > v . multi_sz . strings ) ;
if ( ! ( NT_STATUS_IS_OK ( status ) ) ) {
goto error ;
}
break ;
case REG_BINARY :
value - > v . binary . data = talloc_move ( value , & data ) ;
value - > v . binary . length = length ;
break ;
2006-11-21 02:20:07 +03:00
default :
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
* pvalue = value ;
return NT_STATUS_OK ;
error :
TALLOC_FREE ( value ) ;
return status ;
}
2006-11-21 13:32:08 +03:00
static NTSTATUS registry_push_value ( TALLOC_CTX * mem_ctx ,
const struct registry_value * value ,
DATA_BLOB * presult )
{
switch ( value - > type ) {
case REG_DWORD : {
char buf [ 4 ] ;
SIVAL ( buf , 0 , value - > v . dword ) ;
* presult = data_blob_talloc ( mem_ctx , ( void * ) buf , 4 ) ;
if ( presult - > data = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
break ;
}
case REG_SZ :
case REG_EXPAND_SZ : {
presult - > length = convert_string_talloc (
mem_ctx , CH_UNIX , CH_UTF16LE , value - > v . sz . str ,
MIN ( value - > v . sz . len , strlen ( value - > v . sz . str ) + 1 ) ,
( void * ) & ( presult - > data ) , False ) ;
if ( presult - > length = = ( size_t ) - 1 ) {
return NT_STATUS_NO_MEMORY ;
}
break ;
}
default :
return NT_STATUS_INVALID_PARAMETER ;
}
return NT_STATUS_OK ;
}
2006-11-21 02:20:07 +03:00
static NTSTATUS registry_enumvalues ( TALLOC_CTX * ctx ,
struct rpc_pipe_client * pipe_hnd ,
struct policy_handle * key_hnd ,
uint32 * pnum_values , char * * * pvalnames ,
struct registry_value * * * pvalues )
{
TALLOC_CTX * mem_ctx ;
NTSTATUS status ;
uint32 num_subkeys , max_subkeylen , max_classlen ;
uint32 num_values , max_valnamelen , max_valbufsize ;
uint32 i ;
NTTIME last_changed_time ;
uint32 secdescsize ;
struct winreg_String classname ;
struct registry_value * * values ;
char * * names ;
if ( ! ( mem_ctx = talloc_new ( ctx ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCT ( classname ) ;
status = rpccli_winreg_QueryInfoKey (
pipe_hnd , mem_ctx , key_hnd , & classname , & num_subkeys ,
& max_subkeylen , & max_classlen , & num_values , & max_valnamelen ,
& max_valbufsize , & secdescsize , & last_changed_time ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
if ( num_values = = 0 ) {
* pnum_values = 0 ;
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_OK ;
}
if ( ( ! ( names = TALLOC_ARRAY ( mem_ctx , char * , num_values ) ) ) | |
( ! ( values = TALLOC_ARRAY ( mem_ctx , struct registry_value * ,
num_values ) ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
}
for ( i = 0 ; i < num_values ; i + + ) {
enum winreg_Type type = REG_NONE ;
enum winreg_Type * ptype = & type ;
uint8 d = 0 ;
uint8 * data = & d ;
uint32 data_size ;
uint32 * pdata_size = & data_size ;
uint32 value_length ;
uint32 * pvalue_length = & value_length ;
char n ;
struct winreg_StringBuf name_buf ;
n = ' \0 ' ;
name_buf . name = & n ;
name_buf . size = max_valnamelen + 2 ;
data_size = max_valbufsize ;
value_length = 0 ;
status = rpccli_winreg_EnumValue ( pipe_hnd , mem_ctx , key_hnd ,
i , & name_buf , & ptype ,
& data , & pdata_size ,
& pvalue_length ) ;
if ( W_ERROR_EQUAL ( ntstatus_to_werror ( status ) ,
WERR_NO_MORE_ITEMS ) ) {
status = NT_STATUS_OK ;
break ;
}
if ( ! ( NT_STATUS_IS_OK ( status ) ) ) {
goto error ;
}
if ( ( name_buf . name = = NULL ) | | ( ptype = = NULL ) | |
( data = = NULL ) | | ( pdata_size = = 0 ) | |
( pvalue_length = = NULL ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
if ( ! ( names [ i ] = talloc_strdup ( names , name_buf . name ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
}
status = registry_pull_value ( values , & values [ i ] , * ptype , data ,
* pdata_size , * pvalue_length ) ;
if ( ! ( NT_STATUS_IS_OK ( status ) ) ) {
goto error ;
}
}
* pnum_values = num_values ;
if ( pvalnames ) {
* pvalnames = talloc_move ( ctx , & names ) ;
}
if ( pvalues ) {
* pvalues = talloc_move ( ctx , & values ) ;
}
status = NT_STATUS_OK ;
error :
TALLOC_FREE ( mem_ctx ) ;
return status ;
}
2005-05-23 20:25:31 +04:00
2006-11-21 13:32:08 +03:00
static NTSTATUS registry_setvalue ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * pipe_hnd ,
struct policy_handle * key_hnd ,
const char * name ,
const struct registry_value * value )
{
struct winreg_String name_string ;
DATA_BLOB blob ;
NTSTATUS result ;
result = registry_push_value ( mem_ctx , value , & blob ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
name_string . name = name ;
result = rpccli_winreg_SetValue ( pipe_hnd , blob . data , key_hnd ,
name_string , value - > type ,
blob . data , blob . length ) ;
TALLOC_FREE ( blob . data ) ;
return result ;
}
static NTSTATUS rpc_registry_setvalue_internal ( const DOM_SID * domain_sid ,
const char * domain_name ,
struct cli_state * cli ,
struct rpc_pipe_client * pipe_hnd ,
TALLOC_CTX * mem_ctx ,
int argc ,
const char * * argv )
{
struct policy_handle hive_hnd , key_hnd ;
NTSTATUS status ;
struct registry_value value ;
if ( argc < 4 ) {
d_fprintf ( stderr , " usage: net rpc registry setvalue <key> "
" <valuename> <type> [<val>]+ \n " ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
status = registry_openkey ( mem_ctx , pipe_hnd , argv [ 0 ] , REG_KEY_WRITE ,
& hive_hnd , & key_hnd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr , " registry_openkey failed: %s \n " ,
nt_errstr ( status ) ) ;
return status ;
}
if ( ! strequal ( argv [ 2 ] , " multi_sz " ) & & ( argc ! = 4 ) ) {
d_fprintf ( stderr , " Too many args for type %s \n " , argv [ 2 ] ) ;
return NT_STATUS_NOT_IMPLEMENTED ;
}
if ( strequal ( argv [ 2 ] , " dword " ) ) {
value . type = REG_DWORD ;
value . v . dword = strtoul ( argv [ 3 ] , NULL , 10 ) ;
}
else if ( strequal ( argv [ 2 ] , " sz " ) ) {
value . type = REG_SZ ;
value . v . sz . len = strlen ( argv [ 3 ] ) + 1 ;
value . v . sz . str = CONST_DISCARD ( char * , argv [ 3 ] ) ;
}
else {
d_fprintf ( stderr , " type \" %s \" not implemented \n " , argv [ 3 ] ) ;
status = NT_STATUS_NOT_IMPLEMENTED ;
goto error ;
}
status = registry_setvalue ( mem_ctx , pipe_hnd , & key_hnd ,
argv [ 1 ] , & value ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr , " registry_setvalue failed: %s \n " ,
nt_errstr ( status ) ) ;
}
error :
rpccli_winreg_CloseKey ( pipe_hnd , mem_ctx , & key_hnd ) ;
rpccli_winreg_CloseKey ( pipe_hnd , mem_ctx , & hive_hnd ) ;
return NT_STATUS_OK ;
}
static int rpc_registry_setvalue ( int argc , const char * * argv )
{
return run_rpc_command ( NULL , PI_WINREG , 0 ,
rpc_registry_setvalue_internal , argc , argv ) ;
}
2005-05-23 20:25:31 +04:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
static NTSTATUS rpc_registry_enumerate_internal ( const DOM_SID * domain_sid ,
const char * domain_name ,
struct cli_state * cli ,
struct rpc_pipe_client * pipe_hnd ,
TALLOC_CTX * mem_ctx ,
int argc ,
const char * * argv )
2005-05-23 20:25:31 +04:00
{
WERROR result = WERR_GENERAL_FAILURE ;
uint32 hive ;
pstring subpath ;
POLICY_HND pol_hive , pol_key ;
2006-09-26 19:15:26 +04:00
NTSTATUS status ;
struct winreg_String subkeyname ;
2006-11-21 02:20:07 +03:00
uint32 num_subkeys ;
uint32 num_values ;
char * * names , * * classes ;
NTTIME * * modtimes ;
uint32 i ;
struct registry_value * * values ;
2005-05-23 20:25:31 +04:00
if ( argc ! = 1 ) {
d_printf ( " Usage: net rpc enumerate <path> [recurse] \n " ) ;
2006-03-10 16:14:01 +03:00
d_printf ( " Example: net rpc enumerate 'HKLM \\ Software \\ Samba' \n " ) ;
2005-05-23 20:25:31 +04:00
return NT_STATUS_OK ;
}
if ( ! reg_split_hive ( argv [ 0 ] , & hive , subpath ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " invalid registry path \n " ) ;
2005-05-23 20:25:31 +04:00
return NT_STATUS_OK ;
}
/* open the top level hive and then the registry key */
2006-09-29 01:19:08 +04:00
status = rpccli_winreg_Connect ( pipe_hnd , mem_ctx , hive , MAXIMUM_ALLOWED_ACCESS , & pol_hive ) ;
2006-09-26 19:15:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
d_fprintf ( stderr , " Unable to connect to remote registry: "
2006-09-29 01:19:08 +04:00
" %s \n " , nt_errstr ( status ) ) ;
2006-09-26 19:15:26 +04:00
return status ;
2005-05-23 20:25:31 +04:00
}
2006-09-26 19:15:26 +04:00
subkeyname . name = subpath ;
status = rpccli_winreg_OpenKey ( pipe_hnd , mem_ctx , & pol_hive , subkeyname ,
0 , MAXIMUM_ALLOWED_ACCESS , & pol_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
d_fprintf ( stderr , " Unable to open [%s]: %s \n " , argv [ 0 ] ,
2006-09-29 01:19:08 +04:00
nt_errstr ( status ) ) ;
2006-07-11 22:01:26 +04:00
return werror_to_ntstatus ( result ) ;
2005-05-23 20:25:31 +04:00
}
2006-09-29 01:19:08 +04:00
2006-11-21 02:20:07 +03:00
status = registry_enumkeys ( mem_ctx , pipe_hnd , & pol_key , & num_subkeys ,
& names , & classes , & modtimes ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr , " enumerating keys failed: %s \n " ,
nt_errstr ( status ) ) ;
2006-09-29 01:19:08 +04:00
return status ;
}
2006-11-21 02:20:07 +03:00
for ( i = 0 ; i < num_subkeys ; i + + ) {
d_printf ( " Keyname = %s \n " , names [ i ] ) ;
d_printf ( " Modtime = %s \n " , modtimes [ i ]
? http_timestring ( nt_time_to_unix ( * modtimes [ i ] ) )
: " None " ) ;
2005-05-23 20:25:31 +04:00
d_printf ( " \n " ) ;
}
2006-11-21 02:20:07 +03:00
status = registry_enumvalues ( mem_ctx , pipe_hnd , & pol_key , & num_values ,
& names , & values ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
d_fprintf ( stderr , " enumerating values failed: %s \n " ,
nt_errstr ( status ) ) ;
return status ;
2006-09-29 01:19:08 +04:00
}
2006-11-21 02:20:07 +03:00
for ( i = 0 ; i < num_values ; i + + ) {
struct registry_value * v = values [ i ] ;
d_printf ( " Valuename = %s \n " , names [ i ] ) ;
d_printf ( " Type = %s \n " ,
reg_type_lookup ( v - > type ) ) ;
switch ( v - > type ) {
case REG_DWORD :
d_printf ( " Value = %d \n " , v - > v . dword ) ;
break ;
case REG_SZ :
case REG_EXPAND_SZ :
d_printf ( " Value = \" %s \" \n " , v - > v . sz . str ) ;
break ;
2006-11-21 05:21:45 +03:00
case REG_MULTI_SZ : {
uint32 j ;
for ( j = 0 ; j < v - > v . multi_sz . num_strings ; j + + ) {
d_printf ( " Value[%3.3d] = \" %s \" \n " , j ,
v - > v . multi_sz . strings [ j ] ) ;
}
break ;
}
case REG_BINARY :
d_printf ( " Value = %d bytes \n " ,
v - > v . binary . length ) ;
break ;
2006-11-21 02:20:07 +03:00
default :
d_printf ( " Value = <unprintable> \n " ) ;
2005-05-23 20:25:31 +04:00
break ;
}
2006-11-21 02:20:07 +03:00
d_printf ( " \n " ) ;
2005-05-23 20:25:31 +04:00
}
2006-11-21 02:20:07 +03:00
2005-11-08 19:33:45 +03:00
if ( strlen ( subpath ) ! = 0 )
2006-09-26 19:15:26 +04:00
rpccli_winreg_CloseKey ( pipe_hnd , mem_ctx , & pol_key ) ;
rpccli_winreg_CloseKey ( pipe_hnd , mem_ctx , & pol_hive ) ;
2005-05-23 20:25:31 +04:00
2006-09-26 19:15:26 +04:00
return status ;
2005-05-23 20:25:31 +04:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int rpc_registry_enumerate ( int argc , const char * * argv )
{
return run_rpc_command ( NULL , PI_WINREG , 0 ,
rpc_registry_enumerate_internal , argc , argv ) ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
static NTSTATUS rpc_registry_save_internal ( const DOM_SID * domain_sid ,
const char * domain_name ,
struct cli_state * cli ,
struct rpc_pipe_client * pipe_hnd ,
TALLOC_CTX * mem_ctx ,
int argc ,
const char * * argv )
2005-05-23 20:25:31 +04:00
{
WERROR result = WERR_GENERAL_FAILURE ;
uint32 hive ;
pstring subpath ;
POLICY_HND pol_hive , pol_key ;
2006-09-26 19:15:26 +04:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
struct winreg_String subkeyname ;
2006-09-28 01:37:43 +04:00
struct winreg_String filename ;
2005-05-23 20:25:31 +04:00
if ( argc ! = 2 ) {
d_printf ( " Usage: net rpc backup <path> <file> \n " ) ;
return NT_STATUS_OK ;
}
if ( ! reg_split_hive ( argv [ 0 ] , & hive , subpath ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " invalid registry path \n " ) ;
2005-05-23 20:25:31 +04:00
return NT_STATUS_OK ;
}
/* open the top level hive and then the registry key */
2006-09-29 01:19:08 +04:00
status = rpccli_winreg_Connect ( pipe_hnd , mem_ctx , hive , MAXIMUM_ALLOWED_ACCESS , & pol_hive ) ;
2006-09-26 19:15:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " Unable to connect to remote registry \n " ) ;
2006-09-26 19:15:26 +04:00
return status ;
2005-05-23 20:25:31 +04:00
}
2006-09-26 19:15:26 +04:00
subkeyname . name = subpath ;
status = rpccli_winreg_OpenKey ( pipe_hnd , mem_ctx , & pol_hive , subkeyname ,
0 , MAXIMUM_ALLOWED_ACCESS , & pol_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " Unable to open [%s] \n " , argv [ 0 ] ) ;
2005-05-23 20:25:31 +04:00
return werror_to_ntstatus ( result ) ;
}
2006-09-28 01:37:43 +04:00
filename . name = argv [ 1 ] ;
status = rpccli_winreg_SaveKey ( pipe_hnd , mem_ctx , & pol_key , & filename , NULL ) ;
2005-05-27 00:36:04 +04:00
if ( ! W_ERROR_IS_OK ( result ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " Unable to save [%s] to %s:%s \n " , argv [ 0 ] , cli - > desthost , argv [ 1 ] ) ;
2005-05-23 20:25:31 +04:00
}
/* cleanup */
2006-09-26 19:15:26 +04:00
rpccli_winreg_CloseKey ( pipe_hnd , mem_ctx , & pol_key ) ;
rpccli_winreg_CloseKey ( pipe_hnd , mem_ctx , & pol_hive ) ;
2005-05-23 20:25:31 +04:00
2006-09-26 19:15:26 +04:00
return status ;
2005-05-23 20:25:31 +04:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-27 00:36:04 +04:00
static int rpc_registry_save ( int argc , const char * * argv )
2005-05-23 20:25:31 +04:00
{
return run_rpc_command ( NULL , PI_WINREG , 0 ,
2005-05-27 00:36:04 +04:00
rpc_registry_save_internal , argc , argv ) ;
2005-05-23 20:25:31 +04:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void dump_values ( REGF_NK_REC * nk )
{
int i , j ;
pstring data_str ;
uint32 data_size , data ;
if ( ! nk - > values )
return ;
for ( i = 0 ; i < nk - > num_values ; i + + ) {
d_printf ( " \" %s \" = " , nk - > values [ i ] . valuename ? nk - > values [ i ] . valuename : " (default) " ) ;
2006-07-11 22:01:26 +04:00
d_printf ( " (%s) " , reg_type_lookup ( nk - > values [ i ] . type ) ) ;
2005-05-23 20:25:31 +04:00
data_size = nk - > values [ i ] . data_size & ~ VK_DATA_IN_OFFSET ;
switch ( nk - > values [ i ] . type ) {
case REG_SZ :
rpcstr_pull ( data_str , nk - > values [ i ] . data , sizeof ( data_str ) , - 1 , STR_TERMINATE ) ;
d_printf ( " %s " , data_str ) ;
break ;
case REG_MULTI_SZ :
case REG_EXPAND_SZ :
for ( j = 0 ; j < data_size ; j + + ) {
d_printf ( " %c " , nk - > values [ i ] . data [ j ] ) ;
}
break ;
case REG_DWORD :
data = IVAL ( nk - > values [ i ] . data , 0 ) ;
d_printf ( " 0x%x " , data ) ;
break ;
case REG_BINARY :
for ( j = 0 ; j < data_size ; j + + ) {
d_printf ( " %x " , nk - > values [ i ] . data [ j ] ) ;
}
break ;
default :
d_printf ( " unknown " ) ;
break ;
}
d_printf ( " \n " ) ;
}
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL dump_registry_tree ( REGF_FILE * file , REGF_NK_REC * nk , const char * parent )
{
REGF_NK_REC * key ;
pstring regpath ;
/* depth first dump of the registry tree */
while ( ( key = regfio_fetch_subkey ( file , nk ) ) ) {
pstr_sprintf ( regpath , " %s \\ %s " , parent , key - > keyname ) ;
d_printf ( " [%s] \n " , regpath ) ;
dump_values ( key ) ;
d_printf ( " \n " ) ;
dump_registry_tree ( file , key , regpath ) ;
}
2006-01-18 00:22:00 +03:00
2005-05-23 20:25:31 +04:00
return True ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL write_registry_tree ( REGF_FILE * infile , REGF_NK_REC * nk ,
REGF_NK_REC * parent , REGF_FILE * outfile ,
const char * parentpath )
{
REGF_NK_REC * key , * subkey ;
2005-08-29 18:55:40 +04:00
REGVAL_CTR * values ;
REGSUBKEY_CTR * subkeys ;
2005-05-23 20:25:31 +04:00
int i ;
pstring path ;
2005-08-29 18:55:40 +04:00
if ( ! ( subkeys = TALLOC_ZERO_P ( infile - > mem_ctx , REGSUBKEY_CTR ) ) ) {
DEBUG ( 0 , ( " write_registry_tree: talloc() failed! \n " ) ) ;
return False ;
}
if ( ! ( values = TALLOC_ZERO_P ( subkeys , REGVAL_CTR ) ) ) {
DEBUG ( 0 , ( " write_registry_tree: talloc() failed! \n " ) ) ;
return False ;
}
2005-05-23 20:25:31 +04:00
/* copy values into the REGVAL_CTR */
for ( i = 0 ; i < nk - > num_values ; i + + ) {
2005-08-29 18:55:40 +04:00
regval_ctr_addvalue ( values , nk - > values [ i ] . valuename , nk - > values [ i ] . type ,
2005-10-18 07:24:00 +04:00
( const char * ) nk - > values [ i ] . data , ( nk - > values [ i ] . data_size & ~ VK_DATA_IN_OFFSET ) ) ;
2005-05-23 20:25:31 +04:00
}
/* copy subkeys into the REGSUBKEY_CTR */
while ( ( subkey = regfio_fetch_subkey ( infile , nk ) ) ) {
2005-08-29 18:55:40 +04:00
regsubkey_ctr_addkey ( subkeys , subkey - > keyname ) ;
2005-05-23 20:25:31 +04:00
}
2005-08-29 18:55:40 +04:00
key = regfio_write_key ( outfile , nk - > keyname , values , subkeys , nk - > sec_desc - > sec_desc , parent ) ;
2005-05-23 20:25:31 +04:00
/* write each one of the subkeys out */
pstr_sprintf ( path , " %s%s%s " , parentpath , parent ? " \\ " : " " , nk - > keyname ) ;
nk - > subkey_index = 0 ;
while ( ( subkey = regfio_fetch_subkey ( infile , nk ) ) ) {
write_registry_tree ( infile , subkey , key , outfile , path ) ;
}
2005-08-29 18:55:40 +04:00
TALLOC_FREE ( subkeys ) ;
2005-05-23 20:25:31 +04:00
d_printf ( " [%s] \n " , path ) ;
return True ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int rpc_registry_dump ( int argc , const char * * argv )
{
REGF_FILE * registry ;
REGF_NK_REC * nk ;
if ( argc ! = 1 ) {
d_printf ( " Usage: net rpc dump <file> \n " ) ;
return 0 ;
}
d_printf ( " Opening %s.... " , argv [ 0 ] ) ;
if ( ! ( registry = regfio_open ( argv [ 0 ] , O_RDONLY , 0 ) ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " Failed to open %s for reading \n " , argv [ 0 ] ) ;
2005-05-23 20:25:31 +04:00
return 1 ;
}
d_printf ( " ok \n " ) ;
/* get the root of the registry file */
2006-06-19 23:07:39 +04:00
if ( ( nk = regfio_rootkey ( registry ) ) = = NULL ) {
d_fprintf ( stderr , " Could not get rootkey \n " ) ;
2006-06-28 08:56:23 +04:00
regfio_close ( registry ) ;
2006-06-19 23:07:39 +04:00
return 1 ;
}
2005-05-23 20:25:31 +04:00
d_printf ( " [%s] \n " , nk - > keyname ) ;
dump_values ( nk ) ;
d_printf ( " \n " ) ;
dump_registry_tree ( registry , nk , nk - > keyname ) ;
#if 0
talloc_report_full ( registry - > mem_ctx , stderr ) ;
# endif
d_printf ( " Closing registry... " ) ;
regfio_close ( registry ) ;
d_printf ( " ok \n " ) ;
return 0 ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int rpc_registry_copy ( int argc , const char * * argv )
{
2006-06-28 08:51:23 +04:00
REGF_FILE * infile = NULL , * outfile = NULL ;
2005-05-23 20:25:31 +04:00
REGF_NK_REC * nk ;
2006-01-18 00:22:00 +03:00
int result = 1 ;
2005-05-23 20:25:31 +04:00
if ( argc ! = 2 ) {
d_printf ( " Usage: net rpc copy <srcfile> <newfile> \n " ) ;
return 0 ;
}
d_printf ( " Opening %s.... " , argv [ 0 ] ) ;
if ( ! ( infile = regfio_open ( argv [ 0 ] , O_RDONLY , 0 ) ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " Failed to open %s for reading \n " , argv [ 0 ] ) ;
2005-05-23 20:25:31 +04:00
return 1 ;
}
d_printf ( " ok \n " ) ;
d_printf ( " Opening %s.... " , argv [ 1 ] ) ;
if ( ! ( outfile = regfio_open ( argv [ 1 ] , ( O_RDWR | O_CREAT | O_TRUNC ) , ( S_IREAD | S_IWRITE ) ) ) ) {
2006-01-18 00:22:00 +03:00
d_fprintf ( stderr , " Failed to open %s for writing \n " , argv [ 1 ] ) ;
2006-06-28 08:51:23 +04:00
goto out ;
2005-05-23 20:25:31 +04:00
}
d_printf ( " ok \n " ) ;
/* get the root of the registry file */
2006-06-19 23:07:39 +04:00
if ( ( nk = regfio_rootkey ( infile ) ) = = NULL ) {
d_fprintf ( stderr , " Could not get rootkey \n " ) ;
2006-06-28 08:51:23 +04:00
goto out ;
2006-06-19 23:07:39 +04:00
}
2005-05-23 20:25:31 +04:00
d_printf ( " RootKey: [%s] \n " , nk - > keyname ) ;
write_registry_tree ( infile , nk , NULL , outfile , " " ) ;
2006-01-18 00:22:00 +03:00
result = 0 ;
2006-06-28 08:51:23 +04:00
out :
2005-05-23 20:25:31 +04:00
d_printf ( " Closing %s... " , argv [ 1 ] ) ;
2006-06-28 08:51:23 +04:00
if ( outfile ) {
regfio_close ( outfile ) ;
}
2005-05-23 20:25:31 +04:00
d_printf ( " ok \n " ) ;
d_printf ( " Closing %s... " , argv [ 0 ] ) ;
2006-06-28 08:51:23 +04:00
if ( infile ) {
regfio_close ( infile ) ;
}
2005-05-23 20:25:31 +04:00
d_printf ( " ok \n " ) ;
2006-01-18 00:22:00 +03:00
return ( result ) ;
2005-05-23 20:25:31 +04:00
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int net_help_registry ( int argc , const char * * argv )
{
d_printf ( " net rpc registry enumerate <path> [recurse] Enumerate the subkeya and values for a given registry path \n " ) ;
2005-05-27 00:36:04 +04:00
d_printf ( " net rpc registry save <path> <file> Backup a registry tree to a file on the server \n " ) ;
2005-05-23 20:25:31 +04:00
d_printf ( " net rpc registry dump <file> Dump the contents of a registry file to stdout \n " ) ;
return - 1 ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int net_rpc_registry ( int argc , const char * * argv )
{
struct functable func [ ] = {
{ " enumerate " , rpc_registry_enumerate } ,
2006-11-21 13:32:08 +03:00
{ " setvalue " , rpc_registry_setvalue } ,
2005-05-27 00:36:04 +04:00
{ " save " , rpc_registry_save } ,
2005-05-23 20:25:31 +04:00
{ " dump " , rpc_registry_dump } ,
{ " copy " , rpc_registry_copy } ,
{ NULL , NULL }
} ;
if ( argc )
return net_run_function ( argc , argv , func , net_help_registry ) ;
return net_help_registry ( argc , argv ) ;
}