Line data Source code
1 : /*
2 : Samba Unix/Linux SMB client library
3 : Distributed SMB/CIFS Server Management Utility
4 : Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5 : Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6 : Copyright (C) 2004,2008 Guenther Deschner (gd@samba.org)
7 : Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8 : Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 :
23 : #include "includes.h"
24 : #include "utils/net.h"
25 : #include "libsmb/namequery.h"
26 : #include "rpc_client/cli_pipe.h"
27 : #include "../libcli/auth/libcli_auth.h"
28 : #include "../librpc/gen_ndr/ndr_samr_c.h"
29 : #include "rpc_client/cli_samr.h"
30 : #include "rpc_client/init_samr.h"
31 : #include "../librpc/gen_ndr/ndr_lsa_c.h"
32 : #include "rpc_client/cli_lsarpc.h"
33 : #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 : #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
35 : #include "../librpc/gen_ndr/ndr_spoolss.h"
36 : #include "../librpc/gen_ndr/ndr_initshutdown_c.h"
37 : #include "../librpc/gen_ndr/ndr_winreg_c.h"
38 : #include "secrets.h"
39 : #include "lib/netapi/netapi.h"
40 : #include "lib/netapi/netapi_net.h"
41 : #include "librpc/gen_ndr/libnet_join.h"
42 : #include "libnet/libnet_join.h"
43 : #include "rpc_client/init_lsa.h"
44 : #include "../libcli/security/security.h"
45 : #include "libsmb/libsmb.h"
46 : #include "clirap2.h"
47 : #include "nsswitch/libwbclient/wbclient.h"
48 : #include "passdb.h"
49 : #include "../libcli/smb/smbXcli_base.h"
50 : #include "libsmb/dsgetdcname.h"
51 : #include "lib/util/string_wrappers.h"
52 :
53 : static int net_mode_share;
54 : static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
55 :
56 : /**
57 : * @file net_rpc.c
58 : *
59 : * @brief RPC based subcommands for the 'net' utility.
60 : *
61 : * This file should contain much of the functionality that used to
62 : * be found in rpcclient, except that the commands should change
63 : * less often, and the functionality should be sane (the user is not
64 : * expected to know a rid/sid before they conduct an operation etc.)
65 : *
66 : * @todo Perhaps eventually these should be split out into a number
67 : * of files, as this could get quite big.
68 : **/
69 :
70 :
71 : /**
72 : * Many of the RPC functions need the domain sid. This function gets
73 : * it at the start of every run
74 : *
75 : * @param cli A cli_state already connected to the remote machine
76 : *
77 : * @return The Domain SID of the remote machine.
78 : **/
79 :
80 140 : NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
81 : struct dom_sid **domain_sid,
82 : const char **domain_name)
83 : {
84 140 : struct rpc_pipe_client *lsa_pipe = NULL;
85 : struct policy_handle pol;
86 : NTSTATUS status, result;
87 140 : union lsa_PolicyInformation *info = NULL;
88 : struct dcerpc_binding_handle *b;
89 :
90 140 : status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
91 : &lsa_pipe);
92 140 : if (!NT_STATUS_IS_OK(status)) {
93 0 : d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
94 0 : return status;
95 : }
96 :
97 140 : b = lsa_pipe->binding_handle;
98 :
99 140 : status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
100 : SEC_FLAG_MAXIMUM_ALLOWED,
101 : &pol);
102 140 : if (!NT_STATUS_IS_OK(status)) {
103 0 : d_fprintf(stderr, "open_policy %s: %s\n",
104 : _("failed"),
105 : nt_errstr(status));
106 0 : return status;
107 : }
108 :
109 140 : status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
110 : &pol,
111 : LSA_POLICY_INFO_ACCOUNT_DOMAIN,
112 : &info,
113 : &result);
114 140 : if (any_nt_status_not_ok(status, result, &status)) {
115 0 : d_fprintf(stderr, "lsaquery %s: %s\n",
116 : _("failed"),
117 : nt_errstr(status));
118 0 : return status;
119 : }
120 :
121 140 : *domain_name = info->account_domain.name.string;
122 140 : *domain_sid = info->account_domain.sid;
123 :
124 140 : dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
125 140 : TALLOC_FREE(lsa_pipe);
126 :
127 140 : return NT_STATUS_OK;
128 : }
129 :
130 : /**
131 : * Run a single RPC command, from start to finish.
132 : *
133 : * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
134 : * @param conn_flag a NET_FLAG_ combination. Passed to
135 : * net_make_ipc_connection.
136 : * @param argc Standard main() style argc.
137 : * @param argv Standard main() style argv. Initial components are already
138 : * stripped.
139 : * @return A shell status integer (0 for success).
140 : */
141 :
142 140 : int run_rpc_command(struct net_context *c,
143 : struct cli_state *cli_arg,
144 : const struct ndr_interface_table *table,
145 : int conn_flags,
146 : rpc_command_fn fn,
147 : int argc,
148 : const char **argv)
149 : {
150 140 : struct cli_state *cli = NULL;
151 140 : struct rpc_pipe_client *pipe_hnd = NULL;
152 : TALLOC_CTX *mem_ctx;
153 : NTSTATUS nt_status;
154 : struct dom_sid *domain_sid;
155 : const char *domain_name;
156 140 : int ret = -1;
157 :
158 : /* make use of cli_state handed over as an argument, if possible */
159 140 : if (!cli_arg) {
160 140 : nt_status = net_make_ipc_connection(c, conn_flags, &cli);
161 140 : if (!NT_STATUS_IS_OK(nt_status)) {
162 0 : DEBUG(1, ("failed to make ipc connection: %s\n",
163 : nt_errstr(nt_status)));
164 0 : return -1;
165 : }
166 : } else {
167 0 : cli = cli_arg;
168 : }
169 :
170 140 : if (!cli) {
171 0 : return -1;
172 : }
173 :
174 : /* Create mem_ctx */
175 :
176 140 : if (!(mem_ctx = talloc_init("run_rpc_command"))) {
177 0 : DEBUG(0, ("talloc_init() failed\n"));
178 0 : goto fail;
179 : }
180 :
181 140 : nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
182 : &domain_name);
183 140 : if (!NT_STATUS_IS_OK(nt_status)) {
184 0 : goto fail;
185 : }
186 :
187 140 : if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
188 140 : if (lp_client_schannel()
189 140 : && (ndr_syntax_id_equal(&table->syntax_id,
190 0 : &ndr_table_netlogon.syntax_id))) {
191 0 : const char *remote_name =
192 0 : smbXcli_conn_remote_name(cli->conn);
193 0 : const struct sockaddr_storage *remote_sockaddr =
194 0 : smbXcli_conn_remote_sockaddr(cli->conn);
195 :
196 : /* Always try and create an schannel netlogon pipe. */
197 0 : TALLOC_FREE(c->netlogon_creds);
198 0 : nt_status = cli_rpc_pipe_open_schannel(
199 : cli, c->msg_ctx, table, NCACN_NP,
200 : domain_name,
201 : remote_name,
202 : remote_sockaddr,
203 : &pipe_hnd, c, &c->netlogon_creds);
204 0 : if (!NT_STATUS_IS_OK(nt_status)) {
205 0 : DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
206 : nt_errstr(nt_status) ));
207 0 : goto fail;
208 : }
209 : } else {
210 140 : if (conn_flags & NET_FLAGS_SEAL) {
211 0 : nt_status = cli_rpc_pipe_open_with_creds(
212 : cli, table,
213 0 : (conn_flags & NET_FLAGS_TCP) ?
214 : NCACN_IP_TCP : NCACN_NP,
215 : DCERPC_AUTH_TYPE_NTLMSSP,
216 : DCERPC_AUTH_LEVEL_PRIVACY,
217 0 : smbXcli_conn_remote_name(cli->conn),
218 0 : smbXcli_conn_remote_sockaddr(cli->conn),
219 : c->creds, &pipe_hnd);
220 : } else {
221 140 : nt_status = cli_rpc_pipe_open_noauth(
222 : cli, table,
223 : &pipe_hnd);
224 : }
225 140 : if (!NT_STATUS_IS_OK(nt_status)) {
226 0 : DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
227 : table->name,
228 : nt_errstr(nt_status) ));
229 0 : goto fail;
230 : }
231 : }
232 : }
233 :
234 140 : nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
235 :
236 140 : if (!NT_STATUS_IS_OK(nt_status)) {
237 0 : DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
238 : } else {
239 140 : ret = 0;
240 140 : DEBUG(5, ("rpc command function succeeded\n"));
241 : }
242 :
243 140 : if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
244 140 : if (pipe_hnd) {
245 210 : TALLOC_FREE(pipe_hnd);
246 : }
247 : }
248 :
249 70 : fail:
250 : /* close the connection only if it was opened here */
251 140 : if (!cli_arg) {
252 140 : cli_shutdown(cli);
253 : }
254 :
255 140 : talloc_destroy(mem_ctx);
256 140 : return ret;
257 : }
258 :
259 : /**
260 : * Force a change of the trust account password.
261 : *
262 : * All parameters are provided by the run_rpc_command function, except for
263 : * argc, argv which are passed through.
264 : *
265 : * @param domain_sid The domain sid acquired from the remote server.
266 : * @param cli A cli_state connected to the server.
267 : * @param mem_ctx Talloc context, destroyed on completion of the function.
268 : * @param argc Standard main() style argc.
269 : * @param argv Standard main() style argv. Initial components are already
270 : * stripped.
271 : *
272 : * @return Normal NTSTATUS return.
273 : **/
274 :
275 0 : static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
276 : const struct dom_sid *domain_sid,
277 : const char *domain_name,
278 : struct cli_state *cli,
279 : struct rpc_pipe_client *pipe_hnd,
280 : TALLOC_CTX *mem_ctx,
281 : int argc,
282 : const char **argv)
283 : {
284 : NTSTATUS status;
285 0 : const char *dcname = NULL;
286 :
287 0 : if (cli == NULL) {
288 0 : return NT_STATUS_INTERNAL_ERROR;
289 : }
290 :
291 0 : dcname = smbXcli_conn_remote_name(cli->conn);
292 :
293 0 : status = trust_pw_change(c->netlogon_creds,
294 : c->msg_ctx,
295 : pipe_hnd->binding_handle,
296 : c->opt_target_workgroup,
297 : dcname,
298 : true); /* force */
299 0 : if (!NT_STATUS_IS_OK(status)) {
300 0 : d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
301 : nt_errstr(status));
302 0 : return status;
303 : }
304 :
305 0 : return NT_STATUS_OK;
306 : }
307 :
308 : /**
309 : * Force a change of the trust account password.
310 : *
311 : * @param argc Standard main() style argc.
312 : * @param argv Standard main() style argv. Initial components are already
313 : * stripped.
314 : *
315 : * @return A shell status integer (0 for success).
316 : **/
317 :
318 0 : int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
319 : {
320 0 : int conn_flags = NET_FLAGS_PDC;
321 :
322 0 : if (!c->opt_user_specified && !c->opt_kerberos) {
323 0 : conn_flags |= NET_FLAGS_ANONYMOUS;
324 : }
325 :
326 0 : if (c->display_usage) {
327 0 : d_printf( "%s\n"
328 : "net rpc changetrustpw\n"
329 : " %s\n",
330 : _("Usage:"),
331 : _("Change the machine trust password"));
332 0 : return 0;
333 : }
334 :
335 0 : return run_rpc_command(c, NULL, &ndr_table_netlogon,
336 : conn_flags,
337 : rpc_changetrustpw_internals,
338 : argc, argv);
339 : }
340 :
341 : /**
342 : * Join a domain, the old way. This function exists to allow
343 : * the message to be displayed when oldjoin was explicitly
344 : * requested, but not when it was implied by "net rpc join".
345 : *
346 : * This uses 'machinename' as the initial password, and changes it.
347 : *
348 : * The password should be created with 'server manager' or equiv first.
349 : *
350 : * @param argc Standard main() style argc.
351 : * @param argv Standard main() style argv. Initial components are already
352 : * stripped.
353 : *
354 : * @return A shell status integer (0 for success).
355 : **/
356 :
357 1 : static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
358 : {
359 1 : struct libnet_JoinCtx *r = NULL;
360 : TALLOC_CTX *mem_ctx;
361 : WERROR werr;
362 1 : const char *domain = lp_workgroup(); /* FIXME */
363 1 : bool modify_config = lp_config_backend_is_registry();
364 : enum netr_SchannelType sec_chan_type;
365 1 : char *pw = NULL;
366 :
367 1 : if (c->display_usage) {
368 0 : d_printf("Usage:\n"
369 : "net rpc oldjoin\n"
370 : " Join a domain the old way\n");
371 0 : return 0;
372 : }
373 :
374 1 : net_warn_member_options();
375 :
376 1 : mem_ctx = talloc_init("net_rpc_oldjoin");
377 1 : if (!mem_ctx) {
378 0 : return -1;
379 : }
380 :
381 1 : werr = libnet_init_JoinCtx(mem_ctx, &r);
382 1 : if (!W_ERROR_IS_OK(werr)) {
383 0 : goto fail;
384 : }
385 :
386 : /*
387 : check what type of join - if the user wants to join as
388 : a BDC, the server must agree that we are a BDC.
389 : */
390 1 : if (argc >= 0) {
391 1 : sec_chan_type = get_sec_channel_type(argv[0]);
392 : } else {
393 0 : sec_chan_type = get_sec_channel_type(NULL);
394 : }
395 :
396 1 : if (!c->msg_ctx) {
397 0 : d_fprintf(stderr, _("Could not initialise message context. "
398 : "Try running as root\n"));
399 0 : werr = WERR_ACCESS_DENIED;
400 0 : goto fail;
401 : }
402 :
403 1 : pw = talloc_strndup(r, lp_netbios_name(), 14);
404 1 : if (pw == NULL) {
405 0 : werr = WERR_NOT_ENOUGH_MEMORY;
406 0 : goto fail;
407 : }
408 :
409 1 : r->in.msg_ctx = c->msg_ctx;
410 1 : r->in.domain_name = domain;
411 1 : r->in.secure_channel_type = sec_chan_type;
412 1 : r->in.dc_name = c->opt_host;
413 1 : r->in.admin_account = "";
414 1 : r->in.admin_password = strlower_talloc(r, pw);
415 1 : if (r->in.admin_password == NULL) {
416 0 : werr = WERR_NOT_ENOUGH_MEMORY;
417 0 : goto fail;
418 : }
419 1 : r->in.debug = true;
420 1 : r->in.modify_config = modify_config;
421 1 : r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
422 : WKSSVC_JOIN_FLAGS_JOIN_UNSECURE |
423 : WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
424 :
425 1 : werr = libnet_Join(mem_ctx, r);
426 1 : if (!W_ERROR_IS_OK(werr)) {
427 1 : goto fail;
428 : }
429 :
430 : /* Check the short name of the domain */
431 :
432 0 : if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
433 0 : d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
434 0 : d_printf("domain name obtained from the server.\n");
435 0 : d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
436 0 : d_printf("You should set \"workgroup = %s\" in %s.\n",
437 0 : r->out.netbios_domain_name, get_dyn_CONFIGFILE());
438 : }
439 :
440 0 : d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
441 :
442 0 : if (r->out.dns_domain_name) {
443 0 : d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
444 0 : r->out.dns_domain_name);
445 : } else {
446 0 : d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
447 0 : r->out.netbios_domain_name);
448 : }
449 :
450 : /* print out informative error string in case there is one */
451 0 : if (r->out.error_string != NULL) {
452 0 : d_printf("%s\n", r->out.error_string);
453 : }
454 :
455 0 : TALLOC_FREE(mem_ctx);
456 :
457 0 : return 0;
458 :
459 1 : fail:
460 1 : if (c->opt_flags & NET_FLAGS_EXPECT_FALLBACK) {
461 1 : goto cleanup;
462 : }
463 :
464 : /* issue an overall failure message at the end. */
465 0 : d_fprintf(stderr, _("Failed to join domain: %s\n"),
466 0 : r && r->out.error_string ? r->out.error_string :
467 0 : get_friendly_werror_msg(werr));
468 :
469 1 : cleanup:
470 1 : TALLOC_FREE(mem_ctx);
471 :
472 1 : return -1;
473 : }
474 :
475 : /**
476 : * check that a join is OK
477 : *
478 : * @return A shell status integer (0 for success)
479 : *
480 : **/
481 6 : int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
482 : {
483 : NTSTATUS status;
484 : TALLOC_CTX *mem_ctx;
485 6 : const char *domain = c->opt_target_workgroup;
486 6 : const char *dc = c->opt_host;
487 :
488 6 : if (c->display_usage) {
489 0 : d_printf("Usage\n"
490 : "net rpc testjoin\n"
491 : " Test if a join is OK\n");
492 0 : return 0;
493 : }
494 :
495 6 : net_warn_member_options();
496 :
497 6 : mem_ctx = talloc_init("net_rpc_testjoin");
498 6 : if (!mem_ctx) {
499 0 : return -1;
500 : }
501 :
502 6 : if (!dc) {
503 : struct netr_DsRGetDCNameInfo *info;
504 :
505 6 : if (!c->msg_ctx) {
506 0 : d_fprintf(stderr, _("Could not initialise message context. "
507 : "Try running as root\n"));
508 0 : talloc_destroy(mem_ctx);
509 0 : return -1;
510 : }
511 :
512 6 : status = dsgetdcname(mem_ctx,
513 : c->msg_ctx,
514 : domain,
515 : NULL,
516 : NULL,
517 : DS_RETURN_DNS_NAME,
518 : &info);
519 6 : if (!NT_STATUS_IS_OK(status)) {
520 0 : talloc_destroy(mem_ctx);
521 0 : return -1;
522 : }
523 :
524 6 : dc = strip_hostname(info->dc_unc);
525 : }
526 :
527 : /* Display success or failure */
528 6 : status = libnet_join_ok(c->msg_ctx,
529 : c->opt_workgroup,
530 : dc,
531 6 : c->opt_kerberos);
532 6 : if (!NT_STATUS_IS_OK(status)) {
533 0 : fprintf(stderr,"Join to domain '%s' is not valid: %s\n",
534 : domain, nt_errstr(status));
535 0 : talloc_destroy(mem_ctx);
536 0 : return -1;
537 : }
538 :
539 6 : printf("Join to '%s' is OK\n",domain);
540 6 : talloc_destroy(mem_ctx);
541 :
542 6 : return 0;
543 : }
544 :
545 : /**
546 : * Join a domain using the administrator username and password
547 : *
548 : * @param argc Standard main() style argc
549 : * @param argc Standard main() style argv. Initial components are already
550 : * stripped. Currently not used.
551 : * @return A shell status integer (0 for success)
552 : *
553 : **/
554 :
555 1 : static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
556 : {
557 1 : struct libnet_JoinCtx *r = NULL;
558 : TALLOC_CTX *mem_ctx;
559 : WERROR werr;
560 1 : const char *domain = lp_workgroup(); /* FIXME */
561 1 : bool modify_config = lp_config_backend_is_registry();
562 : enum netr_SchannelType sec_chan_type;
563 :
564 1 : if (c->display_usage) {
565 0 : d_printf("Usage:\n"
566 : "net rpc join\n"
567 : " Join a domain the new way\n");
568 0 : return 0;
569 : }
570 :
571 1 : net_warn_member_options();
572 :
573 1 : mem_ctx = talloc_init("net_rpc_join_newstyle");
574 1 : if (!mem_ctx) {
575 0 : return -1;
576 : }
577 :
578 1 : werr = libnet_init_JoinCtx(mem_ctx, &r);
579 1 : if (!W_ERROR_IS_OK(werr)) {
580 0 : goto fail;
581 : }
582 :
583 : /*
584 : check what type of join - if the user wants to join as
585 : a BDC, the server must agree that we are a BDC.
586 : */
587 1 : if (argc >= 0) {
588 1 : sec_chan_type = get_sec_channel_type(argv[0]);
589 : } else {
590 0 : sec_chan_type = get_sec_channel_type(NULL);
591 : }
592 :
593 1 : if (!c->msg_ctx) {
594 0 : d_fprintf(stderr, _("Could not initialise message context. "
595 : "Try running as root\n"));
596 0 : werr = WERR_ACCESS_DENIED;
597 0 : goto fail;
598 : }
599 :
600 1 : r->in.msg_ctx = c->msg_ctx;
601 1 : r->in.domain_name = domain;
602 1 : r->in.secure_channel_type = sec_chan_type;
603 1 : r->in.dc_name = c->opt_host;
604 1 : r->in.admin_account = c->opt_user_name;
605 1 : r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
606 1 : r->in.debug = true;
607 1 : r->in.use_kerberos = c->opt_kerberos;
608 1 : r->in.modify_config = modify_config;
609 1 : r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
610 : WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
611 : WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
612 :
613 1 : werr = libnet_Join(mem_ctx, r);
614 1 : if (!W_ERROR_IS_OK(werr)) {
615 0 : goto fail;
616 : }
617 :
618 : /* Check the short name of the domain */
619 :
620 1 : if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
621 0 : d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
622 0 : d_printf("domain name obtained from the server.\n");
623 0 : d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
624 0 : d_printf("You should set \"workgroup = %s\" in %s.\n",
625 0 : r->out.netbios_domain_name, get_dyn_CONFIGFILE());
626 : }
627 :
628 1 : d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
629 :
630 1 : if (r->out.dns_domain_name) {
631 0 : d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
632 0 : r->out.dns_domain_name);
633 : } else {
634 1 : d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
635 1 : r->out.netbios_domain_name);
636 : }
637 :
638 : /* print out informative error string in case there is one */
639 1 : if (r->out.error_string != NULL) {
640 0 : d_printf("%s\n", r->out.error_string);
641 : }
642 :
643 1 : TALLOC_FREE(mem_ctx);
644 :
645 1 : return 0;
646 :
647 0 : fail:
648 : /* issue an overall failure message at the end. */
649 0 : d_printf("Failed to join domain: %s\n",
650 0 : r && r->out.error_string ? r->out.error_string :
651 0 : get_friendly_werror_msg(werr));
652 :
653 0 : TALLOC_FREE(mem_ctx);
654 :
655 0 : return -1;
656 : }
657 :
658 : /**
659 : * 'net rpc join' entrypoint.
660 : * @param argc Standard main() style argc.
661 : * @param argv Standard main() style argv. Initial components are already
662 : * stripped
663 : *
664 : * Main 'net_rpc_join()' (where the admin username/password is used) is
665 : * in net_rpc_join.c.
666 : * Try to just change the password, but if that doesn't work, use/prompt
667 : * for a username/password.
668 : **/
669 :
670 1 : int net_rpc_join(struct net_context *c, int argc, const char **argv)
671 : {
672 : int ret;
673 :
674 1 : if (c->display_usage) {
675 0 : d_printf("%s\n%s",
676 : _("Usage:"),
677 : _("net rpc join -U <username>[%%password] <type>\n"
678 : " Join a domain\n"
679 : " username\tName of the admin user"
680 : " password\tPassword of the admin user, will "
681 : "prompt if not specified\n"
682 : " type\tCan be one of the following:\n"
683 : "\t\tMEMBER\tJoin as member server (default)\n"
684 : "\t\tBDC\tJoin as BDC\n"
685 : "\t\tPDC\tJoin as PDC\n"));
686 0 : return 0;
687 : }
688 :
689 1 : if (lp_server_role() == ROLE_STANDALONE) {
690 0 : d_printf(_("cannot join as standalone machine\n"));
691 0 : return -1;
692 : }
693 :
694 1 : net_warn_member_options();
695 :
696 1 : if (strlen(lp_netbios_name()) > 15) {
697 0 : d_printf(_("Our netbios name can be at most 15 chars long, "
698 : "\"%s\" is %u chars long\n"),
699 0 : lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
700 0 : return -1;
701 : }
702 :
703 1 : c->opt_flags |= NET_FLAGS_EXPECT_FALLBACK;
704 1 : ret = net_rpc_oldjoin(c, argc, argv);
705 1 : c->opt_flags &= ~NET_FLAGS_EXPECT_FALLBACK;
706 1 : if (ret == 0) {
707 0 : return 0;
708 : }
709 :
710 1 : return net_rpc_join_newstyle(c, argc, argv);
711 : }
712 :
713 : /**
714 : * display info about a rpc domain
715 : *
716 : * All parameters are provided by the run_rpc_command function, except for
717 : * argc, argv which are passed through.
718 : *
719 : * @param domain_sid The domain sid acquired from the remote server
720 : * @param cli A cli_state connected to the server.
721 : * @param mem_ctx Talloc context, destroyed on completion of the function.
722 : * @param argc Standard main() style argc.
723 : * @param argv Standard main() style argv. Initial components are already
724 : * stripped.
725 : *
726 : * @return Normal NTSTATUS return.
727 : **/
728 :
729 0 : NTSTATUS rpc_info_internals(struct net_context *c,
730 : const struct dom_sid *domain_sid,
731 : const char *domain_name,
732 : struct cli_state *cli,
733 : struct rpc_pipe_client *pipe_hnd,
734 : TALLOC_CTX *mem_ctx,
735 : int argc,
736 : const char **argv)
737 : {
738 : struct policy_handle connect_pol, domain_pol;
739 : NTSTATUS status, result;
740 0 : union samr_DomainInfo *info = NULL;
741 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
742 :
743 : /* Get sam policy handle */
744 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
745 0 : pipe_hnd->desthost,
746 : MAXIMUM_ALLOWED_ACCESS,
747 : &connect_pol,
748 : &result);
749 0 : if (!NT_STATUS_IS_OK(status)) {
750 0 : d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
751 : nt_errstr(status));
752 0 : goto done;
753 : }
754 :
755 0 : if (!NT_STATUS_IS_OK(result)) {
756 0 : status = result;
757 0 : d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
758 : nt_errstr(result));
759 0 : goto done;
760 : }
761 :
762 : /* Get domain policy handle */
763 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
764 : &connect_pol,
765 : MAXIMUM_ALLOWED_ACCESS,
766 : discard_const_p(struct dom_sid2, domain_sid),
767 : &domain_pol,
768 : &result);
769 0 : if (!NT_STATUS_IS_OK(status)) {
770 0 : d_fprintf(stderr, _("Could not open domain: %s\n"),
771 : nt_errstr(status));
772 0 : goto done;
773 : }
774 0 : if (!NT_STATUS_IS_OK(result)) {
775 0 : status = result;
776 0 : d_fprintf(stderr, _("Could not open domain: %s\n"),
777 : nt_errstr(result));
778 0 : goto done;
779 : }
780 :
781 0 : status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
782 : &domain_pol,
783 : 2,
784 : &info,
785 : &result);
786 0 : if (!NT_STATUS_IS_OK(status)) {
787 0 : goto done;
788 : }
789 0 : status = result;
790 0 : if (NT_STATUS_IS_OK(result)) {
791 : struct dom_sid_buf sid_str;
792 :
793 0 : d_printf(_("Domain Name: %s\n"),
794 0 : info->general.domain_name.string);
795 0 : d_printf(_("Domain SID: %s\n"),
796 : dom_sid_str_buf(domain_sid, &sid_str));
797 0 : d_printf(_("Sequence number: %llu\n"),
798 0 : (unsigned long long)info->general.sequence_num);
799 0 : d_printf(_("Num users: %u\n"), info->general.num_users);
800 0 : d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
801 0 : d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
802 : }
803 :
804 0 : done:
805 0 : return status;
806 : }
807 :
808 : /**
809 : * 'net rpc info' entrypoint.
810 : * @param argc Standard main() style argc.
811 : * @param argv Standard main() style argv. Initial components are already
812 : * stripped.
813 : **/
814 :
815 0 : int net_rpc_info(struct net_context *c, int argc, const char **argv)
816 : {
817 0 : if (c->display_usage) {
818 0 : d_printf( "%s\n"
819 : "net rpc info\n"
820 : " %s\n",
821 : _("Usage:"),
822 : _("Display information about the domain"));
823 0 : return 0;
824 : }
825 :
826 0 : net_warn_member_options();
827 :
828 0 : return run_rpc_command(c, NULL, &ndr_table_samr,
829 : NET_FLAGS_PDC, rpc_info_internals,
830 : argc, argv);
831 : }
832 :
833 : /**
834 : * Fetch domain SID into the local secrets.tdb.
835 : *
836 : * All parameters are provided by the run_rpc_command function, except for
837 : * argc, argv which are passed through.
838 : *
839 : * @param domain_sid The domain sid acquired from the remote server.
840 : * @param cli A cli_state connected to the server.
841 : * @param mem_ctx Talloc context, destroyed on completion of the function.
842 : * @param argc Standard main() style argc.
843 : * @param argv Standard main() style argv. Initial components are already
844 : * stripped.
845 : *
846 : * @return Normal NTSTATUS return.
847 : **/
848 :
849 0 : static NTSTATUS rpc_getsid_internals(struct net_context *c,
850 : const struct dom_sid *domain_sid,
851 : const char *domain_name,
852 : struct cli_state *cli,
853 : struct rpc_pipe_client *pipe_hnd,
854 : TALLOC_CTX *mem_ctx,
855 : int argc,
856 : const char **argv)
857 : {
858 : struct dom_sid_buf sid_str;
859 :
860 0 : d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
861 : dom_sid_str_buf(domain_sid, &sid_str),
862 : domain_name);
863 :
864 0 : if (!secrets_store_domain_sid(domain_name, domain_sid)) {
865 0 : DEBUG(0,("Can't store domain SID\n"));
866 0 : return NT_STATUS_UNSUCCESSFUL;
867 : }
868 :
869 0 : return NT_STATUS_OK;
870 : }
871 :
872 : /**
873 : * 'net rpc getsid' entrypoint.
874 : * @param argc Standard main() style argc.
875 : * @param argv Standard main() style argv. Initial components are already
876 : * stripped.
877 : **/
878 :
879 0 : int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
880 : {
881 0 : int conn_flags = NET_FLAGS_PDC;
882 :
883 0 : if (!c->opt_user_specified && !c->opt_kerberos) {
884 0 : conn_flags |= NET_FLAGS_ANONYMOUS;
885 : }
886 :
887 0 : if (c->display_usage) {
888 0 : d_printf( "%s\n"
889 : "net rpc getsid\n"
890 : " %s\n",
891 : _("Usage:"),
892 : _("Fetch domain SID into local secrets.tdb"));
893 0 : return 0;
894 : }
895 :
896 0 : return run_rpc_command(c, NULL, &ndr_table_samr,
897 : conn_flags,
898 : rpc_getsid_internals,
899 : argc, argv);
900 : }
901 :
902 : /****************************************************************************/
903 :
904 : /**
905 : * Basic usage function for 'net rpc user'.
906 : * @param argc Standard main() style argc.
907 : * @param argv Standard main() style argv. Initial components are already
908 : * stripped.
909 : **/
910 :
911 0 : static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
912 : {
913 0 : return net_user_usage(c, argc, argv);
914 : }
915 :
916 : /**
917 : * Add a new user to a remote RPC server.
918 : *
919 : * @param argc Standard main() style argc.
920 : * @param argv Standard main() style argv. Initial components are already
921 : * stripped.
922 : *
923 : * @return A shell status integer (0 for success).
924 : **/
925 :
926 2 : static int rpc_user_add(struct net_context *c, int argc, const char **argv)
927 : {
928 : NET_API_STATUS status;
929 : struct USER_INFO_1 info1;
930 2 : uint32_t parm_error = 0;
931 :
932 2 : if (argc < 1 || c->display_usage) {
933 0 : rpc_user_usage(c, argc, argv);
934 0 : return 0;
935 : }
936 :
937 2 : ZERO_STRUCT(info1);
938 :
939 2 : info1.usri1_name = argv[0];
940 2 : if (argc == 2) {
941 2 : info1.usri1_password = argv[1];
942 : }
943 :
944 2 : status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
945 :
946 2 : if (status != 0) {
947 0 : d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
948 : argv[0], libnetapi_get_error_string(c->netapi_ctx,
949 : status));
950 0 : return -1;
951 : } else {
952 2 : d_printf(_("Added user '%s'.\n"), argv[0]);
953 : }
954 :
955 2 : return 0;
956 : }
957 :
958 : /**
959 : * Rename a user on a remote RPC server.
960 : *
961 : * @param argc Standard main() style argc.
962 : * @param argv Standard main() style argv. Initial components are already
963 : * stripped.
964 : *
965 : * @return A shell status integer (0 for success).
966 : **/
967 :
968 0 : static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
969 : {
970 : NET_API_STATUS status;
971 : struct USER_INFO_0 u0;
972 0 : uint32_t parm_err = 0;
973 :
974 0 : if (argc != 2 || c->display_usage) {
975 0 : rpc_user_usage(c, argc, argv);
976 0 : return 0;
977 : }
978 :
979 0 : u0.usri0_name = argv[1];
980 :
981 0 : status = NetUserSetInfo(c->opt_host, argv[0],
982 : 0, (uint8_t *)&u0, &parm_err);
983 0 : if (status) {
984 0 : d_fprintf(stderr,
985 0 : _("Failed to rename user from %s to %s - %s\n"),
986 0 : argv[0], argv[1],
987 : libnetapi_get_error_string(c->netapi_ctx, status));
988 : } else {
989 0 : d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
990 : }
991 :
992 0 : return status;
993 : }
994 :
995 : /**
996 : * Set a user's primary group
997 : *
998 : * @param argc Standard main() style argc.
999 : * @param argv Standard main() style argv. Initial components are already
1000 : * stripped.
1001 : *
1002 : * @return A shell status integer (0 for success).
1003 : **/
1004 :
1005 0 : static int rpc_user_setprimarygroup(struct net_context *c, int argc,
1006 : const char **argv)
1007 : {
1008 : NET_API_STATUS status;
1009 : uint8_t *buffer;
1010 : struct GROUP_INFO_2 *g2;
1011 : struct USER_INFO_1051 u1051;
1012 0 : uint32_t parm_err = 0;
1013 :
1014 0 : if (argc != 2 || c->display_usage) {
1015 0 : rpc_user_usage(c, argc, argv);
1016 0 : return 0;
1017 : }
1018 :
1019 0 : status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
1020 0 : if (status) {
1021 0 : d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
1022 0 : argv[1],
1023 : libnetapi_get_error_string(c->netapi_ctx, status));
1024 0 : return status;
1025 : }
1026 0 : g2 = (struct GROUP_INFO_2 *)buffer;
1027 :
1028 0 : u1051.usri1051_primary_group_id = g2->grpi2_group_id;
1029 :
1030 0 : NetApiBufferFree(buffer);
1031 :
1032 0 : status = NetUserSetInfo(c->opt_host, argv[0], 1051,
1033 : (uint8_t *)&u1051, &parm_err);
1034 0 : if (status) {
1035 0 : d_fprintf(stderr,
1036 0 : _("Failed to set user's primary group %s to %s - "
1037 0 : "%s\n"), argv[0], argv[1],
1038 : libnetapi_get_error_string(c->netapi_ctx, status));
1039 : } else {
1040 0 : d_printf(_("Set primary group of user %s to %s\n"), argv[0],
1041 0 : argv[1]);
1042 : }
1043 0 : return status;
1044 : }
1045 :
1046 : /**
1047 : * Delete a user from a remote RPC server.
1048 : *
1049 : * @param argc Standard main() style argc.
1050 : * @param argv Standard main() style argv. Initial components are already
1051 : * stripped.
1052 : *
1053 : * @return A shell status integer (0 for success).
1054 : **/
1055 :
1056 2 : static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
1057 : {
1058 : NET_API_STATUS status;
1059 :
1060 2 : if (argc < 1 || c->display_usage) {
1061 0 : rpc_user_usage(c, argc, argv);
1062 0 : return 0;
1063 : }
1064 :
1065 2 : status = NetUserDel(c->opt_host, argv[0]);
1066 :
1067 2 : if (status != 0) {
1068 0 : d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
1069 : argv[0],
1070 : libnetapi_get_error_string(c->netapi_ctx, status));
1071 0 : return -1;
1072 : } else {
1073 2 : d_printf(_("Deleted user '%s'.\n"), argv[0]);
1074 : }
1075 :
1076 2 : return 0;
1077 : }
1078 :
1079 : /**
1080 : * Set a user's password on a remote RPC server.
1081 : *
1082 : * @param argc Standard main() style argc.
1083 : * @param argv Standard main() style argv. Initial components are already
1084 : * stripped.
1085 : *
1086 : * @return A shell status integer (0 for success).
1087 : **/
1088 :
1089 0 : static int rpc_user_password(struct net_context *c, int argc, const char **argv)
1090 : {
1091 : NET_API_STATUS status;
1092 0 : char *prompt = NULL;
1093 : struct USER_INFO_1003 u1003;
1094 0 : uint32_t parm_err = 0;
1095 : int ret;
1096 :
1097 0 : if (argc < 1 || c->display_usage) {
1098 0 : rpc_user_usage(c, argc, argv);
1099 0 : return 0;
1100 : }
1101 :
1102 0 : if (argv[1]) {
1103 0 : u1003.usri1003_password = argv[1];
1104 : } else {
1105 0 : char pwd[256] = {0};
1106 0 : ret = asprintf(&prompt, _("Enter new password for %s:"),
1107 : argv[0]);
1108 0 : if (ret == -1) {
1109 0 : return -1;
1110 : }
1111 :
1112 0 : ret = samba_getpass(prompt, pwd, sizeof(pwd), false, false);
1113 0 : SAFE_FREE(prompt);
1114 0 : if (ret < 0) {
1115 0 : return -1;
1116 : }
1117 :
1118 0 : u1003.usri1003_password = talloc_strdup(c, pwd);
1119 0 : if (u1003.usri1003_password == NULL) {
1120 0 : return -1;
1121 : }
1122 : }
1123 :
1124 0 : status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
1125 :
1126 : /* Display results */
1127 0 : if (status != 0) {
1128 0 : d_fprintf(stderr,
1129 0 : _("Failed to set password for '%s' with error: %s.\n"),
1130 : argv[0], libnetapi_get_error_string(c->netapi_ctx,
1131 : status));
1132 0 : return -1;
1133 : }
1134 :
1135 0 : return 0;
1136 : }
1137 :
1138 : /**
1139 : * List a user's groups from a remote RPC server.
1140 : *
1141 : * @param argc Standard main() style argc.
1142 : * @param argv Standard main() style argv. Initial components are already
1143 : * stripped.
1144 : *
1145 : * @return A shell status integer (0 for success)
1146 : **/
1147 :
1148 0 : static int rpc_user_info(struct net_context *c, int argc, const char **argv)
1149 :
1150 : {
1151 : NET_API_STATUS status;
1152 0 : struct GROUP_USERS_INFO_0 *u0 = NULL;
1153 0 : uint32_t entries_read = 0;
1154 0 : uint32_t total_entries = 0;
1155 : uint32_t i;
1156 :
1157 :
1158 0 : if (argc < 1 || c->display_usage) {
1159 0 : rpc_user_usage(c, argc, argv);
1160 0 : return 0;
1161 : }
1162 :
1163 0 : status = NetUserGetGroups(c->opt_host,
1164 : argv[0],
1165 : 0,
1166 : (uint8_t **)(void *)&u0,
1167 : (uint32_t)-1,
1168 : &entries_read,
1169 : &total_entries);
1170 0 : if (status != 0) {
1171 0 : d_fprintf(stderr,
1172 0 : _("Failed to get groups for '%s' with error: %s.\n"),
1173 : argv[0], libnetapi_get_error_string(c->netapi_ctx,
1174 : status));
1175 0 : return -1;
1176 : }
1177 :
1178 0 : for (i=0; i < entries_read; i++) {
1179 0 : printf("%s\n", u0->grui0_name);
1180 0 : u0++;
1181 : }
1182 :
1183 0 : return 0;
1184 : }
1185 :
1186 : /**
1187 : * List users on a remote RPC server.
1188 : *
1189 : * All parameters are provided by the run_rpc_command function, except for
1190 : * argc, argv which are passed through.
1191 : *
1192 : * @param domain_sid The domain sid acquired from the remote server.
1193 : * @param cli A cli_state connected to the server.
1194 : * @param mem_ctx Talloc context, destroyed on completion of the function.
1195 : * @param argc Standard main() style argc.
1196 : * @param argv Standard main() style argv. Initial components are already
1197 : * stripped.
1198 : *
1199 : * @return Normal NTSTATUS return.
1200 : **/
1201 :
1202 0 : static int rpc_user_list(struct net_context *c, int argc, const char **argv)
1203 : {
1204 : NET_API_STATUS status;
1205 0 : uint32_t start_idx=0, num_entries, i, loop_count = 0;
1206 0 : struct NET_DISPLAY_USER *info = NULL;
1207 0 : void *buffer = NULL;
1208 :
1209 : /* Query domain users */
1210 0 : if (c->opt_long_list_entries)
1211 0 : d_printf(_("\nUser name Comment"
1212 : "\n-----------------------------\n"));
1213 : do {
1214 : uint32_t max_entries, max_size;
1215 :
1216 0 : dcerpc_get_query_dispinfo_params(
1217 : loop_count, &max_entries, &max_size);
1218 :
1219 0 : status = NetQueryDisplayInformation(c->opt_host,
1220 : 1,
1221 : start_idx,
1222 : max_entries,
1223 : max_size,
1224 : &num_entries,
1225 : &buffer);
1226 0 : if (status != 0 && status != ERROR_MORE_DATA) {
1227 0 : return status;
1228 : }
1229 :
1230 0 : info = (struct NET_DISPLAY_USER *)buffer;
1231 :
1232 0 : for (i = 0; i < num_entries; i++) {
1233 :
1234 0 : if (c->opt_long_list_entries)
1235 0 : printf("%-21.21s %s\n", info->usri1_name,
1236 : info->usri1_comment);
1237 : else
1238 0 : printf("%s\n", info->usri1_name);
1239 0 : info++;
1240 : }
1241 :
1242 0 : NetApiBufferFree(buffer);
1243 :
1244 0 : loop_count++;
1245 0 : start_idx += num_entries;
1246 :
1247 0 : } while (status == ERROR_MORE_DATA);
1248 :
1249 0 : return status;
1250 : }
1251 :
1252 : /**
1253 : * 'net rpc user' entrypoint.
1254 : * @param argc Standard main() style argc.
1255 : * @param argv Standard main() style argv. Initial components are already
1256 : * stripped.
1257 : **/
1258 :
1259 4 : int net_rpc_user(struct net_context *c, int argc, const char **argv)
1260 : {
1261 : NET_API_STATUS status;
1262 :
1263 4 : struct functable func[] = {
1264 : {
1265 : "add",
1266 : rpc_user_add,
1267 : NET_TRANSPORT_RPC,
1268 : N_("Add specified user"),
1269 : N_("net rpc user add\n"
1270 : " Add specified user")
1271 : },
1272 : {
1273 : "info",
1274 : rpc_user_info,
1275 : NET_TRANSPORT_RPC,
1276 : N_("List domain groups of user"),
1277 : N_("net rpc user info\n"
1278 : " List domain groups of user")
1279 : },
1280 : {
1281 : "delete",
1282 : rpc_user_delete,
1283 : NET_TRANSPORT_RPC,
1284 : N_("Remove specified user"),
1285 : N_("net rpc user delete\n"
1286 : " Remove specified user")
1287 : },
1288 : {
1289 : "password",
1290 : rpc_user_password,
1291 : NET_TRANSPORT_RPC,
1292 : N_("Change user password"),
1293 : N_("net rpc user password\n"
1294 : " Change user password")
1295 : },
1296 : {
1297 : "rename",
1298 : rpc_user_rename,
1299 : NET_TRANSPORT_RPC,
1300 : N_("Rename specified user"),
1301 : N_("net rpc user rename\n"
1302 : " Rename specified user")
1303 : },
1304 : {
1305 : "setprimarygroup",
1306 : rpc_user_setprimarygroup,
1307 : NET_TRANSPORT_RPC,
1308 : "Set a user's primary group",
1309 : "net rpc user setprimarygroup\n"
1310 : " Set a user's primary group"
1311 : },
1312 : {NULL, NULL, 0, NULL, NULL}
1313 : };
1314 :
1315 4 : status = libnetapi_net_init(&c->netapi_ctx);
1316 4 : if (status != 0) {
1317 0 : return -1;
1318 : }
1319 :
1320 4 : status = libnetapi_set_creds(c->netapi_ctx, c->creds);
1321 4 : if (status != 0) {
1322 0 : return -1;
1323 : }
1324 :
1325 4 : if (argc == 0) {
1326 0 : if (c->display_usage) {
1327 0 : d_printf( "%s\n"
1328 : "net rpc user\n"
1329 : " %s\n",
1330 : _("Usage:"),
1331 : _("List all users"));
1332 0 : net_display_usage_from_functable(func);
1333 0 : return 0;
1334 : }
1335 :
1336 0 : return rpc_user_list(c, argc, argv);
1337 : }
1338 :
1339 4 : return net_run_function(c, argc, argv, "net rpc user", func);
1340 : }
1341 :
1342 0 : static NTSTATUS rpc_sh_user_list(struct net_context *c,
1343 : TALLOC_CTX *mem_ctx,
1344 : struct rpc_sh_ctx *ctx,
1345 : struct rpc_pipe_client *pipe_hnd,
1346 : int argc, const char **argv)
1347 : {
1348 0 : return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1349 : }
1350 :
1351 0 : static NTSTATUS rpc_sh_user_info(struct net_context *c,
1352 : TALLOC_CTX *mem_ctx,
1353 : struct rpc_sh_ctx *ctx,
1354 : struct rpc_pipe_client *pipe_hnd,
1355 : int argc, const char **argv)
1356 : {
1357 0 : return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1358 : }
1359 :
1360 0 : static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1361 : TALLOC_CTX *mem_ctx,
1362 : struct rpc_sh_ctx *ctx,
1363 : struct rpc_pipe_client *pipe_hnd,
1364 : int argc, const char **argv,
1365 : NTSTATUS (*fn)(
1366 : struct net_context *c,
1367 : TALLOC_CTX *mem_ctx,
1368 : struct rpc_sh_ctx *ctx,
1369 : struct rpc_pipe_client *pipe_hnd,
1370 : struct policy_handle *user_hnd,
1371 : int argc, const char **argv))
1372 : {
1373 : struct policy_handle connect_pol, domain_pol, user_pol;
1374 : NTSTATUS status, result;
1375 : struct dom_sid sid;
1376 : uint32_t rid;
1377 : enum lsa_SidType type;
1378 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1379 :
1380 0 : if (argc == 0) {
1381 0 : d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1382 : ctx->whoami);
1383 0 : return NT_STATUS_INVALID_PARAMETER;
1384 : }
1385 :
1386 0 : ZERO_STRUCT(connect_pol);
1387 0 : ZERO_STRUCT(domain_pol);
1388 0 : ZERO_STRUCT(user_pol);
1389 :
1390 0 : status = net_rpc_lookup_name(c, mem_ctx, ctx->cli,
1391 : argv[0], NULL, NULL, &sid, &type);
1392 0 : if (!NT_STATUS_IS_OK(status)) {
1393 0 : d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1394 : nt_errstr(status));
1395 0 : goto done;
1396 : }
1397 :
1398 0 : if (type != SID_NAME_USER) {
1399 0 : d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1400 : sid_type_lookup(type));
1401 0 : status = NT_STATUS_NO_SUCH_USER;
1402 0 : goto done;
1403 : }
1404 :
1405 0 : if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1406 0 : d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1407 0 : status = NT_STATUS_NO_SUCH_USER;
1408 0 : goto done;
1409 : }
1410 :
1411 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
1412 0 : pipe_hnd->desthost,
1413 : MAXIMUM_ALLOWED_ACCESS,
1414 : &connect_pol,
1415 : &result);
1416 0 : if (!NT_STATUS_IS_OK(status)) {
1417 0 : goto done;
1418 : }
1419 0 : if (!NT_STATUS_IS_OK(result)) {
1420 0 : status = result;
1421 0 : goto done;
1422 : }
1423 :
1424 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
1425 : &connect_pol,
1426 : MAXIMUM_ALLOWED_ACCESS,
1427 : ctx->domain_sid,
1428 : &domain_pol,
1429 : &result);
1430 0 : if (!NT_STATUS_IS_OK(status)) {
1431 0 : goto done;
1432 : }
1433 0 : if (!NT_STATUS_IS_OK(result)) {
1434 0 : status = result;
1435 0 : goto done;
1436 : }
1437 :
1438 0 : status = dcerpc_samr_OpenUser(b, mem_ctx,
1439 : &domain_pol,
1440 : MAXIMUM_ALLOWED_ACCESS,
1441 : rid,
1442 : &user_pol,
1443 : &result);
1444 0 : if (!NT_STATUS_IS_OK(status)) {
1445 0 : goto done;
1446 : }
1447 0 : if (!NT_STATUS_IS_OK(result)) {
1448 0 : status = result;
1449 0 : goto done;
1450 : }
1451 :
1452 0 : status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1453 :
1454 0 : done:
1455 0 : if (is_valid_policy_hnd(&user_pol)) {
1456 0 : dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1457 : }
1458 0 : if (is_valid_policy_hnd(&domain_pol)) {
1459 0 : dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1460 : }
1461 0 : if (is_valid_policy_hnd(&connect_pol)) {
1462 0 : dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1463 : }
1464 0 : return status;
1465 : }
1466 :
1467 0 : static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1468 : TALLOC_CTX *mem_ctx,
1469 : struct rpc_sh_ctx *ctx,
1470 : struct rpc_pipe_client *pipe_hnd,
1471 : struct policy_handle *user_hnd,
1472 : int argc, const char **argv)
1473 : {
1474 : NTSTATUS status, result;
1475 0 : union samr_UserInfo *info = NULL;
1476 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1477 :
1478 0 : if (argc != 0) {
1479 0 : d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1480 : ctx->whoami);
1481 0 : return NT_STATUS_INVALID_PARAMETER;
1482 : }
1483 :
1484 0 : status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1485 : user_hnd,
1486 : 21,
1487 : &info,
1488 : &result);
1489 0 : if (!NT_STATUS_IS_OK(status)) {
1490 0 : return status;
1491 : }
1492 0 : if (!NT_STATUS_IS_OK(result)) {
1493 0 : return result;
1494 : }
1495 :
1496 0 : d_printf(_("user rid: %d, group rid: %d\n"),
1497 0 : info->info21.rid,
1498 0 : info->info21.primary_gid);
1499 :
1500 0 : return result;
1501 : }
1502 :
1503 0 : static NTSTATUS rpc_sh_user_show(struct net_context *c,
1504 : TALLOC_CTX *mem_ctx,
1505 : struct rpc_sh_ctx *ctx,
1506 : struct rpc_pipe_client *pipe_hnd,
1507 : int argc, const char **argv)
1508 : {
1509 0 : return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1510 : rpc_sh_user_show_internals);
1511 : }
1512 :
1513 : #define FETCHSTR(name, rec) \
1514 : do { if (strequal(ctx->thiscmd, name)) { \
1515 : oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1516 : } while (0);
1517 :
1518 : #define SETSTR(name, rec, flag) \
1519 : do { if (strequal(ctx->thiscmd, name)) { \
1520 : init_lsa_String(&(info->info21.rec), argv[0]); \
1521 : info->info21.fields_present |= SAMR_FIELD_##flag; } \
1522 : } while (0);
1523 :
1524 0 : static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1525 : TALLOC_CTX *mem_ctx,
1526 : struct rpc_sh_ctx *ctx,
1527 : struct rpc_pipe_client *pipe_hnd,
1528 : struct policy_handle *user_hnd,
1529 : int argc, const char **argv)
1530 : {
1531 : NTSTATUS status, result;
1532 : const char *username;
1533 0 : const char *oldval = "";
1534 0 : union samr_UserInfo *info = NULL;
1535 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1536 :
1537 0 : if (argc > 1) {
1538 0 : d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1539 : _("Usage:"), ctx->whoami);
1540 0 : return NT_STATUS_INVALID_PARAMETER;
1541 : }
1542 :
1543 0 : status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1544 : user_hnd,
1545 : 21,
1546 : &info,
1547 : &result);
1548 0 : if (!NT_STATUS_IS_OK(status)) {
1549 0 : return status;
1550 : }
1551 0 : if (!NT_STATUS_IS_OK(result)) {
1552 0 : return result;
1553 : }
1554 :
1555 0 : username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1556 :
1557 0 : FETCHSTR("fullname", full_name);
1558 0 : FETCHSTR("homedir", home_directory);
1559 0 : FETCHSTR("homedrive", home_drive);
1560 0 : FETCHSTR("logonscript", logon_script);
1561 0 : FETCHSTR("profilepath", profile_path);
1562 0 : FETCHSTR("description", description);
1563 :
1564 0 : if (argc == 0) {
1565 0 : d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1566 0 : goto done;
1567 : }
1568 :
1569 0 : if (strcmp(argv[0], "NULL") == 0) {
1570 0 : argv[0] = "";
1571 : }
1572 :
1573 0 : ZERO_STRUCT(info->info21);
1574 :
1575 0 : SETSTR("fullname", full_name, FULL_NAME);
1576 0 : SETSTR("homedir", home_directory, HOME_DIRECTORY);
1577 0 : SETSTR("homedrive", home_drive, HOME_DRIVE);
1578 0 : SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1579 0 : SETSTR("profilepath", profile_path, PROFILE_PATH);
1580 0 : SETSTR("description", description, DESCRIPTION);
1581 :
1582 0 : status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1583 : user_hnd,
1584 : 21,
1585 : info,
1586 : &result);
1587 0 : if (!NT_STATUS_IS_OK(status)) {
1588 0 : return status;
1589 : }
1590 :
1591 0 : status = result;
1592 :
1593 0 : d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1594 : ctx->thiscmd, oldval, argv[0]);
1595 :
1596 0 : done:
1597 :
1598 0 : return status;
1599 : }
1600 :
1601 : #define HANDLEFLG(name, rec) \
1602 : do { if (strequal(ctx->thiscmd, name)) { \
1603 : oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1604 : if (newval) { \
1605 : newflags = oldflags | ACB_##rec; \
1606 : } else { \
1607 : newflags = oldflags & ~ACB_##rec; \
1608 : } } } while (0);
1609 :
1610 0 : static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1611 : TALLOC_CTX *mem_ctx,
1612 : struct rpc_sh_ctx *ctx,
1613 : struct rpc_pipe_client *pipe_hnd,
1614 : int argc, const char **argv)
1615 : {
1616 0 : return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1617 : rpc_sh_user_str_edit_internals);
1618 : }
1619 :
1620 0 : static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1621 : TALLOC_CTX *mem_ctx,
1622 : struct rpc_sh_ctx *ctx,
1623 : struct rpc_pipe_client *pipe_hnd,
1624 : struct policy_handle *user_hnd,
1625 : int argc, const char **argv)
1626 : {
1627 : NTSTATUS status, result;
1628 : const char *username;
1629 0 : const char *oldval = "unknown";
1630 : uint32_t oldflags, newflags;
1631 : bool newval;
1632 0 : union samr_UserInfo *info = NULL;
1633 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1634 :
1635 0 : if ((argc > 1) ||
1636 0 : ((argc == 1) && !strequal(argv[0], "yes") &&
1637 0 : !strequal(argv[0], "no"))) {
1638 : /* TRANSATORS: The yes|no here are program keywords. Please do
1639 : not translate. */
1640 0 : d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1641 : ctx->whoami);
1642 0 : return NT_STATUS_INVALID_PARAMETER;
1643 : }
1644 :
1645 0 : newval = strequal(argv[0], "yes");
1646 :
1647 0 : status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1648 : user_hnd,
1649 : 21,
1650 : &info,
1651 : &result);
1652 0 : if (!NT_STATUS_IS_OK(status)) {
1653 0 : return status;
1654 : }
1655 0 : if (!NT_STATUS_IS_OK(result)) {
1656 0 : return result;
1657 : }
1658 :
1659 0 : username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1660 0 : oldflags = info->info21.acct_flags;
1661 0 : newflags = info->info21.acct_flags;
1662 :
1663 0 : HANDLEFLG("disabled", DISABLED);
1664 0 : HANDLEFLG("pwnotreq", PWNOTREQ);
1665 0 : HANDLEFLG("autolock", AUTOLOCK);
1666 0 : HANDLEFLG("pwnoexp", PWNOEXP);
1667 :
1668 0 : if (argc == 0) {
1669 0 : d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1670 : oldval);
1671 0 : goto done;
1672 : }
1673 :
1674 0 : ZERO_STRUCT(info->info21);
1675 :
1676 0 : info->info21.acct_flags = newflags;
1677 0 : info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1678 :
1679 0 : status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1680 : user_hnd,
1681 : 21,
1682 : info,
1683 : &result);
1684 0 : if (!NT_STATUS_IS_OK(status)) {
1685 0 : goto done;
1686 : }
1687 0 : status = result;
1688 0 : if (NT_STATUS_IS_OK(result)) {
1689 0 : d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1690 : ctx->thiscmd, oldval, argv[0]);
1691 : }
1692 :
1693 0 : done:
1694 :
1695 0 : return status;
1696 : }
1697 :
1698 0 : static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1699 : TALLOC_CTX *mem_ctx,
1700 : struct rpc_sh_ctx *ctx,
1701 : struct rpc_pipe_client *pipe_hnd,
1702 : int argc, const char **argv)
1703 : {
1704 0 : return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1705 : rpc_sh_user_flag_edit_internals);
1706 : }
1707 :
1708 0 : struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1709 : TALLOC_CTX *mem_ctx,
1710 : struct rpc_sh_ctx *ctx)
1711 : {
1712 : static struct rpc_sh_cmd cmds[] = {
1713 :
1714 : { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1715 : N_("Show/Set a user's full name") },
1716 :
1717 : { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1718 : N_("Show/Set a user's home directory") },
1719 :
1720 : { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1721 : N_("Show/Set a user's home drive") },
1722 :
1723 : { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1724 : N_("Show/Set a user's logon script") },
1725 :
1726 : { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1727 : N_("Show/Set a user's profile path") },
1728 :
1729 : { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1730 : N_("Show/Set a user's description") },
1731 :
1732 : { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1733 : N_("Show/Set whether a user is disabled") },
1734 :
1735 : { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1736 : N_("Show/Set whether a user locked out") },
1737 :
1738 : { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1739 : N_("Show/Set whether a user does not need a password") },
1740 :
1741 : { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1742 : N_("Show/Set whether a user's password does not expire") },
1743 :
1744 : { NULL, NULL, 0, NULL, NULL }
1745 : };
1746 :
1747 0 : return cmds;
1748 : }
1749 :
1750 0 : struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1751 : TALLOC_CTX *mem_ctx,
1752 : struct rpc_sh_ctx *ctx)
1753 : {
1754 : static struct rpc_sh_cmd cmds[] = {
1755 :
1756 : { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1757 : N_("List available users") },
1758 :
1759 : { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1760 : N_("List the domain groups a user is member of") },
1761 :
1762 : { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1763 : N_("Show info about a user") },
1764 :
1765 : { "edit", net_rpc_user_edit_cmds, 0, NULL,
1766 : N_("Show/Modify a user's fields") },
1767 :
1768 : { NULL, NULL, 0, NULL, NULL }
1769 : };
1770 :
1771 0 : return cmds;
1772 : }
1773 :
1774 : /****************************************************************************/
1775 :
1776 : /**
1777 : * Basic usage function for 'net rpc group'.
1778 : * @param argc Standard main() style argc.
1779 : * @param argv Standard main() style argv. Initial components are already
1780 : * stripped.
1781 : **/
1782 :
1783 0 : static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1784 : {
1785 0 : return net_group_usage(c, argc, argv);
1786 : }
1787 :
1788 : /**
1789 : * Delete group on a remote RPC server.
1790 : *
1791 : * All parameters are provided by the run_rpc_command function, except for
1792 : * argc, argv which are passed through.
1793 : *
1794 : * @param domain_sid The domain sid acquired from the remote server.
1795 : * @param cli A cli_state connected to the server.
1796 : * @param mem_ctx Talloc context, destroyed on completion of the function.
1797 : * @param argc Standard main() style argc.
1798 : * @param argv Standard main() style argv. Initial components are already
1799 : * stripped.
1800 : *
1801 : * @return Normal NTSTATUS return.
1802 : **/
1803 :
1804 70 : static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1805 : const struct dom_sid *domain_sid,
1806 : const char *domain_name,
1807 : struct cli_state *cli,
1808 : struct rpc_pipe_client *pipe_hnd,
1809 : TALLOC_CTX *mem_ctx,
1810 : int argc,
1811 : const char **argv)
1812 : {
1813 : struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1814 70 : bool group_is_primary = false;
1815 : NTSTATUS status, result;
1816 : uint32_t group_rid;
1817 70 : struct samr_RidAttrArray *rids = NULL;
1818 : /* char **names; */
1819 : uint32_t i;
1820 : /* struct samr_RidWithAttribute *user_gids; */
1821 70 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1822 :
1823 : struct samr_Ids group_rids, name_types;
1824 : struct lsa_String lsa_acct_name;
1825 70 : union samr_UserInfo *info = NULL;
1826 :
1827 70 : if (argc < 1 || c->display_usage) {
1828 0 : rpc_group_usage(c, argc,argv);
1829 0 : return NT_STATUS_OK; /* ok? */
1830 : }
1831 :
1832 70 : status = dcerpc_samr_Connect2(b, mem_ctx,
1833 70 : pipe_hnd->desthost,
1834 : MAXIMUM_ALLOWED_ACCESS,
1835 : &connect_pol,
1836 : &result);
1837 70 : if (!NT_STATUS_IS_OK(status)) {
1838 0 : d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1839 0 : goto done;
1840 : }
1841 :
1842 70 : if (!NT_STATUS_IS_OK(result)) {
1843 0 : status = result;
1844 0 : d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1845 0 : goto done;
1846 : }
1847 :
1848 70 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
1849 : &connect_pol,
1850 : MAXIMUM_ALLOWED_ACCESS,
1851 : discard_const_p(struct dom_sid2, domain_sid),
1852 : &domain_pol,
1853 : &result);
1854 70 : if (!NT_STATUS_IS_OK(status)) {
1855 0 : d_fprintf(stderr, _("Request open_domain failed\n"));
1856 0 : goto done;
1857 : }
1858 :
1859 70 : if (!NT_STATUS_IS_OK(result)) {
1860 0 : status = result;
1861 0 : d_fprintf(stderr, _("Request open_domain failed\n"));
1862 0 : goto done;
1863 : }
1864 :
1865 70 : init_lsa_String(&lsa_acct_name, argv[0]);
1866 :
1867 70 : status = dcerpc_samr_LookupNames(b, mem_ctx,
1868 : &domain_pol,
1869 : 1,
1870 : &lsa_acct_name,
1871 : &group_rids,
1872 : &name_types,
1873 : &result);
1874 70 : if (!NT_STATUS_IS_OK(status)) {
1875 0 : d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1876 0 : goto done;
1877 : }
1878 :
1879 70 : if (!NT_STATUS_IS_OK(result)) {
1880 0 : status = result;
1881 0 : d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1882 0 : goto done;
1883 : }
1884 70 : if (group_rids.count != 1) {
1885 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1886 0 : goto done;
1887 : }
1888 70 : if (name_types.count != 1) {
1889 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1890 0 : goto done;
1891 : }
1892 :
1893 70 : switch (name_types.ids[0])
1894 : {
1895 70 : case SID_NAME_DOM_GRP:
1896 70 : status = dcerpc_samr_OpenGroup(b, mem_ctx,
1897 : &domain_pol,
1898 : MAXIMUM_ALLOWED_ACCESS,
1899 70 : group_rids.ids[0],
1900 : &group_pol,
1901 : &result);
1902 70 : if (!NT_STATUS_IS_OK(status)) {
1903 0 : d_fprintf(stderr, _("Request open_group failed"));
1904 0 : goto done;
1905 : }
1906 :
1907 70 : if (!NT_STATUS_IS_OK(result)) {
1908 0 : status = result;
1909 0 : d_fprintf(stderr, _("Request open_group failed"));
1910 0 : goto done;
1911 : }
1912 :
1913 70 : group_rid = group_rids.ids[0];
1914 :
1915 70 : status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1916 : &group_pol,
1917 : &rids,
1918 : &result);
1919 70 : if (!NT_STATUS_IS_OK(status)) {
1920 0 : d_fprintf(stderr,
1921 0 : _("Unable to query group members of %s"),
1922 : argv[0]);
1923 0 : goto done;
1924 : }
1925 :
1926 70 : if (!NT_STATUS_IS_OK(result)) {
1927 0 : status = result;
1928 0 : d_fprintf(stderr,
1929 0 : _("Unable to query group members of %s"),
1930 : argv[0]);
1931 0 : goto done;
1932 : }
1933 :
1934 70 : if (c->opt_verbose) {
1935 0 : d_printf(
1936 0 : _("Domain Group %s (rid: %d) has %d members\n"),
1937 0 : argv[0],group_rid, rids->count);
1938 : }
1939 :
1940 : /* Check if group is anyone's primary group */
1941 140 : for (i = 0; i < rids->count; i++)
1942 : {
1943 70 : status = dcerpc_samr_OpenUser(b, mem_ctx,
1944 : &domain_pol,
1945 : MAXIMUM_ALLOWED_ACCESS,
1946 70 : rids->rids[i],
1947 : &user_pol,
1948 : &result);
1949 70 : if (!NT_STATUS_IS_OK(status)) {
1950 0 : d_fprintf(stderr,
1951 0 : _("Unable to open group member %d\n"),
1952 0 : rids->rids[i]);
1953 0 : goto done;
1954 : }
1955 :
1956 70 : if (!NT_STATUS_IS_OK(result)) {
1957 0 : status = result;
1958 0 : d_fprintf(stderr,
1959 0 : _("Unable to open group member %d\n"),
1960 0 : rids->rids[i]);
1961 0 : goto done;
1962 : }
1963 :
1964 70 : status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1965 : &user_pol,
1966 : 21,
1967 : &info,
1968 : &result);
1969 70 : if (!NT_STATUS_IS_OK(status)) {
1970 0 : d_fprintf(stderr,
1971 0 : _("Unable to lookup userinfo for group "
1972 : "member %d\n"),
1973 0 : rids->rids[i]);
1974 0 : goto done;
1975 : }
1976 :
1977 70 : if (!NT_STATUS_IS_OK(result)) {
1978 0 : status = result;
1979 0 : d_fprintf(stderr,
1980 0 : _("Unable to lookup userinfo for group "
1981 : "member %d\n"),
1982 0 : rids->rids[i]);
1983 0 : goto done;
1984 : }
1985 :
1986 70 : if (info->info21.primary_gid == group_rid) {
1987 0 : if (c->opt_verbose) {
1988 0 : d_printf(_("Group is primary group "
1989 : "of %s\n"),
1990 0 : info->info21.account_name.string);
1991 : }
1992 0 : group_is_primary = true;
1993 : }
1994 :
1995 70 : dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1996 : }
1997 :
1998 70 : if (group_is_primary) {
1999 0 : d_fprintf(stderr, _("Unable to delete group because "
2000 : "some of it's members have it as primary "
2001 : "group\n"));
2002 0 : status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
2003 0 : goto done;
2004 : }
2005 :
2006 : /* remove all group members */
2007 140 : for (i = 0; i < rids->count; i++)
2008 : {
2009 70 : if (c->opt_verbose)
2010 0 : d_printf(_("Remove group member %d..."),
2011 0 : rids->rids[i]);
2012 70 : status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2013 : &group_pol,
2014 70 : rids->rids[i],
2015 : &result);
2016 70 : if (!NT_STATUS_IS_OK(status)) {
2017 0 : goto done;
2018 : }
2019 70 : status = result;
2020 70 : if (NT_STATUS_IS_OK(result)) {
2021 70 : if (c->opt_verbose)
2022 0 : d_printf(_("ok\n"));
2023 : } else {
2024 0 : if (c->opt_verbose)
2025 0 : d_printf("%s\n", _("failed"));
2026 0 : goto done;
2027 : }
2028 : }
2029 :
2030 70 : status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
2031 : &group_pol,
2032 : &result);
2033 70 : if (!NT_STATUS_IS_OK(status)) {
2034 0 : break;
2035 : }
2036 :
2037 70 : status = result;
2038 :
2039 70 : break;
2040 : /* removing a local group is easier... */
2041 0 : case SID_NAME_ALIAS:
2042 0 : status = dcerpc_samr_OpenAlias(b, mem_ctx,
2043 : &domain_pol,
2044 : MAXIMUM_ALLOWED_ACCESS,
2045 0 : group_rids.ids[0],
2046 : &group_pol,
2047 : &result);
2048 0 : if (!NT_STATUS_IS_OK(status)) {
2049 0 : d_fprintf(stderr, _("Request open_alias failed\n"));
2050 0 : goto done;
2051 : }
2052 0 : if (!NT_STATUS_IS_OK(result)) {
2053 0 : status = result;
2054 0 : d_fprintf(stderr, _("Request open_alias failed\n"));
2055 0 : goto done;
2056 : }
2057 :
2058 0 : status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
2059 : &group_pol,
2060 : &result);
2061 0 : if (!NT_STATUS_IS_OK(status)) {
2062 0 : break;
2063 : }
2064 :
2065 0 : status = result;
2066 :
2067 0 : break;
2068 0 : default:
2069 0 : d_fprintf(stderr, _("%s is of type %s. This command is only "
2070 : "for deleting local or global groups\n"),
2071 0 : argv[0],sid_type_lookup(name_types.ids[0]));
2072 0 : status = NT_STATUS_UNSUCCESSFUL;
2073 0 : goto done;
2074 : }
2075 :
2076 70 : if (NT_STATUS_IS_OK(status)) {
2077 70 : if (c->opt_verbose)
2078 0 : d_printf(_("Deleted %s '%s'\n"),
2079 0 : sid_type_lookup(name_types.ids[0]), argv[0]);
2080 : } else {
2081 0 : d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
2082 : get_friendly_nt_error_msg(status));
2083 : }
2084 :
2085 70 : done:
2086 70 : return status;
2087 :
2088 : }
2089 :
2090 70 : static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
2091 : {
2092 70 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2093 : rpc_group_delete_internals, argc,argv);
2094 : }
2095 :
2096 70 : static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
2097 : {
2098 : NET_API_STATUS status;
2099 : struct GROUP_INFO_1 info1;
2100 70 : uint32_t parm_error = 0;
2101 :
2102 70 : if (argc != 1 || c->display_usage) {
2103 0 : rpc_group_usage(c, argc, argv);
2104 0 : return 0;
2105 : }
2106 :
2107 70 : ZERO_STRUCT(info1);
2108 :
2109 70 : info1.grpi1_name = argv[0];
2110 70 : if (c->opt_comment && strlen(c->opt_comment) > 0) {
2111 0 : info1.grpi1_comment = c->opt_comment;
2112 : }
2113 :
2114 70 : status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2115 :
2116 70 : if (status != 0) {
2117 0 : d_fprintf(stderr,
2118 0 : _("Failed to add group '%s' with error: %s.\n"),
2119 : argv[0], libnetapi_get_error_string(c->netapi_ctx,
2120 : status));
2121 0 : return -1;
2122 : } else {
2123 70 : d_printf(_("Added group '%s'.\n"), argv[0]);
2124 : }
2125 :
2126 70 : return 0;
2127 : }
2128 :
2129 0 : static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
2130 : {
2131 : NET_API_STATUS status;
2132 : struct LOCALGROUP_INFO_1 info1;
2133 0 : uint32_t parm_error = 0;
2134 :
2135 0 : if (argc != 1 || c->display_usage) {
2136 0 : rpc_group_usage(c, argc, argv);
2137 0 : return 0;
2138 : }
2139 :
2140 0 : ZERO_STRUCT(info1);
2141 :
2142 0 : info1.lgrpi1_name = argv[0];
2143 0 : if (c->opt_comment && strlen(c->opt_comment) > 0) {
2144 0 : info1.lgrpi1_comment = c->opt_comment;
2145 : }
2146 :
2147 0 : status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2148 :
2149 0 : if (status != 0) {
2150 0 : d_fprintf(stderr,
2151 0 : _("Failed to add alias '%s' with error: %s.\n"),
2152 : argv[0], libnetapi_get_error_string(c->netapi_ctx,
2153 : status));
2154 0 : return -1;
2155 : } else {
2156 0 : d_printf(_("Added alias '%s'.\n"), argv[0]);
2157 : }
2158 :
2159 0 : return 0;
2160 : }
2161 :
2162 70 : static int rpc_group_add(struct net_context *c, int argc, const char **argv)
2163 : {
2164 70 : if (c->opt_localgroup)
2165 0 : return rpc_alias_add_internals(c, argc, argv);
2166 :
2167 70 : return rpc_group_add_internals(c, argc, argv);
2168 : }
2169 :
2170 70 : static NTSTATUS get_sid_from_name(struct cli_state *cli,
2171 : TALLOC_CTX *mem_ctx,
2172 : const char *name,
2173 : struct dom_sid *sid,
2174 : enum lsa_SidType *type)
2175 : {
2176 70 : struct dom_sid *sids = NULL;
2177 70 : enum lsa_SidType *types = NULL;
2178 70 : struct rpc_pipe_client *pipe_hnd = NULL;
2179 : struct policy_handle lsa_pol;
2180 : NTSTATUS status, result;
2181 : struct dcerpc_binding_handle *b;
2182 :
2183 70 : status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
2184 : &pipe_hnd);
2185 70 : if (!NT_STATUS_IS_OK(status)) {
2186 0 : goto done;
2187 : }
2188 :
2189 70 : b = pipe_hnd->binding_handle;
2190 :
2191 70 : status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
2192 : SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2193 :
2194 70 : if (!NT_STATUS_IS_OK(status)) {
2195 0 : goto done;
2196 : }
2197 :
2198 70 : status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2199 : &name, NULL, 1, &sids, &types);
2200 :
2201 70 : if (NT_STATUS_IS_OK(status)) {
2202 70 : sid_copy(sid, &sids[0]);
2203 70 : *type = types[0];
2204 : }
2205 :
2206 70 : dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
2207 :
2208 70 : done:
2209 70 : if (pipe_hnd) {
2210 70 : TALLOC_FREE(pipe_hnd);
2211 : }
2212 :
2213 70 : if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
2214 :
2215 : /* Try as S-1-5-whatever */
2216 :
2217 : struct dom_sid tmp_sid;
2218 :
2219 0 : if (string_to_sid(&tmp_sid, name)) {
2220 0 : sid_copy(sid, &tmp_sid);
2221 0 : *type = SID_NAME_UNKNOWN;
2222 0 : status = NT_STATUS_OK;
2223 : }
2224 : }
2225 :
2226 70 : return status;
2227 : }
2228 :
2229 70 : static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2230 : TALLOC_CTX *mem_ctx,
2231 : const struct dom_sid *group_sid,
2232 : const char *member)
2233 : {
2234 : struct policy_handle connect_pol, domain_pol;
2235 : NTSTATUS status, result;
2236 : uint32_t group_rid;
2237 : struct policy_handle group_pol;
2238 70 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2239 :
2240 : struct samr_Ids rids, rid_types;
2241 : struct lsa_String lsa_acct_name;
2242 :
2243 : struct dom_sid sid;
2244 :
2245 70 : sid_copy(&sid, group_sid);
2246 :
2247 70 : if (!sid_split_rid(&sid, &group_rid)) {
2248 0 : return NT_STATUS_UNSUCCESSFUL;
2249 : }
2250 :
2251 : /* Get sam policy handle */
2252 70 : status = dcerpc_samr_Connect2(b, mem_ctx,
2253 70 : pipe_hnd->desthost,
2254 : MAXIMUM_ALLOWED_ACCESS,
2255 : &connect_pol,
2256 : &result);
2257 70 : if (!NT_STATUS_IS_OK(status)) {
2258 0 : return status;
2259 : }
2260 70 : if (!NT_STATUS_IS_OK(result)) {
2261 0 : return result;
2262 : }
2263 :
2264 : /* Get domain policy handle */
2265 70 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
2266 : &connect_pol,
2267 : MAXIMUM_ALLOWED_ACCESS,
2268 : &sid,
2269 : &domain_pol,
2270 : &result);
2271 70 : if (!NT_STATUS_IS_OK(status)) {
2272 0 : return status;
2273 : }
2274 70 : if (!NT_STATUS_IS_OK(result)) {
2275 0 : return result;
2276 : }
2277 :
2278 70 : init_lsa_String(&lsa_acct_name, member);
2279 :
2280 70 : status = dcerpc_samr_LookupNames(b, mem_ctx,
2281 : &domain_pol,
2282 : 1,
2283 : &lsa_acct_name,
2284 : &rids,
2285 : &rid_types,
2286 : &result);
2287 70 : if (!NT_STATUS_IS_OK(status)) {
2288 0 : d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2289 : member);
2290 0 : goto done;
2291 : }
2292 :
2293 70 : if (!NT_STATUS_IS_OK(result)) {
2294 0 : status = result;
2295 0 : d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2296 : member);
2297 0 : goto done;
2298 : }
2299 70 : if (rids.count != 1) {
2300 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2301 0 : goto done;
2302 : }
2303 70 : if (rid_types.count != 1) {
2304 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2305 0 : goto done;
2306 : }
2307 :
2308 70 : status = dcerpc_samr_OpenGroup(b, mem_ctx,
2309 : &domain_pol,
2310 : MAXIMUM_ALLOWED_ACCESS,
2311 : group_rid,
2312 : &group_pol,
2313 : &result);
2314 70 : if (!NT_STATUS_IS_OK(status)) {
2315 0 : goto done;
2316 : }
2317 :
2318 70 : if (!NT_STATUS_IS_OK(result)) {
2319 0 : status = result;
2320 0 : goto done;
2321 : }
2322 :
2323 70 : status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2324 : &group_pol,
2325 70 : rids.ids[0],
2326 : 0x0005, /* unknown flags */
2327 : &result);
2328 70 : if (!NT_STATUS_IS_OK(status)) {
2329 0 : goto done;
2330 : }
2331 :
2332 70 : status = result;
2333 :
2334 70 : done:
2335 70 : dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2336 70 : return status;
2337 : }
2338 :
2339 0 : static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2340 : struct cli_state *cli,
2341 : TALLOC_CTX *mem_ctx,
2342 : const struct dom_sid *alias_sid,
2343 : const char *member)
2344 : {
2345 : struct policy_handle connect_pol, domain_pol;
2346 : NTSTATUS status, result;
2347 : uint32_t alias_rid;
2348 : struct policy_handle alias_pol;
2349 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2350 :
2351 : struct dom_sid member_sid;
2352 : enum lsa_SidType member_type;
2353 :
2354 : struct dom_sid sid;
2355 :
2356 0 : sid_copy(&sid, alias_sid);
2357 :
2358 0 : if (!sid_split_rid(&sid, &alias_rid)) {
2359 0 : return NT_STATUS_UNSUCCESSFUL;
2360 : }
2361 :
2362 0 : result = get_sid_from_name(cli, mem_ctx,
2363 : member, &member_sid, &member_type);
2364 :
2365 0 : if (!NT_STATUS_IS_OK(result)) {
2366 0 : d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2367 : member);
2368 0 : return result;
2369 : }
2370 :
2371 : /* Get sam policy handle */
2372 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
2373 0 : pipe_hnd->desthost,
2374 : MAXIMUM_ALLOWED_ACCESS,
2375 : &connect_pol,
2376 : &result);
2377 0 : if (!NT_STATUS_IS_OK(status)) {
2378 0 : goto done;
2379 : }
2380 0 : if (!NT_STATUS_IS_OK(result)) {
2381 0 : status = result;
2382 0 : goto done;
2383 : }
2384 :
2385 : /* Get domain policy handle */
2386 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
2387 : &connect_pol,
2388 : MAXIMUM_ALLOWED_ACCESS,
2389 : &sid,
2390 : &domain_pol,
2391 : &result);
2392 0 : if (!NT_STATUS_IS_OK(status)) {
2393 0 : goto done;
2394 : }
2395 0 : if (!NT_STATUS_IS_OK(result)) {
2396 0 : status = result;
2397 0 : goto done;
2398 : }
2399 :
2400 0 : status = dcerpc_samr_OpenAlias(b, mem_ctx,
2401 : &domain_pol,
2402 : MAXIMUM_ALLOWED_ACCESS,
2403 : alias_rid,
2404 : &alias_pol,
2405 : &result);
2406 0 : if (!NT_STATUS_IS_OK(status)) {
2407 0 : return status;
2408 : }
2409 0 : if (!NT_STATUS_IS_OK(result)) {
2410 0 : return result;
2411 : }
2412 :
2413 0 : status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2414 : &alias_pol,
2415 : &member_sid,
2416 : &result);
2417 0 : if (!NT_STATUS_IS_OK(status)) {
2418 0 : return status;
2419 : }
2420 :
2421 0 : status = result;
2422 :
2423 0 : done:
2424 0 : dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2425 0 : return status;
2426 : }
2427 :
2428 70 : static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2429 : const struct dom_sid *domain_sid,
2430 : const char *domain_name,
2431 : struct cli_state *cli,
2432 : struct rpc_pipe_client *pipe_hnd,
2433 : TALLOC_CTX *mem_ctx,
2434 : int argc,
2435 : const char **argv)
2436 : {
2437 : struct dom_sid group_sid;
2438 : enum lsa_SidType group_type;
2439 :
2440 70 : if (argc != 2 || c->display_usage) {
2441 0 : d_printf("%s\n%s",
2442 : _("Usage:"),
2443 : _("net rpc group addmem <group> <member>\n"
2444 : " Add a member to a group\n"
2445 : " group\tGroup to add member to\n"
2446 : " member\tMember to add to group\n"));
2447 0 : return NT_STATUS_UNSUCCESSFUL;
2448 : }
2449 :
2450 70 : if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2451 : &group_sid, &group_type))) {
2452 0 : d_fprintf(stderr, _("Could not lookup group name %s\n"),
2453 : argv[0]);
2454 0 : return NT_STATUS_UNSUCCESSFUL;
2455 : }
2456 :
2457 70 : if (group_type == SID_NAME_DOM_GRP) {
2458 70 : NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2459 70 : &group_sid, argv[1]);
2460 :
2461 70 : if (!NT_STATUS_IS_OK(result)) {
2462 0 : d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2463 0 : argv[1], argv[0], nt_errstr(result));
2464 : }
2465 70 : return result;
2466 : }
2467 :
2468 0 : if (group_type == SID_NAME_ALIAS) {
2469 0 : NTSTATUS result = rpc_add_aliasmem(pipe_hnd, cli, mem_ctx,
2470 0 : &group_sid, argv[1]);
2471 :
2472 0 : if (!NT_STATUS_IS_OK(result)) {
2473 0 : d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2474 0 : argv[1], argv[0], nt_errstr(result));
2475 : }
2476 0 : return result;
2477 : }
2478 :
2479 0 : d_fprintf(stderr, _("Can only add members to global or local groups "
2480 : "which %s is not\n"), argv[0]);
2481 :
2482 0 : return NT_STATUS_UNSUCCESSFUL;
2483 : }
2484 :
2485 70 : static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2486 : {
2487 70 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2488 : rpc_group_addmem_internals,
2489 : argc, argv);
2490 : }
2491 :
2492 0 : static NTSTATUS rpc_del_groupmem(struct net_context *c,
2493 : struct rpc_pipe_client *pipe_hnd,
2494 : TALLOC_CTX *mem_ctx,
2495 : const struct dom_sid *group_sid,
2496 : const char *member)
2497 : {
2498 : struct policy_handle connect_pol, domain_pol;
2499 : NTSTATUS status, result;
2500 : uint32_t group_rid;
2501 : struct policy_handle group_pol;
2502 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2503 :
2504 : struct samr_Ids rids, rid_types;
2505 : struct lsa_String lsa_acct_name;
2506 :
2507 : struct dom_sid sid;
2508 :
2509 0 : sid_copy(&sid, group_sid);
2510 :
2511 0 : if (!sid_split_rid(&sid, &group_rid))
2512 0 : return NT_STATUS_UNSUCCESSFUL;
2513 :
2514 : /* Get sam policy handle */
2515 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
2516 0 : pipe_hnd->desthost,
2517 : MAXIMUM_ALLOWED_ACCESS,
2518 : &connect_pol,
2519 : &result);
2520 0 : if (!NT_STATUS_IS_OK(status)) {
2521 0 : return status;
2522 : }
2523 0 : if (!NT_STATUS_IS_OK(result)) {
2524 0 : return result;
2525 : }
2526 :
2527 :
2528 : /* Get domain policy handle */
2529 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
2530 : &connect_pol,
2531 : MAXIMUM_ALLOWED_ACCESS,
2532 : &sid,
2533 : &domain_pol,
2534 : &result);
2535 0 : if (!NT_STATUS_IS_OK(status)) {
2536 0 : return status;
2537 : }
2538 0 : if (!NT_STATUS_IS_OK(result)) {
2539 0 : return result;
2540 : }
2541 :
2542 0 : init_lsa_String(&lsa_acct_name, member);
2543 :
2544 0 : status = dcerpc_samr_LookupNames(b, mem_ctx,
2545 : &domain_pol,
2546 : 1,
2547 : &lsa_acct_name,
2548 : &rids,
2549 : &rid_types,
2550 : &result);
2551 0 : if (!NT_STATUS_IS_OK(status)) {
2552 0 : d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2553 : member);
2554 0 : goto done;
2555 : }
2556 :
2557 0 : if (!NT_STATUS_IS_OK(result)) {
2558 0 : status = result;
2559 0 : d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2560 : member);
2561 0 : goto done;
2562 : }
2563 0 : if (rids.count != 1) {
2564 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2565 0 : goto done;
2566 : }
2567 0 : if (rid_types.count != 1) {
2568 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2569 0 : goto done;
2570 : }
2571 :
2572 0 : status = dcerpc_samr_OpenGroup(b, mem_ctx,
2573 : &domain_pol,
2574 : MAXIMUM_ALLOWED_ACCESS,
2575 : group_rid,
2576 : &group_pol,
2577 : &result);
2578 0 : if (!NT_STATUS_IS_OK(status)) {
2579 0 : goto done;
2580 : }
2581 0 : if (!NT_STATUS_IS_OK(result)) {
2582 0 : status = result;
2583 0 : goto done;
2584 : }
2585 :
2586 0 : status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2587 : &group_pol,
2588 0 : rids.ids[0],
2589 : &result);
2590 0 : if (!NT_STATUS_IS_OK(status)) {
2591 0 : goto done;
2592 : }
2593 :
2594 0 : status = result;
2595 0 : done:
2596 0 : dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2597 0 : return status;
2598 : }
2599 :
2600 0 : static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2601 : struct cli_state *cli,
2602 : TALLOC_CTX *mem_ctx,
2603 : const struct dom_sid *alias_sid,
2604 : const char *member)
2605 : {
2606 : struct policy_handle connect_pol, domain_pol;
2607 : NTSTATUS status, result;
2608 : uint32_t alias_rid;
2609 : struct policy_handle alias_pol;
2610 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2611 :
2612 : struct dom_sid member_sid;
2613 : enum lsa_SidType member_type;
2614 :
2615 : struct dom_sid sid;
2616 :
2617 0 : sid_copy(&sid, alias_sid);
2618 :
2619 0 : if (!sid_split_rid(&sid, &alias_rid))
2620 0 : return NT_STATUS_UNSUCCESSFUL;
2621 :
2622 0 : result = get_sid_from_name(cli, mem_ctx,
2623 : member, &member_sid, &member_type);
2624 :
2625 0 : if (!NT_STATUS_IS_OK(result)) {
2626 0 : d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2627 : member);
2628 0 : return result;
2629 : }
2630 :
2631 : /* Get sam policy handle */
2632 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
2633 0 : pipe_hnd->desthost,
2634 : MAXIMUM_ALLOWED_ACCESS,
2635 : &connect_pol,
2636 : &result);
2637 0 : if (!NT_STATUS_IS_OK(status)) {
2638 0 : goto done;
2639 : }
2640 0 : if (!NT_STATUS_IS_OK(result)) {
2641 0 : status = result;
2642 0 : goto done;
2643 : }
2644 :
2645 : /* Get domain policy handle */
2646 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
2647 : &connect_pol,
2648 : MAXIMUM_ALLOWED_ACCESS,
2649 : &sid,
2650 : &domain_pol,
2651 : &result);
2652 0 : if (!NT_STATUS_IS_OK(status)) {
2653 0 : goto done;
2654 : }
2655 0 : if (!NT_STATUS_IS_OK(result)) {
2656 0 : status = result;
2657 0 : goto done;
2658 : }
2659 :
2660 0 : status = dcerpc_samr_OpenAlias(b, mem_ctx,
2661 : &domain_pol,
2662 : MAXIMUM_ALLOWED_ACCESS,
2663 : alias_rid,
2664 : &alias_pol,
2665 : &result);
2666 0 : if (!NT_STATUS_IS_OK(status)) {
2667 0 : return status;
2668 : }
2669 :
2670 0 : if (!NT_STATUS_IS_OK(result)) {
2671 0 : return result;
2672 : }
2673 :
2674 0 : status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2675 : &alias_pol,
2676 : &member_sid,
2677 : &result);
2678 :
2679 0 : if (!NT_STATUS_IS_OK(status)) {
2680 0 : return status;
2681 : }
2682 :
2683 0 : status = result;
2684 :
2685 0 : done:
2686 0 : dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2687 0 : return status;
2688 : }
2689 :
2690 0 : static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2691 : const struct dom_sid *domain_sid,
2692 : const char *domain_name,
2693 : struct cli_state *cli,
2694 : struct rpc_pipe_client *pipe_hnd,
2695 : TALLOC_CTX *mem_ctx,
2696 : int argc,
2697 : const char **argv)
2698 : {
2699 : struct dom_sid group_sid;
2700 : enum lsa_SidType group_type;
2701 :
2702 0 : if (argc != 2 || c->display_usage) {
2703 0 : d_printf("%s\n%s",
2704 : _("Usage:"),
2705 : _("net rpc group delmem <group> <member>\n"
2706 : " Delete a member from a group\n"
2707 : " group\tGroup to delete member from\n"
2708 : " member\tMember to delete from group\n"));
2709 0 : return NT_STATUS_UNSUCCESSFUL;
2710 : }
2711 :
2712 0 : if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2713 : &group_sid, &group_type))) {
2714 0 : d_fprintf(stderr, _("Could not lookup group name %s\n"),
2715 : argv[0]);
2716 0 : return NT_STATUS_UNSUCCESSFUL;
2717 : }
2718 :
2719 0 : if (group_type == SID_NAME_DOM_GRP) {
2720 0 : NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2721 0 : &group_sid, argv[1]);
2722 :
2723 0 : if (!NT_STATUS_IS_OK(result)) {
2724 0 : d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2725 0 : argv[1], argv[0], nt_errstr(result));
2726 : }
2727 0 : return result;
2728 : }
2729 :
2730 0 : if (group_type == SID_NAME_ALIAS) {
2731 0 : NTSTATUS result = rpc_del_aliasmem(pipe_hnd, cli, mem_ctx,
2732 0 : &group_sid, argv[1]);
2733 :
2734 0 : if (!NT_STATUS_IS_OK(result)) {
2735 0 : d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2736 0 : argv[1], argv[0], nt_errstr(result));
2737 : }
2738 0 : return result;
2739 : }
2740 :
2741 0 : d_fprintf(stderr, _("Can only delete members from global or local "
2742 : "groups which %s is not\n"), argv[0]);
2743 :
2744 0 : return NT_STATUS_UNSUCCESSFUL;
2745 : }
2746 :
2747 0 : static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2748 : {
2749 0 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2750 : rpc_group_delmem_internals,
2751 : argc, argv);
2752 : }
2753 :
2754 : /**
2755 : * List groups on a remote RPC server.
2756 : *
2757 : * All parameters are provided by the run_rpc_command function, except for
2758 : * argc, argv which are passes through.
2759 : *
2760 : * @param domain_sid The domain sid acquired from the remote server.
2761 : * @param cli A cli_state connected to the server.
2762 : * @param mem_ctx Talloc context, destroyed on completion of the function.
2763 : * @param argc Standard main() style argc.
2764 : * @param argv Standard main() style argv. Initial components are already
2765 : * stripped.
2766 : *
2767 : * @return Normal NTSTATUS return.
2768 : **/
2769 :
2770 0 : static NTSTATUS rpc_group_list_internals(struct net_context *c,
2771 : const struct dom_sid *domain_sid,
2772 : const char *domain_name,
2773 : struct cli_state *cli,
2774 : struct rpc_pipe_client *pipe_hnd,
2775 : TALLOC_CTX *mem_ctx,
2776 : int argc,
2777 : const char **argv)
2778 : {
2779 : struct policy_handle connect_pol, domain_pol;
2780 : NTSTATUS status, result;
2781 0 : uint32_t start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2782 0 : struct samr_SamArray *groups = NULL;
2783 0 : bool global = false;
2784 0 : bool local = false;
2785 0 : bool builtin = false;
2786 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2787 :
2788 0 : if (c->display_usage) {
2789 0 : d_printf("%s\n%s",
2790 : _("Usage:"),
2791 : _("net rpc group list [global] [local] [builtin]\n"
2792 : " List groups on RPC server\n"
2793 : " global\tList global groups\n"
2794 : " local\tList local groups\n"
2795 : " builtin\tList builtin groups\n"
2796 : " If none of global, local or builtin is "
2797 : "specified, all three options are considered "
2798 : "set\n"));
2799 0 : return NT_STATUS_OK;
2800 : }
2801 :
2802 0 : if (argc == 0) {
2803 0 : global = true;
2804 0 : local = true;
2805 0 : builtin = true;
2806 : }
2807 :
2808 0 : for (i=0; i<argc; i++) {
2809 0 : if (strequal(argv[i], "global"))
2810 0 : global = true;
2811 :
2812 0 : if (strequal(argv[i], "local"))
2813 0 : local = true;
2814 :
2815 0 : if (strequal(argv[i], "builtin"))
2816 0 : builtin = true;
2817 : }
2818 :
2819 : /* Get sam policy handle */
2820 :
2821 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
2822 0 : pipe_hnd->desthost,
2823 : MAXIMUM_ALLOWED_ACCESS,
2824 : &connect_pol,
2825 : &result);
2826 0 : if (!NT_STATUS_IS_OK(status)) {
2827 0 : goto done;
2828 : }
2829 0 : if (!NT_STATUS_IS_OK(result)) {
2830 0 : status = result;
2831 0 : goto done;
2832 : }
2833 :
2834 : /* Get domain policy handle */
2835 :
2836 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
2837 : &connect_pol,
2838 : MAXIMUM_ALLOWED_ACCESS,
2839 : discard_const_p(struct dom_sid2, domain_sid),
2840 : &domain_pol,
2841 : &result);
2842 0 : if (!NT_STATUS_IS_OK(status)) {
2843 0 : goto done;
2844 : }
2845 0 : if (!NT_STATUS_IS_OK(result)) {
2846 0 : status = result;
2847 0 : goto done;
2848 : }
2849 :
2850 : /* Query domain groups */
2851 0 : if (c->opt_long_list_entries)
2852 0 : d_printf(_("\nGroup name Comment"
2853 : "\n-----------------------------\n"));
2854 : do {
2855 : uint32_t max_size, total_size, returned_size;
2856 : union samr_DispInfo info;
2857 :
2858 0 : if (!global) break;
2859 :
2860 0 : dcerpc_get_query_dispinfo_params(
2861 : loop_count, &max_entries, &max_size);
2862 :
2863 0 : status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2864 : &domain_pol,
2865 : 3,
2866 : start_idx,
2867 : max_entries,
2868 : max_size,
2869 : &total_size,
2870 : &returned_size,
2871 : &info,
2872 : &result);
2873 0 : if (!NT_STATUS_IS_OK(status)) {
2874 0 : goto done;
2875 : }
2876 0 : num_entries = info.info3.count;
2877 0 : start_idx += info.info3.count;
2878 :
2879 0 : if (!NT_STATUS_IS_OK(result) &&
2880 0 : !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2881 0 : break;
2882 :
2883 0 : for (i = 0; i < num_entries; i++) {
2884 :
2885 0 : const char *group = NULL;
2886 0 : const char *desc = NULL;
2887 :
2888 0 : group = info.info3.entries[i].account_name.string;
2889 0 : desc = info.info3.entries[i].description.string;
2890 :
2891 0 : if (c->opt_long_list_entries)
2892 0 : printf("%-21.21s %-50.50s\n",
2893 : group, desc);
2894 : else
2895 0 : printf("%s\n", group);
2896 : }
2897 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2898 : /* query domain aliases */
2899 0 : start_idx = 0;
2900 : do {
2901 0 : if (!local) break;
2902 :
2903 0 : status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2904 : &domain_pol,
2905 : &start_idx,
2906 : &groups,
2907 : 0xffff,
2908 : &num_entries,
2909 : &result);
2910 0 : if (!NT_STATUS_IS_OK(status)) {
2911 0 : goto done;
2912 : }
2913 0 : if (!NT_STATUS_IS_OK(result) &&
2914 0 : !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2915 0 : break;
2916 :
2917 0 : for (i = 0; i < num_entries; i++) {
2918 :
2919 0 : const char *description = NULL;
2920 :
2921 0 : if (c->opt_long_list_entries) {
2922 :
2923 : struct policy_handle alias_pol;
2924 0 : union samr_AliasInfo *info = NULL;
2925 : NTSTATUS _result;
2926 :
2927 0 : status = dcerpc_samr_OpenAlias(b, mem_ctx,
2928 : &domain_pol,
2929 : 0x8,
2930 0 : groups->entries[i].idx,
2931 : &alias_pol,
2932 : &_result);
2933 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2934 0 : status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2935 : &alias_pol,
2936 : 3,
2937 : &info,
2938 : &_result);
2939 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2940 0 : status = dcerpc_samr_Close(b, mem_ctx,
2941 : &alias_pol,
2942 : &_result);
2943 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2944 0 : description = info->description.string;
2945 : }
2946 : }
2947 : }
2948 : }
2949 :
2950 0 : if (description != NULL) {
2951 0 : printf("%-21.21s %-50.50s\n",
2952 0 : groups->entries[i].name.string,
2953 : description);
2954 : } else {
2955 0 : printf("%s\n", groups->entries[i].name.string);
2956 : }
2957 : }
2958 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2959 0 : dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2960 : /* Get builtin policy handle */
2961 :
2962 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
2963 : &connect_pol,
2964 : MAXIMUM_ALLOWED_ACCESS,
2965 : discard_const_p(struct dom_sid2, &global_sid_Builtin),
2966 : &domain_pol,
2967 : &result);
2968 0 : if (!NT_STATUS_IS_OK(status)) {
2969 0 : goto done;
2970 : }
2971 0 : if (!NT_STATUS_IS_OK(result)) {
2972 0 : status = result;
2973 0 : goto done;
2974 : }
2975 :
2976 : /* query builtin aliases */
2977 0 : start_idx = 0;
2978 : do {
2979 0 : if (!builtin) break;
2980 :
2981 0 : status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2982 : &domain_pol,
2983 : &start_idx,
2984 : &groups,
2985 : max_entries,
2986 : &num_entries,
2987 : &result);
2988 0 : if (!NT_STATUS_IS_OK(status)) {
2989 0 : break;
2990 : }
2991 0 : if (!NT_STATUS_IS_OK(result) &&
2992 0 : !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2993 0 : status = result;
2994 0 : break;
2995 : }
2996 :
2997 0 : for (i = 0; i < num_entries; i++) {
2998 :
2999 0 : const char *description = NULL;
3000 :
3001 0 : if (c->opt_long_list_entries) {
3002 :
3003 : struct policy_handle alias_pol;
3004 0 : union samr_AliasInfo *info = NULL;
3005 : NTSTATUS _result;
3006 :
3007 0 : status = dcerpc_samr_OpenAlias(b, mem_ctx,
3008 : &domain_pol,
3009 : 0x8,
3010 0 : groups->entries[i].idx,
3011 : &alias_pol,
3012 : &_result);
3013 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3014 0 : status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
3015 : &alias_pol,
3016 : 3,
3017 : &info,
3018 : &_result);
3019 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3020 0 : status = dcerpc_samr_Close(b, mem_ctx,
3021 : &alias_pol,
3022 : &_result);
3023 0 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3024 0 : description = info->description.string;
3025 : }
3026 : }
3027 : }
3028 : }
3029 :
3030 0 : if (description != NULL) {
3031 0 : printf("%-21.21s %-50.50s\n",
3032 0 : groups->entries[i].name.string,
3033 : description);
3034 : } else {
3035 0 : printf("%s\n", groups->entries[i].name.string);
3036 : }
3037 : }
3038 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3039 :
3040 0 : status = result;
3041 :
3042 0 : done:
3043 0 : return status;
3044 : }
3045 :
3046 0 : static int rpc_group_list(struct net_context *c, int argc, const char **argv)
3047 : {
3048 0 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3049 : rpc_group_list_internals,
3050 : argc, argv);
3051 : }
3052 :
3053 0 : static NTSTATUS rpc_list_group_members(struct net_context *c,
3054 : struct rpc_pipe_client *pipe_hnd,
3055 : TALLOC_CTX *mem_ctx,
3056 : const char *domain_name,
3057 : const struct dom_sid *domain_sid,
3058 : struct policy_handle *domain_pol,
3059 : uint32_t rid)
3060 : {
3061 : NTSTATUS result, status;
3062 : struct policy_handle group_pol;
3063 : uint32_t num_members, *group_rids;
3064 : uint32_t i;
3065 0 : struct samr_RidAttrArray *rids = NULL;
3066 : struct lsa_Strings names;
3067 : struct samr_Ids types;
3068 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3069 :
3070 0 : status = dcerpc_samr_OpenGroup(b, mem_ctx,
3071 : domain_pol,
3072 : MAXIMUM_ALLOWED_ACCESS,
3073 : rid,
3074 : &group_pol,
3075 : &result);
3076 0 : if (!NT_STATUS_IS_OK(status)) {
3077 0 : return status;
3078 : }
3079 0 : if (!NT_STATUS_IS_OK(result)) {
3080 0 : return result;
3081 : }
3082 :
3083 0 : status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
3084 : &group_pol,
3085 : &rids,
3086 : &result);
3087 0 : if (!NT_STATUS_IS_OK(status)) {
3088 0 : return status;
3089 : }
3090 0 : if (!NT_STATUS_IS_OK(result)) {
3091 0 : return result;
3092 : }
3093 :
3094 0 : num_members = rids->count;
3095 0 : group_rids = rids->rids;
3096 :
3097 0 : while (num_members > 0) {
3098 0 : uint32_t this_time = 512;
3099 :
3100 0 : if (num_members < this_time)
3101 0 : this_time = num_members;
3102 :
3103 0 : status = dcerpc_samr_LookupRids(b, mem_ctx,
3104 : domain_pol,
3105 : this_time,
3106 : group_rids,
3107 : &names,
3108 : &types,
3109 : &result);
3110 0 : if (!NT_STATUS_IS_OK(status)) {
3111 0 : return status;
3112 : }
3113 0 : if (!NT_STATUS_IS_OK(result)) {
3114 0 : return result;
3115 : }
3116 0 : if (names.count != this_time) {
3117 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3118 : }
3119 0 : if (types.count != this_time) {
3120 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3121 : }
3122 : /* We only have users as members, but make the output
3123 : the same as the output of alias members */
3124 :
3125 0 : for (i = 0; i < this_time; i++) {
3126 :
3127 0 : if (c->opt_long_list_entries) {
3128 : struct dom_sid sid;
3129 : struct dom_sid_buf sid_str;
3130 :
3131 0 : sid_compose(&sid, domain_sid, group_rids[i]);
3132 :
3133 0 : printf("%s %s\\%s %d\n",
3134 : dom_sid_str_buf(&sid, &sid_str),
3135 : domain_name,
3136 0 : names.names[i].string,
3137 : SID_NAME_USER);
3138 : } else {
3139 0 : printf("%s\\%s\n", domain_name,
3140 0 : names.names[i].string);
3141 : }
3142 : }
3143 :
3144 0 : num_members -= this_time;
3145 0 : group_rids += 512;
3146 : }
3147 :
3148 0 : return NT_STATUS_OK;
3149 : }
3150 :
3151 0 : static NTSTATUS rpc_list_alias_members(struct net_context *c,
3152 : struct rpc_pipe_client *pipe_hnd,
3153 : struct cli_state *cli,
3154 : TALLOC_CTX *mem_ctx,
3155 : struct policy_handle *domain_pol,
3156 : uint32_t rid)
3157 : {
3158 : NTSTATUS result, status;
3159 : struct rpc_pipe_client *lsa_pipe;
3160 : struct policy_handle alias_pol, lsa_pol;
3161 : uint32_t num_members;
3162 : struct dom_sid *alias_sids;
3163 : char **domains;
3164 : char **names;
3165 : enum lsa_SidType *types;
3166 : uint32_t i;
3167 : struct lsa_SidArray sid_array;
3168 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3169 :
3170 0 : status = dcerpc_samr_OpenAlias(b, mem_ctx,
3171 : domain_pol,
3172 : MAXIMUM_ALLOWED_ACCESS,
3173 : rid,
3174 : &alias_pol,
3175 : &result);
3176 0 : if (!NT_STATUS_IS_OK(status)) {
3177 0 : return status;
3178 : }
3179 0 : if (!NT_STATUS_IS_OK(result)) {
3180 0 : return result;
3181 : }
3182 :
3183 0 : status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
3184 : &alias_pol,
3185 : &sid_array,
3186 : &result);
3187 0 : if (!NT_STATUS_IS_OK(status)) {
3188 0 : d_fprintf(stderr, _("Couldn't list alias members\n"));
3189 0 : return status;
3190 : }
3191 0 : if (!NT_STATUS_IS_OK(result)) {
3192 0 : d_fprintf(stderr, _("Couldn't list alias members\n"));
3193 0 : return result;
3194 : }
3195 :
3196 0 : num_members = sid_array.num_sids;
3197 :
3198 0 : if (num_members == 0) {
3199 0 : return NT_STATUS_OK;
3200 : }
3201 :
3202 0 : result = cli_rpc_pipe_open_noauth(cli,
3203 : &ndr_table_lsarpc,
3204 : &lsa_pipe);
3205 0 : if (!NT_STATUS_IS_OK(result)) {
3206 0 : d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
3207 : nt_errstr(result) );
3208 0 : return result;
3209 : }
3210 :
3211 0 : result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
3212 : SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
3213 :
3214 0 : if (!NT_STATUS_IS_OK(result)) {
3215 0 : d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
3216 0 : TALLOC_FREE(lsa_pipe);
3217 0 : return result;
3218 : }
3219 :
3220 0 : alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
3221 0 : if (!alias_sids) {
3222 0 : d_fprintf(stderr, _("Out of memory\n"));
3223 0 : TALLOC_FREE(lsa_pipe);
3224 0 : return NT_STATUS_NO_MEMORY;
3225 : }
3226 :
3227 0 : for (i=0; i<num_members; i++) {
3228 0 : sid_copy(&alias_sids[i], sid_array.sids[i].sid);
3229 : }
3230 :
3231 0 : result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
3232 : num_members, alias_sids,
3233 : &domains, &names, &types);
3234 :
3235 0 : if (!NT_STATUS_IS_OK(result) &&
3236 0 : !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3237 0 : d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
3238 0 : TALLOC_FREE(lsa_pipe);
3239 0 : return result;
3240 : }
3241 :
3242 0 : for (i = 0; i < num_members; i++) {
3243 : struct dom_sid_buf sid_str;
3244 0 : dom_sid_str_buf(&alias_sids[i], &sid_str);
3245 :
3246 0 : if (c->opt_long_list_entries) {
3247 0 : printf("%s %s\\%s %d\n", sid_str.buf,
3248 0 : domains[i] ? domains[i] : _("*unknown*"),
3249 0 : names[i] ? names[i] : _("*unknown*"), types[i]);
3250 : } else {
3251 0 : if (domains[i])
3252 0 : printf("%s\\%s\n", domains[i], names[i]);
3253 : else
3254 0 : printf("%s\n", sid_str.buf);
3255 : }
3256 : }
3257 :
3258 0 : TALLOC_FREE(lsa_pipe);
3259 0 : return NT_STATUS_OK;
3260 : }
3261 :
3262 0 : static NTSTATUS rpc_group_members_internals(struct net_context *c,
3263 : const struct dom_sid *domain_sid,
3264 : const char *domain_name,
3265 : struct cli_state *cli,
3266 : struct rpc_pipe_client *pipe_hnd,
3267 : TALLOC_CTX *mem_ctx,
3268 : int argc,
3269 : const char **argv)
3270 : {
3271 : NTSTATUS result, status;
3272 : struct policy_handle connect_pol, domain_pol;
3273 : struct samr_Ids rids, rid_types;
3274 : struct lsa_String lsa_acct_name;
3275 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3276 :
3277 : /* Get sam policy handle */
3278 :
3279 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
3280 0 : pipe_hnd->desthost,
3281 : MAXIMUM_ALLOWED_ACCESS,
3282 : &connect_pol,
3283 : &result);
3284 0 : if (!NT_STATUS_IS_OK(status)) {
3285 0 : return status;
3286 : }
3287 0 : if (!NT_STATUS_IS_OK(result)) {
3288 0 : return result;
3289 : }
3290 :
3291 : /* Get domain policy handle */
3292 :
3293 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
3294 : &connect_pol,
3295 : MAXIMUM_ALLOWED_ACCESS,
3296 : discard_const_p(struct dom_sid2, domain_sid),
3297 : &domain_pol,
3298 : &result);
3299 0 : if (!NT_STATUS_IS_OK(status)) {
3300 0 : return status;
3301 : }
3302 0 : if (!NT_STATUS_IS_OK(result)) {
3303 0 : return result;
3304 : }
3305 :
3306 0 : init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3307 :
3308 0 : status = dcerpc_samr_LookupNames(b, mem_ctx,
3309 : &domain_pol,
3310 : 1,
3311 : &lsa_acct_name,
3312 : &rids,
3313 : &rid_types,
3314 : &result);
3315 0 : if (!NT_STATUS_IS_OK(status)) {
3316 0 : return status;
3317 : }
3318 :
3319 0 : if (!NT_STATUS_IS_OK(result)) {
3320 :
3321 : /* Ok, did not find it in the global sam, try with builtin */
3322 :
3323 : struct dom_sid sid_Builtin;
3324 :
3325 0 : dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3326 :
3327 0 : sid_copy(&sid_Builtin, &global_sid_Builtin);
3328 :
3329 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
3330 : &connect_pol,
3331 : MAXIMUM_ALLOWED_ACCESS,
3332 : &sid_Builtin,
3333 : &domain_pol,
3334 : &result);
3335 0 : if (!NT_STATUS_IS_OK(status)) {
3336 0 : return status;
3337 : }
3338 0 : if (!NT_STATUS_IS_OK(result)) {
3339 0 : d_fprintf(stderr, _("Couldn't find group %s\n"),
3340 : argv[0]);
3341 0 : return result;
3342 : }
3343 :
3344 0 : status = dcerpc_samr_LookupNames(b, mem_ctx,
3345 : &domain_pol,
3346 : 1,
3347 : &lsa_acct_name,
3348 : &rids,
3349 : &rid_types,
3350 : &result);
3351 0 : if (!NT_STATUS_IS_OK(status)) {
3352 0 : return status;
3353 : }
3354 0 : if (!NT_STATUS_IS_OK(result)) {
3355 0 : d_fprintf(stderr, _("Couldn't find group %s\n"),
3356 : argv[0]);
3357 0 : return result;
3358 : }
3359 : }
3360 :
3361 0 : if (rids.count != 1) {
3362 0 : d_fprintf(stderr, _("Couldn't find group %s\n"),
3363 : argv[0]);
3364 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3365 : }
3366 0 : if (rid_types.count != 1) {
3367 0 : d_fprintf(stderr, _("Couldn't find group %s\n"),
3368 : argv[0]);
3369 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
3370 : }
3371 :
3372 :
3373 0 : if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3374 0 : return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3375 : domain_sid, &domain_pol,
3376 0 : rids.ids[0]);
3377 : }
3378 :
3379 0 : if (rid_types.ids[0] == SID_NAME_ALIAS) {
3380 0 : return rpc_list_alias_members(c, pipe_hnd, cli, mem_ctx, &domain_pol,
3381 0 : rids.ids[0]);
3382 : }
3383 :
3384 0 : return NT_STATUS_NO_SUCH_GROUP;
3385 : }
3386 :
3387 0 : static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3388 : {
3389 0 : if (argc != 1 || c->display_usage) {
3390 0 : return rpc_group_usage(c, argc, argv);
3391 : }
3392 :
3393 0 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3394 : rpc_group_members_internals,
3395 : argc, argv);
3396 : }
3397 :
3398 0 : static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3399 : {
3400 : NET_API_STATUS status;
3401 : struct GROUP_INFO_0 g0;
3402 : uint32_t parm_err;
3403 :
3404 0 : if (argc != 2) {
3405 0 : d_printf(_("Usage:\n"));
3406 0 : d_printf("net rpc group rename group newname\n");
3407 0 : return -1;
3408 : }
3409 :
3410 0 : g0.grpi0_name = argv[1];
3411 :
3412 0 : status = NetGroupSetInfo(c->opt_host,
3413 : argv[0],
3414 : 0,
3415 : (uint8_t *)&g0,
3416 : &parm_err);
3417 :
3418 0 : if (status != 0) {
3419 0 : d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3420 : argv[0], libnetapi_get_error_string(c->netapi_ctx,
3421 : status));
3422 0 : return -1;
3423 : }
3424 :
3425 0 : return 0;
3426 : }
3427 :
3428 0 : static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3429 : {
3430 0 : if (argc != 2 || c->display_usage) {
3431 0 : return rpc_group_usage(c, argc, argv);
3432 : }
3433 :
3434 0 : return rpc_group_rename_internals(c, argc, argv);
3435 : }
3436 :
3437 : /**
3438 : * 'net rpc group' entrypoint.
3439 : * @param argc Standard main() style argc.
3440 : * @param argv Standard main() style argv. Initial components are already
3441 : * stripped.
3442 : **/
3443 :
3444 210 : int net_rpc_group(struct net_context *c, int argc, const char **argv)
3445 : {
3446 : NET_API_STATUS status;
3447 :
3448 210 : struct functable func[] = {
3449 : {
3450 : "add",
3451 : rpc_group_add,
3452 : NET_TRANSPORT_RPC,
3453 : N_("Create specified group"),
3454 : N_("net rpc group add\n"
3455 : " Create specified group")
3456 : },
3457 : {
3458 : "delete",
3459 : rpc_group_delete,
3460 : NET_TRANSPORT_RPC,
3461 : N_("Delete specified group"),
3462 : N_("net rpc group delete\n"
3463 : " Delete specified group")
3464 : },
3465 : {
3466 : "addmem",
3467 : rpc_group_addmem,
3468 : NET_TRANSPORT_RPC,
3469 : N_("Add member to group"),
3470 : N_("net rpc group addmem\n"
3471 : " Add member to group")
3472 : },
3473 : {
3474 : "delmem",
3475 : rpc_group_delmem,
3476 : NET_TRANSPORT_RPC,
3477 : N_("Remove member from group"),
3478 : N_("net rpc group delmem\n"
3479 : " Remove member from group")
3480 : },
3481 : {
3482 : "list",
3483 : rpc_group_list,
3484 : NET_TRANSPORT_RPC,
3485 : N_("List groups"),
3486 : N_("net rpc group list\n"
3487 : " List groups")
3488 : },
3489 : {
3490 : "members",
3491 : rpc_group_members,
3492 : NET_TRANSPORT_RPC,
3493 : N_("List group members"),
3494 : N_("net rpc group members\n"
3495 : " List group members")
3496 : },
3497 : {
3498 : "rename",
3499 : rpc_group_rename,
3500 : NET_TRANSPORT_RPC,
3501 : N_("Rename group"),
3502 : N_("net rpc group rename\n"
3503 : " Rename group")
3504 : },
3505 : {NULL, NULL, 0, NULL, NULL}
3506 : };
3507 :
3508 210 : status = libnetapi_net_init(&c->netapi_ctx);
3509 210 : if (status != 0) {
3510 0 : return -1;
3511 : }
3512 :
3513 210 : status = libnetapi_set_creds(c->netapi_ctx, c->creds);
3514 210 : if (status != 0) {
3515 0 : return -1;
3516 : }
3517 :
3518 210 : if (argc == 0) {
3519 0 : if (c->display_usage) {
3520 0 : d_printf(_("Usage:\n"));
3521 0 : d_printf(_("net rpc group\n"
3522 : " Alias for net rpc group list global "
3523 : "local builtin\n"));
3524 0 : net_display_usage_from_functable(func);
3525 0 : return 0;
3526 : }
3527 :
3528 0 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3529 : rpc_group_list_internals,
3530 : argc, argv);
3531 : }
3532 :
3533 210 : return net_run_function(c, argc, argv, "net rpc group", func);
3534 : }
3535 :
3536 : /****************************************************************************/
3537 :
3538 0 : static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3539 : {
3540 0 : return net_share_usage(c, argc, argv);
3541 : }
3542 :
3543 : /**
3544 : * Add a share on a remote RPC server.
3545 : *
3546 : * @param argc Standard main() style argc.
3547 : * @param argv Standard main() style argv. Initial components are already
3548 : * stripped.
3549 : *
3550 : * @return A shell status integer (0 for success).
3551 : **/
3552 :
3553 0 : static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3554 : {
3555 : NET_API_STATUS status;
3556 : char *sharename;
3557 : char *path;
3558 0 : uint32_t type = STYPE_DISKTREE; /* only allow disk shares to be added */
3559 0 : uint32_t num_users=0, perms=0;
3560 0 : char *password=NULL; /* don't allow a share password */
3561 : struct SHARE_INFO_2 i2;
3562 0 : uint32_t parm_error = 0;
3563 :
3564 0 : if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3565 0 : return rpc_share_usage(c, argc, argv);
3566 : }
3567 :
3568 0 : if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3569 0 : return -1;
3570 : }
3571 :
3572 0 : path = strchr(sharename, '=');
3573 0 : if (!path) {
3574 0 : return -1;
3575 : }
3576 :
3577 0 : *path++ = '\0';
3578 :
3579 0 : i2.shi2_netname = sharename;
3580 0 : i2.shi2_type = type;
3581 0 : i2.shi2_remark = c->opt_comment;
3582 0 : i2.shi2_permissions = perms;
3583 0 : i2.shi2_max_uses = c->opt_maxusers;
3584 0 : i2.shi2_current_uses = num_users;
3585 0 : i2.shi2_path = path;
3586 0 : i2.shi2_passwd = password;
3587 :
3588 0 : status = NetShareAdd(c->opt_host,
3589 : 2,
3590 : (uint8_t *)&i2,
3591 : &parm_error);
3592 0 : if (status != 0) {
3593 0 : printf(_("NetShareAdd failed with: %s\n"),
3594 : libnetapi_get_error_string(c->netapi_ctx, status));
3595 : }
3596 :
3597 0 : return status;
3598 : }
3599 :
3600 : /**
3601 : * Delete a share on a remote RPC server.
3602 : *
3603 : * @param domain_sid The domain sid acquired from the remote server.
3604 : * @param argc Standard main() style argc.
3605 : * @param argv Standard main() style argv. Initial components are already
3606 : * stripped.
3607 : *
3608 : * @return A shell status integer (0 for success).
3609 : **/
3610 0 : static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3611 : {
3612 0 : if (argc < 1 || c->display_usage) {
3613 0 : return rpc_share_usage(c, argc, argv);
3614 : }
3615 :
3616 0 : return NetShareDel(c->opt_host, argv[0], 0);
3617 : }
3618 :
3619 : /**
3620 : * Formatted print of share info
3621 : *
3622 : * @param r pointer to SHARE_INFO_1 to format
3623 : **/
3624 :
3625 0 : static void display_share_info_1(struct net_context *c,
3626 : struct SHARE_INFO_1 *r)
3627 : {
3628 0 : if (c->opt_long_list_entries) {
3629 0 : d_printf("%-12s %-8.8s %-50s\n",
3630 : r->shi1_netname,
3631 0 : net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3632 : r->shi1_remark);
3633 : } else {
3634 0 : d_printf("%s\n", r->shi1_netname);
3635 : }
3636 0 : }
3637 :
3638 0 : static WERROR get_share_info(struct net_context *c,
3639 : struct rpc_pipe_client *pipe_hnd,
3640 : TALLOC_CTX *mem_ctx,
3641 : uint32_t level,
3642 : int argc,
3643 : const char **argv,
3644 : struct srvsvc_NetShareInfoCtr *info_ctr)
3645 : {
3646 : WERROR result;
3647 : NTSTATUS status;
3648 : union srvsvc_NetShareInfo info;
3649 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3650 :
3651 : /* no specific share requested, enumerate all */
3652 0 : if (argc == 0) {
3653 :
3654 0 : uint32_t preferred_len = 0xffffffff;
3655 0 : uint32_t total_entries = 0;
3656 0 : uint32_t resume_handle = 0;
3657 :
3658 0 : info_ctr->level = level;
3659 :
3660 0 : status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3661 0 : pipe_hnd->desthost,
3662 : info_ctr,
3663 : preferred_len,
3664 : &total_entries,
3665 : &resume_handle,
3666 : &result);
3667 0 : if (!NT_STATUS_IS_OK(status)) {
3668 0 : return ntstatus_to_werror(status);
3669 : }
3670 0 : return result;
3671 : }
3672 :
3673 : /* request just one share */
3674 0 : status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3675 0 : pipe_hnd->desthost,
3676 : argv[0],
3677 : level,
3678 : &info,
3679 : &result);
3680 :
3681 0 : if (!NT_STATUS_IS_OK(status)) {
3682 0 : result = ntstatus_to_werror(status);
3683 0 : goto done;
3684 : }
3685 :
3686 0 : if (!W_ERROR_IS_OK(result)) {
3687 0 : goto done;
3688 : }
3689 :
3690 : /* construct ctr */
3691 0 : ZERO_STRUCTP(info_ctr);
3692 :
3693 0 : info_ctr->level = level;
3694 :
3695 0 : switch (level) {
3696 0 : case 1:
3697 : {
3698 : struct srvsvc_NetShareCtr1 *ctr1;
3699 :
3700 0 : ctr1 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr1);
3701 0 : W_ERROR_HAVE_NO_MEMORY(ctr1);
3702 :
3703 0 : ctr1->count = 1;
3704 0 : ctr1->array = info.info1;
3705 :
3706 0 : info_ctr->ctr.ctr1 = ctr1;
3707 :
3708 0 : break;
3709 : }
3710 0 : case 2:
3711 : {
3712 : struct srvsvc_NetShareCtr2 *ctr2;
3713 :
3714 0 : ctr2 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr2);
3715 0 : W_ERROR_HAVE_NO_MEMORY(ctr2);
3716 :
3717 0 : ctr2->count = 1;
3718 0 : ctr2->array = info.info2;
3719 :
3720 0 : info_ctr->ctr.ctr2 = ctr2;
3721 :
3722 0 : break;
3723 : }
3724 0 : case 502:
3725 : {
3726 : struct srvsvc_NetShareCtr502 *ctr502;
3727 :
3728 0 : ctr502 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr502);
3729 0 : W_ERROR_HAVE_NO_MEMORY(ctr502);
3730 :
3731 0 : ctr502->count = 1;
3732 0 : ctr502->array = info.info502;
3733 :
3734 0 : info_ctr->ctr.ctr502 = ctr502;
3735 :
3736 0 : break;
3737 : }
3738 : } /* switch */
3739 0 : done:
3740 0 : return result;
3741 : }
3742 :
3743 : /***
3744 : * 'net rpc share list' entrypoint.
3745 : * @param argc Standard main() style argc.
3746 : * @param argv Standard main() style argv. Initial components are already
3747 : * stripped.
3748 : **/
3749 0 : static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3750 : {
3751 : NET_API_STATUS status;
3752 0 : struct SHARE_INFO_1 *i1 = NULL;
3753 0 : uint32_t entries_read = 0;
3754 0 : uint32_t total_entries = 0;
3755 0 : uint32_t resume_handle = 0;
3756 0 : uint32_t i, level = 1;
3757 :
3758 0 : if (c->display_usage) {
3759 0 : d_printf( "%s\n"
3760 : "net rpc share list\n"
3761 : " %s\n",
3762 : _("Usage:"),
3763 : _("List shares on remote server"));
3764 0 : return 0;
3765 : }
3766 :
3767 0 : status = NetShareEnum(c->opt_host,
3768 : level,
3769 : (uint8_t **)(void *)&i1,
3770 : (uint32_t)-1,
3771 : &entries_read,
3772 : &total_entries,
3773 : &resume_handle);
3774 0 : if (status != 0) {
3775 0 : goto done;
3776 : }
3777 :
3778 : /* Display results */
3779 :
3780 0 : if (c->opt_long_list_entries) {
3781 0 : d_printf(_(
3782 : "\nEnumerating shared resources (exports) on remote server:\n\n"
3783 : "\nShare name Type Description\n"
3784 : "---------- ---- -----------\n"));
3785 : }
3786 0 : for (i = 0; i < entries_read; i++)
3787 0 : display_share_info_1(c, &i1[i]);
3788 0 : done:
3789 0 : return status;
3790 : }
3791 :
3792 0 : static bool check_share_availability(struct cli_state *cli, const char *netname)
3793 : {
3794 : NTSTATUS status;
3795 :
3796 0 : status = cli_tree_connect(cli, netname, "A:", NULL);
3797 0 : if (!NT_STATUS_IS_OK(status)) {
3798 0 : d_printf(_("skipping [%s]: not a file share.\n"), netname);
3799 0 : return false;
3800 : }
3801 :
3802 0 : status = cli_tdis(cli);
3803 0 : if (!NT_STATUS_IS_OK(status)) {
3804 0 : d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3805 0 : return false;
3806 : }
3807 :
3808 0 : return true;
3809 : }
3810 :
3811 0 : static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3812 : const char *netname, uint32_t type)
3813 : {
3814 : /* only support disk shares */
3815 0 : if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3816 0 : printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3817 : type);
3818 0 : return false;
3819 : }
3820 :
3821 : /* skip builtin shares */
3822 : /* FIXME: should print$ be added too ? */
3823 0 : if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3824 0 : strequal(netname,"global"))
3825 0 : return false;
3826 :
3827 0 : if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3828 0 : printf(_("excluding [%s]\n"), netname);
3829 0 : return false;
3830 : }
3831 :
3832 0 : return check_share_availability(cli, netname);
3833 : }
3834 :
3835 : /**
3836 : * Migrate shares from a remote RPC server to the local RPC server.
3837 : *
3838 : * All parameters are provided by the run_rpc_command function, except for
3839 : * argc, argv which are passed through.
3840 : *
3841 : * @param domain_sid The domain sid acquired from the remote server.
3842 : * @param cli A cli_state connected to the server.
3843 : * @param mem_ctx Talloc context, destroyed on completion of the function.
3844 : * @param argc Standard main() style argc.
3845 : * @param argv Standard main() style argv. Initial components are already
3846 : * stripped.
3847 : *
3848 : * @return Normal NTSTATUS return.
3849 : **/
3850 :
3851 0 : static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3852 : const struct dom_sid *domain_sid,
3853 : const char *domain_name,
3854 : struct cli_state *cli,
3855 : struct rpc_pipe_client *pipe_hnd,
3856 : TALLOC_CTX *mem_ctx,
3857 : int argc,
3858 : const char **argv)
3859 : {
3860 : WERROR result;
3861 0 : NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3862 : struct srvsvc_NetShareInfoCtr ctr_src;
3863 : uint32_t i;
3864 0 : struct rpc_pipe_client *srvsvc_pipe = NULL;
3865 0 : struct cli_state *cli_dst = NULL;
3866 0 : uint32_t level = 502; /* includes secdesc */
3867 0 : uint32_t parm_error = 0;
3868 : struct dcerpc_binding_handle *b;
3869 :
3870 0 : result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3871 : &ctr_src);
3872 0 : if (!W_ERROR_IS_OK(result))
3873 0 : goto done;
3874 :
3875 : /* connect destination PI_SRVSVC */
3876 0 : nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3877 : &ndr_table_srvsvc);
3878 0 : if (!NT_STATUS_IS_OK(nt_status))
3879 0 : return nt_status;
3880 :
3881 0 : b = srvsvc_pipe->binding_handle;
3882 :
3883 0 : for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3884 :
3885 : union srvsvc_NetShareInfo info;
3886 0 : struct srvsvc_NetShareInfo502 info502 =
3887 0 : ctr_src.ctr.ctr502->array[i];
3888 :
3889 : /* reset error-code */
3890 0 : nt_status = NT_STATUS_UNSUCCESSFUL;
3891 :
3892 0 : if (!check_share_sanity(c, cli, info502.name, info502.type))
3893 0 : continue;
3894 :
3895 : /* finally add the share on the dst server */
3896 :
3897 0 : printf(_("migrating: [%s], path: %s, comment: %s, without "
3898 : "share-ACLs\n"),
3899 : info502.name, info502.path, info502.comment);
3900 :
3901 0 : info.info502 = &info502;
3902 :
3903 0 : nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3904 0 : srvsvc_pipe->desthost,
3905 : 502,
3906 : &info,
3907 : &parm_error,
3908 : &result);
3909 0 : if (!NT_STATUS_IS_OK(nt_status)) {
3910 0 : printf(_("cannot add share: %s\n"),
3911 : nt_errstr(nt_status));
3912 0 : goto done;
3913 : }
3914 0 : if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3915 0 : printf(_(" [%s] does already exist\n"),
3916 : info502.name);
3917 0 : continue;
3918 : }
3919 :
3920 0 : if (!W_ERROR_IS_OK(result)) {
3921 0 : nt_status = werror_to_ntstatus(result);
3922 0 : printf(_("cannot add share: %s\n"),
3923 : win_errstr(result));
3924 0 : goto done;
3925 : }
3926 :
3927 : }
3928 :
3929 0 : nt_status = NT_STATUS_OK;
3930 :
3931 0 : done:
3932 0 : if (cli_dst) {
3933 0 : cli_shutdown(cli_dst);
3934 : }
3935 :
3936 0 : return nt_status;
3937 :
3938 : }
3939 :
3940 : /**
3941 : * Migrate shares from a RPC server to another.
3942 : *
3943 : * @param argc Standard main() style argc.
3944 : * @param argv Standard main() style argv. Initial components are already
3945 : * stripped.
3946 : *
3947 : * @return A shell status integer (0 for success).
3948 : **/
3949 0 : static int rpc_share_migrate_shares(struct net_context *c, int argc,
3950 : const char **argv)
3951 : {
3952 0 : if (c->display_usage) {
3953 0 : d_printf( "%s\n"
3954 : "net rpc share migrate shares\n"
3955 : " %s\n",
3956 : _("Usage:"),
3957 : _("Migrate shares to local server"));
3958 0 : return 0;
3959 : }
3960 :
3961 0 : if (!c->opt_host) {
3962 0 : printf(_("no server to migrate\n"));
3963 0 : return -1;
3964 : }
3965 :
3966 0 : return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
3967 : rpc_share_migrate_shares_internals,
3968 : argc, argv);
3969 : }
3970 :
3971 : /**
3972 : * Copy a file/dir
3973 : *
3974 : * @param f file_info
3975 : * @param mask current search mask
3976 : * @param state arg-pointer
3977 : *
3978 : **/
3979 0 : static NTSTATUS copy_fn(struct file_info *f,
3980 : const char *mask, void *state)
3981 : {
3982 : static NTSTATUS nt_status;
3983 : static struct copy_clistate *local_state;
3984 : static fstring filename, new_mask;
3985 : fstring dir;
3986 : char *old_dir;
3987 : struct net_context *c;
3988 :
3989 0 : local_state = (struct copy_clistate *)state;
3990 0 : nt_status = NT_STATUS_UNSUCCESSFUL;
3991 :
3992 0 : c = local_state->c;
3993 :
3994 0 : if (strequal(f->name, ".") || strequal(f->name, ".."))
3995 0 : return NT_STATUS_OK;
3996 :
3997 0 : DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3998 :
3999 : /* DIRECTORY */
4000 0 : if (f->attr & FILE_ATTRIBUTE_DIRECTORY) {
4001 :
4002 0 : DEBUG(3,("got dir: %s\n", f->name));
4003 :
4004 0 : fstrcpy(dir, local_state->cwd);
4005 0 : fstrcat(dir, "\\");
4006 0 : fstrcat(dir, f->name);
4007 :
4008 0 : switch (net_mode_share)
4009 : {
4010 0 : case NET_MODE_SHARE_MIGRATE:
4011 : /* create that directory */
4012 0 : nt_status = net_copy_file(c, local_state->mem_ctx,
4013 0 : local_state->cli_share_src,
4014 0 : local_state->cli_share_dst,
4015 : dir, dir,
4016 0 : c->opt_acls? true : false,
4017 0 : c->opt_attrs? true : false,
4018 0 : c->opt_timestamps? true:false,
4019 : false);
4020 0 : break;
4021 0 : default:
4022 0 : d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
4023 0 : return NT_STATUS_INTERNAL_ERROR;
4024 : }
4025 :
4026 0 : if (!NT_STATUS_IS_OK(nt_status)) {
4027 0 : printf(_("could not handle dir %s: %s\n"),
4028 : dir, nt_errstr(nt_status));
4029 0 : return nt_status;
4030 : }
4031 :
4032 : /* search below that directory */
4033 0 : if (strlcpy(new_mask, dir, sizeof(new_mask)) >= sizeof(new_mask)) {
4034 0 : return NT_STATUS_NO_MEMORY;
4035 : }
4036 0 : if (strlcat(new_mask, "\\*", sizeof(new_mask)) >= sizeof(new_mask)) {
4037 0 : return NT_STATUS_NO_MEMORY;
4038 : }
4039 :
4040 0 : old_dir = local_state->cwd;
4041 0 : local_state->cwd = dir;
4042 0 : nt_status = sync_files(local_state, new_mask);
4043 0 : if (!NT_STATUS_IS_OK(nt_status)) {
4044 0 : printf(_("could not handle files\n"));
4045 : }
4046 0 : local_state->cwd = old_dir;
4047 :
4048 0 : return nt_status;
4049 : }
4050 :
4051 :
4052 : /* FILE */
4053 0 : fstrcpy(filename, local_state->cwd);
4054 0 : fstrcat(filename, "\\");
4055 0 : fstrcat(filename, f->name);
4056 :
4057 0 : DEBUG(3,("got file: %s\n", filename));
4058 :
4059 0 : switch (net_mode_share)
4060 : {
4061 0 : case NET_MODE_SHARE_MIGRATE:
4062 0 : nt_status = net_copy_file(c, local_state->mem_ctx,
4063 0 : local_state->cli_share_src,
4064 0 : local_state->cli_share_dst,
4065 : filename, filename,
4066 0 : c->opt_acls? true : false,
4067 0 : c->opt_attrs? true : false,
4068 0 : c->opt_timestamps? true: false,
4069 : true);
4070 0 : break;
4071 0 : default:
4072 0 : d_fprintf(stderr, _("Unsupported file mode %d\n"),
4073 : net_mode_share);
4074 0 : return NT_STATUS_INTERNAL_ERROR;
4075 : }
4076 :
4077 0 : if (!NT_STATUS_IS_OK(nt_status))
4078 0 : printf(_("could not handle file %s: %s\n"),
4079 : filename, nt_errstr(nt_status));
4080 0 : return nt_status;
4081 : }
4082 :
4083 : /**
4084 : * sync files, can be called recursively to list files
4085 : * and then call copy_fn for each file
4086 : *
4087 : * @param cp_clistate pointer to the copy_clistate we work with
4088 : * @param mask the current search mask
4089 : *
4090 : * @return Boolean result
4091 : **/
4092 0 : static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
4093 : {
4094 : struct cli_state *targetcli;
4095 0 : char *targetpath = NULL;
4096 : NTSTATUS status;
4097 :
4098 0 : DEBUG(3,("calling cli_list with mask: %s\n", mask));
4099 :
4100 0 : status = cli_resolve_path(talloc_tos(), "", NULL,
4101 : cp_clistate->cli_share_src,
4102 : mask, &targetcli, &targetpath);
4103 0 : if (!NT_STATUS_IS_OK(status)) {
4104 0 : d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
4105 : "%s\n"),
4106 : mask, nt_errstr(status));
4107 0 : return status;
4108 : }
4109 :
4110 0 : status = cli_list(targetcli, targetpath, cp_clistate->attribute,
4111 : copy_fn, cp_clistate);
4112 0 : if (!NT_STATUS_IS_OK(status)) {
4113 0 : d_fprintf(stderr, _("listing %s failed with error: %s\n"),
4114 : mask, nt_errstr(status));
4115 : }
4116 :
4117 0 : return status;
4118 : }
4119 :
4120 :
4121 : /**
4122 : * Set the top level directory permissions before we do any further copies.
4123 : * Should set up ACL inheritance.
4124 : **/
4125 :
4126 0 : bool copy_top_level_perms(struct net_context *c,
4127 : struct copy_clistate *cp_clistate,
4128 : const char *sharename)
4129 : {
4130 0 : NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4131 :
4132 0 : switch (net_mode_share) {
4133 0 : case NET_MODE_SHARE_MIGRATE:
4134 0 : DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
4135 0 : nt_status = net_copy_fileattr(c,
4136 : cp_clistate->mem_ctx,
4137 : cp_clistate->cli_share_src,
4138 : cp_clistate->cli_share_dst,
4139 : "\\", "\\",
4140 0 : c->opt_acls? true : false,
4141 0 : c->opt_attrs? true : false,
4142 0 : c->opt_timestamps? true: false,
4143 : false);
4144 0 : break;
4145 0 : default:
4146 0 : d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
4147 0 : break;
4148 : }
4149 :
4150 0 : if (!NT_STATUS_IS_OK(nt_status)) {
4151 0 : printf(_("Could handle directory attributes for top level "
4152 : "directory of share %s. Error %s\n"),
4153 : sharename, nt_errstr(nt_status));
4154 0 : return false;
4155 : }
4156 :
4157 0 : return true;
4158 : }
4159 :
4160 : /**
4161 : * Sync all files inside a remote share to another share (over smb).
4162 : *
4163 : * All parameters are provided by the run_rpc_command function, except for
4164 : * argc, argv which are passed through.
4165 : *
4166 : * @param domain_sid The domain sid acquired from the remote server.
4167 : * @param cli A cli_state connected to the server.
4168 : * @param mem_ctx Talloc context, destroyed on completion of the function.
4169 : * @param argc Standard main() style argc.
4170 : * @param argv Standard main() style argv. Initial components are already
4171 : * stripped.
4172 : *
4173 : * @return Normal NTSTATUS return.
4174 : **/
4175 :
4176 0 : static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
4177 : const struct dom_sid *domain_sid,
4178 : const char *domain_name,
4179 : struct cli_state *cli,
4180 : struct rpc_pipe_client *pipe_hnd,
4181 : TALLOC_CTX *mem_ctx,
4182 : int argc,
4183 : const char **argv)
4184 : {
4185 : WERROR result;
4186 0 : NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4187 : struct srvsvc_NetShareInfoCtr ctr_src;
4188 : uint32_t i;
4189 0 : uint32_t level = 502;
4190 : struct copy_clistate cp_clistate;
4191 0 : bool got_src_share = false;
4192 0 : bool got_dst_share = false;
4193 0 : const char *mask = "\\*";
4194 0 : char *dst = NULL;
4195 :
4196 0 : dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
4197 0 : if (dst == NULL) {
4198 0 : nt_status = NT_STATUS_NO_MEMORY;
4199 0 : goto done;
4200 : }
4201 :
4202 0 : result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4203 : &ctr_src);
4204 :
4205 0 : if (!W_ERROR_IS_OK(result))
4206 0 : goto done;
4207 :
4208 0 : for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4209 :
4210 0 : struct srvsvc_NetShareInfo502 info502 =
4211 0 : ctr_src.ctr.ctr502->array[i];
4212 :
4213 0 : if (!check_share_sanity(c, cli, info502.name, info502.type))
4214 0 : continue;
4215 :
4216 : /* one might not want to mirror whole discs :) */
4217 0 : if (strequal(info502.name, "print$") || info502.name[1] == '$') {
4218 0 : d_printf(_("skipping [%s]: builtin/hidden share\n"),
4219 : info502.name);
4220 0 : continue;
4221 : }
4222 :
4223 0 : switch (net_mode_share)
4224 : {
4225 0 : case NET_MODE_SHARE_MIGRATE:
4226 0 : printf("syncing");
4227 0 : break;
4228 0 : default:
4229 0 : d_fprintf(stderr, _("Unsupported mode %d\n"),
4230 : net_mode_share);
4231 0 : break;
4232 : }
4233 0 : printf(_(" [%s] files and directories %s ACLs, %s DOS "
4234 : "Attributes %s\n"),
4235 : info502.name,
4236 0 : c->opt_acls ? _("including") : _("without"),
4237 0 : c->opt_attrs ? _("including") : _("without"),
4238 0 : c->opt_timestamps ? _("(preserving timestamps)") : "");
4239 :
4240 0 : cp_clistate.mem_ctx = mem_ctx;
4241 0 : cp_clistate.cli_share_src = NULL;
4242 0 : cp_clistate.cli_share_dst = NULL;
4243 0 : cp_clistate.cwd = NULL;
4244 0 : cp_clistate.attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
4245 0 : cp_clistate.c = c;
4246 :
4247 : /* open share source */
4248 0 : nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
4249 : smbXcli_conn_remote_sockaddr(cli->conn),
4250 : smbXcli_conn_remote_name(cli->conn),
4251 : info502.name, "A:");
4252 0 : if (!NT_STATUS_IS_OK(nt_status))
4253 0 : goto done;
4254 :
4255 0 : got_src_share = true;
4256 :
4257 0 : if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
4258 : /* open share destination */
4259 0 : nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
4260 : NULL, dst, info502.name, "A:");
4261 0 : if (!NT_STATUS_IS_OK(nt_status))
4262 0 : goto done;
4263 :
4264 0 : got_dst_share = true;
4265 : }
4266 :
4267 0 : if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
4268 0 : d_fprintf(stderr, _("Could not handle the top level "
4269 : "directory permissions for the "
4270 : "share: %s\n"), info502.name);
4271 0 : nt_status = NT_STATUS_UNSUCCESSFUL;
4272 0 : goto done;
4273 : }
4274 :
4275 0 : nt_status = sync_files(&cp_clistate, mask);
4276 0 : if (!NT_STATUS_IS_OK(nt_status)) {
4277 0 : d_fprintf(stderr, _("could not handle files for share: "
4278 : "%s\n"), info502.name);
4279 0 : goto done;
4280 : }
4281 : }
4282 :
4283 0 : nt_status = NT_STATUS_OK;
4284 :
4285 0 : done:
4286 :
4287 0 : if (got_src_share)
4288 0 : cli_shutdown(cp_clistate.cli_share_src);
4289 :
4290 0 : if (got_dst_share)
4291 0 : cli_shutdown(cp_clistate.cli_share_dst);
4292 :
4293 0 : SAFE_FREE(dst);
4294 0 : return nt_status;
4295 :
4296 : }
4297 :
4298 0 : static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
4299 : {
4300 0 : if (c->display_usage) {
4301 0 : d_printf( "%s\n"
4302 : "net share migrate files\n"
4303 : " %s\n",
4304 : _("Usage:"),
4305 : _("Migrate files to local server"));
4306 0 : return 0;
4307 : }
4308 :
4309 0 : if (!c->opt_host) {
4310 0 : d_printf(_("no server to migrate\n"));
4311 0 : return -1;
4312 : }
4313 :
4314 0 : return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4315 : rpc_share_migrate_files_internals,
4316 : argc, argv);
4317 : }
4318 :
4319 : /**
4320 : * Migrate share-ACLs from a remote RPC server to the local RPC server.
4321 : *
4322 : * All parameters are provided by the run_rpc_command function, except for
4323 : * argc, argv which are passed through.
4324 : *
4325 : * @param domain_sid The domain sid acquired from the remote server.
4326 : * @param cli A cli_state connected to the server.
4327 : * @param mem_ctx Talloc context, destroyed on completion of the function.
4328 : * @param argc Standard main() style argc.
4329 : * @param argv Standard main() style argv. Initial components are already
4330 : * stripped.
4331 : *
4332 : * @return Normal NTSTATUS return.
4333 : **/
4334 :
4335 0 : static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
4336 : const struct dom_sid *domain_sid,
4337 : const char *domain_name,
4338 : struct cli_state *cli,
4339 : struct rpc_pipe_client *pipe_hnd,
4340 : TALLOC_CTX *mem_ctx,
4341 : int argc,
4342 : const char **argv)
4343 : {
4344 : WERROR result;
4345 0 : NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4346 : struct srvsvc_NetShareInfoCtr ctr_src;
4347 : union srvsvc_NetShareInfo info;
4348 : uint32_t i;
4349 0 : struct rpc_pipe_client *srvsvc_pipe = NULL;
4350 0 : struct cli_state *cli_dst = NULL;
4351 0 : uint32_t level = 502; /* includes secdesc */
4352 0 : uint32_t parm_error = 0;
4353 : struct dcerpc_binding_handle *b;
4354 :
4355 0 : result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4356 : &ctr_src);
4357 :
4358 0 : if (!W_ERROR_IS_OK(result))
4359 0 : goto done;
4360 :
4361 : /* connect destination PI_SRVSVC */
4362 0 : nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
4363 : &ndr_table_srvsvc);
4364 0 : if (!NT_STATUS_IS_OK(nt_status))
4365 0 : return nt_status;
4366 :
4367 0 : b = srvsvc_pipe->binding_handle;
4368 :
4369 0 : for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4370 :
4371 0 : struct srvsvc_NetShareInfo502 info502 =
4372 0 : ctr_src.ctr.ctr502->array[i];
4373 :
4374 : /* reset error-code */
4375 0 : nt_status = NT_STATUS_UNSUCCESSFUL;
4376 :
4377 0 : if (!check_share_sanity(c, cli, info502.name, info502.type))
4378 0 : continue;
4379 :
4380 0 : printf(_("migrating: [%s], path: %s, comment: %s, including "
4381 : "share-ACLs\n"),
4382 : info502.name, info502.path, info502.comment);
4383 :
4384 0 : if (c->opt_verbose)
4385 0 : display_sec_desc(info502.sd_buf.sd);
4386 :
4387 : /* FIXME: shouldn't we be able to just set the security descriptor ? */
4388 0 : info.info502 = &info502;
4389 :
4390 : /* finally modify the share on the dst server */
4391 0 : nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
4392 0 : srvsvc_pipe->desthost,
4393 : info502.name,
4394 : level,
4395 : &info,
4396 : &parm_error,
4397 : &result);
4398 0 : if (!NT_STATUS_IS_OK(nt_status)) {
4399 0 : printf(_("cannot set share-acl: %s\n"),
4400 : nt_errstr(nt_status));
4401 0 : goto done;
4402 : }
4403 0 : if (!W_ERROR_IS_OK(result)) {
4404 0 : nt_status = werror_to_ntstatus(result);
4405 0 : printf(_("cannot set share-acl: %s\n"),
4406 : win_errstr(result));
4407 0 : goto done;
4408 : }
4409 :
4410 : }
4411 :
4412 0 : nt_status = NT_STATUS_OK;
4413 :
4414 0 : done:
4415 0 : if (cli_dst) {
4416 0 : cli_shutdown(cli_dst);
4417 : }
4418 :
4419 0 : return nt_status;
4420 :
4421 : }
4422 :
4423 : /**
4424 : * Migrate share-acls from a RPC server to another.
4425 : *
4426 : * @param argc Standard main() style argc.
4427 : * @param argv Standard main() style argv. Initial components are already
4428 : * stripped.
4429 : *
4430 : * @return A shell status integer (0 for success).
4431 : **/
4432 0 : static int rpc_share_migrate_security(struct net_context *c, int argc,
4433 : const char **argv)
4434 : {
4435 0 : if (c->display_usage) {
4436 0 : d_printf( "%s\n"
4437 : "net rpc share migrate security\n"
4438 : " %s\n",
4439 : _("Usage:"),
4440 : _("Migrate share-acls to local server"));
4441 0 : return 0;
4442 : }
4443 :
4444 0 : if (!c->opt_host) {
4445 0 : d_printf(_("no server to migrate\n"));
4446 0 : return -1;
4447 : }
4448 :
4449 0 : return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4450 : rpc_share_migrate_security_internals,
4451 : argc, argv);
4452 : }
4453 :
4454 : /**
4455 : * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4456 : * from one server to another.
4457 : *
4458 : * @param argc Standard main() style argc.
4459 : * @param argv Standard main() style argv. Initial components are already
4460 : * stripped.
4461 : *
4462 : * @return A shell status integer (0 for success).
4463 : *
4464 : **/
4465 0 : static int rpc_share_migrate_all(struct net_context *c, int argc,
4466 : const char **argv)
4467 : {
4468 : int ret;
4469 :
4470 0 : if (c->display_usage) {
4471 0 : d_printf( "%s\n"
4472 : "net rpc share migrate all\n"
4473 : " %s\n",
4474 : _("Usage:"),
4475 : _("Migrates shares including all share settings"));
4476 0 : return 0;
4477 : }
4478 :
4479 0 : if (!c->opt_host) {
4480 0 : d_printf(_("no server to migrate\n"));
4481 0 : return -1;
4482 : }
4483 :
4484 : /* order is important. we don't want to be locked out by the share-acl
4485 : * before copying files - gd */
4486 :
4487 0 : ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4488 : rpc_share_migrate_shares_internals, argc, argv);
4489 0 : if (ret)
4490 0 : return ret;
4491 :
4492 0 : ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4493 : rpc_share_migrate_files_internals, argc, argv);
4494 0 : if (ret)
4495 0 : return ret;
4496 :
4497 0 : return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4498 : rpc_share_migrate_security_internals, argc,
4499 : argv);
4500 : }
4501 :
4502 :
4503 : /**
4504 : * 'net rpc share migrate' entrypoint.
4505 : * @param argc Standard main() style argc.
4506 : * @param argv Standard main() style argv. Initial components are already
4507 : * stripped.
4508 : **/
4509 0 : static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4510 : {
4511 :
4512 0 : struct functable func[] = {
4513 : {
4514 : "all",
4515 : rpc_share_migrate_all,
4516 : NET_TRANSPORT_RPC,
4517 : N_("Migrate shares from remote to local server"),
4518 : N_("net rpc share migrate all\n"
4519 : " Migrate shares from remote to local server")
4520 : },
4521 : {
4522 : "files",
4523 : rpc_share_migrate_files,
4524 : NET_TRANSPORT_RPC,
4525 : N_("Migrate files from remote to local server"),
4526 : N_("net rpc share migrate files\n"
4527 : " Migrate files from remote to local server")
4528 : },
4529 : {
4530 : "security",
4531 : rpc_share_migrate_security,
4532 : NET_TRANSPORT_RPC,
4533 : N_("Migrate share-ACLs from remote to local server"),
4534 : N_("net rpc share migrate security\n"
4535 : " Migrate share-ACLs from remote to local server")
4536 : },
4537 : {
4538 : "shares",
4539 : rpc_share_migrate_shares,
4540 : NET_TRANSPORT_RPC,
4541 : N_("Migrate shares from remote to local server"),
4542 : N_("net rpc share migrate shares\n"
4543 : " Migrate shares from remote to local server")
4544 : },
4545 : {NULL, NULL, 0, NULL, NULL}
4546 : };
4547 :
4548 0 : net_mode_share = NET_MODE_SHARE_MIGRATE;
4549 :
4550 0 : return net_run_function(c, argc, argv, "net rpc share migrate", func);
4551 : }
4552 :
4553 : struct full_alias {
4554 : struct dom_sid sid;
4555 : uint32_t num_members;
4556 : struct dom_sid *members;
4557 : };
4558 :
4559 : static int num_server_aliases;
4560 : static struct full_alias *server_aliases;
4561 :
4562 : /*
4563 : * Add an alias to the static list.
4564 : */
4565 0 : static void push_alias(struct full_alias *alias)
4566 : {
4567 : size_t array_size;
4568 :
4569 0 : if (server_aliases == NULL) {
4570 0 : server_aliases = talloc_array(NULL, struct full_alias, 100);
4571 0 : if (server_aliases == NULL) {
4572 0 : smb_panic("talloc_array failed");
4573 : }
4574 : }
4575 :
4576 0 : array_size = talloc_array_length(server_aliases);
4577 0 : if (array_size == num_server_aliases) {
4578 0 : server_aliases = talloc_realloc(NULL, server_aliases,
4579 : struct full_alias, array_size + 100);
4580 0 : if (server_aliases == NULL) {
4581 0 : smb_panic("talloc_realloc failed");
4582 : }
4583 : }
4584 :
4585 0 : server_aliases[num_server_aliases] = *alias;
4586 0 : num_server_aliases += 1;
4587 0 : }
4588 :
4589 : /*
4590 : * For a specific domain on the server, fetch all the aliases
4591 : * and their members. Add all of them to the server_aliases.
4592 : */
4593 :
4594 0 : static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4595 : TALLOC_CTX *mem_ctx,
4596 : struct policy_handle *connect_pol,
4597 : const struct dom_sid *domain_sid)
4598 : {
4599 : uint32_t start_idx, max_entries, num_entries, i;
4600 0 : struct samr_SamArray *groups = NULL;
4601 : NTSTATUS result, status;
4602 : struct policy_handle domain_pol;
4603 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4604 :
4605 : /* Get domain policy handle */
4606 :
4607 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
4608 : connect_pol,
4609 : MAXIMUM_ALLOWED_ACCESS,
4610 : discard_const_p(struct dom_sid2, domain_sid),
4611 : &domain_pol,
4612 : &result);
4613 0 : if (!NT_STATUS_IS_OK(status)) {
4614 0 : return status;
4615 : }
4616 0 : if (!NT_STATUS_IS_OK(result)) {
4617 0 : return result;
4618 : }
4619 :
4620 0 : start_idx = 0;
4621 0 : max_entries = 250;
4622 :
4623 : do {
4624 0 : status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
4625 : &domain_pol,
4626 : &start_idx,
4627 : &groups,
4628 : max_entries,
4629 : &num_entries,
4630 : &result);
4631 0 : if (!NT_STATUS_IS_OK(status)) {
4632 0 : goto done;
4633 : }
4634 0 : for (i = 0; i < num_entries; i++) {
4635 :
4636 : struct policy_handle alias_pol;
4637 : struct full_alias alias;
4638 : struct lsa_SidArray sid_array;
4639 : int j;
4640 : NTSTATUS _result;
4641 :
4642 0 : status = dcerpc_samr_OpenAlias(b, mem_ctx,
4643 : &domain_pol,
4644 : MAXIMUM_ALLOWED_ACCESS,
4645 0 : groups->entries[i].idx,
4646 : &alias_pol,
4647 : &_result);
4648 0 : if (!NT_STATUS_IS_OK(status)) {
4649 0 : goto done;
4650 : }
4651 0 : if (!NT_STATUS_IS_OK(_result)) {
4652 0 : status = _result;
4653 0 : goto done;
4654 : }
4655 :
4656 0 : status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
4657 : &alias_pol,
4658 : &sid_array,
4659 : &_result);
4660 0 : if (!NT_STATUS_IS_OK(status)) {
4661 0 : goto done;
4662 : }
4663 0 : if (!NT_STATUS_IS_OK(_result)) {
4664 0 : status = _result;
4665 0 : goto done;
4666 : }
4667 :
4668 0 : alias.num_members = sid_array.num_sids;
4669 :
4670 0 : status = dcerpc_samr_Close(b, mem_ctx, &alias_pol, &_result);
4671 0 : if (!NT_STATUS_IS_OK(status)) {
4672 0 : goto done;
4673 : }
4674 0 : if (!NT_STATUS_IS_OK(_result)) {
4675 0 : status = _result;
4676 0 : goto done;
4677 : }
4678 :
4679 0 : alias.members = NULL;
4680 :
4681 0 : if (alias.num_members > 0) {
4682 0 : alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4683 0 : if (alias.members == NULL) {
4684 0 : status = NT_STATUS_NO_MEMORY;
4685 0 : goto done;
4686 : }
4687 :
4688 0 : for (j = 0; j < alias.num_members; j++)
4689 0 : sid_copy(&alias.members[j],
4690 0 : sid_array.sids[j].sid);
4691 : }
4692 :
4693 0 : sid_compose(&alias.sid, domain_sid,
4694 0 : groups->entries[i].idx);
4695 :
4696 0 : push_alias(&alias);
4697 : }
4698 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4699 :
4700 0 : status = NT_STATUS_OK;
4701 :
4702 0 : done:
4703 0 : dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
4704 :
4705 0 : return status;
4706 : }
4707 :
4708 : /*
4709 : * Dump server_aliases as names for debugging purposes.
4710 : */
4711 :
4712 0 : static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4713 : const struct dom_sid *domain_sid,
4714 : const char *domain_name,
4715 : struct cli_state *cli,
4716 : struct rpc_pipe_client *pipe_hnd,
4717 : TALLOC_CTX *mem_ctx,
4718 : int argc,
4719 : const char **argv)
4720 : {
4721 : uint32_t i;
4722 : NTSTATUS result;
4723 : struct policy_handle lsa_pol;
4724 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4725 :
4726 0 : result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4727 : SEC_FLAG_MAXIMUM_ALLOWED,
4728 : &lsa_pol);
4729 0 : if (!NT_STATUS_IS_OK(result))
4730 0 : return result;
4731 :
4732 0 : for (i=0; i<num_server_aliases; i++) {
4733 : char **names;
4734 : char **domains;
4735 : enum lsa_SidType *types;
4736 : int j;
4737 :
4738 0 : struct full_alias *alias = &server_aliases[i];
4739 :
4740 0 : result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4741 0 : &alias->sid,
4742 : &domains, &names, &types);
4743 0 : if (!NT_STATUS_IS_OK(result))
4744 0 : continue;
4745 :
4746 0 : DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4747 :
4748 0 : if (alias->num_members == 0) {
4749 0 : DEBUG(1, ("\n"));
4750 0 : continue;
4751 : }
4752 :
4753 0 : result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4754 0 : alias->num_members,
4755 0 : alias->members,
4756 : &domains, &names, &types);
4757 :
4758 0 : if (!NT_STATUS_IS_OK(result) &&
4759 0 : !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4760 0 : continue;
4761 :
4762 0 : for (j=0; j<alias->num_members; j++)
4763 0 : DEBUG(1, ("%s\\%s (%d); ",
4764 : domains[j] ? domains[j] : "*unknown*",
4765 : names[j] ? names[j] : "*unknown*",types[j]));
4766 0 : DEBUG(1, ("\n"));
4767 : }
4768 :
4769 0 : dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
4770 :
4771 0 : return NT_STATUS_OK;
4772 : }
4773 :
4774 : /*
4775 : * Fetch a list of all server aliases and their members into
4776 : * server_aliases.
4777 : */
4778 :
4779 0 : static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4780 : const struct dom_sid *domain_sid,
4781 : const char *domain_name,
4782 : struct cli_state *cli,
4783 : struct rpc_pipe_client *pipe_hnd,
4784 : TALLOC_CTX *mem_ctx,
4785 : int argc,
4786 : const char **argv)
4787 : {
4788 : NTSTATUS result, status;
4789 : struct policy_handle connect_pol;
4790 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4791 :
4792 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
4793 0 : pipe_hnd->desthost,
4794 : MAXIMUM_ALLOWED_ACCESS,
4795 : &connect_pol,
4796 : &result);
4797 0 : if (!NT_STATUS_IS_OK(status)) {
4798 0 : goto done;
4799 : }
4800 0 : if (!NT_STATUS_IS_OK(result)) {
4801 0 : status = result;
4802 0 : goto done;
4803 : }
4804 :
4805 0 : status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4806 : &global_sid_Builtin);
4807 0 : if (!NT_STATUS_IS_OK(status)) {
4808 0 : goto done;
4809 : }
4810 :
4811 0 : status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4812 : domain_sid);
4813 :
4814 0 : dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
4815 0 : done:
4816 0 : return status;
4817 : }
4818 :
4819 0 : static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4820 : {
4821 0 : token->num_sids = 4;
4822 :
4823 0 : if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4824 0 : d_fprintf(stderr, "malloc %s\n",_("failed"));
4825 0 : token->num_sids = 0;
4826 0 : return;
4827 : }
4828 :
4829 0 : token->sids[0] = *user_sid;
4830 0 : sid_copy(&token->sids[1], &global_sid_World);
4831 0 : sid_copy(&token->sids[2], &global_sid_Network);
4832 0 : sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4833 : }
4834 :
4835 0 : static void free_user_token(struct security_token *token)
4836 : {
4837 0 : SAFE_FREE(token->sids);
4838 0 : }
4839 :
4840 0 : static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4841 : {
4842 0 : if (security_token_has_sid(token, sid))
4843 0 : return;
4844 :
4845 0 : token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4846 0 : if (!token->sids) {
4847 0 : return;
4848 : }
4849 :
4850 0 : sid_copy(&token->sids[token->num_sids], sid);
4851 :
4852 0 : token->num_sids += 1;
4853 : }
4854 :
4855 : struct user_token {
4856 : fstring name;
4857 : struct security_token token;
4858 : };
4859 :
4860 0 : static void dump_user_token(struct user_token *token)
4861 : {
4862 : uint32_t i;
4863 :
4864 0 : d_printf("%s\n", token->name);
4865 :
4866 0 : for (i=0; i<token->token.num_sids; i++) {
4867 : struct dom_sid_buf buf;
4868 0 : d_printf(" %s\n",
4869 0 : dom_sid_str_buf(&token->token.sids[i], &buf));
4870 : }
4871 0 : }
4872 :
4873 0 : static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4874 : {
4875 : uint32_t i;
4876 :
4877 0 : for (i=0; i<alias->num_members; i++) {
4878 0 : if (dom_sid_equal(sid, &alias->members[i])) {
4879 0 : return true;
4880 : }
4881 : }
4882 :
4883 0 : return false;
4884 : }
4885 :
4886 0 : static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4887 : {
4888 : int i;
4889 :
4890 0 : for (i=0; i<num_server_aliases; i++) {
4891 0 : if (is_alias_member(&sid, &server_aliases[i]))
4892 0 : add_sid_to_token(token, &server_aliases[i].sid);
4893 : }
4894 0 : }
4895 :
4896 : /*
4897 : * We got a user token with all the SIDs we can know about without asking the
4898 : * server directly. These are the user and domain group sids. All of these can
4899 : * be members of aliases. So scan the list of aliases for each of the SIDs and
4900 : * add them to the token.
4901 : */
4902 :
4903 0 : static void collect_alias_memberships(struct security_token *token)
4904 : {
4905 0 : int num_global_sids = token->num_sids;
4906 : int i;
4907 :
4908 0 : for (i=0; i<num_global_sids; i++) {
4909 0 : collect_sid_memberships(token, token->sids[i]);
4910 : }
4911 0 : }
4912 :
4913 0 : static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4914 : {
4915 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4916 : enum wbcSidType type;
4917 : fstring full_name;
4918 : struct wbcDomainSid wsid;
4919 : char sid_str[WBC_SID_STRING_BUFLEN];
4920 : struct dom_sid user_sid;
4921 : uint32_t num_groups;
4922 0 : gid_t *groups = NULL;
4923 : uint32_t i;
4924 :
4925 0 : fstr_sprintf(full_name, "%s%c%s",
4926 0 : domain, *lp_winbind_separator(), user);
4927 :
4928 : /* First let's find out the user sid */
4929 :
4930 0 : wbc_status = wbcLookupName(domain, user, &wsid, &type);
4931 :
4932 0 : if (!WBC_ERROR_IS_OK(wbc_status)) {
4933 0 : DEBUG(1, ("winbind could not find %s: %s\n",
4934 : full_name, wbcErrorString(wbc_status)));
4935 0 : return false;
4936 : }
4937 :
4938 0 : wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4939 :
4940 0 : if (type != WBC_SID_NAME_USER) {
4941 0 : DEBUG(1, ("%s is not a user\n", full_name));
4942 0 : return false;
4943 : }
4944 :
4945 0 : if (!string_to_sid(&user_sid, sid_str)) {
4946 0 : DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4947 0 : return false;
4948 : }
4949 :
4950 0 : init_user_token(token, &user_sid);
4951 :
4952 : /* And now the groups winbind knows about */
4953 :
4954 0 : wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4955 0 : if (!WBC_ERROR_IS_OK(wbc_status)) {
4956 0 : DEBUG(1, ("winbind could not get groups of %s: %s\n",
4957 : full_name, wbcErrorString(wbc_status)));
4958 0 : return false;
4959 : }
4960 :
4961 0 : for (i = 0; i < num_groups; i++) {
4962 0 : gid_t gid = groups[i];
4963 : struct dom_sid sid;
4964 : bool ok;
4965 :
4966 0 : wbc_status = wbcGidToSid(gid, &wsid);
4967 0 : if (!WBC_ERROR_IS_OK(wbc_status)) {
4968 0 : DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4969 : (unsigned int)gid, wbcErrorString(wbc_status)));
4970 0 : wbcFreeMemory(groups);
4971 0 : return false;
4972 : }
4973 :
4974 0 : wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4975 :
4976 0 : DEBUG(3, (" %s\n", sid_str));
4977 :
4978 0 : ok = string_to_sid(&sid, sid_str);
4979 0 : if (!ok) {
4980 0 : DEBUG(1, ("Failed to convert string to SID\n"));
4981 0 : wbcFreeMemory(groups);
4982 0 : return false;
4983 : }
4984 0 : add_sid_to_token(token, &sid);
4985 : }
4986 0 : wbcFreeMemory(groups);
4987 :
4988 0 : return true;
4989 : }
4990 :
4991 : /**
4992 : * Get a list of all user tokens we want to look at
4993 : **/
4994 :
4995 0 : static bool get_user_tokens(struct net_context *c, int *num_tokens,
4996 : struct user_token **user_tokens)
4997 : {
4998 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4999 : uint32_t i, num_users;
5000 : const char **users;
5001 : struct user_token *result;
5002 0 : TALLOC_CTX *frame = NULL;
5003 :
5004 0 : if (lp_winbind_use_default_domain() &&
5005 0 : (c->opt_target_workgroup == NULL)) {
5006 0 : d_fprintf(stderr, _("winbind use default domain = yes set, "
5007 : "please specify a workgroup\n"));
5008 0 : return false;
5009 : }
5010 :
5011 : /* Send request to winbind daemon */
5012 :
5013 0 : wbc_status = wbcListUsers(NULL, &num_users, &users);
5014 0 : if (!WBC_ERROR_IS_OK(wbc_status)) {
5015 0 : DEBUG(1, (_("winbind could not list users: %s\n"),
5016 : wbcErrorString(wbc_status)));
5017 0 : return false;
5018 : }
5019 :
5020 0 : result = SMB_MALLOC_ARRAY(struct user_token, num_users);
5021 :
5022 0 : if (result == NULL) {
5023 0 : DEBUG(1, ("Could not malloc sid array\n"));
5024 0 : wbcFreeMemory(users);
5025 0 : return false;
5026 : }
5027 :
5028 0 : frame = talloc_stackframe();
5029 0 : for (i=0; i < num_users; i++) {
5030 : fstring domain, user;
5031 : char *p;
5032 :
5033 0 : fstrcpy(result[i].name, users[i]);
5034 :
5035 0 : p = strchr(users[i], *lp_winbind_separator());
5036 :
5037 0 : DEBUG(3, ("%s\n", users[i]));
5038 :
5039 0 : if (p == NULL) {
5040 0 : fstrcpy(domain, c->opt_target_workgroup);
5041 0 : fstrcpy(user, users[i]);
5042 : } else {
5043 0 : *p++ = '\0';
5044 0 : fstrcpy(domain, users[i]);
5045 0 : if (!strupper_m(domain)) {
5046 0 : DEBUG(1, ("strupper_m %s failed\n", domain));
5047 0 : wbcFreeMemory(users);
5048 0 : return false;
5049 : }
5050 0 : fstrcpy(user, p);
5051 : }
5052 :
5053 0 : get_user_sids(domain, user, &(result[i].token));
5054 : }
5055 0 : TALLOC_FREE(frame);
5056 0 : wbcFreeMemory(users);
5057 :
5058 0 : *num_tokens = num_users;
5059 0 : *user_tokens = result;
5060 :
5061 0 : return true;
5062 : }
5063 :
5064 0 : static bool get_user_tokens_from_file(FILE *f,
5065 : int *num_tokens,
5066 : struct user_token **tokens)
5067 : {
5068 0 : struct user_token *token = NULL;
5069 :
5070 0 : while (!feof(f)) {
5071 : fstring line;
5072 :
5073 0 : if (fgets(line, sizeof(line)-1, f) == NULL) {
5074 0 : return true;
5075 : }
5076 :
5077 0 : if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
5078 0 : line[strlen(line)-1] = '\0';
5079 : }
5080 :
5081 0 : if (line[0] == ' ') {
5082 : /* We have a SID */
5083 :
5084 : struct dom_sid sid;
5085 0 : if(!string_to_sid(&sid, &line[1])) {
5086 0 : DEBUG(1,("get_user_tokens_from_file: Could "
5087 : "not convert sid %s \n",&line[1]));
5088 0 : return false;
5089 : }
5090 :
5091 0 : if (token == NULL) {
5092 0 : DEBUG(0, ("File does not begin with username"));
5093 0 : return false;
5094 : }
5095 :
5096 0 : add_sid_to_token(&token->token, &sid);
5097 0 : continue;
5098 : }
5099 :
5100 : /* And a new user... */
5101 :
5102 0 : *num_tokens += 1;
5103 0 : *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
5104 0 : if (*tokens == NULL) {
5105 0 : DEBUG(0, ("Could not realloc tokens\n"));
5106 0 : return false;
5107 : }
5108 :
5109 0 : token = &((*tokens)[*num_tokens-1]);
5110 :
5111 0 : if (strlcpy(token->name, line, sizeof(token->name)) >= sizeof(token->name)) {
5112 0 : return false;
5113 : }
5114 0 : token->token.num_sids = 0;
5115 0 : token->token.sids = NULL;
5116 0 : continue;
5117 : }
5118 :
5119 0 : return false;
5120 : }
5121 :
5122 :
5123 : /*
5124 : * Show the list of all users that have access to a share
5125 : */
5126 :
5127 0 : static void show_userlist(struct rpc_pipe_client *pipe_hnd,
5128 : struct cli_state *cli,
5129 : TALLOC_CTX *mem_ctx,
5130 : const char *netname,
5131 : int num_tokens,
5132 : struct user_token *tokens)
5133 : {
5134 : uint16_t fnum;
5135 0 : struct security_descriptor *share_sd = NULL;
5136 0 : struct security_descriptor *root_sd = NULL;
5137 : int i;
5138 : union srvsvc_NetShareInfo info;
5139 : WERROR result;
5140 : NTSTATUS status;
5141 0 : struct smbXcli_tcon *orig_tcon = NULL;
5142 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5143 :
5144 0 : status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5145 0 : pipe_hnd->desthost,
5146 : netname,
5147 : 502,
5148 : &info,
5149 : &result);
5150 :
5151 0 : if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
5152 0 : DEBUG(1, ("Could not query secdesc for share %s\n",
5153 : netname));
5154 0 : return;
5155 : }
5156 :
5157 0 : share_sd = info.info502->sd_buf.sd;
5158 0 : if (share_sd == NULL) {
5159 0 : DEBUG(1, ("Got no secdesc for share %s\n",
5160 : netname));
5161 : }
5162 :
5163 0 : if (cli_state_has_tcon(cli)) {
5164 0 : orig_tcon = cli_state_save_tcon(cli);
5165 0 : if (orig_tcon == NULL) {
5166 0 : return;
5167 : }
5168 : }
5169 :
5170 0 : if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", NULL))) {
5171 0 : cli_state_restore_tcon(cli, orig_tcon);
5172 0 : return;
5173 : }
5174 :
5175 0 : if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
5176 : FILE_SHARE_READ|FILE_SHARE_WRITE,
5177 : FILE_OPEN, 0x0, 0x0, &fnum, NULL))) {
5178 0 : cli_query_secdesc(cli, fnum, mem_ctx, &root_sd);
5179 : }
5180 :
5181 0 : for (i=0; i<num_tokens; i++) {
5182 : uint32_t acc_granted;
5183 :
5184 0 : if (share_sd != NULL) {
5185 0 : status = se_access_check(share_sd, &tokens[i].token,
5186 : 1, &acc_granted);
5187 :
5188 0 : if (!NT_STATUS_IS_OK(status)) {
5189 0 : DEBUG(1, ("Could not check share_sd for "
5190 : "user %s\n",
5191 : tokens[i].name));
5192 0 : continue;
5193 : }
5194 : }
5195 :
5196 0 : if (root_sd == NULL) {
5197 0 : d_printf(" %s\n", tokens[i].name);
5198 0 : continue;
5199 : }
5200 :
5201 0 : status = se_access_check(root_sd, &tokens[i].token,
5202 : 1, &acc_granted);
5203 0 : if (!NT_STATUS_IS_OK(status)) {
5204 0 : DEBUG(1, ("Could not check root_sd for user %s\n",
5205 : tokens[i].name));
5206 0 : continue;
5207 : }
5208 0 : d_printf(" %s\n", tokens[i].name);
5209 : }
5210 :
5211 0 : if (fnum != (uint16_t)-1)
5212 0 : cli_close(cli, fnum);
5213 0 : cli_tdis(cli);
5214 0 : cli_state_restore_tcon(cli, orig_tcon);
5215 :
5216 0 : return;
5217 : }
5218 :
5219 : /**
5220 : * List shares on a remote RPC server, including the security descriptors.
5221 : *
5222 : * All parameters are provided by the run_rpc_command function, except for
5223 : * argc, argv which are passed through.
5224 : *
5225 : * @param domain_sid The domain sid acquired from the remote server.
5226 : * @param cli A cli_state connected to the server.
5227 : * @param mem_ctx Talloc context, destroyed on completion of the function.
5228 : * @param argc Standard main() style argc.
5229 : * @param argv Standard main() style argv. Initial components are already
5230 : * stripped.
5231 : *
5232 : * @return Normal NTSTATUS return.
5233 : **/
5234 :
5235 0 : static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
5236 : const struct dom_sid *domain_sid,
5237 : const char *domain_name,
5238 : struct cli_state *cli,
5239 : struct rpc_pipe_client *pipe_hnd,
5240 : TALLOC_CTX *mem_ctx,
5241 : int argc,
5242 : const char **argv)
5243 : {
5244 : bool r;
5245 : FILE *f;
5246 0 : NTSTATUS nt_status = NT_STATUS_OK;
5247 0 : uint32_t total_entries = 0;
5248 0 : uint32_t resume_handle = 0;
5249 0 : uint32_t preferred_len = 0xffffffff;
5250 : uint32_t i;
5251 0 : struct dcerpc_binding_handle *b = NULL;
5252 : struct srvsvc_NetShareInfoCtr info_ctr;
5253 : struct srvsvc_NetShareCtr1 ctr1;
5254 : WERROR result;
5255 :
5256 0 : struct user_token *tokens = NULL;
5257 0 : int num_tokens = 0;
5258 :
5259 0 : if (argc == 0) {
5260 0 : f = stdin;
5261 : } else {
5262 0 : if (strequal(argv[0], "-")) {
5263 0 : f = stdin;
5264 : } else {
5265 0 : f = fopen(argv[0], "r");
5266 : }
5267 0 : argv++;
5268 0 : argc--;
5269 : }
5270 :
5271 0 : if (f == NULL) {
5272 0 : DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
5273 0 : return NT_STATUS_UNSUCCESSFUL;
5274 : }
5275 :
5276 0 : r = get_user_tokens_from_file(f, &num_tokens, &tokens);
5277 :
5278 0 : if (f != stdin)
5279 0 : fclose(f);
5280 :
5281 0 : if (!r) {
5282 0 : DEBUG(0, ("Could not read users from file\n"));
5283 0 : return NT_STATUS_UNSUCCESSFUL;
5284 : }
5285 :
5286 0 : for (i=0; i<num_tokens; i++)
5287 0 : collect_alias_memberships(&tokens[i].token);
5288 :
5289 0 : ZERO_STRUCT(info_ctr);
5290 0 : ZERO_STRUCT(ctr1);
5291 :
5292 0 : info_ctr.level = 1;
5293 0 : info_ctr.ctr.ctr1 = &ctr1;
5294 :
5295 0 : b = pipe_hnd->binding_handle;
5296 :
5297 0 : if (argc != 0) {
5298 : /* Show results only for shares listed on the command line. */
5299 0 : while (*argv) {
5300 0 : const char *netname = *argv++;
5301 0 : d_printf("%s\n", netname);
5302 0 : show_userlist(pipe_hnd, cli, mem_ctx, netname,
5303 : num_tokens, tokens);
5304 : }
5305 0 : goto done;
5306 : }
5307 :
5308 : /* Issue the NetShareEnum RPC call and retrieve the response */
5309 0 : nt_status = dcerpc_srvsvc_NetShareEnumAll(b,
5310 : talloc_tos(),
5311 0 : pipe_hnd->desthost,
5312 : &info_ctr,
5313 : preferred_len,
5314 : &total_entries,
5315 : &resume_handle,
5316 : &result);
5317 :
5318 : /* Was it successful? */
5319 0 : if (!NT_STATUS_IS_OK(nt_status)) {
5320 : /* Nope. Go clean up. */
5321 0 : goto done;
5322 : }
5323 :
5324 0 : if (!W_ERROR_IS_OK(result)) {
5325 : /* Nope. Go clean up. */
5326 0 : nt_status = werror_to_ntstatus(result);
5327 0 : goto done;
5328 : }
5329 :
5330 0 : if (total_entries == 0) {
5331 0 : goto done;
5332 : }
5333 :
5334 : /* For each returned entry... */
5335 0 : for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
5336 0 : const char *netname = info_ctr.ctr.ctr1->array[i].name;
5337 :
5338 0 : if (info_ctr.ctr.ctr1->array[i].type != STYPE_DISKTREE) {
5339 0 : continue;
5340 : }
5341 :
5342 0 : d_printf("%s\n", netname);
5343 :
5344 0 : show_userlist(pipe_hnd, cli, mem_ctx, netname,
5345 : num_tokens, tokens);
5346 : }
5347 0 : done:
5348 0 : for (i=0; i<num_tokens; i++) {
5349 0 : free_user_token(&tokens[i].token);
5350 : }
5351 0 : SAFE_FREE(tokens);
5352 0 : TALLOC_FREE(server_aliases);
5353 :
5354 0 : return nt_status;
5355 : }
5356 :
5357 0 : static int rpc_share_allowedusers(struct net_context *c, int argc,
5358 : const char **argv)
5359 : {
5360 : int result;
5361 :
5362 0 : if (c->display_usage) {
5363 0 : d_printf( "%s\n"
5364 : "net rpc share allowedusers\n"
5365 : " %s\n",
5366 : _("Usage:"),
5367 : _("List allowed users"));
5368 0 : return 0;
5369 : }
5370 :
5371 0 : result = run_rpc_command(c, NULL, &ndr_table_samr, 0,
5372 : rpc_aliaslist_internals,
5373 : argc, argv);
5374 0 : if (result != 0)
5375 0 : return result;
5376 :
5377 0 : result = run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
5378 : rpc_aliaslist_dump,
5379 : argc, argv);
5380 0 : if (result != 0)
5381 0 : return result;
5382 :
5383 0 : return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
5384 : rpc_share_allowedusers_internals,
5385 : argc, argv);
5386 : }
5387 :
5388 0 : int net_usersidlist(struct net_context *c, int argc, const char **argv)
5389 : {
5390 0 : int num_tokens = 0;
5391 0 : struct user_token *tokens = NULL;
5392 : int i;
5393 :
5394 0 : if (argc != 0) {
5395 0 : net_usersidlist_usage(c, argc, argv);
5396 0 : return 0;
5397 : }
5398 :
5399 0 : if (!get_user_tokens(c, &num_tokens, &tokens)) {
5400 0 : DEBUG(0, ("Could not get the user/sid list\n"));
5401 0 : return -1;
5402 : }
5403 :
5404 0 : for (i=0; i<num_tokens; i++) {
5405 0 : dump_user_token(&tokens[i]);
5406 0 : free_user_token(&tokens[i].token);
5407 : }
5408 :
5409 0 : SAFE_FREE(tokens);
5410 0 : return 0;
5411 : }
5412 :
5413 0 : int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
5414 : {
5415 0 : d_printf(_("net usersidlist\n"
5416 : "\tprints out a list of all users the running winbind knows\n"
5417 : "\tabout, together with all their SIDs. This is used as\n"
5418 : "\tinput to the 'net rpc share allowedusers' command.\n\n"));
5419 :
5420 0 : net_common_flags_usage(c, argc, argv);
5421 0 : return -1;
5422 : }
5423 :
5424 : /**
5425 : * 'net rpc share' entrypoint.
5426 : * @param argc Standard main() style argc.
5427 : * @param argv Standard main() style argv. Initial components are already
5428 : * stripped.
5429 : **/
5430 :
5431 0 : int net_rpc_share(struct net_context *c, int argc, const char **argv)
5432 : {
5433 : NET_API_STATUS status;
5434 :
5435 0 : struct functable func[] = {
5436 : {
5437 : "add",
5438 : rpc_share_add,
5439 : NET_TRANSPORT_RPC,
5440 : N_("Add share"),
5441 : N_("net rpc share add\n"
5442 : " Add share")
5443 : },
5444 : {
5445 : "delete",
5446 : rpc_share_delete,
5447 : NET_TRANSPORT_RPC,
5448 : N_("Remove share"),
5449 : N_("net rpc share delete\n"
5450 : " Remove share")
5451 : },
5452 : {
5453 : "allowedusers",
5454 : rpc_share_allowedusers,
5455 : NET_TRANSPORT_RPC,
5456 : N_("List allowed users"),
5457 : N_("net rpc share allowedusers\n"
5458 : " List allowed users")
5459 : },
5460 : {
5461 : "migrate",
5462 : rpc_share_migrate,
5463 : NET_TRANSPORT_RPC,
5464 : N_("Migrate share to local server"),
5465 : N_("net rpc share migrate\n"
5466 : " Migrate share to local server")
5467 : },
5468 : {
5469 : "list",
5470 : rpc_share_list,
5471 : NET_TRANSPORT_RPC,
5472 : N_("List shares"),
5473 : N_("net rpc share list\n"
5474 : " List shares")
5475 : },
5476 : {NULL, NULL, 0, NULL, NULL}
5477 : };
5478 :
5479 0 : status = libnetapi_net_init(&c->netapi_ctx);
5480 0 : if (status != 0) {
5481 0 : return -1;
5482 : }
5483 :
5484 0 : status = libnetapi_set_creds(c->netapi_ctx, c->creds);
5485 0 : if (status != 0) {
5486 0 : return -1;
5487 : }
5488 :
5489 :
5490 0 : if (argc == 0) {
5491 0 : if (c->display_usage) {
5492 0 : d_printf("%s\n%s",
5493 : _("Usage:"),
5494 : _("net rpc share\n"
5495 : " List shares\n"
5496 : " Alias for net rpc share list\n"));
5497 0 : net_display_usage_from_functable(func);
5498 0 : return 0;
5499 : }
5500 :
5501 0 : return rpc_share_list(c, argc, argv);
5502 : }
5503 :
5504 0 : return net_run_function(c, argc, argv, "net rpc share", func);
5505 : }
5506 :
5507 0 : static NTSTATUS rpc_sh_share_list(struct net_context *c,
5508 : TALLOC_CTX *mem_ctx,
5509 : struct rpc_sh_ctx *ctx,
5510 : struct rpc_pipe_client *pipe_hnd,
5511 : int argc, const char **argv)
5512 : {
5513 :
5514 0 : return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5515 : }
5516 :
5517 0 : static NTSTATUS rpc_sh_share_add(struct net_context *c,
5518 : TALLOC_CTX *mem_ctx,
5519 : struct rpc_sh_ctx *ctx,
5520 : struct rpc_pipe_client *pipe_hnd,
5521 : int argc, const char **argv)
5522 : {
5523 : NET_API_STATUS status;
5524 0 : uint32_t parm_err = 0;
5525 : struct SHARE_INFO_2 i2;
5526 :
5527 0 : if ((argc < 2) || (argc > 3)) {
5528 0 : d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5529 : ctx->whoami);
5530 0 : return NT_STATUS_INVALID_PARAMETER;
5531 : }
5532 :
5533 0 : i2.shi2_netname = argv[0];
5534 0 : i2.shi2_type = STYPE_DISKTREE;
5535 0 : i2.shi2_remark = (argc == 3) ? argv[2] : "";
5536 0 : i2.shi2_permissions = 0;
5537 0 : i2.shi2_max_uses = 0;
5538 0 : i2.shi2_current_uses = 0;
5539 0 : i2.shi2_path = argv[1];
5540 0 : i2.shi2_passwd = NULL;
5541 :
5542 0 : status = NetShareAdd(pipe_hnd->desthost,
5543 : 2,
5544 : (uint8_t *)&i2,
5545 : &parm_err);
5546 :
5547 0 : return werror_to_ntstatus(W_ERROR(status));
5548 : }
5549 :
5550 0 : static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5551 : TALLOC_CTX *mem_ctx,
5552 : struct rpc_sh_ctx *ctx,
5553 : struct rpc_pipe_client *pipe_hnd,
5554 : int argc, const char **argv)
5555 : {
5556 0 : if (argc != 1) {
5557 0 : d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5558 0 : return NT_STATUS_INVALID_PARAMETER;
5559 : }
5560 :
5561 0 : return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5562 : }
5563 :
5564 0 : static NTSTATUS rpc_sh_share_info(struct net_context *c,
5565 : TALLOC_CTX *mem_ctx,
5566 : struct rpc_sh_ctx *ctx,
5567 : struct rpc_pipe_client *pipe_hnd,
5568 : int argc, const char **argv)
5569 : {
5570 : union srvsvc_NetShareInfo info;
5571 : WERROR result;
5572 : NTSTATUS status;
5573 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5574 :
5575 0 : if (argc != 1) {
5576 0 : d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5577 0 : return NT_STATUS_INVALID_PARAMETER;
5578 : }
5579 :
5580 0 : status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5581 0 : pipe_hnd->desthost,
5582 : argv[0],
5583 : 2,
5584 : &info,
5585 : &result);
5586 0 : if (!NT_STATUS_IS_OK(status)) {
5587 0 : result = ntstatus_to_werror(status);
5588 0 : goto done;
5589 : }
5590 0 : if (!W_ERROR_IS_OK(result)) {
5591 0 : goto done;
5592 : }
5593 :
5594 0 : d_printf(_("Name: %s\n"), info.info2->name);
5595 0 : d_printf(_("Comment: %s\n"), info.info2->comment);
5596 0 : d_printf(_("Path: %s\n"), info.info2->path);
5597 0 : d_printf(_("Password: %s\n"), info.info2->password);
5598 :
5599 0 : done:
5600 0 : return werror_to_ntstatus(result);
5601 : }
5602 :
5603 0 : struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5604 : struct rpc_sh_ctx *ctx)
5605 : {
5606 : static struct rpc_sh_cmd cmds[] = {
5607 :
5608 : { "list", NULL, &ndr_table_srvsvc, rpc_sh_share_list,
5609 : N_("List available shares") },
5610 :
5611 : { "add", NULL, &ndr_table_srvsvc, rpc_sh_share_add,
5612 : N_("Add a share") },
5613 :
5614 : { "delete", NULL, &ndr_table_srvsvc, rpc_sh_share_delete,
5615 : N_("Delete a share") },
5616 :
5617 : { "info", NULL, &ndr_table_srvsvc, rpc_sh_share_info,
5618 : N_("Get information about a share") },
5619 :
5620 : { NULL, NULL, 0, NULL, NULL }
5621 : };
5622 :
5623 0 : return cmds;
5624 : }
5625 :
5626 : /****************************************************************************/
5627 :
5628 0 : static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5629 : {
5630 0 : return net_file_usage(c, argc, argv);
5631 : }
5632 :
5633 : /**
5634 : * Close a file on a remote RPC server.
5635 : *
5636 : * @param argc Standard main() style argc.
5637 : * @param argv Standard main() style argv. Initial components are already
5638 : * stripped.
5639 : *
5640 : * @return A shell status integer (0 for success).
5641 : **/
5642 0 : static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5643 : {
5644 0 : if (argc < 1 || c->display_usage) {
5645 0 : return rpc_file_usage(c, argc, argv);
5646 : }
5647 :
5648 0 : return NetFileClose(c->opt_host, atoi(argv[0]));
5649 : }
5650 :
5651 : /**
5652 : * Formatted print of open file info
5653 : *
5654 : * @param r struct FILE_INFO_3 contents
5655 : **/
5656 :
5657 0 : static void display_file_info_3(struct FILE_INFO_3 *r)
5658 : {
5659 0 : d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5660 : r->fi3_id, r->fi3_username, r->fi3_permissions,
5661 : r->fi3_num_locks, r->fi3_pathname);
5662 0 : }
5663 :
5664 : /**
5665 : * List files for a user on a remote RPC server.
5666 : *
5667 : * @param argc Standard main() style argc.
5668 : * @param argv Standard main() style argv. Initial components are already
5669 : * stripped.
5670 : *
5671 : * @return A shell status integer (0 for success)..
5672 : **/
5673 :
5674 0 : static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5675 : {
5676 : NET_API_STATUS status;
5677 0 : uint32_t preferred_len = 0xffffffff, i;
5678 0 : char *username=NULL;
5679 0 : uint32_t total_entries = 0;
5680 0 : uint32_t entries_read = 0;
5681 0 : uint32_t resume_handle = 0;
5682 0 : struct FILE_INFO_3 *i3 = NULL;
5683 :
5684 0 : if (c->display_usage) {
5685 0 : return rpc_file_usage(c, argc, argv);
5686 : }
5687 :
5688 : /* if argc > 0, must be user command */
5689 0 : if (argc > 0) {
5690 0 : username = smb_xstrdup(argv[0]);
5691 : }
5692 :
5693 0 : status = NetFileEnum(c->opt_host,
5694 : NULL,
5695 : username,
5696 : 3,
5697 : (uint8_t **)(void *)&i3,
5698 : preferred_len,
5699 : &entries_read,
5700 : &total_entries,
5701 : &resume_handle);
5702 :
5703 0 : if (status != 0) {
5704 0 : goto done;
5705 : }
5706 :
5707 : /* Display results */
5708 :
5709 0 : d_printf(_(
5710 : "\nEnumerating open files on remote server:\n\n"
5711 : "\nFileId Opened by Perms Locks Path"
5712 : "\n------ --------- ----- ----- ---- \n"));
5713 0 : for (i = 0; i < entries_read; i++) {
5714 0 : display_file_info_3(&i3[i]);
5715 : }
5716 0 : done:
5717 0 : SAFE_FREE(username);
5718 0 : return status;
5719 : }
5720 :
5721 : /**
5722 : * 'net rpc file' entrypoint.
5723 : * @param argc Standard main() style argc.
5724 : * @param argv Standard main() style argv. Initial components are already
5725 : * stripped.
5726 : **/
5727 :
5728 0 : int net_rpc_file(struct net_context *c, int argc, const char **argv)
5729 : {
5730 : NET_API_STATUS status;
5731 :
5732 0 : struct functable func[] = {
5733 : {
5734 : "close",
5735 : rpc_file_close,
5736 : NET_TRANSPORT_RPC,
5737 : N_("Close opened file"),
5738 : N_("net rpc file close\n"
5739 : " Close opened file")
5740 : },
5741 : {
5742 : "user",
5743 : rpc_file_user,
5744 : NET_TRANSPORT_RPC,
5745 : N_("List files opened by user"),
5746 : N_("net rpc file user\n"
5747 : " List files opened by user")
5748 : },
5749 : #if 0
5750 : {
5751 : "info",
5752 : rpc_file_info,
5753 : NET_TRANSPORT_RPC,
5754 : N_("Display information about opened file"),
5755 : N_("net rpc file info\n"
5756 : " Display information about opened file")
5757 : },
5758 : #endif
5759 : {NULL, NULL, 0, NULL, NULL}
5760 : };
5761 :
5762 0 : status = libnetapi_net_init(&c->netapi_ctx);
5763 0 : if (status != 0) {
5764 0 : return -1;
5765 : }
5766 :
5767 0 : status = libnetapi_set_creds(c->netapi_ctx, c->creds);
5768 0 : if (status != 0) {
5769 0 : return -1;
5770 : }
5771 :
5772 0 : if (argc == 0) {
5773 0 : if (c->display_usage) {
5774 0 : d_printf(_("Usage:\n"));
5775 0 : d_printf(_("net rpc file\n"
5776 : " List opened files\n"));
5777 0 : net_display_usage_from_functable(func);
5778 0 : return 0;
5779 : }
5780 :
5781 0 : return rpc_file_user(c, argc, argv);
5782 : }
5783 :
5784 0 : return net_run_function(c, argc, argv, "net rpc file", func);
5785 : }
5786 :
5787 : /**
5788 : * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5789 : *
5790 : * All parameters are provided by the run_rpc_command function, except for
5791 : * argc, argv which are passed through.
5792 : *
5793 : * @param c A net_context structure.
5794 : * @param domain_sid The domain sid acquired from the remote server.
5795 : * @param cli A cli_state connected to the server.
5796 : * @param mem_ctx Talloc context, destroyed on completion of the function.
5797 : * @param argc Standard main() style argc.
5798 : * @param argv Standard main() style argv. Initial components are already
5799 : * stripped.
5800 : *
5801 : * @return Normal NTSTATUS return.
5802 : **/
5803 :
5804 0 : static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5805 : const struct dom_sid *domain_sid,
5806 : const char *domain_name,
5807 : struct cli_state *cli,
5808 : struct rpc_pipe_client *pipe_hnd,
5809 : TALLOC_CTX *mem_ctx,
5810 : int argc,
5811 : const char **argv)
5812 : {
5813 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5814 : WERROR result;
5815 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5816 :
5817 0 : status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5818 0 : if (!NT_STATUS_IS_OK(status)) {
5819 0 : return status;
5820 : }
5821 0 : if (W_ERROR_IS_OK(result)) {
5822 0 : d_printf(_("\nShutdown successfully aborted\n"));
5823 0 : DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5824 : } else
5825 0 : DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5826 :
5827 0 : return werror_to_ntstatus(result);
5828 : }
5829 :
5830 : /**
5831 : * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5832 : *
5833 : * All parameters are provided by the run_rpc_command function, except for
5834 : * argc, argv which are passed through.
5835 : *
5836 : * @param c A net_context structure.
5837 : * @param domain_sid The domain sid acquired from the remote server.
5838 : * @param cli A cli_state connected to the server.
5839 : * @param mem_ctx Talloc context, destroyed on completion of the function.
5840 : * @param argc Standard main() style argc.
5841 : * @param argv Standard main() style argv. Initial components are already
5842 : * stripped.
5843 : *
5844 : * @return Normal NTSTATUS return.
5845 : **/
5846 :
5847 0 : static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5848 : const struct dom_sid *domain_sid,
5849 : const char *domain_name,
5850 : struct cli_state *cli,
5851 : struct rpc_pipe_client *pipe_hnd,
5852 : TALLOC_CTX *mem_ctx,
5853 : int argc,
5854 : const char **argv)
5855 : {
5856 0 : NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5857 : WERROR werr;
5858 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5859 :
5860 0 : result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5861 :
5862 0 : if (!NT_STATUS_IS_OK(result)) {
5863 0 : DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5864 0 : return result;
5865 : }
5866 0 : if (W_ERROR_IS_OK(werr)) {
5867 0 : d_printf(_("\nShutdown successfully aborted\n"));
5868 0 : DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5869 : } else
5870 0 : DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5871 :
5872 0 : return werror_to_ntstatus(werr);
5873 : }
5874 :
5875 : /**
5876 : * ABORT the shutdown of a remote RPC server.
5877 : *
5878 : * @param argc Standard main() style argc.
5879 : * @param argv Standard main() style argv. Initial components are already
5880 : * stripped.
5881 : *
5882 : * @return A shell status integer (0 for success).
5883 : **/
5884 :
5885 0 : static int rpc_shutdown_abort(struct net_context *c, int argc,
5886 : const char **argv)
5887 : {
5888 0 : int rc = -1;
5889 :
5890 0 : if (c->display_usage) {
5891 0 : d_printf( "%s\n"
5892 : "net rpc abortshutdown\n"
5893 : " %s\n",
5894 : _("Usage:"),
5895 : _("Abort a scheduled shutdown"));
5896 0 : return 0;
5897 : }
5898 :
5899 0 : rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5900 : rpc_shutdown_abort_internals, argc, argv);
5901 :
5902 0 : if (rc == 0)
5903 0 : return rc;
5904 :
5905 0 : DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5906 :
5907 0 : return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5908 : rpc_reg_shutdown_abort_internals,
5909 : argc, argv);
5910 : }
5911 :
5912 : /**
5913 : * Shut down a remote RPC Server via initshutdown pipe.
5914 : *
5915 : * All parameters are provided by the run_rpc_command function, except for
5916 : * argc, argv which are passed through.
5917 : *
5918 : * @param c A net_context structure.
5919 : * @param domain_sid The domain sid acquired from the remote server.
5920 : * @param cli A cli_state connected to the server.
5921 : * @param mem_ctx Talloc context, destroyed on completion of the function.
5922 : * @param argc Standard main() style argc.
5923 : * @param argv Standard main() style argv. Initial components are already
5924 : * stripped.
5925 : *
5926 : * @return Normal NTSTATUS return.
5927 : **/
5928 :
5929 0 : NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5930 : const struct dom_sid *domain_sid,
5931 : const char *domain_name,
5932 : struct cli_state *cli,
5933 : struct rpc_pipe_client *pipe_hnd,
5934 : TALLOC_CTX *mem_ctx,
5935 : int argc,
5936 : const char **argv)
5937 : {
5938 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5939 : WERROR result;
5940 0 : const char *msg = N_("This machine will be shutdown shortly");
5941 0 : uint32_t timeout = 20;
5942 : struct lsa_StringLarge msg_string;
5943 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5944 :
5945 0 : if (c->opt_comment) {
5946 0 : msg = c->opt_comment;
5947 : }
5948 0 : if (c->opt_timeout) {
5949 0 : timeout = c->opt_timeout;
5950 : }
5951 :
5952 0 : msg_string.string = msg;
5953 :
5954 : /* create an entry */
5955 0 : status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5956 0 : &msg_string, timeout, c->opt_force, c->opt_reboot,
5957 : &result);
5958 0 : if (!NT_STATUS_IS_OK(status)) {
5959 0 : return status;
5960 : }
5961 0 : if (W_ERROR_IS_OK(result)) {
5962 0 : d_printf(_("\nShutdown of remote machine succeeded\n"));
5963 0 : DEBUG(5,("Shutdown of remote machine succeeded\n"));
5964 : } else {
5965 0 : DEBUG(1,("Shutdown of remote machine failed!\n"));
5966 : }
5967 0 : return werror_to_ntstatus(result);
5968 : }
5969 :
5970 : /**
5971 : * Shut down a remote RPC Server via winreg pipe.
5972 : *
5973 : * All parameters are provided by the run_rpc_command function, except for
5974 : * argc, argv which are passed through.
5975 : *
5976 : * @param c A net_context structure.
5977 : * @param domain_sid The domain sid acquired from the remote server.
5978 : * @param cli A cli_state connected to the server.
5979 : * @param mem_ctx Talloc context, destroyed on completion of the function.
5980 : * @param argc Standard main() style argc.
5981 : * @param argv Standard main() style argv. Initial components are already
5982 : * stripped.
5983 : *
5984 : * @return Normal NTSTATUS return.
5985 : **/
5986 :
5987 0 : NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5988 : const struct dom_sid *domain_sid,
5989 : const char *domain_name,
5990 : struct cli_state *cli,
5991 : struct rpc_pipe_client *pipe_hnd,
5992 : TALLOC_CTX *mem_ctx,
5993 : int argc,
5994 : const char **argv)
5995 : {
5996 0 : const char *msg = N_("This machine will be shutdown shortly");
5997 0 : uint32_t timeout = 20;
5998 : struct lsa_StringLarge msg_string;
5999 : NTSTATUS result;
6000 : WERROR werr;
6001 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6002 :
6003 0 : if (c->opt_comment) {
6004 0 : msg = c->opt_comment;
6005 : }
6006 0 : msg_string.string = msg;
6007 :
6008 0 : if (c->opt_timeout) {
6009 0 : timeout = c->opt_timeout;
6010 : }
6011 :
6012 : /* create an entry */
6013 0 : result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
6014 0 : &msg_string, timeout, c->opt_force, c->opt_reboot,
6015 : &werr);
6016 0 : if (!NT_STATUS_IS_OK(result)) {
6017 0 : d_fprintf(stderr, "\nShutdown of remote machine failed\n");
6018 0 : return result;
6019 : }
6020 :
6021 0 : if (W_ERROR_IS_OK(werr)) {
6022 0 : d_printf(_("\nShutdown of remote machine succeeded\n"));
6023 : } else {
6024 0 : d_fprintf(stderr, "\nShutdown of remote machine failed\n");
6025 0 : if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
6026 0 : d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
6027 : else
6028 0 : d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
6029 : }
6030 :
6031 0 : return werror_to_ntstatus(werr);
6032 : }
6033 :
6034 : /**
6035 : * Shut down a remote RPC server.
6036 : *
6037 : * @param argc Standard main() style argc.
6038 : * @param argv Standard main() style argv. Initial components are already
6039 : * stripped.
6040 : *
6041 : * @return A shell status integer (0 for success).
6042 : **/
6043 :
6044 0 : static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
6045 : {
6046 0 : int rc = -1;
6047 :
6048 0 : if (c->display_usage) {
6049 0 : d_printf( "%s\n"
6050 : "net rpc shutdown\n"
6051 : " %s\n",
6052 : _("Usage:"),
6053 : _("Shut down a remote RPC server"));
6054 0 : return 0;
6055 : }
6056 :
6057 0 : rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
6058 : rpc_init_shutdown_internals, argc, argv);
6059 :
6060 0 : if (rc) {
6061 0 : DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
6062 0 : rc = run_rpc_command(c, NULL, &ndr_table_winreg, 0,
6063 : rpc_reg_shutdown_internals, argc, argv);
6064 : }
6065 :
6066 0 : return rc;
6067 : }
6068 :
6069 : /***************************************************************************
6070 : NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
6071 : ***************************************************************************/
6072 :
6073 : /**
6074 : * Add interdomain trust account to the RPC server.
6075 : * All parameters (except for argc and argv) are passed by run_rpc_command
6076 : * function.
6077 : *
6078 : * @param c A net_context structure.
6079 : * @param domain_sid The domain sid acquired from the server.
6080 : * @param cli A cli_state connected to the server.
6081 : * @param mem_ctx Talloc context, destroyed on completion of the function.
6082 : * @param argc Standard main() style argc.
6083 : * @param argv Standard main() style argv. Initial components are already
6084 : * stripped.
6085 : *
6086 : * @return normal NTSTATUS return code.
6087 : */
6088 :
6089 0 : static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
6090 : const struct dom_sid *domain_sid,
6091 : const char *domain_name,
6092 : struct cli_state *cli,
6093 : struct rpc_pipe_client *pipe_hnd,
6094 : TALLOC_CTX *mem_ctx,
6095 : int argc,
6096 : const char **argv)
6097 : {
6098 : struct policy_handle connect_pol, domain_pol, user_pol;
6099 : NTSTATUS status, result;
6100 : char *acct_name;
6101 : struct lsa_String lsa_acct_name;
6102 : uint32_t acb_info;
6103 0 : uint32_t acct_flags=0;
6104 : uint32_t user_rid;
6105 0 : uint32_t access_granted = 0;
6106 : union samr_UserInfo info;
6107 : unsigned int orig_timeout;
6108 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6109 0 : DATA_BLOB session_key = data_blob_null;
6110 0 : TALLOC_CTX *frame = NULL;
6111 :
6112 0 : if (argc != 2) {
6113 0 : d_printf("%s\n%s",
6114 : _("Usage:"),
6115 : _(" net rpc trustdom add <domain_name> "
6116 : "<trust password>\n"));
6117 0 : return NT_STATUS_INVALID_PARAMETER;
6118 : }
6119 :
6120 0 : frame = talloc_stackframe();
6121 :
6122 : /*
6123 : * Make valid trusting domain account (ie. uppercased and with '$' appended)
6124 : */
6125 :
6126 0 : if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
6127 0 : status = NT_STATUS_NO_MEMORY;
6128 : }
6129 :
6130 0 : if (!strupper_m(acct_name)) {
6131 0 : status = NT_STATUS_INVALID_PARAMETER;
6132 0 : goto done;
6133 : }
6134 :
6135 0 : init_lsa_String(&lsa_acct_name, acct_name);
6136 :
6137 0 : status = cli_get_session_key(frame, pipe_hnd, &session_key);
6138 0 : if (!NT_STATUS_IS_OK(status)) {
6139 0 : DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
6140 : nt_errstr(status)));
6141 0 : goto done;
6142 : }
6143 :
6144 : /* Get samr policy handle */
6145 0 : status = dcerpc_samr_Connect2(b, frame,
6146 0 : pipe_hnd->desthost,
6147 : MAXIMUM_ALLOWED_ACCESS,
6148 : &connect_pol,
6149 : &result);
6150 0 : if (!NT_STATUS_IS_OK(status)) {
6151 0 : goto done;
6152 : }
6153 0 : if (!NT_STATUS_IS_OK(result)) {
6154 0 : status = result;
6155 0 : goto done;
6156 : }
6157 :
6158 : /* Get domain policy handle */
6159 0 : status = dcerpc_samr_OpenDomain(b, frame,
6160 : &connect_pol,
6161 : MAXIMUM_ALLOWED_ACCESS,
6162 : discard_const_p(struct dom_sid2, domain_sid),
6163 : &domain_pol,
6164 : &result);
6165 0 : if (!NT_STATUS_IS_OK(status)) {
6166 0 : goto done;
6167 : }
6168 0 : if (!NT_STATUS_IS_OK(result)) {
6169 0 : status = result;
6170 0 : goto done;
6171 : }
6172 :
6173 : /* This call can take a long time - allow the server to time out.
6174 : * 35 seconds should do it. */
6175 :
6176 0 : orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
6177 :
6178 : /* Create trusting domain's account */
6179 0 : acb_info = ACB_NORMAL;
6180 0 : acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
6181 : SEC_STD_WRITE_DAC | SEC_STD_DELETE |
6182 : SAMR_USER_ACCESS_SET_PASSWORD |
6183 : SAMR_USER_ACCESS_GET_ATTRIBUTES |
6184 : SAMR_USER_ACCESS_SET_ATTRIBUTES;
6185 :
6186 0 : status = dcerpc_samr_CreateUser2(b, frame,
6187 : &domain_pol,
6188 : &lsa_acct_name,
6189 : acb_info,
6190 : acct_flags,
6191 : &user_pol,
6192 : &access_granted,
6193 : &user_rid,
6194 : &result);
6195 0 : if (!NT_STATUS_IS_OK(status)) {
6196 0 : goto done;
6197 : }
6198 : /* And restore our original timeout. */
6199 0 : rpccli_set_timeout(pipe_hnd, orig_timeout);
6200 :
6201 0 : if (!NT_STATUS_IS_OK(result)) {
6202 0 : status = result;
6203 0 : d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
6204 : acct_name, nt_errstr(result));
6205 0 : goto done;
6206 : }
6207 :
6208 : {
6209 : struct samr_CryptPassword crypt_pwd;
6210 :
6211 0 : ZERO_STRUCT(info.info23);
6212 :
6213 0 : status = init_samr_CryptPassword(argv[1],
6214 : &session_key,
6215 : &crypt_pwd);
6216 0 : if (!NT_STATUS_IS_OK(status)) {
6217 0 : goto done;
6218 : }
6219 :
6220 0 : info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
6221 : SAMR_FIELD_NT_PASSWORD_PRESENT;
6222 0 : info.info23.info.acct_flags = ACB_DOMTRUST;
6223 0 : info.info23.password = crypt_pwd;
6224 :
6225 0 : status = dcerpc_samr_SetUserInfo2(b, frame,
6226 : &user_pol,
6227 : 23,
6228 : &info,
6229 : &result);
6230 0 : if (!NT_STATUS_IS_OK(status)) {
6231 0 : goto done;
6232 : }
6233 :
6234 0 : if (!NT_STATUS_IS_OK(result)) {
6235 0 : status = result;
6236 0 : DEBUG(0,("Could not set trust account password: %s\n",
6237 : nt_errstr(result)));
6238 0 : goto done;
6239 : }
6240 : }
6241 :
6242 0 : status = NT_STATUS_OK;
6243 0 : done:
6244 0 : SAFE_FREE(acct_name);
6245 0 : data_blob_clear_free(&session_key);
6246 0 : TALLOC_FREE(frame);
6247 0 : return status;
6248 : }
6249 :
6250 : /**
6251 : * Create interdomain trust account for a remote domain.
6252 : *
6253 : * @param argc Standard argc.
6254 : * @param argv Standard argv without initial components.
6255 : *
6256 : * @return Integer status (0 means success).
6257 : **/
6258 :
6259 0 : static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
6260 : {
6261 0 : if (argc > 0 && !c->display_usage) {
6262 0 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6263 : rpc_trustdom_add_internals, argc, argv);
6264 : } else {
6265 0 : d_printf("%s\n%s",
6266 : _("Usage:"),
6267 : _("net rpc trustdom add <domain_name> <trust "
6268 : "password>\n"));
6269 0 : return -1;
6270 : }
6271 : }
6272 :
6273 :
6274 : /**
6275 : * Remove interdomain trust account from the RPC server.
6276 : * All parameters (except for argc and argv) are passed by run_rpc_command
6277 : * function.
6278 : *
6279 : * @param c A net_context structure.
6280 : * @param domain_sid The domain sid acquired from the server.
6281 : * @param cli A cli_state connected to the server.
6282 : * @param mem_ctx Talloc context, destroyed on completion of the function.
6283 : * @param argc Standard main() style argc.
6284 : * @param argv Standard main() style argv. Initial components are already
6285 : * stripped.
6286 : *
6287 : * @return normal NTSTATUS return code.
6288 : */
6289 :
6290 0 : static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
6291 : const struct dom_sid *domain_sid,
6292 : const char *domain_name,
6293 : struct cli_state *cli,
6294 : struct rpc_pipe_client *pipe_hnd,
6295 : TALLOC_CTX *mem_ctx,
6296 : int argc,
6297 : const char **argv)
6298 : {
6299 : struct policy_handle connect_pol, domain_pol, user_pol;
6300 : NTSTATUS status, result;
6301 : char *acct_name;
6302 : struct dom_sid trust_acct_sid;
6303 : struct samr_Ids user_rids, name_types;
6304 : struct lsa_String lsa_acct_name;
6305 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6306 :
6307 0 : if (argc != 1) {
6308 0 : d_printf("%s\n%s",
6309 : _("Usage:"),
6310 : _(" net rpc trustdom del <domain_name>\n"));
6311 0 : return NT_STATUS_INVALID_PARAMETER;
6312 : }
6313 :
6314 : /*
6315 : * Make valid trusting domain account (ie. uppercased and with '$' appended)
6316 : */
6317 0 : acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
6318 :
6319 0 : if (acct_name == NULL)
6320 0 : return NT_STATUS_NO_MEMORY;
6321 :
6322 0 : if (!strupper_m(acct_name)) {
6323 0 : TALLOC_FREE(acct_name);
6324 0 : return NT_STATUS_INVALID_PARAMETER;
6325 : }
6326 :
6327 : /* Get samr policy handle */
6328 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
6329 0 : pipe_hnd->desthost,
6330 : MAXIMUM_ALLOWED_ACCESS,
6331 : &connect_pol,
6332 : &result);
6333 0 : if (!NT_STATUS_IS_OK(status)) {
6334 0 : goto done;
6335 : }
6336 0 : if (!NT_STATUS_IS_OK(result)) {
6337 0 : status = result;
6338 0 : goto done;
6339 : }
6340 :
6341 : /* Get domain policy handle */
6342 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
6343 : &connect_pol,
6344 : MAXIMUM_ALLOWED_ACCESS,
6345 : discard_const_p(struct dom_sid2, domain_sid),
6346 : &domain_pol,
6347 : &result);
6348 0 : if (!NT_STATUS_IS_OK(status)) {
6349 0 : goto done;
6350 : }
6351 0 : if (!NT_STATUS_IS_OK(result)) {
6352 0 : status = result;
6353 0 : goto done;
6354 : }
6355 :
6356 0 : init_lsa_String(&lsa_acct_name, acct_name);
6357 :
6358 0 : status = dcerpc_samr_LookupNames(b, mem_ctx,
6359 : &domain_pol,
6360 : 1,
6361 : &lsa_acct_name,
6362 : &user_rids,
6363 : &name_types,
6364 : &result);
6365 0 : if (!NT_STATUS_IS_OK(status)) {
6366 0 : d_printf(_("net rpc trustdom del: LookupNames on user %s "
6367 : "failed %s\n"),
6368 : acct_name, nt_errstr(status));
6369 0 : goto done;
6370 : }
6371 0 : if (!NT_STATUS_IS_OK(result)) {
6372 0 : status = result;
6373 0 : d_printf(_("net rpc trustdom del: LookupNames on user %s "
6374 : "failed %s\n"),
6375 : acct_name, nt_errstr(result) );
6376 0 : goto done;
6377 : }
6378 0 : if (user_rids.count != 1) {
6379 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6380 0 : goto done;
6381 : }
6382 0 : if (name_types.count != 1) {
6383 0 : status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6384 0 : goto done;
6385 : }
6386 :
6387 0 : status = dcerpc_samr_OpenUser(b, mem_ctx,
6388 : &domain_pol,
6389 : MAXIMUM_ALLOWED_ACCESS,
6390 0 : user_rids.ids[0],
6391 : &user_pol,
6392 : &result);
6393 0 : if (!NT_STATUS_IS_OK(status)) {
6394 0 : d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6395 : "%s\n"),
6396 : acct_name, nt_errstr(status) );
6397 0 : goto done;
6398 : }
6399 :
6400 0 : if (!NT_STATUS_IS_OK(result)) {
6401 0 : status = result;
6402 0 : d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6403 : "%s\n"),
6404 : acct_name, nt_errstr(result) );
6405 0 : goto done;
6406 : }
6407 :
6408 : /* append the rid to the domain sid */
6409 0 : if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6410 0 : goto done;
6411 : }
6412 :
6413 : /* remove the sid */
6414 :
6415 0 : status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6416 : &user_pol,
6417 : &trust_acct_sid,
6418 : &result);
6419 0 : if (!NT_STATUS_IS_OK(status)) {
6420 0 : d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6421 : " on user %s failed %s\n"),
6422 : acct_name, nt_errstr(status));
6423 0 : goto done;
6424 : }
6425 0 : if (!NT_STATUS_IS_OK(result)) {
6426 0 : status = result;
6427 0 : d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6428 : " on user %s failed %s\n"),
6429 : acct_name, nt_errstr(result) );
6430 0 : goto done;
6431 : }
6432 :
6433 :
6434 : /* Delete user */
6435 :
6436 0 : status = dcerpc_samr_DeleteUser(b, mem_ctx,
6437 : &user_pol,
6438 : &result);
6439 0 : if (!NT_STATUS_IS_OK(status)) {
6440 0 : d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6441 : "%s\n"),
6442 : acct_name, nt_errstr(status));
6443 0 : goto done;
6444 : }
6445 :
6446 0 : if (!NT_STATUS_IS_OK(result)) {
6447 0 : result = status;
6448 0 : d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6449 : "%s\n"),
6450 : acct_name, nt_errstr(result) );
6451 0 : goto done;
6452 : }
6453 :
6454 0 : if (!NT_STATUS_IS_OK(result)) {
6455 0 : d_printf(_("Could not set trust account password: %s\n"),
6456 : nt_errstr(result));
6457 0 : goto done;
6458 : }
6459 :
6460 0 : done:
6461 0 : return status;
6462 : }
6463 :
6464 : /**
6465 : * Delete interdomain trust account for a remote domain.
6466 : *
6467 : * @param argc Standard argc.
6468 : * @param argv Standard argv without initial components.
6469 : *
6470 : * @return Integer status (0 means success).
6471 : **/
6472 :
6473 0 : static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6474 : {
6475 0 : if (argc > 0 && !c->display_usage) {
6476 0 : return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6477 : rpc_trustdom_del_internals, argc, argv);
6478 : } else {
6479 0 : d_printf("%s\n%s",
6480 : _("Usage:"),
6481 : _("net rpc trustdom del <domain>\n"));
6482 0 : return -1;
6483 : }
6484 : }
6485 :
6486 0 : static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6487 : struct cli_state *cli,
6488 : TALLOC_CTX *mem_ctx,
6489 : const char *domain_name)
6490 : {
6491 0 : char *dc_name = NULL;
6492 0 : const char *buffer = NULL;
6493 : struct rpc_pipe_client *netr;
6494 : NTSTATUS status;
6495 : WERROR result;
6496 : struct dcerpc_binding_handle *b;
6497 :
6498 : /* Use NetServerEnum2 */
6499 :
6500 0 : if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6501 0 : SAFE_FREE(dc_name);
6502 0 : return NT_STATUS_OK;
6503 : }
6504 :
6505 0 : DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6506 : for domain %s\n", domain_name));
6507 :
6508 : /* Try netr_GetDcName */
6509 :
6510 0 : status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon,
6511 : &netr);
6512 0 : if (!NT_STATUS_IS_OK(status)) {
6513 0 : return status;
6514 : }
6515 :
6516 0 : b = netr->binding_handle;
6517 :
6518 0 : status = dcerpc_netr_GetDcName(b, mem_ctx,
6519 0 : netr->desthost,
6520 : domain_name,
6521 : &buffer,
6522 : &result);
6523 0 : TALLOC_FREE(netr);
6524 :
6525 0 : if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6526 0 : return status;
6527 : }
6528 :
6529 0 : DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6530 : for domain %s\n", domain_name));
6531 :
6532 0 : if (!NT_STATUS_IS_OK(status)) {
6533 0 : return status;
6534 : }
6535 :
6536 0 : return werror_to_ntstatus(result);
6537 : }
6538 :
6539 : /**
6540 : * Establish trust relationship to a trusting domain.
6541 : * Interdomain account must already be created on remote PDC.
6542 : *
6543 : * @param c A net_context structure.
6544 : * @param argc Standard argc.
6545 : * @param argv Standard argv without initial components.
6546 : *
6547 : * @return Integer status (0 means success).
6548 : **/
6549 :
6550 0 : static int rpc_trustdom_establish(struct net_context *c, int argc,
6551 : const char **argv)
6552 : {
6553 0 : struct cli_state *cli = NULL;
6554 : struct sockaddr_storage server_ss;
6555 0 : struct rpc_pipe_client *pipe_hnd = NULL;
6556 : struct policy_handle connect_hnd;
6557 : TALLOC_CTX *mem_ctx;
6558 : NTSTATUS nt_status, result;
6559 : struct dom_sid *domain_sid;
6560 :
6561 : char* domain_name;
6562 : char* acct_name;
6563 : fstring pdc_name;
6564 0 : union lsa_PolicyInformation *info = NULL;
6565 : struct dcerpc_binding_handle *b;
6566 :
6567 : /*
6568 : * Connect to \\server\ipc$ as 'our domain' account with password
6569 : */
6570 :
6571 0 : if (argc != 1 || c->display_usage) {
6572 0 : d_printf("%s\n%s",
6573 : _("Usage:"),
6574 : _("net rpc trustdom establish <domain_name>\n"));
6575 0 : return -1;
6576 : }
6577 :
6578 0 : domain_name = smb_xstrdup(argv[0]);
6579 0 : if (!strupper_m(domain_name)) {
6580 0 : SAFE_FREE(domain_name);
6581 0 : return -1;
6582 : }
6583 :
6584 : /* account name used at first is our domain's name with '$' */
6585 0 : if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6586 0 : return -1;
6587 : }
6588 0 : if (!strupper_m(acct_name)) {
6589 0 : SAFE_FREE(domain_name);
6590 0 : SAFE_FREE(acct_name);
6591 0 : return -1;
6592 : }
6593 :
6594 : /*
6595 : * opt_workgroup will be used by connection functions further,
6596 : * hence it should be set to remote domain name instead of ours
6597 : */
6598 0 : if (c->opt_workgroup) {
6599 0 : c->opt_workgroup = smb_xstrdup(domain_name);
6600 : };
6601 :
6602 0 : c->opt_user_name = acct_name;
6603 0 : c->opt_user_specified = true;
6604 :
6605 : /* find the domain controller */
6606 0 : if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6607 0 : DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6608 0 : return -1;
6609 : }
6610 :
6611 : /* connect to ipc$ as username/password */
6612 0 : nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6613 0 : if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6614 :
6615 : /* Is it trusting domain account for sure ? */
6616 0 : DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6617 : nt_errstr(nt_status)));
6618 0 : return -1;
6619 : }
6620 :
6621 : /* store who we connected to */
6622 :
6623 0 : saf_store( domain_name, pdc_name );
6624 :
6625 : /*
6626 : * Connect to \\server\ipc$ again (this time anonymously)
6627 : */
6628 :
6629 0 : nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6630 : (char*)pdc_name);
6631 :
6632 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6633 0 : DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6634 : domain_name, nt_errstr(nt_status)));
6635 0 : return -1;
6636 : }
6637 :
6638 0 : if (!(mem_ctx = talloc_init("establishing trust relationship to "
6639 : "domain %s", domain_name))) {
6640 0 : DEBUG(0, ("talloc_init() failed\n"));
6641 0 : cli_shutdown(cli);
6642 0 : return -1;
6643 : }
6644 :
6645 : /* Make sure we're talking to a proper server */
6646 :
6647 0 : nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6648 0 : if (!NT_STATUS_IS_OK(nt_status)) {
6649 0 : cli_shutdown(cli);
6650 0 : talloc_destroy(mem_ctx);
6651 0 : return -1;
6652 : }
6653 :
6654 : /*
6655 : * Call LsaOpenPolicy and LsaQueryInfo
6656 : */
6657 :
6658 0 : nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6659 : &pipe_hnd);
6660 0 : if (!NT_STATUS_IS_OK(nt_status)) {
6661 0 : DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6662 0 : cli_shutdown(cli);
6663 0 : talloc_destroy(mem_ctx);
6664 0 : return -1;
6665 : }
6666 :
6667 0 : b = pipe_hnd->binding_handle;
6668 :
6669 0 : nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6670 : &connect_hnd);
6671 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6672 0 : DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6673 : nt_errstr(nt_status)));
6674 0 : cli_shutdown(cli);
6675 0 : talloc_destroy(mem_ctx);
6676 0 : return -1;
6677 : }
6678 :
6679 : /* Querying info level 5 */
6680 :
6681 0 : nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6682 : &connect_hnd,
6683 : LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6684 : &info,
6685 : &result);
6686 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6687 0 : DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6688 : nt_errstr(nt_status)));
6689 0 : cli_shutdown(cli);
6690 0 : talloc_destroy(mem_ctx);
6691 0 : return -1;
6692 : }
6693 0 : if (NT_STATUS_IS_ERR(result)) {
6694 0 : DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6695 : nt_errstr(result)));
6696 0 : cli_shutdown(cli);
6697 0 : talloc_destroy(mem_ctx);
6698 0 : return -1;
6699 : }
6700 :
6701 0 : domain_sid = info->account_domain.sid;
6702 :
6703 : /* There should be actually query info level 3 (following nt serv behaviour),
6704 : but I still don't know if it's _really_ necessary */
6705 :
6706 : /*
6707 : * Store the password in secrets db
6708 : */
6709 :
6710 0 : if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6711 0 : DEBUG(0, ("Storing password for trusted domain failed.\n"));
6712 0 : cli_shutdown(cli);
6713 0 : talloc_destroy(mem_ctx);
6714 0 : return -1;
6715 : }
6716 :
6717 : /*
6718 : * Close the pipes and clean up
6719 : */
6720 :
6721 0 : nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6722 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6723 0 : DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6724 : nt_errstr(nt_status)));
6725 0 : cli_shutdown(cli);
6726 0 : talloc_destroy(mem_ctx);
6727 0 : return -1;
6728 : }
6729 :
6730 0 : cli_shutdown(cli);
6731 :
6732 0 : talloc_destroy(mem_ctx);
6733 :
6734 0 : d_printf(_("Trust to domain %s established\n"), domain_name);
6735 0 : return 0;
6736 : }
6737 :
6738 : /**
6739 : * Revoke trust relationship to the remote domain.
6740 : *
6741 : * @param c A net_context structure.
6742 : * @param argc Standard argc.
6743 : * @param argv Standard argv without initial components.
6744 : *
6745 : * @return Integer status (0 means success).
6746 : **/
6747 :
6748 0 : static int rpc_trustdom_revoke(struct net_context *c, int argc,
6749 : const char **argv)
6750 : {
6751 : char* domain_name;
6752 0 : int rc = -1;
6753 :
6754 0 : if (argc < 1 || c->display_usage) {
6755 0 : d_printf("%s\n%s",
6756 : _("Usage:"),
6757 : _("net rpc trustdom revoke <domain_name>\n"
6758 : " Revoke trust relationship\n"
6759 : " domain_name\tName of domain to revoke trust\n"));
6760 0 : return -1;
6761 : }
6762 :
6763 : /* generate upper cased domain name */
6764 0 : domain_name = smb_xstrdup(argv[0]);
6765 0 : if (!strupper_m(domain_name)) {
6766 0 : SAFE_FREE(domain_name);
6767 0 : return -1;
6768 : }
6769 :
6770 : /* delete password of the trust */
6771 0 : if (!pdb_del_trusteddom_pw(domain_name)) {
6772 0 : DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6773 : domain_name));
6774 0 : goto done;
6775 : };
6776 :
6777 0 : rc = 0;
6778 0 : done:
6779 0 : SAFE_FREE(domain_name);
6780 0 : return rc;
6781 : }
6782 :
6783 0 : static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6784 : const struct dom_sid *domain_sid,
6785 : const char *domain_name,
6786 : struct cli_state *cli,
6787 : struct rpc_pipe_client *pipe_hnd,
6788 : TALLOC_CTX *mem_ctx,
6789 : int argc,
6790 : const char **argv)
6791 : {
6792 : struct dom_sid_buf sid_str;
6793 0 : d_printf("%s\n", dom_sid_str_buf(domain_sid, &sid_str));
6794 0 : return NT_STATUS_OK;
6795 : }
6796 :
6797 0 : static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6798 : {
6799 : struct dom_sid_buf sid_str;
6800 :
6801 0 : d_printf("%-20s%s\n",
6802 : trusted_dom_name,
6803 : dom_sid_str_buf(dom_sid, &sid_str));
6804 0 : }
6805 :
6806 0 : static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6807 : TALLOC_CTX *mem_ctx,
6808 : struct policy_handle *pol,
6809 : struct dom_sid dom_sid,
6810 : const char *trusted_dom_name)
6811 : {
6812 : NTSTATUS nt_status, result;
6813 0 : union lsa_TrustedDomainInfo *info = NULL;
6814 0 : char *cleartextpwd = NULL;
6815 : DATA_BLOB session_key;
6816 0 : DATA_BLOB data = data_blob_null;
6817 0 : struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6818 :
6819 0 : nt_status = dcerpc_lsa_QueryTrustedDomainInfoBySid(b, mem_ctx,
6820 : pol,
6821 : &dom_sid,
6822 : LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6823 : &info,
6824 : &result);
6825 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6826 0 : DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6827 : nt_errstr(nt_status)));
6828 0 : goto done;
6829 : }
6830 0 : if (NT_STATUS_IS_ERR(result)) {
6831 0 : nt_status = result;
6832 0 : DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6833 : nt_errstr(result)));
6834 0 : goto done;
6835 : }
6836 :
6837 0 : data = data_blob(info->password.password->data,
6838 : info->password.password->length);
6839 :
6840 0 : nt_status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6841 0 : if (!NT_STATUS_IS_OK(nt_status)) {
6842 0 : DEBUG(0, ("Could not retrieve session key: %s\n", nt_errstr(nt_status)));
6843 0 : goto done;
6844 : }
6845 :
6846 0 : cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key);
6847 0 : data_blob_free(&session_key);
6848 :
6849 0 : if (cleartextpwd == NULL) {
6850 0 : DEBUG(0,("retrieved NULL password\n"));
6851 0 : nt_status = NT_STATUS_UNSUCCESSFUL;
6852 0 : goto done;
6853 : }
6854 :
6855 0 : if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6856 0 : DEBUG(0, ("Storing password for trusted domain failed.\n"));
6857 0 : nt_status = NT_STATUS_UNSUCCESSFUL;
6858 0 : goto done;
6859 : }
6860 :
6861 : #ifdef DEBUG_PASSWORD
6862 : {
6863 : struct dom_sid_buf buf;
6864 0 : DEBUG(100,("successfully vampired trusted domain [%s], "
6865 : "sid: [%s], password: [%s]\n",
6866 : trusted_dom_name,
6867 : dom_sid_str_buf(&dom_sid, &buf),
6868 : cleartextpwd));
6869 : }
6870 : #endif
6871 :
6872 0 : done:
6873 0 : SAFE_FREE(cleartextpwd);
6874 0 : data_blob_free(&data);
6875 :
6876 0 : return nt_status;
6877 : }
6878 :
6879 0 : static int rpc_trustdom_vampire(struct net_context *c, int argc,
6880 : const char **argv)
6881 : {
6882 : /* common variables */
6883 : TALLOC_CTX* mem_ctx;
6884 0 : struct cli_state *cli = NULL;
6885 0 : struct rpc_pipe_client *pipe_hnd = NULL;
6886 : NTSTATUS nt_status, result;
6887 0 : const char *domain_name = NULL;
6888 : struct policy_handle connect_hnd;
6889 0 : union lsa_PolicyInformation *info = NULL;
6890 :
6891 : /* trusted domains listing variables */
6892 0 : unsigned int enum_ctx = 0;
6893 : struct lsa_DomainList dom_list;
6894 : fstring pdc_name;
6895 : struct dcerpc_binding_handle *b;
6896 :
6897 0 : if (c->display_usage) {
6898 0 : d_printf( "%s\n"
6899 : "net rpc trustdom vampire\n"
6900 : " %s\n",
6901 : _("Usage:"),
6902 : _("Vampire trust relationship from remote server"));
6903 0 : return 0;
6904 : }
6905 :
6906 : /*
6907 : * Listing trusted domains (stored in secrets.tdb, if local)
6908 : */
6909 :
6910 0 : mem_ctx = talloc_init("trust relationships vampire");
6911 :
6912 : /*
6913 : * set domain and pdc name to local samba server (default)
6914 : * or to remote one given in command line
6915 : */
6916 :
6917 0 : if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6918 0 : domain_name = c->opt_workgroup;
6919 0 : c->opt_target_workgroup = c->opt_workgroup;
6920 : } else {
6921 0 : fstrcpy(pdc_name, lp_netbios_name());
6922 0 : domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6923 0 : c->opt_target_workgroup = domain_name;
6924 : };
6925 :
6926 : /* open \PIPE\lsarpc and open policy handle */
6927 0 : nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6928 0 : if (!NT_STATUS_IS_OK(nt_status)) {
6929 0 : DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6930 : nt_errstr(nt_status)));
6931 0 : talloc_destroy(mem_ctx);
6932 0 : return -1;
6933 : };
6934 :
6935 0 : nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6936 : &pipe_hnd);
6937 0 : if (!NT_STATUS_IS_OK(nt_status)) {
6938 0 : DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6939 : nt_errstr(nt_status) ));
6940 0 : cli_shutdown(cli);
6941 0 : talloc_destroy(mem_ctx);
6942 0 : return -1;
6943 : };
6944 :
6945 0 : b = pipe_hnd->binding_handle;
6946 :
6947 0 : nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6948 : &connect_hnd);
6949 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6950 0 : DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6951 : nt_errstr(nt_status)));
6952 0 : cli_shutdown(cli);
6953 0 : talloc_destroy(mem_ctx);
6954 0 : return -1;
6955 : };
6956 :
6957 : /* query info level 5 to obtain sid of a domain being queried */
6958 0 : nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6959 : &connect_hnd,
6960 : LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6961 : &info,
6962 : &result);
6963 :
6964 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6965 0 : DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6966 : nt_errstr(nt_status)));
6967 0 : cli_shutdown(cli);
6968 0 : talloc_destroy(mem_ctx);
6969 0 : return -1;
6970 : }
6971 0 : if (NT_STATUS_IS_ERR(result)) {
6972 0 : DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6973 : nt_errstr(result)));
6974 0 : cli_shutdown(cli);
6975 0 : talloc_destroy(mem_ctx);
6976 0 : return -1;
6977 : }
6978 :
6979 : /*
6980 : * Keep calling LsaEnumTrustdom over opened pipe until
6981 : * the end of enumeration is reached
6982 : */
6983 :
6984 0 : d_printf(_("Vampire trusted domains:\n\n"));
6985 :
6986 : do {
6987 : uint32_t i;
6988 :
6989 0 : nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6990 : &connect_hnd,
6991 : &enum_ctx,
6992 : &dom_list,
6993 : (uint32_t)-1,
6994 : &result);
6995 0 : if (NT_STATUS_IS_ERR(nt_status)) {
6996 0 : DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6997 : nt_errstr(nt_status)));
6998 0 : cli_shutdown(cli);
6999 0 : talloc_destroy(mem_ctx);
7000 0 : return -1;
7001 : };
7002 0 : if (NT_STATUS_IS_ERR(result)) {
7003 0 : nt_status = result;
7004 0 : DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7005 : nt_errstr(result)));
7006 0 : cli_shutdown(cli);
7007 0 : talloc_destroy(mem_ctx);
7008 0 : return -1;
7009 : };
7010 :
7011 :
7012 0 : for (i = 0; i < dom_list.count; i++) {
7013 :
7014 0 : print_trusted_domain(dom_list.domains[i].sid,
7015 0 : dom_list.domains[i].name.string);
7016 :
7017 0 : nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
7018 0 : *dom_list.domains[i].sid,
7019 0 : dom_list.domains[i].name.string);
7020 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7021 0 : cli_shutdown(cli);
7022 0 : talloc_destroy(mem_ctx);
7023 0 : return -1;
7024 : }
7025 : };
7026 :
7027 : /*
7028 : * in case of no trusted domains say something rather
7029 : * than just display blank line
7030 : */
7031 0 : if (!dom_list.count) d_printf(_("none\n"));
7032 :
7033 0 : } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
7034 :
7035 : /* close this connection before doing next one */
7036 0 : nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
7037 0 : if (NT_STATUS_IS_ERR(nt_status)) {
7038 0 : DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
7039 : nt_errstr(nt_status)));
7040 0 : cli_shutdown(cli);
7041 0 : talloc_destroy(mem_ctx);
7042 0 : return -1;
7043 : };
7044 :
7045 : /* close lsarpc pipe and connection to IPC$ */
7046 0 : cli_shutdown(cli);
7047 :
7048 0 : talloc_destroy(mem_ctx);
7049 0 : return 0;
7050 : }
7051 :
7052 0 : static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
7053 : {
7054 : /* common variables */
7055 : TALLOC_CTX* mem_ctx;
7056 0 : struct cli_state *cli = NULL, *remote_cli = NULL;
7057 0 : struct rpc_pipe_client *pipe_hnd = NULL;
7058 : NTSTATUS nt_status, result;
7059 0 : const char *domain_name = NULL;
7060 : struct dom_sid *queried_dom_sid;
7061 : int ascii_dom_name_len;
7062 : struct policy_handle connect_hnd;
7063 0 : union lsa_PolicyInformation *info = NULL;
7064 0 : struct dcerpc_binding_handle *b = NULL;
7065 :
7066 : /* trusted domains listing variables */
7067 0 : unsigned int num_domains, enum_ctx = 0;
7068 : uint32_t i;
7069 : struct lsa_DomainList dom_list;
7070 : fstring pdc_name;
7071 : bool found_domain;
7072 :
7073 : /* trusting domains listing variables */
7074 : struct policy_handle domain_hnd;
7075 0 : struct samr_SamArray *trusts = NULL;
7076 :
7077 0 : if (c->display_usage) {
7078 0 : d_printf( "%s\n"
7079 : "net rpc trustdom list\n"
7080 : " %s\n",
7081 : _("Usage:"),
7082 : _("List incoming and outgoing trust relationships"));
7083 0 : return 0;
7084 : }
7085 :
7086 : /*
7087 : * Listing trusted domains (stored in secrets.tdb, if local)
7088 : */
7089 :
7090 0 : mem_ctx = talloc_init("trust relationships listing");
7091 :
7092 : /*
7093 : * set domain and pdc name to local samba server (default)
7094 : * or to remote one given in command line
7095 : */
7096 :
7097 0 : if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
7098 0 : domain_name = c->opt_workgroup;
7099 0 : c->opt_target_workgroup = c->opt_workgroup;
7100 : } else {
7101 0 : fstrcpy(pdc_name, lp_netbios_name());
7102 0 : domain_name = talloc_strdup(mem_ctx, lp_workgroup());
7103 0 : c->opt_target_workgroup = domain_name;
7104 : };
7105 :
7106 : /* open \PIPE\lsarpc and open policy handle */
7107 0 : nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
7108 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7109 0 : DEBUG(0, ("Couldn't connect to domain controller: %s\n",
7110 : nt_errstr(nt_status)));
7111 0 : talloc_destroy(mem_ctx);
7112 0 : return -1;
7113 : };
7114 :
7115 0 : nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
7116 : &pipe_hnd);
7117 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7118 0 : DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
7119 : nt_errstr(nt_status) ));
7120 0 : cli_shutdown(cli);
7121 0 : talloc_destroy(mem_ctx);
7122 0 : return -1;
7123 : };
7124 :
7125 0 : b = pipe_hnd->binding_handle;
7126 :
7127 0 : nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
7128 : &connect_hnd);
7129 0 : if (NT_STATUS_IS_ERR(nt_status)) {
7130 0 : DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
7131 : nt_errstr(nt_status)));
7132 0 : cli_shutdown(cli);
7133 0 : talloc_destroy(mem_ctx);
7134 0 : return -1;
7135 : };
7136 :
7137 : /* query info level 5 to obtain sid of a domain being queried */
7138 0 : nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
7139 : &connect_hnd,
7140 : LSA_POLICY_INFO_ACCOUNT_DOMAIN,
7141 : &info,
7142 : &result);
7143 :
7144 0 : if (NT_STATUS_IS_ERR(nt_status)) {
7145 0 : DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7146 : nt_errstr(nt_status)));
7147 0 : cli_shutdown(cli);
7148 0 : talloc_destroy(mem_ctx);
7149 0 : return -1;
7150 : }
7151 0 : if (NT_STATUS_IS_ERR(result)) {
7152 0 : DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7153 : nt_errstr(result)));
7154 0 : cli_shutdown(cli);
7155 0 : talloc_destroy(mem_ctx);
7156 0 : return -1;
7157 : }
7158 :
7159 0 : queried_dom_sid = info->account_domain.sid;
7160 :
7161 : /*
7162 : * Keep calling LsaEnumTrustdom over opened pipe until
7163 : * the end of enumeration is reached
7164 : */
7165 :
7166 0 : d_printf(_("Trusted domains list:\n\n"));
7167 :
7168 0 : found_domain = false;
7169 :
7170 : do {
7171 0 : nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
7172 : &connect_hnd,
7173 : &enum_ctx,
7174 : &dom_list,
7175 : (uint32_t)-1,
7176 : &result);
7177 0 : if (NT_STATUS_IS_ERR(nt_status)) {
7178 0 : DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7179 : nt_errstr(nt_status)));
7180 0 : cli_shutdown(cli);
7181 0 : talloc_destroy(mem_ctx);
7182 0 : return -1;
7183 : };
7184 0 : if (NT_STATUS_IS_ERR(result)) {
7185 0 : DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7186 : nt_errstr(result)));
7187 0 : cli_shutdown(cli);
7188 0 : talloc_destroy(mem_ctx);
7189 0 : return -1;
7190 : };
7191 :
7192 :
7193 0 : for (i = 0; i < dom_list.count; i++) {
7194 0 : print_trusted_domain(dom_list.domains[i].sid,
7195 0 : dom_list.domains[i].name.string);
7196 0 : found_domain = true;
7197 : };
7198 :
7199 :
7200 0 : } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
7201 :
7202 : /*
7203 : * in case of no trusted domains say something rather
7204 : * than just display blank line
7205 : */
7206 0 : if (!found_domain) {
7207 0 : d_printf(_("none\n"));
7208 : }
7209 :
7210 : /* close this connection before doing next one */
7211 0 : nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
7212 0 : if (NT_STATUS_IS_ERR(nt_status)) {
7213 0 : DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
7214 : nt_errstr(nt_status)));
7215 0 : cli_shutdown(cli);
7216 0 : talloc_destroy(mem_ctx);
7217 0 : return -1;
7218 : };
7219 :
7220 0 : TALLOC_FREE(pipe_hnd);
7221 :
7222 : /*
7223 : * Listing trusting domains (stored in passdb backend, if local)
7224 : */
7225 :
7226 0 : d_printf(_("\nTrusting domains list:\n\n"));
7227 :
7228 : /*
7229 : * Open \PIPE\samr and get needed policy handles
7230 : */
7231 0 : nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
7232 : &pipe_hnd);
7233 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7234 0 : DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
7235 0 : cli_shutdown(cli);
7236 0 : talloc_destroy(mem_ctx);
7237 0 : return -1;
7238 : };
7239 :
7240 0 : b = pipe_hnd->binding_handle;
7241 :
7242 : /* SamrConnect2 */
7243 0 : nt_status = dcerpc_samr_Connect2(b, mem_ctx,
7244 0 : pipe_hnd->desthost,
7245 : SAMR_ACCESS_LOOKUP_DOMAIN,
7246 : &connect_hnd,
7247 : &result);
7248 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7249 0 : DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7250 : nt_errstr(nt_status)));
7251 0 : cli_shutdown(cli);
7252 0 : talloc_destroy(mem_ctx);
7253 0 : return -1;
7254 : };
7255 0 : if (!NT_STATUS_IS_OK(result)) {
7256 0 : nt_status = result;
7257 0 : DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7258 : nt_errstr(result)));
7259 0 : cli_shutdown(cli);
7260 0 : talloc_destroy(mem_ctx);
7261 0 : return -1;
7262 : };
7263 :
7264 : /* SamrOpenDomain - we have to open domain policy handle in order to be
7265 : able to enumerate accounts*/
7266 0 : nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
7267 : &connect_hnd,
7268 : SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
7269 : queried_dom_sid,
7270 : &domain_hnd,
7271 : &result);
7272 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7273 0 : DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7274 : nt_errstr(nt_status)));
7275 0 : cli_shutdown(cli);
7276 0 : talloc_destroy(mem_ctx);
7277 0 : return -1;
7278 : };
7279 0 : if (!NT_STATUS_IS_OK(result)) {
7280 0 : nt_status = result;
7281 0 : DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7282 : nt_errstr(result)));
7283 0 : cli_shutdown(cli);
7284 0 : talloc_destroy(mem_ctx);
7285 0 : return -1;
7286 : };
7287 :
7288 : /*
7289 : * perform actual enumeration
7290 : */
7291 :
7292 0 : found_domain = false;
7293 :
7294 0 : enum_ctx = 0; /* reset enumeration context from last enumeration */
7295 : do {
7296 :
7297 0 : nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
7298 : &domain_hnd,
7299 : &enum_ctx,
7300 : ACB_DOMTRUST,
7301 : &trusts,
7302 : 0xffff,
7303 : &num_domains,
7304 : &result);
7305 0 : if (NT_STATUS_IS_ERR(nt_status)) {
7306 0 : DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7307 : nt_errstr(nt_status)));
7308 0 : cli_shutdown(cli);
7309 0 : talloc_destroy(mem_ctx);
7310 0 : return -1;
7311 : };
7312 0 : if (NT_STATUS_IS_ERR(result)) {
7313 0 : nt_status = result;
7314 0 : DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7315 : nt_errstr(result)));
7316 0 : cli_shutdown(cli);
7317 0 : talloc_destroy(mem_ctx);
7318 0 : return -1;
7319 : };
7320 :
7321 0 : for (i = 0; i < num_domains; i++) {
7322 :
7323 0 : char *str = discard_const_p(char, trusts->entries[i].name.string);
7324 :
7325 0 : found_domain = true;
7326 :
7327 : /*
7328 : * get each single domain's sid (do we _really_ need this ?):
7329 : * 1) connect to domain's pdc
7330 : * 2) query the pdc for domain's sid
7331 : */
7332 :
7333 : /* get rid of '$' tail */
7334 0 : ascii_dom_name_len = strlen(str);
7335 0 : if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
7336 0 : str[ascii_dom_name_len - 1] = '\0';
7337 :
7338 : /* set opt_* variables to remote domain */
7339 0 : if (!strupper_m(str)) {
7340 0 : cli_shutdown(cli);
7341 0 : talloc_destroy(mem_ctx);
7342 0 : return -1;
7343 : }
7344 0 : c->opt_workgroup = talloc_strdup(mem_ctx, str);
7345 0 : c->opt_target_workgroup = c->opt_workgroup;
7346 :
7347 0 : d_printf("%-20s", str);
7348 :
7349 : /* connect to remote domain controller */
7350 0 : nt_status = net_make_ipc_connection(c,
7351 : NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
7352 : &remote_cli);
7353 0 : if (NT_STATUS_IS_OK(nt_status)) {
7354 : /* query for domain's sid */
7355 0 : if (run_rpc_command(
7356 : c, remote_cli,
7357 : &ndr_table_lsarpc, 0,
7358 : rpc_query_domain_sid, argc,
7359 : argv))
7360 0 : d_printf(_("strange - couldn't get domain's sid\n"));
7361 :
7362 0 : cli_shutdown(remote_cli);
7363 :
7364 : } else {
7365 0 : d_fprintf(stderr, _("domain controller is not "
7366 : "responding: %s\n"),
7367 : nt_errstr(nt_status));
7368 0 : d_printf(_("couldn't get domain's sid\n"));
7369 : }
7370 : }
7371 :
7372 0 : } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
7373 :
7374 0 : if (!found_domain) {
7375 0 : d_printf("none\n");
7376 : }
7377 :
7378 : /* close opened samr and domain policy handles */
7379 0 : nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
7380 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7381 0 : DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
7382 : };
7383 :
7384 0 : nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
7385 0 : if (!NT_STATUS_IS_OK(nt_status)) {
7386 0 : DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
7387 : };
7388 :
7389 : /* close samr pipe and connection to IPC$ */
7390 0 : cli_shutdown(cli);
7391 :
7392 0 : talloc_destroy(mem_ctx);
7393 0 : return 0;
7394 : }
7395 :
7396 : /**
7397 : * Entrypoint for 'net rpc trustdom' code.
7398 : *
7399 : * @param argc Standard argc.
7400 : * @param argv Standard argv without initial components.
7401 : *
7402 : * @return Integer status (0 means success).
7403 : */
7404 :
7405 0 : static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
7406 : {
7407 0 : struct functable func[] = {
7408 : {
7409 : "add",
7410 : rpc_trustdom_add,
7411 : NET_TRANSPORT_RPC,
7412 : N_("Add trusting domain's account"),
7413 : N_("net rpc trustdom add\n"
7414 : " Add trusting domain's account")
7415 : },
7416 : {
7417 : "del",
7418 : rpc_trustdom_del,
7419 : NET_TRANSPORT_RPC,
7420 : N_("Remove trusting domain's account"),
7421 : N_("net rpc trustdom del\n"
7422 : " Remove trusting domain's account")
7423 : },
7424 : {
7425 : "establish",
7426 : rpc_trustdom_establish,
7427 : NET_TRANSPORT_RPC,
7428 : N_("Establish outgoing trust relationship"),
7429 : N_("net rpc trustdom establish\n"
7430 : " Establish outgoing trust relationship")
7431 : },
7432 : {
7433 : "revoke",
7434 : rpc_trustdom_revoke,
7435 : NET_TRANSPORT_RPC,
7436 : N_("Revoke outgoing trust relationship"),
7437 : N_("net rpc trustdom revoke\n"
7438 : " Revoke outgoing trust relationship")
7439 : },
7440 : {
7441 : "list",
7442 : rpc_trustdom_list,
7443 : NET_TRANSPORT_RPC,
7444 : N_("List in- and outgoing domain trusts"),
7445 : N_("net rpc trustdom list\n"
7446 : " List in- and outgoing domain trusts")
7447 : },
7448 : {
7449 : "vampire",
7450 : rpc_trustdom_vampire,
7451 : NET_TRANSPORT_RPC,
7452 : N_("Vampire trusts from remote server"),
7453 : N_("net rpc trustdom vampire\n"
7454 : " Vampire trusts from remote server")
7455 : },
7456 : {NULL, NULL, 0, NULL, NULL}
7457 : };
7458 :
7459 0 : return net_run_function(c, argc, argv, "net rpc trustdom", func);
7460 : }
7461 :
7462 : /**
7463 : * Check if a server will take rpc commands
7464 : * @param flags Type of server to connect to (PDC, DMB, localhost)
7465 : * if the host is not explicitly specified
7466 : * @return bool (true means rpc supported)
7467 : */
7468 0 : bool net_rpc_check(struct net_context *c, unsigned flags)
7469 : {
7470 : struct cli_state *cli;
7471 0 : bool ret = false;
7472 : struct sockaddr_storage server_ss;
7473 0 : char *server_name = NULL;
7474 : NTSTATUS status;
7475 :
7476 : /* flags (i.e. server type) may depend on command */
7477 0 : if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7478 0 : return false;
7479 :
7480 0 : status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
7481 : lp_netbios_name(), SMB_SIGNING_IPC_DEFAULT,
7482 : 0, &cli);
7483 0 : if (!NT_STATUS_IS_OK(status)) {
7484 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
7485 0 : DBG_ERR("NetBIOS support disabled, unable to connect\n");
7486 : }
7487 0 : return false;
7488 : }
7489 0 : status = smbXcli_negprot(cli->conn, cli->timeout,
7490 0 : lp_client_min_protocol(),
7491 0 : lp_client_max_protocol());
7492 0 : if (!NT_STATUS_IS_OK(status))
7493 0 : goto done;
7494 0 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1)
7495 0 : goto done;
7496 :
7497 0 : ret = true;
7498 0 : done:
7499 0 : cli_shutdown(cli);
7500 0 : return ret;
7501 : }
7502 :
7503 : /* syncronise sam database via samsync rpc calls */
7504 0 : static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7505 : {
7506 0 : struct functable func[] = {
7507 : {
7508 : "keytab",
7509 : rpc_vampire_keytab,
7510 : NET_TRANSPORT_RPC,
7511 : N_("Dump remote SAM database to Kerberos Keytab"),
7512 : N_("net rpc vampire keytab\n"
7513 : " Dump remote SAM database to Kerberos keytab "
7514 : "file")
7515 : },
7516 : {
7517 : "passdb",
7518 : rpc_vampire_passdb,
7519 : NET_TRANSPORT_RPC,
7520 : N_("Dump remote SAM database to passdb"),
7521 : N_("net rpc vampire passdb\n"
7522 : " Dump remote SAM database to passdb")
7523 : },
7524 :
7525 : {NULL, NULL, 0, NULL, NULL}
7526 : };
7527 :
7528 0 : if (argc == 0) {
7529 0 : if (c->display_usage) {
7530 0 : d_printf( "%s\n"
7531 : "net rpc vampire\n"
7532 : " %s\n",
7533 : _("Usage:"),
7534 : _("Vampire remote SAM database"));
7535 0 : return 0;
7536 : }
7537 :
7538 0 : return rpc_vampire_passdb(c, argc, argv);
7539 : }
7540 :
7541 0 : return net_run_function(c, argc, argv, "net rpc vampire", func);
7542 : }
7543 :
7544 : /**
7545 : * Migrate everything from a print server.
7546 : *
7547 : * @param c A net_context structure.
7548 : * @param argc Standard main() style argc.
7549 : * @param argv Standard main() style argv. Initial components are already
7550 : * stripped.
7551 : *
7552 : * @return A shell status integer (0 for success).
7553 : *
7554 : * The order is important !
7555 : * To successfully add drivers the print queues have to exist !
7556 : * Applying ACLs should be the last step, because you're easily locked out.
7557 : *
7558 : **/
7559 0 : static int rpc_printer_migrate_all(struct net_context *c, int argc,
7560 : const char **argv)
7561 : {
7562 : int ret;
7563 :
7564 0 : if (c->display_usage) {
7565 0 : d_printf( "%s\n"
7566 : "net rpc printer migrate all\n"
7567 : " %s\n",
7568 : _("Usage:"),
7569 : _("Migrate everything from a print server"));
7570 0 : return 0;
7571 : }
7572 :
7573 0 : if (!c->opt_host) {
7574 0 : d_printf(_("no server to migrate\n"));
7575 0 : return -1;
7576 : }
7577 :
7578 0 : ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7579 : rpc_printer_migrate_printers_internals, argc,
7580 : argv);
7581 0 : if (ret)
7582 0 : return ret;
7583 :
7584 0 : ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7585 : rpc_printer_migrate_drivers_internals, argc,
7586 : argv);
7587 0 : if (ret)
7588 0 : return ret;
7589 :
7590 0 : ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7591 : rpc_printer_migrate_forms_internals, argc, argv);
7592 0 : if (ret)
7593 0 : return ret;
7594 :
7595 0 : ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7596 : rpc_printer_migrate_settings_internals, argc,
7597 : argv);
7598 0 : if (ret)
7599 0 : return ret;
7600 :
7601 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7602 : rpc_printer_migrate_security_internals, argc,
7603 : argv);
7604 :
7605 : }
7606 :
7607 : /**
7608 : * Migrate print drivers from a print server.
7609 : *
7610 : * @param c A net_context structure.
7611 : * @param argc Standard main() style argc.
7612 : * @param argv Standard main() style argv. Initial components are already
7613 : * stripped.
7614 : *
7615 : * @return A shell status integer (0 for success).
7616 : **/
7617 0 : static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7618 : const char **argv)
7619 : {
7620 0 : if (c->display_usage) {
7621 0 : d_printf( "%s\n"
7622 : "net rpc printer migrate drivers\n"
7623 : " %s\n",
7624 : _("Usage:"),
7625 : _("Migrate print-drivers from a print-server"));
7626 0 : return 0;
7627 : }
7628 :
7629 0 : if (!c->opt_host) {
7630 0 : d_printf(_("no server to migrate\n"));
7631 0 : return -1;
7632 : }
7633 :
7634 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7635 : rpc_printer_migrate_drivers_internals,
7636 : argc, argv);
7637 : }
7638 :
7639 : /**
7640 : * Migrate print-forms from a print-server.
7641 : *
7642 : * @param c A net_context structure.
7643 : * @param argc Standard main() style argc.
7644 : * @param argv Standard main() style argv. Initial components are already
7645 : * stripped.
7646 : *
7647 : * @return A shell status integer (0 for success).
7648 : **/
7649 0 : static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7650 : const char **argv)
7651 : {
7652 0 : if (c->display_usage) {
7653 0 : d_printf( "%s\n"
7654 : "net rpc printer migrate forms\n"
7655 : " %s\n",
7656 : _("Usage:"),
7657 : _("Migrate print-forms from a print-server"));
7658 0 : return 0;
7659 : }
7660 :
7661 0 : if (!c->opt_host) {
7662 0 : d_printf(_("no server to migrate\n"));
7663 0 : return -1;
7664 : }
7665 :
7666 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7667 : rpc_printer_migrate_forms_internals,
7668 : argc, argv);
7669 : }
7670 :
7671 : /**
7672 : * Migrate printers from a print-server.
7673 : *
7674 : * @param c A net_context structure.
7675 : * @param argc Standard main() style argc.
7676 : * @param argv Standard main() style argv. Initial components are already
7677 : * stripped.
7678 : *
7679 : * @return A shell status integer (0 for success).
7680 : **/
7681 0 : static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7682 : const char **argv)
7683 : {
7684 0 : if (c->display_usage) {
7685 0 : d_printf( "%s\n"
7686 : "net rpc printer migrate printers\n"
7687 : " %s\n",
7688 : _("Usage:"),
7689 : _("Migrate printers from a print-server"));
7690 0 : return 0;
7691 : }
7692 :
7693 0 : if (!c->opt_host) {
7694 0 : d_printf(_("no server to migrate\n"));
7695 0 : return -1;
7696 : }
7697 :
7698 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7699 : rpc_printer_migrate_printers_internals,
7700 : argc, argv);
7701 : }
7702 :
7703 : /**
7704 : * Migrate printer-ACLs from a print-server
7705 : *
7706 : * @param c A net_context structure.
7707 : * @param argc Standard main() style argc.
7708 : * @param argv Standard main() style argv. Initial components are already
7709 : * stripped.
7710 : *
7711 : * @return A shell status integer (0 for success).
7712 : **/
7713 0 : static int rpc_printer_migrate_security(struct net_context *c, int argc,
7714 : const char **argv)
7715 : {
7716 0 : if (c->display_usage) {
7717 0 : d_printf( "%s\n"
7718 : "net rpc printer migrate security\n"
7719 : " %s\n",
7720 : _("Usage:"),
7721 : _("Migrate printer-ACLs from a print-server"));
7722 0 : return 0;
7723 : }
7724 :
7725 0 : if (!c->opt_host) {
7726 0 : d_printf(_("no server to migrate\n"));
7727 0 : return -1;
7728 : }
7729 :
7730 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7731 : rpc_printer_migrate_security_internals,
7732 : argc, argv);
7733 : }
7734 :
7735 : /**
7736 : * Migrate printer-settings from a print-server.
7737 : *
7738 : * @param c A net_context structure.
7739 : * @param argc Standard main() style argc.
7740 : * @param argv Standard main() style argv. Initial components are already
7741 : * stripped.
7742 : *
7743 : * @return A shell status integer (0 for success).
7744 : **/
7745 0 : static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7746 : const char **argv)
7747 : {
7748 0 : if (c->display_usage) {
7749 0 : d_printf( "%s\n"
7750 : "net rpc printer migrate settings\n"
7751 : " %s\n",
7752 : _("Usage:"),
7753 : _("Migrate printer-settings from a "
7754 : "print-server"));
7755 0 : return 0;
7756 : }
7757 :
7758 0 : if (!c->opt_host) {
7759 0 : d_printf(_("no server to migrate\n"));
7760 0 : return -1;
7761 : }
7762 :
7763 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7764 : rpc_printer_migrate_settings_internals,
7765 : argc, argv);
7766 : }
7767 :
7768 : /**
7769 : * 'net rpc printer' entrypoint.
7770 : *
7771 : * @param c A net_context structure.
7772 : * @param argc Standard main() style argc.
7773 : * @param argv Standard main() style argv. Initial components are already
7774 : * stripped.
7775 : **/
7776 :
7777 0 : int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7778 : {
7779 :
7780 : /* ouch: when addriver and setdriver are called from within
7781 : rpc_printer_migrate_drivers_internals, the printer-queue already
7782 : *has* to exist */
7783 :
7784 0 : struct functable func[] = {
7785 : {
7786 : "all",
7787 : rpc_printer_migrate_all,
7788 : NET_TRANSPORT_RPC,
7789 : N_("Migrate all from remote to local print server"),
7790 : N_("net rpc printer migrate all\n"
7791 : " Migrate all from remote to local print server")
7792 : },
7793 : {
7794 : "drivers",
7795 : rpc_printer_migrate_drivers,
7796 : NET_TRANSPORT_RPC,
7797 : N_("Migrate drivers to local server"),
7798 : N_("net rpc printer migrate drivers\n"
7799 : " Migrate drivers to local server")
7800 : },
7801 : {
7802 : "forms",
7803 : rpc_printer_migrate_forms,
7804 : NET_TRANSPORT_RPC,
7805 : N_("Migrate froms to local server"),
7806 : N_("net rpc printer migrate forms\n"
7807 : " Migrate froms to local server")
7808 : },
7809 : {
7810 : "printers",
7811 : rpc_printer_migrate_printers,
7812 : NET_TRANSPORT_RPC,
7813 : N_("Migrate printers to local server"),
7814 : N_("net rpc printer migrate printers\n"
7815 : " Migrate printers to local server")
7816 : },
7817 : {
7818 : "security",
7819 : rpc_printer_migrate_security,
7820 : NET_TRANSPORT_RPC,
7821 : N_("Migrate printer ACLs to local server"),
7822 : N_("net rpc printer migrate security\n"
7823 : " Migrate printer ACLs to local server")
7824 : },
7825 : {
7826 : "settings",
7827 : rpc_printer_migrate_settings,
7828 : NET_TRANSPORT_RPC,
7829 : N_("Migrate printer settings to local server"),
7830 : N_("net rpc printer migrate settings\n"
7831 : " Migrate printer settings to local server")
7832 : },
7833 : {NULL, NULL, 0, NULL, NULL}
7834 : };
7835 :
7836 0 : return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7837 : }
7838 :
7839 :
7840 : /**
7841 : * List printers on a remote RPC server.
7842 : *
7843 : * @param c A net_context structure.
7844 : * @param argc Standard main() style argc.
7845 : * @param argv Standard main() style argv. Initial components are already
7846 : * stripped.
7847 : *
7848 : * @return A shell status integer (0 for success).
7849 : **/
7850 0 : static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7851 : {
7852 0 : if (c->display_usage) {
7853 0 : d_printf( "%s\n"
7854 : "net rpc printer list\n"
7855 : " %s\n",
7856 : _("Usage:"),
7857 : _("List printers on a remote RPC server"));
7858 0 : return 0;
7859 : }
7860 :
7861 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7862 : rpc_printer_list_internals,
7863 : argc, argv);
7864 : }
7865 :
7866 : /**
7867 : * List printer-drivers on a remote RPC server.
7868 : *
7869 : * @param c A net_context structure.
7870 : * @param argc Standard main() style argc.
7871 : * @param argv Standard main() style argv. Initial components are already
7872 : * stripped.
7873 : *
7874 : * @return A shell status integer (0 for success).
7875 : **/
7876 0 : static int rpc_printer_driver_list(struct net_context *c, int argc,
7877 : const char **argv)
7878 : {
7879 0 : if (c->display_usage) {
7880 0 : d_printf( "%s\n"
7881 : "net rpc printer driver\n"
7882 : " %s\n",
7883 : _("Usage:"),
7884 : _("List printer-drivers on a remote RPC server"));
7885 0 : return 0;
7886 : }
7887 :
7888 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7889 : rpc_printer_driver_list_internals,
7890 : argc, argv);
7891 : }
7892 :
7893 : /**
7894 : * Publish printer in ADS via MSRPC.
7895 : *
7896 : * @param c A net_context structure.
7897 : * @param argc Standard main() style argc.
7898 : * @param argv Standard main() style argv. Initial components are already
7899 : * stripped.
7900 : *
7901 : * @return A shell status integer (0 for success).
7902 : **/
7903 0 : static int rpc_printer_publish_publish(struct net_context *c, int argc,
7904 : const char **argv)
7905 : {
7906 0 : if (c->display_usage) {
7907 0 : d_printf( "%s\n"
7908 : "net rpc printer publish publish\n"
7909 : " %s\n",
7910 : _("Usage:"),
7911 : _("Publish printer in ADS via MSRPC"));
7912 0 : return 0;
7913 : }
7914 :
7915 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7916 : rpc_printer_publish_publish_internals,
7917 : argc, argv);
7918 : }
7919 :
7920 : /**
7921 : * Update printer in ADS via MSRPC.
7922 : *
7923 : * @param c A net_context structure.
7924 : * @param argc Standard main() style argc.
7925 : * @param argv Standard main() style argv. Initial components are already
7926 : * stripped.
7927 : *
7928 : * @return A shell status integer (0 for success).
7929 : **/
7930 0 : static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7931 : {
7932 0 : if (c->display_usage) {
7933 0 : d_printf( "%s\n"
7934 : "net rpc printer publish update\n"
7935 : " %s\n",
7936 : _("Usage:"),
7937 : _("Update printer in ADS via MSRPC"));
7938 0 : return 0;
7939 : }
7940 :
7941 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7942 : rpc_printer_publish_update_internals,
7943 : argc, argv);
7944 : }
7945 :
7946 : /**
7947 : * UnPublish printer in ADS via MSRPC.
7948 : *
7949 : * @param c A net_context structure.
7950 : * @param argc Standard main() style argc.
7951 : * @param argv Standard main() style argv. Initial components are already
7952 : * stripped.
7953 : *
7954 : * @return A shell status integer (0 for success).
7955 : **/
7956 0 : static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7957 : const char **argv)
7958 : {
7959 0 : if (c->display_usage) {
7960 0 : d_printf( "%s\n"
7961 : "net rpc printer publish unpublish\n"
7962 : " %s\n",
7963 : _("Usage:\n"),
7964 : _("UnPublish printer in ADS via MSRPC"));
7965 0 : return 0;
7966 : }
7967 :
7968 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7969 : rpc_printer_publish_unpublish_internals,
7970 : argc, argv);
7971 : }
7972 :
7973 : /**
7974 : * List published printers via MSRPC.
7975 : *
7976 : * @param c A net_context structure.
7977 : * @param argc Standard main() style argc.
7978 : * @param argv Standard main() style argv. Initial components are already
7979 : * stripped.
7980 : *
7981 : * @return A shell status integer (0 for success).
7982 : **/
7983 0 : static int rpc_printer_publish_list(struct net_context *c, int argc,
7984 : const char **argv)
7985 : {
7986 0 : if (c->display_usage) {
7987 0 : d_printf( "%s\n"
7988 : "net rpc printer publish list\n"
7989 : " %s\n",
7990 : _("Usage:"),
7991 : _("List published printers via MSRPC"));
7992 0 : return 0;
7993 : }
7994 :
7995 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7996 : rpc_printer_publish_list_internals,
7997 : argc, argv);
7998 : }
7999 :
8000 :
8001 : /**
8002 : * Publish printer in ADS.
8003 : *
8004 : * @param c A net_context structure.
8005 : * @param argc Standard main() style argc.
8006 : * @param argv Standard main() style argv. Initial components are already
8007 : * stripped.
8008 : *
8009 : * @return A shell status integer (0 for success).
8010 : **/
8011 0 : static int rpc_printer_publish(struct net_context *c, int argc,
8012 : const char **argv)
8013 : {
8014 :
8015 0 : struct functable func[] = {
8016 : {
8017 : "publish",
8018 : rpc_printer_publish_publish,
8019 : NET_TRANSPORT_RPC,
8020 : N_("Publish printer in AD"),
8021 : N_("net rpc printer publish publish\n"
8022 : " Publish printer in AD")
8023 : },
8024 : {
8025 : "update",
8026 : rpc_printer_publish_update,
8027 : NET_TRANSPORT_RPC,
8028 : N_("Update printer in AD"),
8029 : N_("net rpc printer publish update\n"
8030 : " Update printer in AD")
8031 : },
8032 : {
8033 : "unpublish",
8034 : rpc_printer_publish_unpublish,
8035 : NET_TRANSPORT_RPC,
8036 : N_("Unpublish printer"),
8037 : N_("net rpc printer publish unpublish\n"
8038 : " Unpublish printer")
8039 : },
8040 : {
8041 : "list",
8042 : rpc_printer_publish_list,
8043 : NET_TRANSPORT_RPC,
8044 : N_("List published printers"),
8045 : N_("net rpc printer publish list\n"
8046 : " List published printers")
8047 : },
8048 : {NULL, NULL, 0, NULL, NULL}
8049 : };
8050 :
8051 0 : if (argc == 0) {
8052 0 : if (c->display_usage) {
8053 0 : d_printf(_("Usage:\n"));
8054 0 : d_printf(_("net rpc printer publish\n"
8055 : " List published printers\n"
8056 : " Alias of net rpc printer publish "
8057 : "list\n"));
8058 0 : net_display_usage_from_functable(func);
8059 0 : return 0;
8060 : }
8061 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8062 : rpc_printer_publish_list_internals,
8063 : argc, argv);
8064 : }
8065 :
8066 0 : return net_run_function(c, argc, argv, "net rpc printer publish",func);
8067 :
8068 : }
8069 :
8070 :
8071 : /**
8072 : * Display rpc printer help page.
8073 : *
8074 : * @param c A net_context structure.
8075 : * @param argc Standard main() style argc.
8076 : * @param argv Standard main() style argv. Initial components are already
8077 : * stripped.
8078 : **/
8079 0 : int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
8080 : {
8081 0 : d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
8082 : "\tlists all printers on print-server\n\n"));
8083 0 : d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
8084 : "\tlists all printer-drivers on print-server\n\n"));
8085 0 : d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
8086 : "\tpublishes printer settings in Active Directory\n"
8087 : "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
8088 0 : d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
8089 : "\n\tmigrates printers from remote to local server\n\n"));
8090 0 : d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
8091 : "\n\tmigrates printer-settings from remote to local server\n\n"));
8092 0 : d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
8093 : "\n\tmigrates printer-drivers from remote to local server\n\n"));
8094 0 : d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
8095 : "\n\tmigrates printer-forms from remote to local server\n\n"));
8096 0 : d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
8097 : "\n\tmigrates printer-ACLs from remote to local server\n\n"));
8098 0 : d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
8099 : "\n\tmigrates drivers, forms, queues, settings and acls from\n"
8100 : "\tremote to local print-server\n\n"));
8101 0 : net_common_methods_usage(c, argc, argv);
8102 0 : net_common_flags_usage(c, argc, argv);
8103 0 : d_printf(_(
8104 : "\t-v or --verbose\t\t\tgive verbose output\n"
8105 : "\t --destination\t\tmigration target server (default: localhost)\n"));
8106 :
8107 0 : return -1;
8108 : }
8109 :
8110 : /**
8111 : * 'net rpc printer' entrypoint.
8112 : *
8113 : * @param c A net_context structure.
8114 : * @param argc Standard main() style argc.
8115 : * @param argv Standard main() style argv. Initial components are already
8116 : * stripped.
8117 : **/
8118 0 : int net_rpc_printer(struct net_context *c, int argc, const char **argv)
8119 : {
8120 0 : struct functable func[] = {
8121 : {
8122 : "list",
8123 : rpc_printer_list,
8124 : NET_TRANSPORT_RPC,
8125 : N_("List all printers on print server"),
8126 : N_("net rpc printer list\n"
8127 : " List all printers on print server")
8128 : },
8129 : {
8130 : "migrate",
8131 : rpc_printer_migrate,
8132 : NET_TRANSPORT_RPC,
8133 : N_("Migrate printer to local server"),
8134 : N_("net rpc printer migrate\n"
8135 : " Migrate printer to local server")
8136 : },
8137 : {
8138 : "driver",
8139 : rpc_printer_driver_list,
8140 : NET_TRANSPORT_RPC,
8141 : N_("List printer drivers"),
8142 : N_("net rpc printer driver\n"
8143 : " List printer drivers")
8144 : },
8145 : {
8146 : "publish",
8147 : rpc_printer_publish,
8148 : NET_TRANSPORT_RPC,
8149 : N_("Publish printer in AD"),
8150 : N_("net rpc printer publish\n"
8151 : " Publish printer in AD")
8152 : },
8153 : {NULL, NULL, 0, NULL, NULL}
8154 : };
8155 :
8156 0 : if (argc == 0) {
8157 0 : if (c->display_usage) {
8158 0 : d_printf(_("Usage:\n"));
8159 0 : d_printf(_("net rpc printer\n"
8160 : " List printers\n"));
8161 0 : net_display_usage_from_functable(func);
8162 0 : return 0;
8163 : }
8164 0 : return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8165 : rpc_printer_list_internals,
8166 : argc, argv);
8167 : }
8168 :
8169 0 : return net_run_function(c, argc, argv, "net rpc printer", func);
8170 : }
8171 :
8172 : /**
8173 : * 'net rpc' entrypoint.
8174 : *
8175 : * @param c A net_context structure.
8176 : * @param argc Standard main() style argc.
8177 : * @param argv Standard main() style argv. Initial components are already
8178 : * stripped.
8179 : **/
8180 :
8181 221 : int net_rpc(struct net_context *c, int argc, const char **argv)
8182 : {
8183 : NET_API_STATUS status;
8184 :
8185 221 : struct functable func[] = {
8186 : {
8187 : "audit",
8188 : net_rpc_audit,
8189 : NET_TRANSPORT_RPC,
8190 : N_("Modify global audit settings"),
8191 : N_("net rpc audit\n"
8192 : " Modify global audit settings")
8193 : },
8194 : {
8195 : "info",
8196 : net_rpc_info,
8197 : NET_TRANSPORT_RPC,
8198 : N_("Show basic info about a domain"),
8199 : N_("net rpc info\n"
8200 : " Show basic info about a domain")
8201 : },
8202 : {
8203 : "join",
8204 : net_rpc_join,
8205 : NET_TRANSPORT_RPC,
8206 : N_("Join a domain"),
8207 : N_("net rpc join\n"
8208 : " Join a domain")
8209 : },
8210 : {
8211 : "oldjoin",
8212 : net_rpc_oldjoin,
8213 : NET_TRANSPORT_RPC,
8214 : N_("Join a domain created in server manager"),
8215 : N_("net rpc oldjoin\n"
8216 : " Join a domain created in server manager")
8217 : },
8218 : {
8219 : "testjoin",
8220 : net_rpc_testjoin,
8221 : NET_TRANSPORT_RPC,
8222 : N_("Test that a join is valid"),
8223 : N_("net rpc testjoin\n"
8224 : " Test that a join is valid")
8225 : },
8226 : {
8227 : "user",
8228 : net_rpc_user,
8229 : NET_TRANSPORT_RPC,
8230 : N_("List/modify users"),
8231 : N_("net rpc user\n"
8232 : " List/modify users")
8233 : },
8234 : {
8235 : "password",
8236 : rpc_user_password,
8237 : NET_TRANSPORT_RPC,
8238 : N_("Change a user password"),
8239 : N_("net rpc password\n"
8240 : " Change a user password\n"
8241 : " Alias for net rpc user password")
8242 : },
8243 : {
8244 : "group",
8245 : net_rpc_group,
8246 : NET_TRANSPORT_RPC,
8247 : N_("List/modify groups"),
8248 : N_("net rpc group\n"
8249 : " List/modify groups")
8250 : },
8251 : {
8252 : "share",
8253 : net_rpc_share,
8254 : NET_TRANSPORT_RPC,
8255 : N_("List/modify shares"),
8256 : N_("net rpc share\n"
8257 : " List/modify shares")
8258 : },
8259 : {
8260 : "file",
8261 : net_rpc_file,
8262 : NET_TRANSPORT_RPC,
8263 : N_("List open files"),
8264 : N_("net rpc file\n"
8265 : " List open files")
8266 : },
8267 : {
8268 : "printer",
8269 : net_rpc_printer,
8270 : NET_TRANSPORT_RPC,
8271 : N_("List/modify printers"),
8272 : N_("net rpc printer\n"
8273 : " List/modify printers")
8274 : },
8275 : {
8276 : "changetrustpw",
8277 : net_rpc_changetrustpw,
8278 : NET_TRANSPORT_RPC,
8279 : N_("Change trust account password"),
8280 : N_("net rpc changetrustpw\n"
8281 : " Change trust account password")
8282 : },
8283 : {
8284 : "trustdom",
8285 : rpc_trustdom,
8286 : NET_TRANSPORT_RPC,
8287 : N_("Modify domain trusts"),
8288 : N_("net rpc trustdom\n"
8289 : " Modify domain trusts")
8290 : },
8291 : {
8292 : "abortshutdown",
8293 : rpc_shutdown_abort,
8294 : NET_TRANSPORT_RPC,
8295 : N_("Abort a remote shutdown"),
8296 : N_("net rpc abortshutdown\n"
8297 : " Abort a remote shutdown")
8298 : },
8299 : {
8300 : "shutdown",
8301 : rpc_shutdown,
8302 : NET_TRANSPORT_RPC,
8303 : N_("Shutdown a remote server"),
8304 : N_("net rpc shutdown\n"
8305 : " Shutdown a remote server")
8306 : },
8307 : {
8308 : "vampire",
8309 : rpc_vampire,
8310 : NET_TRANSPORT_RPC,
8311 : N_("Sync a remote NT PDC's data into local passdb"),
8312 : N_("net rpc vampire\n"
8313 : " Sync a remote NT PDC's data into local passdb")
8314 : },
8315 : {
8316 : "getsid",
8317 : net_rpc_getsid,
8318 : NET_TRANSPORT_RPC,
8319 : N_("Fetch the domain sid into local secrets.tdb"),
8320 : N_("net rpc getsid\n"
8321 : " Fetch the domain sid into local secrets.tdb")
8322 : },
8323 : {
8324 : "rights",
8325 : net_rpc_rights,
8326 : NET_TRANSPORT_RPC,
8327 : N_("Manage privileges assigned to SID"),
8328 : N_("net rpc rights\n"
8329 : " Manage privileges assigned to SID")
8330 : },
8331 : {
8332 : "service",
8333 : net_rpc_service,
8334 : NET_TRANSPORT_RPC,
8335 : N_("Start/stop/query remote services"),
8336 : N_("net rpc service\n"
8337 : " Start/stop/query remote services")
8338 : },
8339 : {
8340 : "registry",
8341 : net_rpc_registry,
8342 : NET_TRANSPORT_RPC,
8343 : N_("Manage registry hives"),
8344 : N_("net rpc registry\n"
8345 : " Manage registry hives")
8346 : },
8347 : {
8348 : "shell",
8349 : net_rpc_shell,
8350 : NET_TRANSPORT_RPC,
8351 : N_("Open interactive shell on remote server"),
8352 : N_("net rpc shell\n"
8353 : " Open interactive shell on remote server")
8354 : },
8355 : {
8356 : "trust",
8357 : net_rpc_trust,
8358 : NET_TRANSPORT_RPC,
8359 : N_("Manage trusts"),
8360 : N_("net rpc trust\n"
8361 : " Manage trusts")
8362 : },
8363 : {
8364 : "conf",
8365 : net_rpc_conf,
8366 : NET_TRANSPORT_RPC,
8367 : N_("Configure a remote samba server"),
8368 : N_("net rpc conf\n"
8369 : " Configure a remote samba server")
8370 : },
8371 : {NULL, NULL, 0, NULL, NULL}
8372 : };
8373 :
8374 221 : status = libnetapi_net_init(&c->netapi_ctx);
8375 221 : if (status != 0) {
8376 0 : return -1;
8377 : }
8378 :
8379 221 : status = libnetapi_set_creds(c->netapi_ctx, c->creds);
8380 221 : if (status != 0) {
8381 0 : return -1;
8382 : }
8383 :
8384 221 : return net_run_function(c, argc, argv, "net rpc", func);
8385 : }
|