/*
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 .
*/
#include "includes.h"
#include "rpcclient.h"
#include "../librpc/gen_ndr/ndr_winreg_c.h"
#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;
struct dcerpc_binding_handle *b = cli->binding_handle;
if (argc < 2) {
printf("usage: %s [name]\n", argv[0]);
return WERR_OK;
}
status = dcerpc_winreg_OpenHKLM(b, mem_ctx,
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;
status = dcerpc_winreg_EnumKey(b, mem_ctx,
&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)) {
return WERR_GEN_FAILURE;
}
return WERR_OK;
}
/****************************************************************************
****************************************************************************/
static void display_winreg_data(const char *v,
enum winreg_Type type,
uint8_t *data,
uint32_t length)
{
size_t i;
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:
printf("%-20s: REG_DWORD: 0x%08x\n", v, r.value);
break;
case REG_SZ:
printf("%-20s: REG_SZ: %s\n", v, r.string);
break;
case REG_BINARY: {
char *hex = hex_encode_talloc(NULL,
r.binary.data, r.binary.length);
size_t len;
printf("%-20s: REG_BINARY:", v);
len = strlen(hex);
for (i=0; ibinding_handle;
struct QueryMultipleValue *values_in, *values_out;
uint32_t num_values;
uint8_t *buffer = NULL;
uint32_t i;
if (argc < 2) {
printf("usage: %s [key] [value1] [value2] ...\n", argv[0]);
return WERR_OK;
}
status = dcerpc_winreg_OpenHKLM(b, mem_ctx,
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];
status = dcerpc_winreg_OpenKey(b, mem_ctx,
&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) {
return WERR_NOT_ENOUGH_MEMORY;
}
values_out = talloc_zero_array(mem_ctx, struct QueryMultipleValue, num_values);
if (values_out == NULL) {
return WERR_NOT_ENOUGH_MEMORY;
}
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) {
return WERR_NOT_ENOUGH_MEMORY;
}
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;
status = dcerpc_winreg_QueryMultipleValues2(b, mem_ctx,
&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_EQUAL(werr, WERR_MORE_DATA)) {
offered = needed;
buffer = talloc_zero_array(mem_ctx, uint8_t, needed);
if (buffer == NULL) {
return WERR_NOT_ENOUGH_MEMORY;
}
status = dcerpc_winreg_QueryMultipleValues2(b, mem_ctx,
&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) {
return WERR_NOT_ENOUGH_MEMORY;
}
status = dcerpc_winreg_QueryMultipleValues(b, mem_ctx,
&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);
}
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;
}
/* List of commands exported by this module */
struct cmd_set winreg_commands[] = {
{
.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 = "",
},
{
.name = "winreg_enumval",
.returntype = RPC_RTYPE_WERROR,
.ntfn = NULL,
.wfn = cmd_winreg_enumval,
.table = &ndr_table_winreg,
.rpc_pipe = NULL,
.description = "Enumerate Values",
.usage = "",
},
{
.name = NULL,
},
};