cac_winreg.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,003 行 · 第 1/2 页

C
1,003
字号
/*  *  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;   struct rpc_pipe_client *pipe_hnd = 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(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_WINREG, &(hnd->status)))) {         return CAC_FAILURE;      }      hnd->_internal.pipes[PI_WINREG] = True;   }   key = talloc(mem_ctx, POLICY_HND);   if(!key) {      hnd->status = NT_STATUS_NO_MEMORY;   }   err = rpccli_reg_connect( pipe_hnd, 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) {   struct rpc_pipe_client *pipe_hnd = 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;   }   pipe_hnd = cac_GetPipe(hnd, PI_WINREG);   if(!pipe_hnd) {      hnd->status = NT_STATUS_INVALID_HANDLE;      return CAC_FAILURE;   }   err = rpccli_reg_close(pipe_hnd, 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) {   struct rpc_pipe_client *pipe_hnd = 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;   }   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, &reg_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;   }   pipe_hnd = cac_GetPipe(hnd, PI_WINREG);   if(!pipe_hnd) {      hnd->status = NT_STATUS_INVALID_HANDLE;      return CAC_FAILURE;   }   err = rpccli_reg_open_entry( pipe_hnd, 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 = rpccli_reg_close( pipe_hnd, 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) {   struct rpc_pipe_client *pipe_hnd = NULL;   WERROR err;   /*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 {      err = rpccli_reg_enum_key( pipe_hnd, 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) {   struct rpc_pipe_client *pipe_hnd = 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;   }   /*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;   }   err = rpccli_reg_create_key_ex( pipe_hnd, 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 rpc_pipe_client *pipe_hnd, 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 = rpccli_reg_enum_key( pipe_hnd, 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 = rpccli_reg_open_entry(pipe_hnd, mem_ctx, key, subkey_name, REG_KEY_ALL, &subkey);      if(!W_ERROR_IS_OK(err))         break;      err = cac_delete_subkeys_recursive(pipe_hnd, 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*/      rpccli_reg_flush_key(pipe_hnd, mem_ctx, key);            /*close the key that we opened*/      rpccli_reg_close(pipe_hnd, mem_ctx, &subkey);      /*now we delete the subkey*/      err = rpccli_reg_delete_key(pipe_hnd, mem_ctx, key, subkey_name);      cur_key++;   }   return err;}int cac_RegDeleteKey(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDeleteKey *op) {   struct rpc_pipe_client *pipe_hnd = 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;   }   pipe_hnd = cac_GetPipe(hnd, PI_WINREG);   if(!pipe_hnd) {      hnd->status = NT_STATUS_INVALID_HANDLE;      return CAC_FAILURE;   }   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(pipe_hnd, 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 = rpccli_reg_delete_key( pipe_hnd, 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) {   struct rpc_pipe_client *pipe_hnd = 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;   }   pipe_hnd = cac_GetPipe(hnd, PI_WINREG);   if(!pipe_hnd) {      hnd->status = NT_STATUS_INVALID_HANDLE;      return CAC_FAILURE;   }   err = rpccli_reg_delete_val( pipe_hnd, 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) {   struct rpc_pipe_client *pipe_hnd = NULL;   WERROR err;   char *class_name_out    = NULL;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?