s3-net: Implemented net rpc conf addshare command
[gd/samba-autobuild/.git] / source3 / utils / net_rpc_conf.c
index bc77fb1703d1a80ecfb2f7f79bab008ab40106f8..27eab10b0ae385b28a2490d6df2f008097f0156a 100644 (file)
@@ -58,6 +58,32 @@ static int rpc_conf_listshares_usage(struct net_context *c, int argc,
        return -1;
 }
 
+static int rpc_conf_delshare_usage(struct net_context *c, int argc,
+                                  const char **argv)
+{
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _("net rpc conf delshare <sharename>\n"));
+       return -1;
+}
+
+static int rpc_conf_addshare_usage(struct net_context *c, int argc,
+                                  const char **argv)
+{
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net rpc conf addshare <sharename> <path> "
+                  "[writeable={y|N} [guest_ok={y|N} [<comment>]]]\n"
+                  "\t<sharename>      the new share name.\n"
+                  "\t<path>           the path on the filesystem to export.\n"
+                  "\twriteable={y|N}  set \"writeable to \"yes\" or "
+                  "\"no\" (default) on this share.\n"
+                  "\tguest_ok={y|N}   set \"guest ok\" to \"yes\" or "
+                  "\"no\" (default)   on this share.\n"
+                  "\t<comment>        optional comment for the new share.\n"));
+       return -1;
+
+}
 static int rpc_conf_showshare_usage(struct net_context *c, int argc,
                                    const char **argv)
 {
@@ -74,6 +100,146 @@ static int rpc_conf_drop_usage(struct net_context *c, int argc,
        return -1;
 }
 
+static int rpc_conf_getparm_usage(struct net_context *c, int argc,
+                              const char **argv)
+{
+       d_printf("%s\nnet rpc conf getparm <sharename> <parameter>\n",
+                       _("Usage:"));
+       return -1;
+}
+
+static int rpc_conf_setparm_usage(struct net_context *c, int argc,
+                                 const char **argv)
+{
+       d_printf("%s\n%s",
+                _("Usage:"),
+                _(" net rpc conf setparm <section> <param> <value>\n"));
+       return -1;
+}
+
+static int rpc_conf_delparm_usage(struct net_context *c, int argc,
+                               const char **argv)
+{
+       d_printf("%s\nnet rpc conf delparm <sharename> <parameter>\n",
+                       _("Usage:"));
+       return -1;
+}
+
+static int rpc_conf_getincludes_usage(struct net_context *c, int argc,
+                               const char **argv)
+{
+       d_printf("%s\nnet rpc conf getincludes <sharename>\n",
+                       _("Usage:"));
+       return -1;
+}
+
+static int rpc_conf_setincludes_usage(struct net_context *c, int argc,
+                               const char **argv)
+{
+       d_printf("%s\nnet rpc conf setincludes <sharename> [<filename>]*\n",
+                       _("Usage:"));
+       return -1;
+}
+
+static int rpc_conf_delincludes_usage(struct net_context *c, int argc,
+                               const char **argv)
+{
+       d_printf("%s\nnet rpc conf delincludes <sharename>\n",
+                       _("Usage:"));
+       return -1;
+}
+
+static bool rpc_conf_reg_valname_forbidden(const char * valname)
+{
+       const char *forbidden_valnames[] = {
+               "lock directory",
+               "lock dir",
+               "config backend",
+               "include",
+               "includes", /* this has a special meaning internally */
+               NULL
+       };
+       const char **forbidden = NULL;
+
+       for (forbidden = forbidden_valnames; *forbidden != NULL; forbidden++) {
+               if (strwicmp(valname, *forbidden) == 0) {
+                       return true;
+               }
+       }
+       return false;
+
+}
+static NTSTATUS rpc_conf_del_value(TALLOC_CTX *mem_ctx,
+                                  struct dcerpc_binding_handle *b,
+                                  struct policy_handle *parent_hnd,
+                                  const char *share_name,
+                                  const char *value,
+                                  WERROR *werr)
+{
+
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR result = WERR_OK;
+       WERROR _werr;
+
+       struct winreg_String keyname, valuename;
+       struct policy_handle child_hnd;
+
+       ZERO_STRUCT(child_hnd);
+       ZERO_STRUCT(keyname);
+       ZERO_STRUCT(valuename);
+
+       keyname.name = share_name;
+       valuename.name = value;
+
+       status = dcerpc_winreg_OpenKey(b, frame, parent_hnd, keyname, 0,
+                                      REG_KEY_WRITE, &child_hnd, &result);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, _("Failed to open key '%s': %s\n"),
+                               keyname.name, nt_errstr(status));
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(result))) {
+               d_fprintf(stderr, _("Failed to open key '%s': %s\n"),
+                               keyname.name, win_errstr(result));
+               goto error;
+       }
+
+       status = dcerpc_winreg_DeleteValue(b,
+                                          frame,
+                                          &child_hnd,
+                                          valuename,
+                                          &result);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, _("Failed to delete value %s\n"),
+                               nt_errstr(status));
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(result))) {
+               if (W_ERROR_EQUAL(result, WERR_BADFILE)){
+                       result = WERR_OK;
+                       goto error;
+               }
+
+               d_fprintf(stderr, _("Failed to delete value  %s\n"),
+                               win_errstr(result));
+               goto error;
+       }
+
+error:
+       *werr = result;
+
+       dcerpc_winreg_CloseKey(b, frame, &child_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;;
+
+}
+
 static NTSTATUS rpc_conf_get_share(TALLOC_CTX *mem_ctx,
                                   struct dcerpc_binding_handle *b,
                                   struct policy_handle *parent_hnd,
@@ -449,6 +615,90 @@ error:
        return status;;
 }
 
+static NTSTATUS rpc_conf_delshare_internal(struct net_context *c,
+                                          const struct 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 )
+{
+
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
+
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
+
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd;
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+
+
+       if (argc != 1 || c->display_usage) {
+               rpc_conf_delshare_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
+
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_ALL,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+       status = dcerpc_winreg_delete_subkeys_recursive(frame,
+                                                       b,
+                                                       &key_hnd,
+                                                       REG_KEY_ALL,
+                                                       argv[0],
+                                                       &werr);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr,
+                         "winreg_delete_subkeys: Could not delete key %s: %s\n",
+                         argv[0], nt_errstr(status));
+               goto error;
+       }
+
+       if (W_ERROR_EQUAL(werr, WERR_BADFILE)){
+               d_fprintf(stderr, _("ERROR: Key does not exist\n"));
+       }
+
+
+       if (!W_ERROR_IS_OK(werr)) {
+               d_fprintf(stderr,
+                         "winreg_delete_subkeys: Could not delete key %s: %s\n",
+                         argv[0], win_errstr(werr));
+               goto error;
+       }
+
+error:
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+
+       return status;
+}
+
 static NTSTATUS rpc_conf_list_internal(struct net_context *c,
                                       const struct dom_sid *domain_sid,
                                       const char *domain_name,
@@ -765,84 +1015,1004 @@ error:
        return status;
 }
 
-static int rpc_conf_drop(struct net_context *c, int argc,
-                               const char **argv)
+static NTSTATUS rpc_conf_addshare_internal(struct net_context *c,
+                                          const struct 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 )
 {
-       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
-               rpc_conf_drop_internal, argc, argv );
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
 
-}
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
 
-static int rpc_conf_showshare(struct net_context *c, int argc,
-                               const char **argv)
-{
-       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
-               rpc_conf_showshare_internal, argc, argv );
-}
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd, share_hnd;
+       char *sharename = NULL;
+       const char *path = NULL;
+       const char *comment = NULL;
+       const char *guest_ok = "no";
+       const char *read_only = "yes";
+       struct winreg_String key, keyclass;
+       enum winreg_CreateAction action = 0;
 
-static int rpc_conf_listshares(struct net_context *c, int argc,
-                               const char **argv)
-{
-       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
-               rpc_conf_listshares_internal, argc, argv );
-}
 
-static int rpc_conf_list(struct net_context *c, int argc,
-                            const char **argv)
-{
-       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
-               rpc_conf_list_internal, argc, argv );
-}
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+       ZERO_STRUCT(share_hnd);
 
-static int rpc_conf_delshare(struct net_context *c, int argc,
-                            const char **argv)
-{
-       d_printf("Function not yet implemented\n");
-       return 0;
-};
+       ZERO_STRUCT(key);
+       ZERO_STRUCT(keyclass);
 
-/* function calls */
-int net_rpc_conf(struct net_context *c, int argc,
-                const char **argv)
-{
-       struct functable func_table[] = {
-               {
-                       "list",
-                       rpc_conf_list,
-                       NET_TRANSPORT_RPC,
-                       N_("Dump the complete remote configuration in smb.conf like "
-                          "format."),
-                       N_("net rpc conf list\n"
-                          "    Dump the complete remote configuration in smb.conf "
-                          "like format.")
+       if (c->display_usage) {
+               rpc_conf_addshare_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
 
-               },
-               {
-                       "listshares",
-                       rpc_conf_listshares,
-                       NET_TRANSPORT_RPC,
-                       N_("List the remote share names."),
-                       N_("net rpc conf list\n"
-                          "    List the remote share names.")
+       switch (argc) {
+               case 0:
+               case 1:
+               default:
+                       rpc_conf_addshare_usage(c, argc, argv);
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto error;
+               case 5:
+                       comment = argv[4];
+               case 4:
+                       if (!strnequal(argv[3], "guest_ok=", 9)) {
+                               rpc_conf_addshare_usage(c, argc, argv);
+                               status = NT_STATUS_INVALID_PARAMETER;
+                               goto error;
+                       }
+                       switch (argv[3][9]) {
+                               case 'y':
+                               case 'Y':
+                                       guest_ok = "yes";
+                                       break;
+                               case 'n':
+                               case 'N':
+                                       guest_ok = "no";
+                                       break;
+                               default:
+                                       rpc_conf_addshare_usage(c, argc, argv);
+                                       status = NT_STATUS_INVALID_PARAMETER;
+                                       goto error;
+                       }
+               case 3:
+                       if (!strnequal(argv[2], "writeable=", 10)) {
+                               rpc_conf_addshare_usage(c, argc, argv);
+                               status = NT_STATUS_INVALID_PARAMETER;
+                               goto error;
+                       }
+                       switch (argv[2][10]) {
+                               case 'y':
+                               case 'Y':
+                                       read_only = "no";
+                                       break;
+                               case 'n':
+                               case 'N':
+                                       read_only = "yes";
+                                       break;
+                               default:
+                                       rpc_conf_addshare_usage(c, argc, argv);
+                                       status = NT_STATUS_INVALID_PARAMETER;
+                                       goto error;
+                       }
+               case 2:
+                       path = argv[1];
+                       sharename = talloc_strdup(frame, argv[0]);
+                       if (sharename == NULL) {
+                               d_printf(_("error: out of memory!\n"));
+                               goto error;
+                       }
 
-               },
-               {
-                       "drop",
-                       rpc_conf_drop,
-                       NET_TRANSPORT_RPC,
-                       N_("Delete the complete remote configuration."),
-                       N_("net rpc conf drop\n"
-                          "    Delete the complete remote configuration.")
+                       break;
+       }
 
-               },
-               {
-                       "showshare",
-                       rpc_conf_showshare,
-                       NET_TRANSPORT_RPC,
-                       N_("Show the definition of a remote share."),
-                       N_("net rpc conf showshare\n"
-                          "    Show the definition of a remote share.")
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_READ,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
 
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+       key.name = argv[0];
+       keyclass.name = "";
+
+       status = dcerpc_winreg_CreateKey(b, frame, &key_hnd, key, keyclass,
+                       0, REG_KEY_READ, NULL, &share_hnd,
+                       &action, &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], nt_errstr(status));
+               goto error;
+       }
+
+       if (!W_ERROR_IS_OK(werr)) {
+               d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], win_errstr(werr));
+               goto error;
+       }
+
+       switch (action) {
+               case REG_ACTION_NONE:
+                       werr = WERR_CREATE_FAILED;
+                       d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], win_errstr(werr));
+                       goto error;
+               case REG_CREATED_NEW_KEY:
+                       DEBUG(5, ("net rpc conf setincludes:"
+                                       "createkey created %s\n", argv[0]));
+                       break;
+               case REG_OPENED_EXISTING_KEY:
+                       d_fprintf(stderr, _("ERROR: Share '%s' already exists\n"), argv[0]);
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto error;
+       }
+
+       /* set the path parameter */
+       status = dcerpc_winreg_set_sz(frame, b, &share_hnd,
+                                       "path", path, &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               "path", path, nt_errstr(status));
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               "path", path, win_errstr(werr));
+               goto error;
+       }
+
+       /* set the writeable parameter */
+       status = dcerpc_winreg_set_sz(frame, b, &share_hnd,
+                                       "read only", read_only, &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               "read only", read_only, nt_errstr(status));
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               "read only", read_only, win_errstr(werr));
+               goto error;
+       }
+
+       /* set the guest ok parameter */
+       status = dcerpc_winreg_set_sz(frame, b, &share_hnd,
+                                       "guest ok", guest_ok, &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               "guest ok", guest_ok, nt_errstr(status));
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               "guest ok", guest_ok, win_errstr(werr));
+               goto error;
+       }
+
+       if (argc == 5) {
+               /* set the comment parameter */
+               status = dcerpc_winreg_set_sz(frame, b, &share_hnd,
+                                               "comment", comment, &werr);
+
+               if (!(NT_STATUS_IS_OK(status))) {
+                       d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                                       " with value %s\n %s\n",
+                                       "comment", comment, nt_errstr(status));
+                       goto error;
+               }
+
+               if (!(W_ERROR_IS_OK(werr))) {
+                       d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                                       " with value %s\n %s\n",
+                                       "comment", comment, win_errstr(werr));
+                       goto error;
+               }
+       }
+error:
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &share_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;
+}
+
+static NTSTATUS rpc_conf_getparm_internal(struct net_context *c,
+                                         const struct 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 )
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
+
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
+
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd;
+       struct smbconf_service *service = NULL;
+
+       bool param_is_set = false;
+       uint32_t param_count;
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+
+
+       if (argc != 2 || c->display_usage) {
+               rpc_conf_getparm_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
+
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_READ,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+
+       service = talloc(frame, struct smbconf_service);
+
+       status = rpc_conf_get_share(frame,
+                                   b,
+                                   &key_hnd,
+                                   argv[0],
+                                   service,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+                       goto error;
+       }
+
+       if (W_ERROR_EQUAL(werr, WERR_BADFILE)) {
+               d_fprintf(stderr, _("ERROR: Share %s does not exist\n"),
+                               argv[0]);
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+                       goto error;
+       }
+
+       for (param_count = 0;
+            param_count < service->num_params;
+            param_count++)
+       {
+               /* should includes also be printed? */
+               if (strcmp(service->param_names[param_count], argv[1]) == 0) {
+                       d_printf(_("%s\n"),
+                               service->param_values[param_count]);
+                       param_is_set = true;
+               }
+       }
+
+       if (!param_is_set) {
+               d_fprintf(stderr, _("ERROR: Given parameter '%s' has not been set\n"),
+                               argv[1]);
+               werr = WERR_BADFILE;
+               goto error;
+       }
+
+error:
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;
+
+}
+
+static NTSTATUS rpc_conf_setparm_internal(struct net_context *c,
+                                         const struct 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 )
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
+
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
+
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd, share_hnd;
+
+       struct winreg_String key, keyclass;
+       enum winreg_CreateAction action = 0;
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+       ZERO_STRUCT(share_hnd);
+
+       ZERO_STRUCT(key);
+       ZERO_STRUCT(keyclass);
+
+       if (argc != 3 || c->display_usage) {
+               rpc_conf_setparm_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
+
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_READ,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+       key.name = argv[0];
+       keyclass.name = "";
+
+       status = dcerpc_winreg_CreateKey(b, frame, &key_hnd, key, keyclass,
+                       0, REG_KEY_READ, NULL, &share_hnd,
+                       &action, &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], nt_errstr(status));
+               goto error;
+       }
+
+       if (!W_ERROR_IS_OK(werr)) {
+               d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], win_errstr(werr));
+               goto error;
+       }
+
+       switch (action) {
+               case REG_ACTION_NONE:
+                       werr = WERR_CREATE_FAILED;
+                       d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], win_errstr(werr));
+                       goto error;
+               case REG_CREATED_NEW_KEY:
+                       DEBUG(5, ("net rpc conf setparm:"
+                                       "createkey created %s\n", argv[0]));
+                       break;
+               case REG_OPENED_EXISTING_KEY:
+                       DEBUG(5, ("net rpc conf setparm:"
+                                       "createkey opened existing %s\n", argv[0]));
+
+                       /* delete posibly existing value */
+                       status = rpc_conf_del_value(frame,
+                                                   b,
+                                                   &key_hnd,
+                                                   argv[0],
+                                                   argv[1],
+                                                   &werr);
+
+                       if (!(NT_STATUS_IS_OK(status))) {
+                               goto error;
+                       }
+
+                       if (!(W_ERROR_IS_OK(werr))) {
+                               goto error;
+                       }
+
+                       break;
+       }
+
+
+       const char *canon_valname;
+       const char *canon_valstr;
+       /* check if parameter is valid for writing */
+       if (!lp_canonicalize_parameter_with_value(argv[1], argv[2],
+                                                 &canon_valname,
+                                                 &canon_valstr))
+       {
+               if (canon_valname == NULL) {
+                       d_fprintf(stderr, "invalid parameter '%s' given\n",
+                                 argv[1]);
+               } else {
+                       d_fprintf(stderr, "invalid value '%s' given for "
+                                 "parameter '%s'\n", argv[1], argv[2]);
+               }
+               werr = WERR_INVALID_PARAM;
+               goto error;
+       }
+
+       if (rpc_conf_reg_valname_forbidden(canon_valname)) {
+               d_fprintf(stderr, "Parameter '%s' not allowed in registry.\n",
+                         canon_valname);
+               werr = WERR_INVALID_PARAM;
+               goto error;
+       }
+
+       if (!strequal(argv[0], "global") &&
+           lp_parameter_is_global(argv[1]))
+       {
+               d_fprintf(stderr, "Global parameter '%s' not allowed in "
+                         "service definition ('%s').\n", canon_valname,
+                         argv[0]);
+               werr = WERR_INVALID_PARAM;
+               goto error;
+       }
+
+       /* set the parameter */
+       status = dcerpc_winreg_set_sz(frame, b, &share_hnd,
+                                       argv[1], argv[2], &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               argv[1], argv[2], nt_errstr(status));
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               d_fprintf(stderr, "ERROR: Could not set parameter '%s'"
+                               " with value %s\n %s\n",
+                               argv[1], argv[2], win_errstr(werr));
+               goto error;
+       }
+
+error:
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &share_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;
+}
+
+static NTSTATUS rpc_conf_delparm_internal(struct net_context *c,
+                                         const struct 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 )
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
+
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
+
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd;
+
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+
+
+       if (argc != 2 || c->display_usage) {
+               rpc_conf_delparm_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
+
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_READ,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+       status = rpc_conf_del_value(frame,
+                                   b,
+                                   &key_hnd,
+                                   argv[0],
+                                   argv[1],
+                                   &werr);
+
+error:
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;
+
+}
+
+static NTSTATUS rpc_conf_getincludes_internal(struct net_context *c,
+                                             const struct 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 )
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
+
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
+
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd;
+       struct smbconf_service *service = NULL;
+
+       uint32_t param_count;
+
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+
+
+       if (argc != 1 || c->display_usage) {
+               rpc_conf_getincludes_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
+
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_READ,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+       service = talloc(frame, struct smbconf_service);
+
+       status = rpc_conf_get_share(frame,
+                                   b,
+                                   &key_hnd,
+                                   argv[0],
+                                   service,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+                       goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+                       goto error;
+       }
+
+       for (param_count = 0;
+            param_count < service->num_params;
+            param_count++)
+       {
+               if (strcmp(service->param_names[param_count], "include") == 0) {
+                       d_printf(_("%s = %s\n"),
+                               service->param_names[param_count],
+                               service->param_values[param_count]);
+               }
+       }
+
+error:
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;
+
+}
+
+static NTSTATUS rpc_conf_setincludes_internal(struct net_context *c,
+                                             const struct 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 )
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
+
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
+
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd, share_hnd;
+
+       struct winreg_String key, keyclass;
+       enum winreg_CreateAction action = 0;
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+       ZERO_STRUCT(share_hnd);
+
+       ZERO_STRUCT(key);
+       ZERO_STRUCT(keyclass);
+
+       if (argc < 1 || c->display_usage) {
+               rpc_conf_setincludes_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
+
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_READ,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+       key.name = argv[0];
+       keyclass.name = "";
+
+       status = dcerpc_winreg_CreateKey(b, frame, &key_hnd, key, keyclass,
+                       0, REG_KEY_READ, NULL, &share_hnd,
+                       &action, &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], nt_errstr(status));
+               goto error;
+       }
+
+       if (!W_ERROR_IS_OK(werr)) {
+               d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], win_errstr(werr));
+               goto error;
+       }
+
+       switch (action) {
+               case REG_ACTION_NONE:
+                       /* Is there any other way to treat this? */
+                       werr = WERR_CREATE_FAILED;
+                       d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"),
+                               argv[0], win_errstr(werr));
+                       goto error;
+               case REG_CREATED_NEW_KEY:
+                       DEBUG(5, ("net rpc conf setincludes:"
+                                       "createkey created %s\n", argv[0]));
+                       break;
+               case REG_OPENED_EXISTING_KEY:
+                       DEBUG(5, ("net rpc conf setincludes:"
+                                       "createkey opened existing %s\n", argv[0]));
+
+                       /* delete posibly existing value */
+                       status = rpc_conf_del_value(frame,
+                                                   b,
+                                                   &key_hnd,
+                                                   argv[0],
+                                                   "includes",
+                                                   &werr);
+
+                       if (!(NT_STATUS_IS_OK(status))) {
+                               goto error;
+                       }
+
+                       if (!(W_ERROR_IS_OK(werr))) {
+                               goto error;
+                       }
+                       break;
+       }
+
+       /* set the 'includes' values */
+       status = dcerpc_winreg_set_multi_sz(frame, b, &share_hnd,
+                                           "includes", argv + 1, &werr);
+       if (!(NT_STATUS_IS_OK(status))) {
+               d_fprintf(stderr, "ERROR: Could not set includes\n %s\n",
+                               nt_errstr(status));
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               d_fprintf(stderr, "ERROR: Could not set includes\n %s\n",
+                               win_errstr(werr));
+               goto error;
+       }
+
+error:
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &share_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;
+}
+
+static NTSTATUS rpc_conf_delincludes_internal(struct net_context *c,
+                                             const struct 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 )
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       WERROR werr = WERR_OK;
+       WERROR _werr;
+
+       struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
+
+       /* key info */
+       struct policy_handle hive_hnd, key_hnd;
+
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+
+
+       if (argc != 1 || c->display_usage) {
+               rpc_conf_delincludes_usage(c, argc, argv);
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto error;
+       }
+/* try REG_KEY_WRITE */
+       status = rpc_conf_open_conf(frame,
+                                   b,
+                                   REG_KEY_READ,
+                                   &hive_hnd,
+                                   &key_hnd,
+                                   &werr);
+
+       if (!(NT_STATUS_IS_OK(status))) {
+               goto error;
+       }
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               goto error;
+       }
+
+       status = rpc_conf_del_value(frame,
+                                   b,
+                                   &key_hnd,
+                                   argv[0],
+                                   "includes",
+                                   &werr);
+
+error:
+
+       if (!(W_ERROR_IS_OK(werr))) {
+               status =  werror_to_ntstatus(werr);
+       }
+
+       dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
+       dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
+
+       TALLOC_FREE(frame);
+       return status;
+
+}
+
+static int rpc_conf_drop(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_drop_internal, argc, argv );
+
+}
+
+static int rpc_conf_showshare(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_showshare_internal, argc, argv );
+}
+
+static int rpc_conf_addshare(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_addshare_internal, argc, argv );
+}
+
+static int rpc_conf_listshares(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_listshares_internal, argc, argv );
+}
+
+static int rpc_conf_list(struct net_context *c, int argc,
+                            const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_list_internal, argc, argv );
+}
+
+static int rpc_conf_delshare(struct net_context *c, int argc,
+                            const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_delshare_internal, argc, argv );
+}
+
+static int rpc_conf_getparm(struct net_context *c, int argc,
+                            const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_getparm_internal, argc, argv );
+}
+
+static int rpc_conf_setparm(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_setparm_internal, argc, argv );
+}
+static int rpc_conf_delparm(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_delparm_internal, argc, argv );
+}
+
+static int rpc_conf_getincludes(struct net_context *c, int argc,
+                            const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_getincludes_internal, argc, argv );
+}
+
+static int rpc_conf_setincludes(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_setincludes_internal, argc, argv );
+}
+
+static int rpc_conf_delincludes(struct net_context *c, int argc,
+                               const char **argv)
+{
+       return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
+               rpc_conf_delincludes_internal, argc, argv );
+}
+
+/* function calls */
+int net_rpc_conf(struct net_context *c, int argc,
+                const char **argv)
+{
+       struct functable func_table[] = {
+               {
+                       "list",
+                       rpc_conf_list,
+                       NET_TRANSPORT_RPC,
+                       N_("Dump the complete remote configuration in smb.conf like "
+                          "format."),
+                       N_("net rpc conf list\n"
+                          "    Dump the complete remote configuration in smb.conf "
+                          "like format.")
+
+               },
+               {
+                       "listshares",
+                       rpc_conf_listshares,
+                       NET_TRANSPORT_RPC,
+                       N_("List the remote share names."),
+                       N_("net rpc conf list\n"
+                          "    List the remote share names.")
+
+               },
+               {
+                       "drop",
+                       rpc_conf_drop,
+                       NET_TRANSPORT_RPC,
+                       N_("Delete the complete remote configuration."),
+                       N_("net rpc conf drop\n"
+                          "    Delete the complete remote configuration.")
+
+               },
+               {
+                       "showshare",
+                       rpc_conf_showshare,
+                       NET_TRANSPORT_RPC,
+                       N_("Show the definition of a remote share."),
+                       N_("net rpc conf showshare\n"
+                          "    Show the definition of a remote share.")
+
+               },
+               {
+                       "addshare",
+                       rpc_conf_addshare,
+                       NET_TRANSPORT_RPC,
+                       N_("Create a new remote share."),
+                       N_("net rpc conf addshare\n"
+                          "    Create a new remote share.")
                },
                {
                        "delshare",
@@ -852,6 +2022,54 @@ int net_rpc_conf(struct net_context *c, int argc,
                        N_("net rpc conf delshare\n"
                           "    Delete a remote share.")
                },
+               {
+                       "getparm",
+                       rpc_conf_getparm,
+                       NET_TRANSPORT_RPC,
+                       N_("Retrieve the value of a parameter."),
+                       N_("net rpc conf getparm\n"
+                          "    Retrieve the value of a parameter.")
+               },
+               {
+                       "setparm",
+                       rpc_conf_setparm,
+                       NET_TRANSPORT_RPC,
+                       N_("Store a parameter."),
+                       N_("net rpc conf setparm\n"
+                          "    Store a parameter.")
+               },
+               {
+                       "delparm",
+                       rpc_conf_delparm,
+                       NET_TRANSPORT_RPC,
+                       N_("Delete a parameter."),
+                       N_("net rpc conf delparm\n"
+                          "    Delete a parameter.")
+               },
+               {
+                       "getincludes",
+                       rpc_conf_getincludes,
+                       NET_TRANSPORT_RPC,
+                       N_("Show the includes of a share definition."),
+                       N_("net rpc conf getincludes\n"
+                          "    Show the includes of a share definition.")
+               },
+               {
+                       "setincludes",
+                       rpc_conf_setincludes,
+                       NET_TRANSPORT_RPC,
+                       N_("Set includes for a share."),
+                       N_("net rpc conf setincludes\n"
+                          "    Set includes for a share.")
+               },
+               {
+                       "delincludes",
+                       rpc_conf_delincludes,
+                       NET_TRANSPORT_RPC,
+                       N_("Delete includes from a share definition."),
+                       N_("net rpc conf delincludes\n"
+                          "    Delete includes from a share definition.")
+               },
                {NULL, NULL, 0, NULL, NULL}
        };