summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/net_rpc.c456
1 files changed, 334 insertions, 122 deletions
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 614f19c803..fb34b1e9e3 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -708,7 +708,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
SAM_USER_INFO_7 info7;
if (argc != 2) {
- d_printf("New and old username must be specified\n");
+ d_printf("Old and new username must be specified\n");
rpc_user_usage(argc, argv);
return NT_STATUS_OK;
}
@@ -1151,12 +1151,9 @@ int net_rpc_user(int argc, const char **argv)
};
if (argc == 0) {
- if (opt_long_list_entries) {
- } else {
- }
- return run_rpc_command(NULL,PI_SAMR, 0,
- rpc_user_list_internals,
- argc, argv);
+ return run_rpc_command(NULL,PI_SAMR, 0,
+ rpc_user_list_internals,
+ argc, argv);
}
return net_run_function(argc, argv, func, rpc_user_usage);
@@ -2436,9 +2433,6 @@ int net_rpc_group(int argc, const char **argv)
};
if (argc == 0) {
- if (opt_long_list_entries) {
- } else {
- }
return run_rpc_command(NULL, PI_SAMR, 0,
rpc_group_list_internals,
argc, argv);
@@ -2477,7 +2471,7 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
WERROR result;
char *sharename=talloc_strdup(mem_ctx, argv[0]);
char *path;
- uint32 type=0; /* only allow disk shares to be added */
+ uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
uint32 num_users=0, perms=0;
char *password=NULL; /* don't allow a share password */
uint32 level = 2;
@@ -2574,6 +2568,139 @@ static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
}
+
+static WERROR get_share_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 level, int argc, const char **argv,
+ SRV_SHARE_INFO_CTR *ctr)
+{
+ WERROR result;
+ SRV_SHARE_INFO info;
+
+ /* no specific share requested, enumerate all */
+ if (argc == 0) {
+
+ ENUM_HND hnd;
+ uint32 preferred_len = 0xffffffff;
+
+ init_enum_hnd(&hnd, 0);
+
+ result = cli_srvsvc_net_share_enum(cli, mem_ctx, level, ctr,
+ preferred_len, &hnd);
+ goto done;
+ }
+
+ /* request just one share */
+ result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[0], level, &info);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* construct ctr */
+ ZERO_STRUCTP(ctr);
+
+ ctr->info_level = ctr->switch_value = level;
+ ctr->ptr_share_info = ctr->ptr_entries = 1;
+ ctr->num_entries = ctr->num_entries2 = 1;
+
+ switch (level) {
+ case 1:
+ {
+ char *s;
+ SRV_SHARE_INFO_1 *info1;
+
+ ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
+ info1 = ctr->share.info1;
+
+ memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
+
+ /* Copy pointer crap */
+
+ memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
+
+ /* Duplicate strings */
+
+ s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_netname);
+ if (s)
+ init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
+
+ s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_remark);
+ if (s)
+ init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
+ }
+ case 2:
+ {
+ char *s;
+ SRV_SHARE_INFO_2 *info2;
+
+ ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
+ info2 = ctr->share.info2;
+
+ memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
+
+ /* Copy pointer crap */
+
+ memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
+
+ /* Duplicate strings */
+
+ s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_netname);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
+
+ s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_remark);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
+
+ s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_path);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
+
+ s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
+ }
+ case 502:
+ {
+ char *s;
+ SRV_SHARE_INFO_502 *info502;
+
+ ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
+ info502 = ctr->share.info502;
+
+ memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
+
+ /* Copy pointer crap */
+
+ memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
+
+ /* Duplicate strings */
+
+ s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_netname);
+ if (s)
+ init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
+
+ s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_remark);
+ if (s)
+ init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
+
+ s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_path);
+ if (s)
+ init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
+
+ s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
+ if (s)
+ init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
+
+ info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
+
+ }
+
+ } /* switch */
+
+done:
+ return result;
+}
+
/**
* List shares on a remote RPC server
*
@@ -2597,14 +2724,9 @@ rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name,
{
SRV_SHARE_INFO_CTR ctr;
WERROR result;
- ENUM_HND hnd;
- uint32 preferred_len = 0xffffffff, i;
-
- init_enum_hnd(&hnd, 0);
-
- result = cli_srvsvc_net_share_enum(
- cli, mem_ctx, 1, &ctr, preferred_len, &hnd);
+ uint32 i, level = 1;
+ result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr);
if (!W_ERROR_IS_OK(result))
goto done;
@@ -2622,6 +2744,52 @@ rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name,
return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
+/***
+ * 'net rpc share list' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+static int rpc_share_list(int argc, const char **argv)
+{
+ return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
+}
+
+static BOOL check_share_availability(struct cli_state *cli, const char *netname)
+{
+ if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
+ d_printf("skipping [%s]: not a file share.\n", netname);
+ return False;
+ }
+
+ if (!cli_tdis(cli))
+ return False;
+
+ return True;
+}
+
+static BOOL check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
+{
+ /* only support disk shares */
+ if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
+ printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
+ return False;
+ }
+
+ /* skip builtin shares */
+ /* FIXME: should print$ be added too ? */
+ if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
+ strequal(netname,"global"))
+ return False;
+
+ if (opt_exclude && in_list(netname, opt_exclude, False)) {
+ printf("excluding [%s]\n", netname);
+ return False;
+ }
+
+ return check_share_availability(cli, netname);
+}
+
/**
* Migrate shares from a remote RPC server to the local RPC srever
*
@@ -2645,24 +2813,18 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain
WERROR result;
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
SRV_SHARE_INFO_CTR ctr_src;
- ENUM_HND hnd;
- uint32 type = 0; /* only allow disk shares to be added */
- uint32 num_uses = 0, perms = 0, max_uses = 0;
+ uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
char *password = NULL; /* don't allow a share password */
- uint32 preferred_len = 0xffffffff, i;
+ uint32 i;
BOOL got_dst_srvsvc_pipe = False;
struct cli_state *cli_dst = NULL;
uint32 level = 502; /* includes secdesc */
- SEC_DESC *share_sd = NULL;
- init_enum_hnd(&hnd, 0);
-
- result = cli_srvsvc_net_share_enum(
- cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
+ result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
if (!W_ERROR_IS_OK(result))
goto done;
- /* connect local PI_SRVSVC */
+ /* connect destination PI_SRVSVC */
nt_status = connect_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
if (!NT_STATUS_IS_OK(nt_status))
return nt_status;
@@ -2680,58 +2842,24 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain
remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
rpcstr_pull_unistr2_fstring(
path, &ctr_src.share.info502[i].info_502_str.uni_path);
- num_uses = ctr_src.share.info502[i].info_502.num_uses;
- max_uses = ctr_src.share.info502[i].info_502.max_uses;
- perms = ctr_src.share.info502[i].info_502.perms;
-
-
- if (opt_acls)
- share_sd = dup_sec_desc(
- mem_ctx, ctr_src.share.info502[i].info_502_str.sd);
- /* since we do not have NetShareGetInfo implemented in samba3 we
- only can skip inside the enum-ctr_src */
- if (argc == 1) {
- char *one_share = talloc_strdup(mem_ctx, argv[0]);
- if (!strequal(netname, one_share))
- continue;
- }
-
- /* skip builtin shares */
- /* FIXME: should print$ be added too ? */
- if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
- strequal(netname,"global"))
- continue;
-
- if (opt_exclude && in_list(netname, opt_exclude, False)) {
- printf("excluding [%s]\n", netname);
+ if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
continue;
- }
- /* only work with file-shares */
- if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
- d_printf("skipping [%s]: not a file share.\n", netname);
- continue;
- }
-
- if (!cli_tdis(cli))
- goto done;
-
-
- /* finallly add the share on the dst server
- please note that samba currently does not allow to
- add a share without existing directory */
+ /* finally add the share on the dst server */
printf("migrating: [%s], path: %s, comment: %s, %s share-ACLs\n",
netname, path, remark, opt_acls ? "including" : "without" );
if (opt_verbose && opt_acls)
- display_sec_desc(share_sd);
-
- result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type,
- remark, perms, max_uses,
- num_uses, path, password,
- level, share_sd);
+ display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
+
+ result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type, remark,
+ ctr_src.share.info502[i].info_502.perms,
+ ctr_src.share.info502[i].info_502.max_uses,
+ ctr_src.share.info502[i].info_502.num_uses,
+ path, password, level,
+ opt_acls? ctr_src.share.info502[i].info_502_str.sd : NULL);
if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
printf(" [%s] does already exist\n", netname);
@@ -2962,13 +3090,12 @@ rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_
WERROR result;
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
SRV_SHARE_INFO_CTR ctr_src;
- ENUM_HND hnd;
- uint32 preferred_len = 0xffffffff, i;
- uint32 level = 2;
+ uint32 i;
+ uint32 level = 502;
struct copy_clistate cp_clistate;
BOOL got_src_share = False;
BOOL got_dst_share = False;
- pstring mask;
+ pstring mask = "\\*";
char *dst = NULL;
/* decrese argc and safe mode */
@@ -2976,57 +3103,27 @@ rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_
dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
- init_enum_hnd(&hnd, 0);
-
- result = cli_srvsvc_net_share_enum(
- cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
+ result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
if (!W_ERROR_IS_OK(result))
goto done;
for (i = 0; i < ctr_src.num_entries; i++) {
- fstring netname = "", remark = "", path = "";
+ fstring netname = "";
rpcstr_pull_unistr2_fstring(
- netname, &ctr_src.share.info2[i].info_2_str.uni_netname);
- rpcstr_pull_unistr2_fstring(
- remark, &ctr_src.share.info2[i].info_2_str.uni_remark);
- rpcstr_pull_unistr2_fstring(
- path, &ctr_src.share.info2[i].info_2_str.uni_path);
-
- /* since we do not have NetShareGetInfo implemented in samba3 we
- only can skip inside the enum-ctr_src */
- if (argc == 1) {
- char *one_share = talloc_strdup(mem_ctx, argv[0]);
- if (!strequal(netname, one_share))
- continue;
- }
+ netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
- /* skip builtin and hidden shares
- In particular, one might not want to mirror whole discs :) */
- if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$"))
+ if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
continue;
-
+
+ /* one might not want to mirror whole discs :) */
if (strequal(netname, "print$") || netname[1] == '$') {
d_printf("skipping [%s]: builtin/hidden share\n", netname);
continue;
}
- if (opt_exclude && in_list(netname, opt_exclude, False)) {
- printf("excluding [%s]\n", netname);
- continue;
- }
-
- /* only work with file-shares */
- if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
- d_printf("skipping [%s]: not a file share.\n", netname);
- continue;
- }
-
- if (!cli_tdis(cli))
- return NT_STATUS_UNSUCCESSFUL;
-
switch (cp_clistate.mode)
{
case NET_MODE_SHARE_MIGRATE:
@@ -3073,10 +3170,6 @@ rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_
goto done;
}
- /* now call the filesync */
- pstrcpy(mask, "\\*");
-
-
if (!sync_files(&cp_clistate, mask)) {
d_printf("could not handle files for share: %s\n", netname);
nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -3112,6 +3205,121 @@ static int rpc_share_migrate_files(int argc, const char **argv)
}
/**
+ * Migrate share-ACLs from a remote RPC server to the local RPC srever
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ SRV_SHARE_INFO_CTR ctr_src;
+ SRV_SHARE_INFO info;
+ uint32 i;
+ BOOL got_dst_srvsvc_pipe = False;
+ struct cli_state *cli_dst = NULL;
+ uint32 level = 502; /* includes secdesc */
+
+ result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* connect destination PI_SRVSVC */
+ nt_status = connect_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ for (i = 0; i < ctr_src.num_entries; i++) {
+
+ fstring netname = "", remark = "", path = "";
+ /* reset error-code */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ rpcstr_pull_unistr2_fstring(
+ netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
+ rpcstr_pull_unistr2_fstring(
+ remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
+ rpcstr_pull_unistr2_fstring(
+ path, &ctr_src.share.info502[i].info_502_str.uni_path);
+
+ if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
+ continue;
+
+ printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n",
+ netname, path, remark);
+
+ if (opt_verbose)
+ display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
+
+ /* init info */
+ ZERO_STRUCT(info);
+
+ info.switch_value = level;
+ info.ptr_share_ctr = 1;
+
+ /* FIXME: shouldn't we be able to just set the security descriptor ? */
+ info.share.info502 = ctr_src.share.info502[i];
+
+ /* finally modify the share on the dst server */
+ result = cli_srvsvc_net_share_set_info(cli_dst, mem_ctx, netname, level, &info);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot set share-acl: %s\n", dos_errstr(result));
+ goto done;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (got_dst_srvsvc_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+
+ return nt_status;
+
+}
+
+/**
+ * Migrate share-acls from a rpc-server to another
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_share_migrate_security(int argc, const char **argv)
+{
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SRVSVC, 0,
+ rpc_share_migrate_security_internals,
+ argc, argv);
+}
+
+/**
* Migrate shares (including share-definitions, share-acls and files with acls/attrs)
* from one server to another
*
@@ -3131,15 +3339,18 @@ static int rpc_share_migrate_all(int argc, const char **argv)
return -1;
}
+ /* order is important. we don't want to be locked out by the share-acl
+ * before copying files - gd */
+
ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
if (ret)
return ret;
-#if 0
- ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_security_internals, argc, argv);
+
+ ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
if (ret)
return ret;
-#endif
- return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
+
+ return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
}
@@ -3156,7 +3367,7 @@ static int rpc_share_migrate(int argc, const char **argv)
{"all", rpc_share_migrate_all},
{"files", rpc_share_migrate_files},
{"help", rpc_share_usage},
-/* {"security", rpc_share_migrate_security},*/
+ {"security", rpc_share_migrate_security},
{"shares", rpc_share_migrate_shares},
{NULL, NULL}
};
@@ -3169,7 +3380,7 @@ static int rpc_share_migrate(int argc, const char **argv)
struct full_alias {
DOM_SID sid;
- int num_members;
+ uint32 num_members;
DOM_SID *members;
};
@@ -3951,6 +4162,7 @@ int net_rpc_share(int argc, const char **argv)
{"delete", rpc_share_delete},
{"allowedusers", rpc_share_allowedusers},
{"migrate", rpc_share_migrate},
+ {"list", rpc_share_list},
{NULL, NULL}
};