1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

r7632: Cleanup "net share migrate"-code.

* Allow to copy share security descriptors to already existing shares
  separatly.

* Added abstraction function to enum all or a single share info

Guenther
(This used to be commit 97097497ae42d7a03286bbe16bcffb8224137688)
This commit is contained in:
Günther Deschner 2005-06-16 09:36:53 +00:00 committed by Gerald (Jerry) Carter
parent b162a396fe
commit 75545d578e
3 changed files with 395 additions and 121 deletions

View File

@ -267,6 +267,63 @@ WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli,
info->switch_value = info_level;
switch(info_level) {
case 1:
{
SRV_SHARE_INFO_1 *info1 = &info->share.info1;
SH_INFO_1_STR *info1_str = &info1->info_1_str;
char *s;
info->share.info1 = r.info.share.info1;
/* Duplicate strings */
s = unistr2_tdup(mem_ctx, &info1_str->uni_netname);
if (s)
init_unistr2(&info1_str->uni_netname,
s, UNI_STR_TERMINATE);
s = unistr2_tdup(mem_ctx, &info1_str->uni_remark);
if (s)
init_unistr2(&info1_str->uni_remark,
s, UNI_STR_TERMINATE);
break;
}
case 2:
{
SRV_SHARE_INFO_2 *info2 = &info->share.info2;
SH_INFO_2_STR *info2_str = &info2->info_2_str;
char *s;
info->share.info2 = r.info.share.info2;
/* Duplicate strings */
s = unistr2_tdup(mem_ctx, &info2_str->uni_netname);
if (s)
init_unistr2(&info2_str->uni_netname,
s, UNI_STR_TERMINATE);
s = unistr2_tdup(mem_ctx, &info2_str->uni_remark);
if (s)
init_unistr2(&info2_str->uni_remark,
s, UNI_STR_TERMINATE);
s = unistr2_tdup(mem_ctx, &info2_str->uni_path);
if (s)
init_unistr2(&info2_str->uni_path,
s, UNI_STR_TERMINATE);
s = unistr2_tdup(mem_ctx, &info2_str->uni_passwd);
if (s)
init_unistr2(&info2_str->uni_passwd,
s, UNI_STR_TERMINATE);
break;
}
case 502:
{
SRV_SHARE_INFO_502 *info502 = &info->share.info502;

View File

@ -260,6 +260,11 @@ static void display_share_info_502(SRV_SHARE_INFO_502 *info502)
printf("\tpath:\t%s\n", path);
printf("\tpassword:\t%s\n", passwd);
printf("\ttype:\t0x%x\n", info502->info_502.type);
printf("\tperms:\t%d\n", info502->info_502.perms);
printf("\tmax_uses:\t%d\n", info502->info_502.max_uses);
printf("\tnum_uses:\t%d\n", info502->info_502.num_uses);
if (info502->info_502_str.sd)
display_sec_desc(info502->info_502_str.sd);

View File

@ -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"))
if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
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))
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);
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, perms, max_uses,
num_uses, path, password,
level, share_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);
netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
/* 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 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;
@ -3111,6 +3204,121 @@ static int rpc_share_migrate_files(int argc, const char **argv)
argc, 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}
};