s3-net: add command rpc registry import
authorGregor Beck <gbeck@sernet.de>
Wed, 29 Sep 2010 13:11:49 +0000 (15:11 +0200)
committerGregor Beck <gbeck@sernet.de>
Wed, 29 Sep 2010 13:18:28 +0000 (15:18 +0200)
source3/utils/net_rpc_registry.c

index 87063a18bf4e1c99b11a760648afa242a87b04b2..d76e72e541f35d2c9db314543d333f4384676c99 100644 (file)
@@ -22,6 +22,8 @@
 #include "utils/net_registry_util.h"
 #include "regfio.h"
 #include "reg_objects.h"
+#include "registry/reg_import.h"
+#include <assert.h>
 
 static bool reg_hive_key(TALLOC_CTX *ctx, const char *fullname,
                         uint32 *reg_type, const char **key_name)
@@ -1215,6 +1217,290 @@ static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv
 
 /********************************************************************
 ********************************************************************/
+/**
+ * @defgroup net_rpc_registry_import Import
+ * @ingroup net_rpc_registry
+ * @{
+ */
+
+struct import_ctx {
+       struct rpc_pipe_client *pipe_hnd;
+       TALLOC_CTX *mem_ctx;
+};
+
+static WERROR import_create_key(struct import_ctx* ctx,
+                               struct policy_handle* parent, const char* name,
+                               void** pkey, bool* existing)
+{
+       WERROR werr=WERR_OK;
+       NTSTATUS status;
+       void* mem_ctx = talloc_new(ctx->mem_ctx);
+
+       struct policy_handle* key = NULL;
+       struct policy_handle  hive;
+       struct winreg_String  keyclass, keyname;
+       enum winreg_CreateAction action = REG_ACTION_NONE;
+
+       ZERO_STRUCT(keyname);
+       keyname.name = name;
+
+       if (parent == NULL) {
+               uint32 hive_idx = 0;
+               if (!reg_hive_key(mem_ctx, name, &hive_idx, &keyname.name)) {
+                       werr = WERR_FOOBAR;
+                       goto done;
+               }
+
+               status = rpccli_winreg_Connect(ctx->pipe_hnd, mem_ctx,
+                                              hive_idx, SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hive);
+               werr = ntstatus_to_werror(status);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr, "rpccli_winreg_Connect returned %s\n",
+                                 nt_errstr(status));
+                       goto done;
+               }
+
+               parent = &hive;
+       }
+
+       key = talloc_zero(mem_ctx, struct policy_handle);
+       if (key == NULL) {
+               werr = WERR_NOMEM;
+               goto done;
+       }
+
+       ZERO_STRUCT(keyclass);
+       keyclass.name = "";
+
+       status = rpccli_winreg_CreateKey(ctx->pipe_hnd, mem_ctx,
+                                        parent, keyname,
+                                        keyclass, 0, REG_KEY_READ, NULL,
+                                        key, &action, &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "rpccli_winreg_CreateKey returned %s\n",
+                         nt_errstr(status));
+               goto done;
+       }
+
+       switch (action) {
+       case REG_CREATED_NEW_KEY:
+               d_printf("createkey created %s\n", name);
+               if (existing != NULL)
+                       *existing = false;
+               break;
+
+       case REG_OPENED_EXISTING_KEY:
+               d_printf("createkey opened existing %s\n", name);
+               if (existing != NULL)
+                       *existing = true;
+               break;
+
+       case REG_ACTION_NONE:
+               d_printf("createkey did nothing -- huh?\n");
+               werr = WERR_FOOBAR;
+               break;
+       default:
+               assert(false);
+       }
+
+done:
+       if ( parent == &hive ) {
+               rpccli_winreg_CloseKey(ctx->pipe_hnd, mem_ctx,
+                                      parent, NULL);
+       }
+
+       if (pkey!=NULL) {
+               *pkey = talloc_steal(ctx->mem_ctx, key);
+       }
+
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+static WERROR import_delete_key(struct import_ctx* ctx,
+                               struct policy_handle* parent, const char* name)
+{
+       WERROR werr;
+       NTSTATUS status;
+       void* mem_ctx = talloc_new(ctx->mem_ctx);
+       struct winreg_String  keyname;
+       struct policy_handle  hive;
+
+       keyname.name = name;
+
+       if (parent == NULL) {
+               uint32 hive_idx;
+               if (!reg_hive_key(mem_ctx, name, &hive_idx, &keyname.name)) {
+                       werr = WERR_FOOBAR;
+                       goto done;
+               }
+
+               status = rpccli_winreg_Connect(ctx->pipe_hnd, mem_ctx, hive_idx,
+                                              SEC_FLAG_MAXIMUM_ALLOWED, &hive);
+               werr =  ntstatus_to_werror(status);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr, "rpccli_winreg_Connect returned %s\n",
+                                 nt_errstr(status));
+                       goto done;
+               }
+
+               parent = &hive;
+       }
+
+       status = rpccli_winreg_DeleteKey(ctx->pipe_hnd, mem_ctx, parent,
+                                        keyname, &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "rpccli_winreg_DeleteKey returned %s\n",
+                         nt_errstr(status));
+               goto done;
+       }
+
+done:
+       if ( parent == &hive ) {
+               rpccli_winreg_CloseKey(ctx->pipe_hnd, mem_ctx, parent, NULL);
+       }
+
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+static WERROR import_close_key(struct import_ctx* ctx,
+                              struct policy_handle* key)
+{
+       WERROR werr;
+       NTSTATUS status;
+       void* mem_ctx = talloc_new(ctx->mem_ctx);
+
+       status = rpccli_winreg_CloseKey(ctx->pipe_hnd, mem_ctx, key, &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "rpccli_winreg_CloseKey returned %s\n",
+                         nt_errstr(status));
+               goto done;
+       }
+
+       werr = (talloc_free(key) == 0) ? WERR_OK : WERR_GENERAL_FAILURE;
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+static WERROR import_create_val(struct import_ctx* ctx,
+                               struct policy_handle* parent, const char* name,
+                               uint32_t type, const uint8_t* val, uint32_t len)
+{
+       WERROR werr;
+       NTSTATUS status;
+       void* mem_ctx = talloc_new(ctx->mem_ctx);
+       struct winreg_String valuename;
+
+       if (parent == NULL) {
+               return WERR_INVALID_PARAM;
+       }
+
+       ZERO_STRUCT(valuename);
+       valuename.name = name;
+
+       status = rpccli_winreg_SetValue(ctx->pipe_hnd, mem_ctx, parent,
+                                       valuename, type,
+                                       discard_const(val), len, &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "registry_setvalue failed: %s\n",
+                         nt_errstr(status));
+               goto done;
+       }
+
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+static WERROR import_delete_val(struct import_ctx* ctx,
+                               struct policy_handle* parent, const char* name)
+{
+       WERROR werr;
+       NTSTATUS status;
+       void* mem_ctx = talloc_new(ctx->mem_ctx);
+       struct winreg_String valuename;
+
+       if (parent == NULL) {
+               return WERR_INVALID_PARAM;
+       }
+
+       ZERO_STRUCT(valuename);
+       valuename.name = name;
+
+       status = rpccli_winreg_DeleteValue(ctx->pipe_hnd, mem_ctx,
+                                          parent, valuename, &werr);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "registry_deletevalue failed: %s\n",
+                         nt_errstr(status));
+               goto done;
+       }
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+
+
+static NTSTATUS rpc_registry_import_internal(struct net_context *c,
+                                            const DOM_SID *domain_sid,
+                                            const char *domain_name,
+                                            struct cli_state *cli,
+                                            struct rpc_pipe_client *pipe_hnd,
+                                            TALLOC_CTX *mem_ctx,
+                                            int argc,
+                                            const char **argv )
+{
+       struct import_ctx import_ctx;
+
+       struct reg_import_callback import_callback = {
+               .openkey     = NULL,
+               .closekey    = (reg_import_callback_closekey_t)&import_close_key,
+               .createkey   = (reg_import_callback_createkey_t)&import_create_key,
+               .deletekey   = (reg_import_callback_deletekey_t)&import_delete_key,
+               .deleteval   = (reg_import_callback_deleteval_t)&import_delete_val,
+               .setval.blob = (reg_import_callback_setval_blob_t)&import_create_val,
+               .setval_type = BLOB,
+               .data = &import_ctx
+       };
+
+       int ret;
+       if (argc < 1 || argc > 2 || c->display_usage) {
+               d_printf("%s\n%s",
+                        "Usage:",
+                        "net rpc registry import <file> [options]\n");
+               d_printf("%s  net rpc registry export "
+                        "samba.reg enc=CP1252,flags=0\n", "Example:");
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       ZERO_STRUCT(import_ctx);
+       import_ctx.pipe_hnd = pipe_hnd;
+       import_ctx.mem_ctx  = mem_ctx;
+       ret = reg_parse_file(argv[0],
+                            reg_import_adapter(import_ctx.mem_ctx,
+                                               import_callback
+                                    ),
+                            (argc > 1) ? argv[1] : NULL
+               );
+
+       return ret==0 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+
+static int rpc_registry_import(struct net_context *c, int argc,
+                              const char **argv )
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+                              rpc_registry_import_internal, argc, argv );
+}
+
+/**@}*/
+/********************************************************************
+ ********************************************************************/
 
 int net_rpc_registry(struct net_context *c, int argc, const char **argv)
 {
@@ -1307,6 +1593,14 @@ int net_rpc_registry(struct net_context *c, int argc, const char **argv)
                        "net rpc registry getsd\n"
                        "    Get security descriptior"
                },
+               {
+                       "import",
+                       rpc_registry_import,
+                       NET_TRANSPORT_RPC,
+                       "Import .reg file",
+                       "net rpc registry import\n"
+                       "    Import .reg file"
+               },
                {NULL, NULL, 0, NULL, NULL}
        };