1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00

r1692: first commit :)

* add IA64 to the architecture table of printer-drivers

* add new "net"-subcommands:

  net rpc printer migrate {drivers|printers|forms|security|settings|all}
        [printer]
  net rpc share migrate {shares|files|all} [share]

  this is the first part of the migration suite. this will will (once
  feature-complete) allow to do 1:1 server-cloning in the best possible way by
  making heavy use of samba's rpc_client-functions. all migration-steps
  are implemented as rpc/smb-client-calls; net communicates via rpc/smb
  with two servers at the same time (a remote, source server and a
  destination server that currently defaults to the local smbd). this
  allows e. g. printer-driver migration including driverfiles, recursive
  mirroring of file-shares including file-acls, etc. almost any migration
  step can be called with a migrate-subcommand to provide more flexibility
  during a migration process (at the cost of quite some redundancy :) ).

  "net rpc printer migrate settings" is still in a bad condition (many
  open questions that hopefully can be adressed soon).

  "net rpc share migrate security" as an isolated call to just migrate
  share-ACLs will be added later.

  Before playing with it, make sure to use a test-server. Migration is a
  serious business and this tool-set can perfectly overwrite your
  existing file/print-shares.

* along with the migration functions had to make I the following
  changes:

        - implement setprinter level 3 client-side

        - implement net_add_share level 502 client-side

        - allow security descriptor to be set in setprinterdata level 2
          serverside

guenther
(This used to be commit 8f1716a29b7e85baf738bc14df7dabf03762f723)
This commit is contained in:
Günther Deschner 2004-08-10 14:27:17 +00:00 committed by Gerald (Jerry) Carter
parent 16de9d9711
commit 60727acc3b
12 changed files with 3052 additions and 26 deletions

View File

@ -533,7 +533,7 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \
utils/net_status.o
utils/net_status.o utils/net_rpc_printer.o
NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \

View File

@ -209,6 +209,7 @@ struct table_node {
#define SPL_ARCH_W32MIPS "W32MIPS"
#define SPL_ARCH_W32ALPHA "W32ALPHA"
#define SPL_ARCH_W32PPC "W32PPC"
#define SPL_ARCH_IA64 "IA64"
static const struct table_node archi_table[]= {
@ -217,6 +218,7 @@ static const struct table_node archi_table[]= {
{"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
{"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
{"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
{"Windows IA64", SPL_ARCH_IA64, 3 },
{NULL, "", -1 }
};

View File

@ -269,7 +269,8 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
const char *netname, uint32 type,
const char *remark, uint32 perms,
uint32 max_uses, uint32 num_uses,
const char *path, const char *passwd)
const char *path, const char *passwd,
int level, SEC_DESC *sd)
{
prs_struct qbuf, rbuf;
SRV_Q_NET_SHARE_ADD q;
@ -285,7 +286,8 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark,
perms, max_uses, num_uses, path, passwd);
perms, max_uses, num_uses, path, passwd,
level, sd);
/* Marshall data and send request */

View File

@ -1053,6 +1053,28 @@ BOOL make_spoolss_printer_info_2(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2
return True;
}
/*******************************************************************
create a SPOOL_PRINTER_INFO_3 struct from a PRINTER_INFO_3 struct
*******************************************************************/
BOOL make_spoolss_printer_info_3(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3 **spool_info3,
PRINTER_INFO_3 *info)
{
SPOOL_PRINTER_INFO_LEVEL_3 *inf;
/* allocate the necessary memory */
if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_3*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_3)))) {
DEBUG(0,("make_spoolss_printer_info_3: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_3 sruct!\n"));
return False;
}
inf->secdesc_ptr = (info->secdesc!=NULL)?1:0;
*spool_info3 = inf;
return True;
}
/*******************************************************************
* read a structure.
@ -4112,6 +4134,20 @@ BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u,
q_u->devmode_ctr.size = 0;
q_u->devmode_ctr.devmode = NULL;
#endif
break;
case 3:
secdesc = info->printers_3->secdesc;
make_spoolss_printer_info_3 (mem_ctx, &q_u->info.info_3, info->printers_3);
q_u->secdesc_ctr = (SEC_DESC_BUF*)malloc(sizeof(SEC_DESC_BUF));
if (!q_u->secdesc_ctr)
return False;
q_u->secdesc_ctr->ptr = (secdesc != NULL) ? 1: 0;
q_u->secdesc_ctr->max_len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
q_u->secdesc_ctr->len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
q_u->secdesc_ctr->sec = secdesc;
break;
default:
DEBUG(0,("make_spoolss_q_setprinter: Unknown info level [%d]\n", level));

View File

@ -1456,12 +1456,29 @@ BOOL srv_io_q_net_share_add(const char *desc, SRV_Q_NET_SHARE_ADD *q_n, prs_stru
void init_srv_q_net_share_add(SRV_Q_NET_SHARE_ADD *q, const char *srvname,
const char *netname, uint32 type, const char *remark,
uint32 perms, uint32 max_uses, uint32 num_uses,
const char *path, const char *passwd)
const char *path, const char *passwd,
int level, SEC_DESC *sd)
{
switch(level) {
case 502: {
size_t sd_size = sec_desc_size(sd);
q->ptr_srv_name = 1;
init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
q->info.switch_value = q->info_level = 2;
q->info.switch_value = q->info_level = level;
q->info.ptr_share_ctr = 1;
init_srv_share_info502(&q->info.share.info502.info_502, netname, type,
remark, perms, max_uses, num_uses, path, passwd, sd, sd_size);
init_srv_share_info502_str(&q->info.share.info502.info_502_str, netname,
remark, path, passwd, sd, sd_size);
q->ptr_err_index = 1;
q->err_index = 0;
}
break;
case 2:
default:
q->ptr_srv_name = 1;
init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
q->info.switch_value = q->info_level = level;
q->info.ptr_share_ctr = 1;
init_srv_share_info2(&q->info.share.info2.info_2, netname, type,
remark, perms, max_uses, num_uses, path, passwd);
@ -1469,6 +1486,8 @@ void init_srv_q_net_share_add(SRV_Q_NET_SHARE_ADD *q, const char *srvname,
remark, path, passwd);
q->ptr_err_index = 1;
q->err_index = 0;
break;
}
}

View File

@ -1972,6 +1972,7 @@ static int get_version_id (char * arch)
{"Windows NT R4000", "W32MIPS", 2 },
{"Windows NT Alpha_AXP", "W32ALPHA", 2 },
{"Windows NT PowerPC", "W32PPC", 2 },
{"Windows IA64", "IA64", 3 },
{NULL, "", -1 }
};
@ -6220,6 +6221,7 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET
DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
uint32 command = q_u->command;
WERROR result;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
@ -6233,7 +6235,12 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET
case 0:
return control_printer(handle, command, p);
case 2:
return update_printer(p, handle, level, info, devmode_ctr.devmode);
result = update_printer(p, handle, level, info, devmode_ctr.devmode);
if (!W_ERROR_IS_OK(result))
return result;
if (secdesc_ctr)
result = update_printer_sec(handle, level, info, p, secdesc_ctr);
return result;
case 3:
return update_printer_sec(handle, level, info, p,
secdesc_ctr);

View File

@ -39,6 +39,7 @@ static const struct table_node archi_table[]= {
{"Windows NT R4000", "W32MIPS", 2 },
{"Windows NT Alpha_AXP", "W32ALPHA", 2 },
{"Windows NT PowerPC", "W32PPC", 2 },
{"Windows IA64", "IA64", 3 },
{NULL, "", -1 }
};
@ -1126,6 +1127,13 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
cli, mem_ctx, needed, NULL, info_level,
archi_table[i].long_archi, &returned, &ctr);
if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
printf ("Server does not support environment [%s]\n",
archi_table[i].long_archi);
werror = WERR_OK;
continue;
}
if (returned == 0)
continue;

View File

@ -78,6 +78,8 @@ BOOL opt_localgroup = False;
BOOL opt_domaingroup = False;
const char *opt_newntname = "";
int opt_rid = 0;
int opt_acls = 0;
const char *opt_exclude = NULL;
BOOL opt_have_ip = False;
struct in_addr opt_dest_ip;
@ -126,12 +128,13 @@ int net_run_function(int argc, const char **argv, struct functable *table,
return usage_fn(argc, argv);
}
/****************************************************************************
connect to \\server\ipc$
connect to \\server\service
****************************************************************************/
NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
const char *server_name)
NTSTATUS connect_to_service(struct cli_state **c, struct in_addr *server_ip,
const char *server_name,
const char *service_name,
const char *service_type)
{
NTSTATUS nt_status;
@ -144,7 +147,7 @@ NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
nt_status = cli_full_connection(c, NULL, server_name,
server_ip, opt_port,
"IPC$", "IPC",
service_name, service_type,
opt_user_name, opt_workgroup,
opt_password, 0, Undefined, NULL);
@ -171,6 +174,16 @@ NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
}
}
/****************************************************************************
connect to \\server\ipc$
****************************************************************************/
NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
const char *server_name)
{
return connect_to_service(c, server_ip, server_name, "IPC$", "IPC");
}
/****************************************************************************
connect to \\server\ipc$ anonymously
****************************************************************************/
@ -193,6 +206,40 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
}
}
/**
* Connect the local server and open a given pipe
*
* @param cli_local A cli_state to the local spoolss-server
* @param pipe The pipe to open
* @param got_pipe boolean to that stores if got a pipe
*
* @return Normal NTSTATUS return.
**/
NTSTATUS connect_local_pipe(struct cli_state **cli_local, int pipe, BOOL *got_pipe)
{
NTSTATUS nt_status;
extern struct in_addr loopback_ip;
char *server_name = strdup("127.0.0.1");
struct cli_state *cli_tmp = NULL;
/* make a connection to smbd via loopback */
nt_status = connect_to_ipc(&cli_tmp, &loopback_ip, server_name);
if (!NT_STATUS_IS_OK(nt_status))
return nt_status;
if (!cli_nt_session_open(cli_tmp, pipe)) {
DEBUG(0, ("couldn't not initialise spoolss pipe\n"));
cli_shutdown(cli_tmp);
return NT_STATUS_UNSUCCESSFUL;
}
*cli_local = cli_tmp;
*got_pipe = True;
return nt_status;
}
/****************************************************************************
Use the local machine's password for this session
****************************************************************************/
@ -690,6 +737,9 @@ static struct functable net_func[] = {
{"domain", 'D', POPT_ARG_NONE, &opt_domaingroup},
{"ntname", 'N', POPT_ARG_STRING, &opt_newntname},
{"rid", 'R', POPT_ARG_INT, &opt_rid},
/* Options for 'net rpc share migrate' */
{"acls", 'a', POPT_ARG_NONE, &opt_acls},
{"exclude", 'e', POPT_ARG_STRING, &opt_exclude},
POPT_COMMON_SAMBA
{ 0, 0, 0, 0}

View File

@ -62,6 +62,8 @@ extern BOOL opt_localgroup;
extern BOOL opt_domaingroup;
extern const char *opt_newntname;
extern int opt_rid;
extern int opt_acls;
extern const char *opt_exclude;
extern BOOL opt_have_ip;
extern struct in_addr opt_dest_ip;

View File

@ -122,13 +122,25 @@ int net_help_share(int argc, const char **argv)
"on target server\n\n"
"net [<method>] share ADD <name=serverpath> [misc. options] [targets]"
"\n\tAdds a share from a server (makes the export active)\n\n"
"net [<method>] share DELETE <sharename> [misc. options] [targets]\n"
"\n\tDeletes a share from a server (makes the export inactive)\n");
"net [<method>] share DELETE <sharename> [misc. options] [targets]"
"\n\tDeletes a share from a server (makes the export inactive)\n\n"
"net [<method>] share MIGRATE FILES <sharename> [misc. options] [targets]"
"\n\tMigrates files from remote to local server\n\n"
"net [<method>] share MIGRATE SHARES <sharename> [misc. options] [targets]"
"\n\tMigrates shares from remote to local server\n\n"
/* "net [<method>] share MIGRATE SECURITY <sharename> [misc. options] [targets]"
"\n\tMigrates share-ACLs from remote to local server\n\n" */
"net [<method>] share MIGRATE ALL <sharename> [misc. options] [targets]"
"\n\tMigrates shares (including directories, files) from remote\n"
"\tto local server\n\n"
);
net_common_methods_usage(argc, argv);
net_common_flags_usage(argc, argv);
d_printf(
"\t-C or --comment=<comment>\tdescriptive comment (for add only)\n"
"\t-M or --maxusers=<num>\t\tmax users allowed for share\n");
"\t-M or --maxusers=<num>\t\tmax users allowed for share\n"
"\t-a or --acls\t\t\tcopies ACLs as well\n"
"\t-e or --exclude\t\t\tlist of shares to be excluded from mirroring\n");
return -1;
}
@ -149,6 +161,31 @@ int net_help_file(int argc, const char **argv)
return -1;
}
int net_help_printer(int argc, const char **argv)
{
d_printf("net rpc printer LIST [printer]\n"\
"\tlists all printers on print-server\n\n");
d_printf("net rpc printer DRIVER [printer]\n"\
"\tlists all printer-drivers on print-server\n\n");
d_printf("net rpc printer MIGRATE PRINTERS [printer]"\
"\n\tmigrates printers from remote to local server\n\n");
d_printf("net rpc printer MIGRATE SETTINGS [printer]"\
"\n\tmigrates printer-settings from remote to local server\n\n");
d_printf("net rpc printer MIGRATE DRIVERS [printer]"\
"\n\tmigrates printer-drivers from remote to local server\n\n");
d_printf("net rpc printer MIGRATE FORMS [printer]"\
"\n\tmigrates printer-forms from remote to local server\n\n");
d_printf("net rpc printer MIGRATE SECURITY [printer]"\
"\n\tmigrates printer-ACLs from remote to local server\n\n");
d_printf("net rpc printer MIGRATE ALL [printer]\n"\
"\tmigrates drivers, forms, queues, settings and acls from\n"\
"\tremote to local print-server\n\n");
net_common_methods_usage(argc, argv);
net_common_flags_usage(argc, argv);
return -1;
}
int net_help_status(int argc, const char **argv)
{
d_printf(" net status sessions [parseable] "

View File

@ -2351,6 +2351,7 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
uint32 type=0; /* 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;
path = strchr(sharename, '=');
if (!path)
@ -2359,7 +2360,8 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
result = cli_srvsvc_net_share_add(cli, mem_ctx, sharename, type,
opt_comment, perms, opt_maxusers,
num_users, path, password);
num_users, path, password,
level, NULL);
return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
@ -2491,6 +2493,458 @@ 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;
}
/**
* Migrate shares 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_shares_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;
ENUM_HND hnd;
uint32 type = 0; /* only allow disk shares to be added */
uint32 num_uses = 0, perms = 0, max_uses = 0;
char *password = NULL; /* don't allow a share password */
uint32 preferred_len = 0xffffffff, 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);
if (!W_ERROR_IS_OK(result))
goto done;
/* connect local PI_SRVSVC */
nt_status = connect_local_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);
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;
/* 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 */
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);
if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
printf("share does already exist\n");
continue;
}
if (!W_ERROR_IS_OK(result)) {
printf("cannot add share: %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 shares 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_shares(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SRVSVC, 0,
rpc_share_migrate_shares_internals,
argc, argv);
}
typedef struct copy_clistate {
TALLOC_CTX *mem_ctx;
struct cli_state *cli_share_src;
struct cli_state *cli_share_dst;
const char *cwd;
} copy_clistate;
/**
* Copy a file/dir
*
* @param f file_info
* @param mask current search mask
* @param state arg-pointer
*
**/
static void copy_fn(file_info *f, const char *mask, void *state)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct copy_clistate *local_state = (struct copy_clistate *)state;
fstring filename, new_mask, dir;
if (strequal(f->name, ".") || strequal(f->name, ".."))
return;
DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
/* DIRECTORY */
if (f->mode & aDIR) {
DEBUG(3,("got dir: %s\n", f->name));
fstrcpy(dir, local_state->cwd);
fstrcat(dir, "\\");
fstrcat(dir, f->name);
/* create that directory */
nt_status = net_copy_file(local_state->mem_ctx,
local_state->cli_share_src,
local_state->cli_share_dst,
dir, dir,
opt_acls? True : False, False);
if (!NT_STATUS_IS_OK(nt_status))
printf("could not copy dir %s: %s\n",
dir, nt_errstr(nt_status));
/* search below that directory */
fstrcpy(new_mask, dir);
fstrcat(new_mask, "\\*");
if (!sync_files(local_state->mem_ctx,
local_state->cli_share_src,
local_state->cli_share_dst,
new_mask, dir))
printf("could not sync files\n");
return;
}
/* FILE */
fstrcpy(filename, local_state->cwd);
fstrcat(filename, "\\");
fstrcat(filename, f->name);
DEBUG(3,("got file: %s\n", filename));
nt_status = net_copy_file(local_state->mem_ctx,
local_state->cli_share_src,
local_state->cli_share_dst,
filename, filename,
opt_acls? True : False, True);
if (!NT_STATUS_IS_OK(nt_status))
printf("could not copy file %s: %s\n",
filename, nt_errstr(nt_status));
}
/**
* sync files, can be called recursivly to list files
* and then call copy_fn for each file
*
* @param mem_ctx TALLOC_CTX
* @param cli_share_src a connected share on the originating server
* @param cli_share_dst a connected share on the destination server
* @param mask the current search mask
* @param cwd the current path
*
* @return Boolean result
**/
BOOL sync_files(TALLOC_CTX *mem_ctx,
struct cli_state *cli_share_src,
struct cli_state *cli_share_dst,
pstring mask, fstring cwd)
{
uint16 attribute = aSYSTEM | aHIDDEN | aDIR;
struct copy_clistate clistate;
clistate.mem_ctx = mem_ctx;
clistate.cli_share_src = cli_share_src;
clistate.cli_share_dst = cli_share_dst;
clistate.cwd = cwd;
DEBUG(3,("calling cli_list with mask: %s\n", mask));
if (cli_list(cli_share_src, mask, attribute, copy_fn, &clistate) == -1) {
d_printf("listing %s failed with error: %s\n",
mask, cli_errstr(cli_share_src));
return False;
}
return True;
}
/**
* Sync all files inside a remote share to another share (over smb)
*
* 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_files_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;
ENUM_HND hnd;
uint32 preferred_len = 0xffffffff, i;
uint32 level = 2;
struct cli_state *cli_share_src = NULL;
struct cli_state *cli_share_dst = NULL;
BOOL got_src_share = False;
BOOL got_dst_share = False;
pstring mask;
extern struct in_addr loopback_ip;
init_enum_hnd(&hnd, 0);
result = cli_srvsvc_net_share_enum(
cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
if (!W_ERROR_IS_OK(result))
goto done;
for (i = 0; i < ctr_src.num_entries; i++) {
fstring netname = "", remark = "", path = "";
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;
}
/* skip builtin and hidden shares
In particular, one might not want to mirror whole discs :) */
if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$"))
continue;
if (strequal(netname, "print$") || netname[1] == '$') {
d_printf("skipping [%s]: builtin/hidden share\n", netname);
continue;
}
if (opt_exclude && in_list(netname, (char *)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;
printf("syncing [%s] files and directories %s ACLs\n",
netname, opt_acls ? "including" : "without");
/* open share source */
nt_status = connect_to_service(&cli_share_src, &cli->dest_ip,
cli->desthost, netname, "A:");
if (!NT_STATUS_IS_OK(nt_status))
goto done;
got_src_share = True;
/* open share destination */
nt_status = connect_to_service(&cli_share_dst, &loopback_ip,
"127.0.0.1", netname, "A:");
if (!NT_STATUS_IS_OK(nt_status))
goto done;
got_dst_share = True;
/* now call the filesync */
pstrcpy(mask, "\\*");
if (!sync_files(mem_ctx, cli_share_src, cli_share_dst, mask, NULL)) {
d_printf("could not sync files for share: %s\n", netname);
nt_status = NT_STATUS_UNSUCCESSFUL;
goto done;
}
}
nt_status = NT_STATUS_OK;
done:
if (got_src_share)
cli_shutdown(cli_share_src);
if (got_dst_share)
cli_shutdown(cli_share_dst);
return nt_status;
}
static int rpc_share_migrate_files(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SRVSVC, 0,
rpc_share_migrate_files_internals,
argc, argv);
}
/**
* Migrate shares (including share-definitions, share-acls and files with acls)
* from one 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_all(int argc, const char **argv)
{
int ret;
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);
if (ret)
return ret;
#endif
return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
}
/**
* 'net rpc share migrate' entrypoint.
* @param argc Standard main() style argc
* @param argv Standard main() style argv. Initial components are already
* stripped
**/
static int rpc_share_migrate(int argc, const char **argv)
{
struct functable func[] = {
{"all", rpc_share_migrate_all},
{"files", rpc_share_migrate_files},
/* {"security", rpc_share_migrate_security},*/
{"shares", rpc_share_migrate_shares},
{NULL, NULL}
};
return net_run_function(argc, argv, func, rpc_share_usage);
}
/**
* 'net rpc share' entrypoint.
* @param argc Standard main() style argc
@ -2503,6 +2957,7 @@ int net_rpc_share(int argc, const char **argv)
struct functable func[] = {
{"add", rpc_share_add},
{"delete", rpc_share_delete},
{"migrate", rpc_share_migrate},
{NULL, NULL}
};
@ -3570,6 +4025,227 @@ static int rpc_vampire(int argc, const char **argv) {
return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
argc, argv);
}
/**
* Migrate everything from a print-server
*
* @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)
*
* The order is important !
* To successfully add drivers the print-queues have to exist !
* Applying ACLs should be the last step, because you're easily locked out
*
**/
static int rpc_printer_migrate_all(int argc, const char **argv)
{
int ret;
ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
if (ret)
return ret;
ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
if (ret)
return ret;
ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
if (ret)
return ret;
ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
if (ret)
return ret;
return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
}
/**
* Migrate print-drivers from a print-server
*
* @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_printer_migrate_drivers(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_migrate_drivers_internals,
argc, argv);
}
/**
* Migrate print-forms from a print-server
*
* @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_printer_migrate_forms(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_migrate_forms_internals,
argc, argv);
}
/**
* Migrate printers from a print-server
*
* @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_printer_migrate_printers(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_migrate_printers_internals,
argc, argv);
}
/**
* Migrate printer-ACLs from a print-server
*
* @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_printer_migrate_security(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_migrate_security_internals,
argc, argv);
}
/**
* Migrate printer-settings from a print-server
*
* @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_printer_migrate_settings(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_migrate_settings_internals,
argc, argv);
}
/**
* 'net rpc printer' entrypoint.
* @param argc Standard main() style argc
* @param argv Standard main() style argv. Initial components are already
* stripped
**/
int rpc_printer_migrate(int argc, const char **argv)
{
/* ouch: when addriver and setdriver are called from within
rpc_printer_migrate_drivers_internals, the printer-queue already
*has* to exist */
struct functable func[] = {
{"all", rpc_printer_migrate_all},
{"drivers", rpc_printer_migrate_drivers},
{"forms", rpc_printer_migrate_forms},
{"help", rpc_printer_usage},
{"printers", rpc_printer_migrate_printers},
{"security", rpc_printer_migrate_security},
{"settings", rpc_printer_migrate_settings},
{NULL, NULL}
};
return net_run_function(argc, argv, func, rpc_printer_usage);
}
/**
* List printers on a remote RPC server
*
* @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_printer_list(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_list_internals,
argc, argv);
}
/**
* List printer-drivers on a remote RPC server
*
* @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_printer_driver_list(int argc, const char **argv)
{
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_driver_list_internals,
argc, argv);
}
/**
* Display rpc printer help page.
* @param argc Standard main() style argc
* @param argv Standard main() style argv. Initial components are already
* stripped
**/
int rpc_printer_usage(int argc, const char **argv)
{
return net_help_printer(argc, argv);
}
/**
* 'net rpc printer' entrypoint.
* @param argc Standard main() style argc
* @param argv Standard main() style argv. Initial components are already
* stripped
**/
int net_rpc_printer(int argc, const char **argv)
{
struct functable func[] = {
{"list", rpc_printer_list},
{"migrate", rpc_printer_migrate},
{"driver", rpc_printer_driver_list},
{NULL, NULL}
};
if (argc == 0)
return run_rpc_command(NULL, PI_SPOOLSS, 0,
rpc_printer_list_internals,
argc, argv);
return net_run_function(argc, argv, func, rpc_printer_usage);
}
/****************************************************************************/
@ -3590,6 +4266,7 @@ int net_rpc_usage(int argc, const char **argv)
d_printf(" net rpc password <username> [<password>] -Uadmin_username%%admin_pass");
d_printf(" net rpc group \t\tto list groups\n");
d_printf(" net rpc share \t\tto add, delete, and list shares\n");
d_printf(" net rpc printer \t\tto list and migrate printers\n");
d_printf(" net rpc file \t\t\tto list open files\n");
d_printf(" net rpc changetrustpw \tto change the trust account password\n");
d_printf(" net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
@ -3659,6 +4336,7 @@ int net_rpc(int argc, const char **argv)
{"group", net_rpc_group},
{"share", net_rpc_share},
{"file", net_rpc_file},
{"printer", net_rpc_printer},
{"changetrustpw", net_rpc_changetrustpw},
{"trustdom", rpc_trustdom},
{"abortshutdown", rpc_shutdown_abort},

File diff suppressed because it is too large Load Diff