diff options
author | Gerald Carter <jerry@samba.org> | 2005-09-03 16:55:45 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:03:30 -0500 |
commit | 3c6b0f965588aab0edbc4d115fb9e72c884ded3b (patch) | |
tree | ce3740784555e729297955c924e4701feaf69d38 /source3/libmsrpc/cac_winreg.c | |
parent | a44e97c99f61916db3f7cc02cd2581c8d64be73a (diff) | |
download | samba-3c6b0f965588aab0edbc4d115fb9e72c884ded3b.tar.gz samba-3c6b0f965588aab0edbc4d115fb9e72c884ded3b.tar.bz2 samba-3c6b0f965588aab0edbc4d115fb9e72c884ded3b.zip |
r10003: in the rush for 10k, I forgot to run add the rest of Chris' libmsrpc files
(This used to be commit 32bebc452dffa8348b94c5b866350b1fe761986f)
Diffstat (limited to 'source3/libmsrpc/cac_winreg.c')
-rw-r--r-- | source3/libmsrpc/cac_winreg.c | 1033 |
1 files changed, 1033 insertions, 0 deletions
diff --git a/source3/libmsrpc/cac_winreg.c b/source3/libmsrpc/cac_winreg.c new file mode 100644 index 0000000000..3a90aa871e --- /dev/null +++ b/source3/libmsrpc/cac_winreg.c @@ -0,0 +1,1033 @@ +/* + * 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 02139, USA. + */ + +#include "libmsrpc.h" +#include "libmsrpc_internal.h" + + +int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect *op) { + SMBCSRV *srv = NULL; + 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]) { + if(!cli_nt_session_open(&srv->cli, PI_WINREG)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_WINREG] = True; + } + + key = talloc(mem_ctx, POLICY_HND); + if(!key) { + hnd->status = NT_STATUS_NO_MEMORY; + } + + err = cli_reg_connect( &(srv->cli), mem_ctx, op->in.root, op->in.access, key); + 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) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + err = cli_reg_close(&srv->cli, mem_ctx, key); + 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) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + 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, ®_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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_open_entry( &(srv->cli), mem_ctx, parent_key, key_name, op->in.access, key_out); + 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*/ + err = cli_reg_close( &(srv->cli), mem_ctx, parent_key); + 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) { + SMBCSRV *srv = NULL; + WERROR err; + + /*buffers for cli_reg_enum_key call*/ + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + /**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; + talloc_free(key_names_out); + 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; + talloc_free(key_names_out); + talloc_free(class_names_out); + + return CAC_FAILURE; + } + + resume_idx = op->out.resume_idx; + + do { + err = cli_reg_enum_key( &(srv->cli), mem_ctx, op->in.key, resume_idx, key_name_in, class_name_in, &mod_times_out[num_keys_out]); + 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) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + 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*/ + srv->cli.pipe_idx = PI_WINREG; + + key_out = talloc(mem_ctx, POLICY_HND); + if(!key_out) { + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + err = cli_reg_create_key_ex( &(srv->cli), mem_ctx, op->in.parent_key, op->in.key_name, op->in.class_name, op->in.access, key_out); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + op->out.key = key_out; + + return CAC_SUCCESS; + +} + +WERROR cac_delete_subkeys_recursive(struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *key) { + /*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)) { + err = cli_reg_enum_key( cli, mem_ctx, key, cur_key, subkey_name, class_buf, &mod_time_buf); + + if(!W_ERROR_IS_OK(err)) + break; + + /*try to open the key with full access*/ + err = cli_reg_open_entry(cli, mem_ctx, key, subkey_name, REG_KEY_ALL, &subkey); + + if(!W_ERROR_IS_OK(err)) + break; + + err = cac_delete_subkeys_recursive(cli, mem_ctx, &subkey); + + if(!W_ERROR_EQUAL(err,WERR_NO_MORE_ITEMS) && !W_ERROR_IS_OK(err)) + break; + + /*flush the key just to be safe*/ + cli_reg_flush_key(cli, mem_ctx, key); + + /*close the key that we opened*/ + cli_reg_close(cli, mem_ctx, &subkey); + + /*now we delete the subkey*/ + err = cli_reg_delete_key(cli, mem_ctx, key, subkey_name); + + + cur_key++; + } + + + return err; +} + + + +int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + 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; + + err = cac_delete_subkeys_recursive(&(srv->cli), mem_ctx, rok.out.key); + + /*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*/ + } + + err = cli_reg_delete_key( &(srv->cli), mem_ctx, op->in.parent_key, op->in.name); + 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) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_delete_val( &(srv->cli), mem_ctx, op->in.parent_key, op->in.name); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + return CAC_SUCCESS; +} + +int cac_RegQueryKeyInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryKeyInfo *op) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_query_key( &(srv->cli), mem_ctx, op->in.key, + 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; +} + +int cac_RegQueryValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryValue *op) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_query_value(&srv->cli, mem_ctx, op->in.key, op->in.val_name, &val_type, &buffer); + 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) { + SMBCSRV *srv = NULL; + WERROR err; + + /*buffers for cli_reg_enum_key call*/ + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + /*we need to assume that the max number of values will be enumerated*/ + types_out = talloc_array(mem_ctx, int, op->in.max_values); + 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) { + talloc_free(types_out); + 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) { + talloc_free(types_out); + talloc_free(values_out); + hnd->status = NT_STATUS_NO_MEMORY; + return CAC_FAILURE; + } + + resume_idx = op->out.resume_idx; + do { + ZERO_STRUCT(val_buf); + + err = cli_reg_enum_val(&srv->cli, mem_ctx, op->in.key, resume_idx, val_name_buf, &types_out[num_values_out], &val_buf); + 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) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + 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; + } + + err = cli_reg_set_val(&srv->cli, mem_ctx, op->in.key, op->in.val_name, op->in.type, buffer); + hnd->status = werror_to_ntstatus(err); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + /*flush*/ + err = cli_reg_flush_key(&(srv->cli), mem_ctx, op->in.key); + 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) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_getversion( &(srv->cli), mem_ctx, op->in.key, &version_out); + 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) { + SMBCSRV *srv = NULL; + WERROR err; + + uint32 buf_size; + SEC_DESC_BUF *buf = 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.info_type == 0 || !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; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_get_key_sec(&(srv->cli), mem_ctx, op->in.key, op->in.info_type, &buf_size, buf); + hnd->status = werror_to_ntstatus(err); + + + if(!NT_STATUS_IS_OK(hnd->status)) { + return CAC_FAILURE; + } + + op->out.size = buf->len; + op->out.descriptor = buf->sec; + + return CAC_SUCCESS; +} + +int cac_RegSetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetKeySecurity *op) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_set_key_sec(&(srv->cli), mem_ctx, op->in.key, op->in.info_type, op->in.size, op->in.descriptor); + 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) { + SMBCSRV *srv = NULL; + 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; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_WINREG; + + err = cli_reg_save_key( &(srv->cli), mem_ctx, op->in.key, op->in.filename); + 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; + + 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) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + /*initialize for winreg pipe if we have to*/ + if(!hnd->_internal.pipes[PI_SHUTDOWN]) { + if(!cli_nt_session_open(&srv->cli, PI_SHUTDOWN)) { + hnd->status = NT_STATUS_UNSUCCESSFUL; + return CAC_FAILURE; + } + + hnd->_internal.pipes[PI_SHUTDOWN] = True; + } + + srv->cli.pipe_idx = PI_SHUTDOWN; + + 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) { + hnd->status = cli_shutdown_init_ex( &(srv->cli), mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force, op->in.reason); + } + + if(hnd->_internal.srv_level < SRV_WIN_2K || !NT_STATUS_IS_OK(hnd->status)) { + hnd->status = cli_shutdown_init( &(srv->cli), mem_ctx, msg, op->in.timeout, op->in.reboot, op->in.force); + + 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) { + SMBCSRV *srv = NULL; + + if(!hnd) + return CAC_FAILURE; + + if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN]) { + hnd->status = NT_STATUS_INVALID_HANDLE; + return CAC_FAILURE; + } + + srv = cac_GetServer(hnd); + if(!srv) { + hnd->status = NT_STATUS_INVALID_CONNECTION; + return CAC_FAILURE; + } + + srv->cli.pipe_idx = PI_SHUTDOWN; + + hnd->status = cli_shutdown_abort(&(srv->cli), mem_ctx); + + if(!NT_STATUS_IS_OK(hnd->status)) + return CAC_FAILURE; + + return CAC_SUCCESS; +} + |