+
/*
* Unix SMB/CIFS implementation.
* MS-RPC client library implementation (WINREG pipe)
*
* 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
+ * 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,
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#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;
+NTSTATUS cac_delete_subkeys_recursive(struct rpc_pipe_client * pipe_hnd,
+ TALLOC_CTX * mem_ctx, POLICY_HND * key);
+
+int cac_RegConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegConnect *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ POLICY_HND *key = NULL;
+
+ 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 ( !
+ ( pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_WINREG,
+ &hnd->status ) ) ) {
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_WINREG] = True;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ key = talloc( mem_ctx, POLICY_HND );
+ if ( !key ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ hnd->status =
+ rpccli_winreg_Connect( pipe_hnd, mem_ctx, op->in.root,
+ op->in.access, key );
+
+ 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;
+int cac_RegClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ POLICY_HND * key )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- 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;
- }
+ 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;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = cli_reg_close(&srv->cli, mem_ctx, key);
- hnd->status = werror_to_ntstatus(err);
+ hnd->status = rpccli_winreg_CloseKey( pipe_hnd, mem_ctx, key );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ 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;
+int cac_RegOpenKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegOpenKey *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct winreg_String key_string;
- char *key_name = NULL;
- uint32 reg_type = 0;
+ POLICY_HND *key_out;
+ POLICY_HND *parent_key;
- struct RegConnect rc;
+ char *key_name = NULL;
+ uint32 reg_type = 0;
- if(!hnd)
- return CAC_FAILURE;
+ struct RegConnect rc;
- if(!hnd->_internal.ctx) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!op || !op->in.name || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.name || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- key_out = talloc(mem_ctx, POLICY_HND);
- if(!key_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- 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;
- }
+ 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);
+ /*use cac_RegConnect because it handles the session setup */
+ ZERO_STRUCT( rc );
- rc.in.access = op->in.access;
- rc.in.root = reg_type;
+ rc.in.access = op->in.access;
+ rc.in.root = reg_type;
- if(!cac_RegConnect(hnd, mem_ctx, &rc)) {
- return CAC_FAILURE;
- }
+ 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;
+ 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;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ key_string.name = key_name;
+ hnd->status =
+ rpccli_winreg_OpenKey( pipe_hnd, mem_ctx, parent_key,
+ key_string, 0, op->in.access,
+ key_out );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ if ( !op->in.parent_key ) {
+ /*then close the one that we opened above */
+ hnd->status =
+ rpccli_winreg_CloseKey( pipe_hnd, mem_ctx,
+ parent_key );
+
+ 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_RegEnumKeys( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegEnumKeys *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+
+ /*buffers for rpccli_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;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /* 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 {
+#if 0
+ hnd->status =
+ rpccli_winreg_EnumKey( pipe_hnd, mem_ctx, op->in.key,
+ resume_idx, key_name_in,
+ class_name_in,
+ &mod_times_out );
+#endif
+
+ 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;
- }
+int cac_RegCreateKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegCreateKey *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ POLICY_HND *key_out;
+ struct RegOpenKey rok;
+ struct winreg_String key_string, class_string;
+ enum winreg_CreateAction action = 0;
+
+ 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;
+ }
+
+ /*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 */
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ key_out = talloc( mem_ctx, POLICY_HND );
+ if ( !key_out ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ key_string.name = op->in.key_name;
+ class_string.name = op->in.class_name;
+ hnd->status =
+ rpccli_winreg_CreateKey( pipe_hnd, mem_ctx, op->in.parent_key,
+ key_string, class_string, 0,
+ op->in.access, NULL, key_out,
+ &action );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ op->out.key = key_out;
+
+ return CAC_SUCCESS;
- 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;
+NTSTATUS cac_delete_subkeys_recursive( struct rpc_pipe_client * pipe_hnd,
+ TALLOC_CTX * mem_ctx, POLICY_HND * key )
+{
+ POLICY_HND subkey;
+ fstring subkey_name;
+ int cur_key = 0;
+ NTSTATUS status;
+ uint32 num_subkeys, max_subkeylen, max_classlen;
+ uint32 num_values, max_valnamelen, maxvalbufsize;
+ char *name_buffer;
+ struct winreg_String class_string;
- if(cac_RegOpenKey(hnd, mem_ctx, &rok)) {
- /*then we got the key, return*/
- op->out.key = rok.out.key;
- return CAC_SUCCESS;
- }
+ NTTIME modtime;
+ uint32 secdescsize;
- /*just be ultra-safe*/
- srv->cli.pipe_idx = PI_WINREG;
+ /* First get the max subkey name length */
- key_out = talloc(mem_ctx, POLICY_HND);
- if(!key_out) {
- hnd->status = NT_STATUS_NO_MEMORY;
- return CAC_FAILURE;
- }
+ class_string.name = NULL;
+ status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, key,
+ &class_string, &num_subkeys,
+ &max_subkeylen, &max_classlen,
+ &num_values, &max_valnamelen,
+ &maxvalbufsize, &secdescsize,
+ &modtime );
- 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;
- }
+ if ( !NT_STATUS_IS_OK( status ) ) {
+ return status;
+ }
- op->out.key = key_out;
+ if ( (name_buffer = TALLOC_ARRAY( mem_ctx, char, max_subkeylen )) == NULL ) {
+ d_fprintf(stderr, "Memory allocation error.\n");
+ return NT_STATUS_NO_MEMORY;
+ }
- return CAC_SUCCESS;
-}
+ while ( NT_STATUS_IS_OK( status ) ) {
+ struct winreg_String key_string;
+ struct winreg_StringBuf subkey_string;
+ fstring subkeyname;
-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*/
+ memset( name_buffer, 0x0, max_subkeylen );
+ subkey_string.name = name_buffer;
+ subkey_string.length = 0;
+ subkey_string.size = max_subkeylen;
- WERROR err = WERR_OK;
+ status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key, cur_key,
+ &subkey_string, NULL, NULL);
- POLICY_HND subkey;
- fstring subkey_name;
- fstring class_buf;
- time_t mod_time_buf;
+ if ( !NT_STATUS_IS_OK( status ) )
+ break;
- int cur_key = 0;
+ /* copy the keyname and add the terminating NULL */
- while(W_ERROR_IS_OK(err)) {
- err = cli_reg_enum_key( cli, mem_ctx, key, cur_key, subkey_name, class_buf, &mod_time_buf);
+ StrnCpy( subkeyname, subkey_string.name,
+ MIN(subkey_string.length, sizeof(subkeyname)-1) );
+ subkeyname[MIN(subkey_string.length, sizeof(subkeyname)-1)] = '\0';
- if(!W_ERROR_IS_OK(err))
- break;
+ /*try to open the key with full access */
- /*try to open the key with full access*/
- err = cli_reg_open_entry(cli, mem_ctx, key, subkey_name, REG_KEY_ALL, &subkey);
+ key_string.name = subkeyname;
+ status = rpccli_winreg_OpenKey( pipe_hnd, mem_ctx, key,
+ key_string, 0, REG_KEY_ALL,
+ &subkey );
- if(!W_ERROR_IS_OK(err))
- break;
+ if ( !NT_STATUS_IS_OK( status ) )
+ break;
- err = cac_delete_subkeys_recursive(cli, mem_ctx, &subkey);
+ status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
+ &subkey );
- if(!W_ERROR_EQUAL(err,WERR_NO_MORE_ITEMS) && !W_ERROR_IS_OK(err))
- break;
+ if ( !W_ERROR_EQUAL( ntstatus_to_werror(status), WERR_NO_MORE_ITEMS )
+ && !NT_STATUS_IS_OK( status ) )
+ 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);
+ /*flush the key just to be safe */
+ rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, key );
- /*now we delete the subkey*/
- err = cli_reg_delete_key(cli, mem_ctx, key, subkey_name);
+ /*close the key that we opened */
+ rpccli_winreg_CloseKey( pipe_hnd, mem_ctx, &subkey );
+ /*now we delete the subkey */
+ key_string.name = subkey_name;
+ status = rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, key,
+ key_string );
- cur_key++;
- }
+ cur_key++;
+ }
- return err;
+ return status;
}
-int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) {
- SMBCSRV *srv = NULL;
- WERROR err;
+int cac_RegDeleteKey( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegDeleteKey *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct winreg_String key_string;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- 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;
- }
+ 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;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv->cli.pipe_idx = PI_WINREG;
+ if ( op->in.recursive ) {
- if(op->in.recursive) {
- /*first open the key, and then delete all of it's subkeys recursively*/
- struct RegOpenKey rok;
- ZERO_STRUCT(rok);
+ /* first open the key, and then delete all of
+ it's subkeys recursively */
- rok.in.parent_key = op->in.parent_key;
- rok.in.name = op->in.name;
- rok.in.access = REG_KEY_ALL;
+ struct RegOpenKey rok;
- if(!cac_RegOpenKey(hnd, mem_ctx, &rok))
- return CAC_FAILURE;
+ ZERO_STRUCT( rok );
- err = cac_delete_subkeys_recursive(&(srv->cli), mem_ctx, rok.out.key);
+ rok.in.parent_key = op->in.parent_key;
+ rok.in.name = op->in.name;
+ rok.in.access = REG_KEY_ALL;
- /*close the key that we opened*/
- cac_RegClose(hnd, mem_ctx, rok.out.key);
+ if ( !cac_RegOpenKey( hnd, mem_ctx, &rok ) )
+ return CAC_FAILURE;
- hnd->status = werror_to_ntstatus(err);
+ hnd->status = cac_delete_subkeys_recursive( pipe_hnd, mem_ctx,
+ rok.out.key );
- if(NT_STATUS_V(hnd->status) != NT_STATUS_V(NT_STATUS_GUIDS_EXHAUSTED) && !NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ /*close the key that we opened */
+ cac_RegClose( hnd, mem_ctx, rok.out.key );
- /*now go on to actually delete the key*/
- }
+ if ( NT_STATUS_V( hnd->status ) !=
+ NT_STATUS_V( NT_STATUS_GUIDS_EXHAUSTED )
+ && !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- err = cli_reg_delete_key( &(srv->cli), mem_ctx, op->in.parent_key, op->in.name);
- hnd->status = werror_to_ntstatus(err);
+ /*now go on to actually delete the key */
+ }
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
-
- return CAC_SUCCESS;
-}
+ key_string.name = op->in.name;
+ hnd->status =
+ rpccli_winreg_DeleteKey( pipe_hnd, mem_ctx, op->in.parent_key,
+ key_string );
-int cac_RegDeleteValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteValue *op) {
- SMBCSRV *srv = NULL;
- WERROR err;
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- 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;
+ 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_RegDeleteValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegDeleteValue *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct winreg_String value_string;
+
+ 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;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ value_string.name = op->in.name;
+ hnd->status =
+ rpccli_winreg_DeleteValue( pipe_hnd, mem_ctx,
+ op->in.parent_key, value_string );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
+
+ return CAC_SUCCESS;
}
-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;
+int cac_RegQueryKeyInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegQueryKeyInfo *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ 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;
+ struct winreg_String class_string;
+
+ 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;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx,
+ op->in.key,
+ &class_string,
+ &num_subkeys_out,
+ &long_subkey_out,
+ &long_class_out,
+ &num_values_out,
+ &long_value_out,
+ &long_data_out,
+ &secdesc_size, &mod_time );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ if ( !class_string.name ) {
+ op->out.class_name = talloc_strdup( mem_ctx, "" );
+ } else {
+ op->out.class_name = talloc_strdup( mem_ctx, class_string.name );
+ }
+
+ 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;
+}
- return CAC_SUCCESS;
+int cac_RegQueryValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegQueryValue *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct winreg_String value_string;
+ REGVAL_BUFFER buffer;
+ REG_VALUE_DATA *data_out = NULL;
+ enum winreg_Type val_type;
+ uint8 *buf;
+ uint32 buf_size = 4096;
+ uint32 length = 0;
+
+ 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;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ value_string.name = op->in.val_name;
+
+ if ( ( buf = TALLOC_ARRAY( mem_ctx, uint8, buf_size ) ) == NULL ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ return CAC_FAILURE;
+ }
+
+ hnd->status = rpccli_winreg_QueryValue( pipe_hnd, mem_ctx, op->in.key,
+ value_string, &val_type, buf,
+ &buf_size, &length );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
+
+ init_regval_buffer( &buffer, buf, length );
+
+ 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_RegEnumValues( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegEnumValues *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ char *name_buffer;
+ REGVAL_BUFFER val_buf;
+ uint32 *types_out = NULL;
+ REG_VALUE_DATA **values_out = NULL;
+ char **val_names_out = NULL;
+ uint32 num_values_out = 0;
+ uint32 resume_idx = 0;
+ uint32 num_subkeys, max_subkeylen, max_classlen;
+ uint32 num_values, max_valnamelen, maxvalbufsize;
+ struct winreg_String class_string;
+ NTTIME modtime;
+ uint32 secdescsize;
+ uint8 *buffer;
+
+ 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;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /*we need to assume that the max number of values will be enumerated */
+ types_out = TALLOC_ARRAY( mem_ctx, uint32, 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;
+
+ class_string.name = NULL;
+ hnd->status = rpccli_winreg_QueryInfoKey( pipe_hnd, mem_ctx, op->in.key,
+ &class_string, &num_subkeys,
+ &max_subkeylen, &max_classlen,
+ &num_values, &max_valnamelen,
+ &maxvalbufsize, &secdescsize,
+ &modtime );
+
+ if ( !NT_STATUS_IS_OK(hnd->status) ) {
+ TALLOC_FREE( types_out );
+ TALLOC_FREE( values_out );
+
+ return CAC_FAILURE;
+ }
+
+ if ( (buffer = TALLOC_ARRAY( mem_ctx, uint8, maxvalbufsize )) == NULL ) {
+ TALLOC_FREE( types_out );
+ TALLOC_FREE( values_out );
+ hnd->status = NT_STATUS_NO_MEMORY;
+
+ return CAC_FAILURE;
+ }
+
+ if ( (name_buffer = TALLOC_ARRAY(mem_ctx, char, max_valnamelen)) == NULL ) {
+ TALLOC_FREE( types_out );
+ TALLOC_FREE( values_out );
+ TALLOC_FREE( buffer );
+ hnd->status = NT_STATUS_NO_MEMORY;
+
+ return CAC_FAILURE;
+ }
+
+ do {
+ uint32 data_size = maxvalbufsize;
+ uint32 data_length = 0;
+ struct winreg_ValNameBuf name_buf;
+
+ memset( name_buffer, 0x0, max_valnamelen );
+ name_buf.name = name_buffer;
+ name_buf.size = max_valnamelen;
+ name_buf.length = 0;
+
+ hnd->status = rpccli_winreg_EnumValue( pipe_hnd, mem_ctx,
+ op->in.key,
+ resume_idx, &name_buf,
+ &types_out[num_values_out], buffer,
+ &data_size,
+ &data_length );
+
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ break;
+
+ ZERO_STRUCT( val_buf );
+ init_regval_buffer( &val_buf, buffer, data_length );
+
+ values_out[num_values_out] = cac_MakeRegValueData( mem_ctx,
+ types_out[num_values_out],
+ val_buf );
+ val_names_out[num_values_out] = TALLOC_ARRAY( mem_ctx, char, name_buf.length+1 );
+
+ if ( !val_names_out[num_values_out]
+ || !values_out[num_values_out] ) {
+ hnd->status = NT_STATUS_NO_MEMORY;
+ break;
+ }
+
+ StrnCpy( val_names_out[num_values_out], name_buf.name, name_buf.length );
+ (val_names_out[num_values_out])[name_buf.length] = '\0';
+
+ 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;
+int cac_RegSetValue( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegSetValue *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct winreg_String value_string;
- RPC_DATA_BLOB *buffer;
+ RPC_DATA_BLOB *buffer;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- 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;
- }
+ 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;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv->cli.pipe_idx = PI_WINREG;
+ buffer = cac_MakeRpcDataBlob( mem_ctx, op->in.type, op->in.value );
- 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;
- if(!buffer) {
- if(errno == ENOMEM)
- hnd->status = NT_STATUS_NO_MEMORY;
- else
- hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- return CAC_FAILURE;
- }
+ value_string.name = op->in.val_name;
+ hnd->status =
+ rpccli_winreg_SetValue( pipe_hnd, mem_ctx, op->in.key,
+ value_string, op->in.type,
+ buffer->buffer, buffer->buf_len );
- 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;
+ 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);
+ /*flush */
+ hnd->status = rpccli_winreg_FlushKey( pipe_hnd, mem_ctx, op->in.key );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- return CAC_SUCCESS;
+ 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;
+int cac_RegGetVersion( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegGetVersion *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ uint32 version_out;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!op || !op->in.key || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ if ( !op || !op->in.key || !mem_ctx ) {
+ hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
+ }
- srv->cli.pipe_idx = PI_WINREG;
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- err = cli_reg_getversion( &(srv->cli), mem_ctx, op->in.key, &version_out);
- hnd->status = werror_to_ntstatus(err);
+ hnd->status =
+ rpccli_winreg_GetVersion( pipe_hnd, mem_ctx, op->in.key,
+ &version_out );
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- op->out.version = version_out;
+ op->out.version = version_out;
- return CAC_SUCCESS;
+ 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;
+int cac_RegGetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegGetKeySecurity *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct KeySecurityData keysec;
- return CAC_SUCCESS;
-}
-
-int cac_RegSetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegSetKeySecurity *op) {
- SMBCSRV *srv = NULL;
- WERROR err;
+ ZERO_STRUCT( keysec );
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- 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;
- }
+ 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;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv->cli.pipe_idx = PI_WINREG;
+ hnd->status =
+ rpccli_winreg_GetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
+ op->in.info_type, &keysec );
- 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;
+ }
+#if 0 /* FIX ME!!!! unmarshall the security descriptor */
+ op->out.size = buf.sd_size;
+ op->out.descriptor = dup_sec_desc( mem_ctx, buf.sd );
+#endif
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( op->out.descriptor == NULL ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ 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;
+int cac_RegSetKeySecurity( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct RegSetKeySecurity *op )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct KeySecurityData keysec;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ ZERO_STRUCT( keysec );
- if(!op || !op->in.key || !op->in.filename || !mem_ctx) {
- hnd->status = NT_STATUS_INVALID_PARAMETER;
- return CAC_FAILURE;
- }
+ if ( !hnd )
+ return CAC_FAILURE;
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_WINREG] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv->cli.pipe_idx = PI_WINREG;
+ 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;
+ }
- err = cli_reg_save_key( &(srv->cli), mem_ctx, op->in.key, op->in.filename);
- hnd->status = werror_to_ntstatus(err);
+ pipe_hnd = cac_GetPipe( hnd, PI_WINREG );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+ /* FIXME!!! Marshall in the input sec_desc to struct KeySecurityData */
+ hnd->status =
+ rpccli_winreg_SetKeySecurity( pipe_hnd, mem_ctx, op->in.key,
+ op->in.info_type, &keysec );
- if(!NT_STATUS_IS_OK(hnd->status)) {
- return CAC_FAILURE;
- }
+ if ( !NT_STATUS_IS_OK( hnd->status ) ) {
+ return CAC_FAILURE;
+ }
- return CAC_SUCCESS;
+ 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_Shutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
+ struct Shutdown *op )
+{
+ SMBCSRV *srv = NULL;
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ struct initshutdown_String msg_string;
+ struct initshutdown_String_sub s;
+
+ 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_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ /*initialize for winreg pipe if we have to */
+ if ( !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
+ if ( !
+ ( pipe_hnd =
+ cli_rpc_pipe_open_noauth( srv->cli, PI_INITSHUTDOWN,
+ &( hnd->status ) ) ) ) {
+ return CAC_FAILURE;
+ }
+
+ hnd->_internal.pipes[PI_INITSHUTDOWN] = True;
+ }
+
+ pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
+
+ msg = ( op->in.message !=
+ NULL ) ? op->in.message : talloc_strdup( mem_ctx, "" );
+ msg_string.name = &s;
+ msg_string.name->name = msg;
+
+ hnd->status = NT_STATUS_OK;
+
+ if ( hnd->_internal.srv_level > SRV_WIN_NT4 ) {
+ hnd->status =
+ rpccli_initshutdown_InitEx( pipe_hnd, mem_ctx, NULL,
+ &msg_string,
+ 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 =
+ rpccli_initshutdown_Init( pipe_hnd, mem_ctx, NULL,
+ &msg_string, 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;
+int cac_AbortShutdown( CacServerHandle * hnd, TALLOC_CTX * mem_ctx )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
- if(!hnd)
- return CAC_FAILURE;
+ if ( !hnd )
+ return CAC_FAILURE;
- if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SHUTDOWN]) {
- hnd->status = NT_STATUS_INVALID_HANDLE;
- return CAC_FAILURE;
- }
+ if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_INITSHUTDOWN] ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv = cac_GetServer(hnd);
- if(!srv) {
- hnd->status = NT_STATUS_INVALID_CONNECTION;
- return CAC_FAILURE;
- }
+ pipe_hnd = cac_GetPipe( hnd, PI_INITSHUTDOWN );
+ if ( !pipe_hnd ) {
+ hnd->status = NT_STATUS_INVALID_HANDLE;
+ return CAC_FAILURE;
+ }
- srv->cli.pipe_idx = PI_SHUTDOWN;
+ hnd->status = rpccli_initshutdown_Abort( pipe_hnd, mem_ctx, NULL );
- hnd->status = cli_shutdown_abort(&(srv->cli), mem_ctx);
+ if ( !NT_STATUS_IS_OK( hnd->status ) )
+ return CAC_FAILURE;
- if(!NT_STATUS_IS_OK(hnd->status))
- return CAC_FAILURE;
-
- return CAC_SUCCESS;
+ return CAC_SUCCESS;
}
-