2011-01-27 14:27:23 +03:00
/*
* Unix SMB / CIFS implementation .
*
* WINREG internal client routines
*
* Copyright ( c ) 2011 Andreas Schneider < asn @ samba . org >
*
* 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"
2011-02-08 13:54:15 +03:00
# include "include/registry.h"
# include "librpc/gen_ndr/ndr_winreg_c.h"
2011-01-27 14:27:23 +03:00
# include "rpc_client/cli_winreg_int.h"
# include "rpc_server/rpc_ncacn_np.h"
2011-06-07 19:21:28 +04:00
# include "../lib/tsocket/tsocket.h"
2011-01-27 14:27:23 +03:00
2011-02-08 13:54:15 +03:00
/**
* Split path into hive name and subkeyname
* normalizations performed :
* - if the path contains no ' \\ ' characters ,
* assume that the legacy format of using ' / '
* as a separator is used and convert ' / ' to ' \\ '
* - strip trailing ' \\ ' chars
*/
static WERROR _split_hive_key ( TALLOC_CTX * mem_ctx ,
const char * path ,
char * * hivename ,
char * * subkeyname )
{
char * p ;
const char * tmp_subkeyname ;
if ( ( path = = NULL ) | | ( hivename = = NULL ) | | ( subkeyname = = NULL ) ) {
2015-12-03 17:24:25 +03:00
return WERR_INVALID_PARAMETER ;
2011-02-08 13:54:15 +03:00
}
if ( strlen ( path ) = = 0 ) {
2015-12-03 17:24:25 +03:00
return WERR_INVALID_PARAMETER ;
2011-02-08 13:54:15 +03:00
}
if ( strchr ( path , ' \\ ' ) = = NULL ) {
* hivename = talloc_string_sub ( mem_ctx , path , " / " , " \\ " ) ;
} else {
* hivename = talloc_strdup ( mem_ctx , path ) ;
}
if ( * hivename = = NULL ) {
2015-12-03 17:24:15 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2011-02-08 13:54:15 +03:00
}
/* strip trailing '\\' chars */
p = strrchr ( * hivename , ' \\ ' ) ;
while ( ( p ! = NULL ) & & ( p [ 1 ] = = ' \0 ' ) ) {
* p = ' \0 ' ;
p = strrchr ( * hivename , ' \\ ' ) ;
}
p = strchr ( * hivename , ' \\ ' ) ;
if ( ( p = = NULL ) | | ( * p = = ' \0 ' ) ) {
/* just the hive - no subkey given */
tmp_subkeyname = " " ;
} else {
* p = ' \0 ' ;
tmp_subkeyname = p + 1 ;
}
* subkeyname = talloc_strdup ( mem_ctx , tmp_subkeyname ) ;
if ( * subkeyname = = NULL ) {
2015-12-03 17:24:15 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2011-02-08 13:54:15 +03:00
}
return WERR_OK ;
}
static NTSTATUS _winreg_int_openkey ( TALLOC_CTX * mem_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * session_info ,
2011-02-08 13:54:15 +03:00
struct messaging_context * msg_ctx ,
struct dcerpc_binding_handle * * h ,
uint32_t reg_type ,
const char * key ,
bool create_key ,
uint32_t access_mask ,
struct policy_handle * hive_handle ,
struct policy_handle * key_handle ,
WERROR * pwerr )
2011-01-27 14:27:23 +03:00
{
2011-06-07 19:21:28 +04:00
struct tsocket_address * local ;
2011-01-27 14:27:23 +03:00
struct dcerpc_binding_handle * binding_handle ;
struct winreg_String wkey , wkeyclass ;
NTSTATUS status ;
WERROR result = WERR_OK ;
2011-06-07 19:21:28 +04:00
int rc ;
2011-01-27 14:27:23 +03:00
2011-06-07 19:21:28 +04:00
rc = tsocket_address_inet_from_strings ( mem_ctx ,
" ip " ,
2018-03-17 21:50:49 +03:00
" 127.0.0.1 " ,
2011-06-07 19:21:28 +04:00
0 ,
& local ) ;
if ( rc < 0 ) {
return NT_STATUS_NO_MEMORY ;
}
2011-01-27 14:27:23 +03:00
status = rpcint_binding_handle ( mem_ctx ,
& ndr_table_winreg ,
2011-06-07 19:21:28 +04:00
local ,
2017-02-24 03:29:12 +03:00
NULL ,
2011-02-21 12:25:52 +03:00
session_info ,
2011-01-27 14:27:23 +03:00
msg_ctx ,
& binding_handle ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-02-02 17:12:55 +03:00
DBG_WARNING ( " Could not connect to winreg pipe: %s \n " ,
nt_errstr ( status ) ) ;
2011-01-27 14:27:23 +03:00
return status ;
}
2011-02-08 13:54:15 +03:00
switch ( reg_type ) {
case HKEY_LOCAL_MACHINE :
status = dcerpc_winreg_OpenHKLM ( binding_handle ,
mem_ctx ,
NULL ,
access_mask ,
hive_handle ,
& result ) ;
break ;
case HKEY_CLASSES_ROOT :
status = dcerpc_winreg_OpenHKCR ( binding_handle ,
mem_ctx ,
NULL ,
access_mask ,
hive_handle ,
& result ) ;
break ;
case HKEY_USERS :
status = dcerpc_winreg_OpenHKU ( binding_handle ,
mem_ctx ,
NULL ,
access_mask ,
hive_handle ,
& result ) ;
break ;
case HKEY_CURRENT_USER :
status = dcerpc_winreg_OpenHKCU ( binding_handle ,
mem_ctx ,
NULL ,
access_mask ,
hive_handle ,
& result ) ;
break ;
case HKEY_PERFORMANCE_DATA :
status = dcerpc_winreg_OpenHKPD ( binding_handle ,
mem_ctx ,
NULL ,
access_mask ,
hive_handle ,
& result ) ;
break ;
default :
result = WERR_INVALID_PARAMETER ;
status = NT_STATUS_OK ;
}
2011-01-27 14:27:23 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( binding_handle ) ;
return status ;
}
if ( ! W_ERROR_IS_OK ( result ) ) {
talloc_free ( binding_handle ) ;
* pwerr = result ;
return status ;
}
ZERO_STRUCT ( wkey ) ;
wkey . name = key ;
if ( create_key ) {
enum winreg_CreateAction action = REG_ACTION_NONE ;
ZERO_STRUCT ( wkeyclass ) ;
wkeyclass . name = " " ;
status = dcerpc_winreg_CreateKey ( binding_handle ,
mem_ctx ,
hive_handle ,
wkey ,
wkeyclass ,
0 ,
access_mask ,
NULL ,
key_handle ,
& action ,
& result ) ;
switch ( action ) {
case REG_ACTION_NONE :
DEBUG ( 8 , ( " dcerpc_winreg_int_openkey: createkey "
" did nothing -- huh? \n " ) ) ;
break ;
case REG_CREATED_NEW_KEY :
DEBUG ( 8 , ( " dcerpc_winreg_int_openkey: createkey "
" created %s \n " , key ) ) ;
break ;
case REG_OPENED_EXISTING_KEY :
DEBUG ( 8 , ( " dcerpc_winreg_int_openkey: createkey "
" opened existing %s \n " , key ) ) ;
break ;
}
} else {
status = dcerpc_winreg_OpenKey ( binding_handle ,
mem_ctx ,
hive_handle ,
wkey ,
0 ,
access_mask ,
key_handle ,
& result ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( binding_handle ) ;
return status ;
}
if ( ! W_ERROR_IS_OK ( result ) ) {
talloc_free ( binding_handle ) ;
* pwerr = result ;
return status ;
}
* h = binding_handle ;
return status ;
}
2011-02-08 13:54:15 +03:00
NTSTATUS dcerpc_winreg_int_openkey ( TALLOC_CTX * mem_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * server_info ,
2011-02-08 13:54:15 +03:00
struct messaging_context * msg_ctx ,
struct dcerpc_binding_handle * * h ,
const char * key ,
bool create_key ,
uint32_t access_mask ,
struct policy_handle * hive_handle ,
struct policy_handle * key_handle ,
WERROR * pwerr )
{
char * hivename = NULL ;
char * subkey = NULL ;
uint32_t reg_type ;
WERROR result ;
result = _split_hive_key ( mem_ctx , key , & hivename , & subkey ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
* pwerr = result ;
return NT_STATUS_OK ;
}
if ( strequal ( hivename , " HKLM " ) | |
strequal ( hivename , " HKEY_LOCAL_MACHINE " ) ) {
reg_type = HKEY_LOCAL_MACHINE ;
} else if ( strequal ( hivename , " HKCR " ) | |
strequal ( hivename , " HKEY_CLASSES_ROOT " ) ) {
reg_type = HKEY_CLASSES_ROOT ;
} else if ( strequal ( hivename , " HKU " ) | |
strequal ( hivename , " HKEY_USERS " ) ) {
reg_type = HKEY_USERS ;
} else if ( strequal ( hivename , " HKCU " ) | |
strequal ( hivename , " HKEY_CURRENT_USER " ) ) {
reg_type = HKEY_CURRENT_USER ;
} else if ( strequal ( hivename , " HKPD " ) | |
strequal ( hivename , " HKEY_PERFORMANCE_DATA " ) ) {
reg_type = HKEY_PERFORMANCE_DATA ;
} else {
DEBUG ( 10 , ( " dcerpc_winreg_int_openkey: unrecognised hive key %s \n " ,
key ) ) ;
* pwerr = WERR_INVALID_PARAMETER ;
return NT_STATUS_OK ;
}
return _winreg_int_openkey ( mem_ctx ,
server_info ,
msg_ctx ,
h ,
reg_type ,
key ,
create_key ,
access_mask ,
hive_handle ,
key_handle ,
pwerr ) ;
}
NTSTATUS dcerpc_winreg_int_hklm_openkey ( TALLOC_CTX * mem_ctx ,
2011-07-18 07:06:47 +04:00
const struct auth_session_info * server_info ,
2011-02-08 13:54:15 +03:00
struct messaging_context * msg_ctx ,
struct dcerpc_binding_handle * * h ,
const char * key ,
bool create_key ,
uint32_t access_mask ,
struct policy_handle * hive_handle ,
struct policy_handle * key_handle ,
WERROR * pwerr )
{
return _winreg_int_openkey ( mem_ctx ,
server_info ,
msg_ctx ,
h ,
HKEY_LOCAL_MACHINE ,
key ,
create_key ,
access_mask ,
hive_handle ,
key_handle ,
pwerr ) ;
}
2011-01-27 14:27:23 +03:00
/* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */