dsdb: Align integer types
[Samba.git] / source3 / utils / net_rpc.c
blobe4cf7ef05f54648eb0736f61cee360037bb3f5d1
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)
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.
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.
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/>. */
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 "libsmb/clirap.h"
47 #include "nsswitch/libwbclient/wbclient.h"
48 #include "passdb.h"
49 #include "../libcli/smb/smbXcli_base.h"
50 #include "libsmb/dsgetdcname.h"
52 static int net_mode_share;
53 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
55 /**
56 * @file net_rpc.c
58 * @brief RPC based subcommands for the 'net' utility.
60 * This file should contain much of the functionality that used to
61 * be found in rpcclient, except that the commands should change
62 * less often, and the functionality should be sane (the user is not
63 * expected to know a rid/sid before they conduct an operation etc.)
65 * @todo Perhaps eventually these should be split out into a number
66 * of files, as this could get quite big.
67 **/
70 /**
71 * Many of the RPC functions need the domain sid. This function gets
72 * it at the start of every run
74 * @param cli A cli_state already connected to the remote machine
76 * @return The Domain SID of the remote machine.
77 **/
79 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
80 struct dom_sid **domain_sid,
81 const char **domain_name)
83 struct rpc_pipe_client *lsa_pipe = NULL;
84 struct policy_handle pol;
85 NTSTATUS status, result;
86 union lsa_PolicyInformation *info = NULL;
87 struct dcerpc_binding_handle *b;
89 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
90 &lsa_pipe);
91 if (!NT_STATUS_IS_OK(status)) {
92 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
93 return status;
96 b = lsa_pipe->binding_handle;
98 status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
99 SEC_FLAG_MAXIMUM_ALLOWED,
100 &pol);
101 if (!NT_STATUS_IS_OK(status)) {
102 d_fprintf(stderr, "open_policy %s: %s\n",
103 _("failed"),
104 nt_errstr(status));
105 return status;
108 status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
109 &pol,
110 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
111 &info,
112 &result);
113 if (!NT_STATUS_IS_OK(status)) {
114 d_fprintf(stderr, "lsaquery %s: %s\n",
115 _("failed"),
116 nt_errstr(status));
117 return status;
119 if (!NT_STATUS_IS_OK(result)) {
120 d_fprintf(stderr, "lsaquery %s: %s\n",
121 _("failed"),
122 nt_errstr(result));
123 return result;
126 *domain_name = info->account_domain.name.string;
127 *domain_sid = info->account_domain.sid;
129 dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
130 TALLOC_FREE(lsa_pipe);
132 return NT_STATUS_OK;
136 * Run a single RPC command, from start to finish.
138 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
139 * @param conn_flag a NET_FLAG_ combination. Passed to
140 * net_make_ipc_connection.
141 * @param argc Standard main() style argc.
142 * @param argv Standard main() style argv. Initial components are already
143 * stripped.
144 * @return A shell status integer (0 for success).
147 int run_rpc_command(struct net_context *c,
148 struct cli_state *cli_arg,
149 const struct ndr_interface_table *table,
150 int conn_flags,
151 rpc_command_fn fn,
152 int argc,
153 const char **argv)
155 struct cli_state *cli = NULL;
156 struct rpc_pipe_client *pipe_hnd = NULL;
157 TALLOC_CTX *mem_ctx;
158 NTSTATUS nt_status;
159 struct dom_sid *domain_sid;
160 const char *domain_name;
161 int ret = -1;
163 /* make use of cli_state handed over as an argument, if possible */
164 if (!cli_arg) {
165 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
166 if (!NT_STATUS_IS_OK(nt_status)) {
167 DEBUG(1, ("failed to make ipc connection: %s\n",
168 nt_errstr(nt_status)));
169 return -1;
171 } else {
172 cli = cli_arg;
175 if (!cli) {
176 return -1;
179 /* Create mem_ctx */
181 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
182 DEBUG(0, ("talloc_init() failed\n"));
183 goto fail;
186 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
187 &domain_name);
188 if (!NT_STATUS_IS_OK(nt_status)) {
189 goto fail;
192 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
193 if (lp_client_schannel()
194 && (ndr_syntax_id_equal(&table->syntax_id,
195 &ndr_table_netlogon.syntax_id))) {
196 /* Always try and create an schannel netlogon pipe. */
197 TALLOC_FREE(c->netlogon_creds);
198 nt_status = cli_rpc_pipe_open_schannel(
199 cli, c->msg_ctx, table, NCACN_NP,
200 domain_name,
201 &pipe_hnd, c, &c->netlogon_creds);
202 if (!NT_STATUS_IS_OK(nt_status)) {
203 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
204 nt_errstr(nt_status) ));
205 goto fail;
207 } else {
208 if (conn_flags & NET_FLAGS_SEAL) {
209 nt_status = cli_rpc_pipe_open_generic_auth(
210 cli, table,
211 (conn_flags & NET_FLAGS_TCP) ?
212 NCACN_IP_TCP : NCACN_NP,
213 CRED_DONT_USE_KERBEROS,
214 DCERPC_AUTH_TYPE_NTLMSSP,
215 DCERPC_AUTH_LEVEL_PRIVACY,
216 smbXcli_conn_remote_name(cli->conn),
217 lp_workgroup(), c->opt_user_name,
218 c->opt_password, &pipe_hnd);
219 } else {
220 nt_status = cli_rpc_pipe_open_noauth(
221 cli, table,
222 &pipe_hnd);
224 if (!NT_STATUS_IS_OK(nt_status)) {
225 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
226 table->name,
227 nt_errstr(nt_status) ));
228 goto fail;
233 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
235 if (!NT_STATUS_IS_OK(nt_status)) {
236 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
237 } else {
238 ret = 0;
239 DEBUG(5, ("rpc command function succeeded\n"));
242 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
243 if (pipe_hnd) {
244 TALLOC_FREE(pipe_hnd);
248 fail:
249 /* close the connection only if it was opened here */
250 if (!cli_arg) {
251 cli_shutdown(cli);
254 talloc_destroy(mem_ctx);
255 return ret;
259 * Force a change of the trust account password.
261 * All parameters are provided by the run_rpc_command function, except for
262 * argc, argv which are passed through.
264 * @param domain_sid The domain sid acquired from the remote server.
265 * @param cli A cli_state connected to the server.
266 * @param mem_ctx Talloc context, destroyed on completion of the function.
267 * @param argc Standard main() style argc.
268 * @param argv Standard main() style argv. Initial components are already
269 * stripped.
271 * @return Normal NTSTATUS return.
274 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
275 const struct dom_sid *domain_sid,
276 const char *domain_name,
277 struct cli_state *cli,
278 struct rpc_pipe_client *pipe_hnd,
279 TALLOC_CTX *mem_ctx,
280 int argc,
281 const char **argv)
283 NTSTATUS status;
284 const char *dcname = NULL;
286 if (cli == NULL) {
287 return NT_STATUS_INTERNAL_ERROR;
290 dcname = smbXcli_conn_remote_name(cli->conn);
292 status = trust_pw_change(c->netlogon_creds,
293 c->msg_ctx,
294 pipe_hnd->binding_handle,
295 c->opt_target_workgroup,
296 dcname,
297 true); /* force */
298 if (!NT_STATUS_IS_OK(status)) {
299 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
300 nt_errstr(status));
301 return status;
304 return NT_STATUS_OK;
308 * Force a change of the trust account password.
310 * @param argc Standard main() style argc.
311 * @param argv Standard main() style argv. Initial components are already
312 * stripped.
314 * @return A shell status integer (0 for success).
317 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
319 int conn_flags = NET_FLAGS_PDC;
321 if (!c->opt_user_specified && !c->opt_kerberos) {
322 conn_flags |= NET_FLAGS_ANONYMOUS;
325 if (c->display_usage) {
326 d_printf( "%s\n"
327 "net rpc changetrustpw\n"
328 " %s\n",
329 _("Usage:"),
330 _("Change the machine trust password"));
331 return 0;
334 return run_rpc_command(c, NULL, &ndr_table_netlogon,
335 conn_flags,
336 rpc_changetrustpw_internals,
337 argc, argv);
341 * Join a domain, the old way. This function exists to allow
342 * the message to be displayed when oldjoin was explicitly
343 * requested, but not when it was implied by "net rpc join".
345 * This uses 'machinename' as the initial password, and changes it.
347 * The password should be created with 'server manager' or equiv first.
349 * @param argc Standard main() style argc.
350 * @param argv Standard main() style argv. Initial components are already
351 * stripped.
353 * @return A shell status integer (0 for success).
356 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
358 struct libnet_JoinCtx *r = NULL;
359 TALLOC_CTX *mem_ctx;
360 WERROR werr;
361 const char *domain = lp_workgroup(); /* FIXME */
362 bool modify_config = lp_config_backend_is_registry();
363 enum netr_SchannelType sec_chan_type;
364 char *pw = NULL;
366 if (c->display_usage) {
367 d_printf("Usage:\n"
368 "net rpc oldjoin\n"
369 " Join a domain the old way\n");
370 return 0;
373 mem_ctx = talloc_init("net_rpc_oldjoin");
374 if (!mem_ctx) {
375 return -1;
378 werr = libnet_init_JoinCtx(mem_ctx, &r);
379 if (!W_ERROR_IS_OK(werr)) {
380 goto fail;
384 check what type of join - if the user wants to join as
385 a BDC, the server must agree that we are a BDC.
387 if (argc >= 0) {
388 sec_chan_type = get_sec_channel_type(argv[0]);
389 } else {
390 sec_chan_type = get_sec_channel_type(NULL);
393 if (!c->msg_ctx) {
394 d_fprintf(stderr, _("Could not initialise message context. "
395 "Try running as root\n"));
396 werr = WERR_ACCESS_DENIED;
397 goto fail;
400 pw = talloc_strndup(r, lp_netbios_name(), 14);
401 if (pw == NULL) {
402 werr = WERR_NOT_ENOUGH_MEMORY;
403 goto fail;
406 r->in.msg_ctx = c->msg_ctx;
407 r->in.domain_name = domain;
408 r->in.secure_channel_type = sec_chan_type;
409 r->in.dc_name = c->opt_host;
410 r->in.admin_account = "";
411 r->in.admin_password = strlower_talloc(r, pw);
412 if (r->in.admin_password == NULL) {
413 werr = WERR_NOT_ENOUGH_MEMORY;
414 goto fail;
416 r->in.debug = true;
417 r->in.modify_config = modify_config;
418 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
419 WKSSVC_JOIN_FLAGS_JOIN_UNSECURE |
420 WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
422 werr = libnet_Join(mem_ctx, r);
423 if (!W_ERROR_IS_OK(werr)) {
424 goto fail;
427 /* Check the short name of the domain */
429 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
430 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
431 d_printf("domain name obtained from the server.\n");
432 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
433 d_printf("You should set \"workgroup = %s\" in %s.\n",
434 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
437 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
439 if (r->out.dns_domain_name) {
440 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
441 r->out.dns_domain_name);
442 } else {
443 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
444 r->out.netbios_domain_name);
447 /* print out informative error string in case there is one */
448 if (r->out.error_string != NULL) {
449 d_printf("%s\n", r->out.error_string);
452 TALLOC_FREE(mem_ctx);
454 return 0;
456 fail:
457 if (c->opt_flags & NET_FLAGS_EXPECT_FALLBACK) {
458 goto cleanup;
461 /* issue an overall failure message at the end. */
462 d_fprintf(stderr, _("Failed to join domain: %s\n"),
463 r && r->out.error_string ? r->out.error_string :
464 get_friendly_werror_msg(werr));
466 cleanup:
467 TALLOC_FREE(mem_ctx);
469 return -1;
473 * check that a join is OK
475 * @return A shell status integer (0 for success)
478 int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
480 NTSTATUS status;
481 TALLOC_CTX *mem_ctx;
482 const char *domain = c->opt_target_workgroup;
483 const char *dc = c->opt_host;
485 if (c->display_usage) {
486 d_printf("Usage\n"
487 "net rpc testjoin\n"
488 " Test if a join is OK\n");
489 return 0;
492 mem_ctx = talloc_init("net_rpc_testjoin");
493 if (!mem_ctx) {
494 return -1;
497 if (!dc) {
498 struct netr_DsRGetDCNameInfo *info;
500 if (!c->msg_ctx) {
501 d_fprintf(stderr, _("Could not initialise message context. "
502 "Try running as root\n"));
503 talloc_destroy(mem_ctx);
504 return -1;
507 status = dsgetdcname(mem_ctx,
508 c->msg_ctx,
509 domain,
510 NULL,
511 NULL,
512 DS_RETURN_DNS_NAME,
513 &info);
514 if (!NT_STATUS_IS_OK(status)) {
515 talloc_destroy(mem_ctx);
516 return -1;
519 dc = strip_hostname(info->dc_unc);
522 /* Display success or failure */
523 status = libnet_join_ok(c->msg_ctx,
524 c->opt_workgroup,
526 c->opt_kerberos);
527 if (!NT_STATUS_IS_OK(status)) {
528 fprintf(stderr,"Join to domain '%s' is not valid: %s\n",
529 domain, nt_errstr(status));
530 talloc_destroy(mem_ctx);
531 return -1;
534 printf("Join to '%s' is OK\n",domain);
535 talloc_destroy(mem_ctx);
537 return 0;
541 * Join a domain using the administrator username and password
543 * @param argc Standard main() style argc
544 * @param argc Standard main() style argv. Initial components are already
545 * stripped. Currently not used.
546 * @return A shell status integer (0 for success)
550 static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
552 struct libnet_JoinCtx *r = NULL;
553 TALLOC_CTX *mem_ctx;
554 WERROR werr;
555 const char *domain = lp_workgroup(); /* FIXME */
556 bool modify_config = lp_config_backend_is_registry();
557 enum netr_SchannelType sec_chan_type;
559 if (c->display_usage) {
560 d_printf("Usage:\n"
561 "net rpc join\n"
562 " Join a domain the new way\n");
563 return 0;
566 mem_ctx = talloc_init("net_rpc_join_newstyle");
567 if (!mem_ctx) {
568 return -1;
571 werr = libnet_init_JoinCtx(mem_ctx, &r);
572 if (!W_ERROR_IS_OK(werr)) {
573 goto fail;
577 check what type of join - if the user wants to join as
578 a BDC, the server must agree that we are a BDC.
580 if (argc >= 0) {
581 sec_chan_type = get_sec_channel_type(argv[0]);
582 } else {
583 sec_chan_type = get_sec_channel_type(NULL);
586 if (!c->msg_ctx) {
587 d_fprintf(stderr, _("Could not initialise message context. "
588 "Try running as root\n"));
589 werr = WERR_ACCESS_DENIED;
590 goto fail;
593 r->in.msg_ctx = c->msg_ctx;
594 r->in.domain_name = domain;
595 r->in.secure_channel_type = sec_chan_type;
596 r->in.dc_name = c->opt_host;
597 r->in.admin_account = c->opt_user_name;
598 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
599 r->in.debug = true;
600 r->in.use_kerberos = c->opt_kerberos;
601 r->in.modify_config = modify_config;
602 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
603 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
604 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
606 werr = libnet_Join(mem_ctx, r);
607 if (!W_ERROR_IS_OK(werr)) {
608 goto fail;
611 /* Check the short name of the domain */
613 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
614 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
615 d_printf("domain name obtained from the server.\n");
616 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
617 d_printf("You should set \"workgroup = %s\" in %s.\n",
618 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
621 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
623 if (r->out.dns_domain_name) {
624 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
625 r->out.dns_domain_name);
626 } else {
627 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
628 r->out.netbios_domain_name);
631 /* print out informative error string in case there is one */
632 if (r->out.error_string != NULL) {
633 d_printf("%s\n", r->out.error_string);
636 TALLOC_FREE(mem_ctx);
638 return 0;
640 fail:
641 /* issue an overall failure message at the end. */
642 d_printf("Failed to join domain: %s\n",
643 r && r->out.error_string ? r->out.error_string :
644 get_friendly_werror_msg(werr));
646 TALLOC_FREE(mem_ctx);
648 return -1;
652 * 'net rpc join' entrypoint.
653 * @param argc Standard main() style argc.
654 * @param argv Standard main() style argv. Initial components are already
655 * stripped
657 * Main 'net_rpc_join()' (where the admin username/password is used) is
658 * in net_rpc_join.c.
659 * Try to just change the password, but if that doesn't work, use/prompt
660 * for a username/password.
663 int net_rpc_join(struct net_context *c, int argc, const char **argv)
665 int ret;
667 if (c->display_usage) {
668 d_printf("%s\n%s",
669 _("Usage:"),
670 _("net rpc join -U <username>[%%password] <type>\n"
671 " Join a domain\n"
672 " username\tName of the admin user"
673 " password\tPassword of the admin user, will "
674 "prompt if not specified\n"
675 " type\tCan be one of the following:\n"
676 "\t\tMEMBER\tJoin as member server (default)\n"
677 "\t\tBDC\tJoin as BDC\n"
678 "\t\tPDC\tJoin as PDC\n"));
679 return 0;
682 if (lp_server_role() == ROLE_STANDALONE) {
683 d_printf(_("cannot join as standalone machine\n"));
684 return -1;
687 if (strlen(lp_netbios_name()) > 15) {
688 d_printf(_("Our netbios name can be at most 15 chars long, "
689 "\"%s\" is %u chars long\n"),
690 lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
691 return -1;
694 c->opt_flags |= NET_FLAGS_EXPECT_FALLBACK;
695 ret = net_rpc_oldjoin(c, argc, argv);
696 c->opt_flags &= ~NET_FLAGS_EXPECT_FALLBACK;
697 if (ret == 0) {
698 return 0;
701 return net_rpc_join_newstyle(c, argc, argv);
705 * display info about a rpc domain
707 * All parameters are provided by the run_rpc_command function, except for
708 * argc, argv which are passed through.
710 * @param domain_sid The domain sid acquired from the remote server
711 * @param cli A cli_state connected to the server.
712 * @param mem_ctx Talloc context, destroyed on completion of the function.
713 * @param argc Standard main() style argc.
714 * @param argv Standard main() style argv. Initial components are already
715 * stripped.
717 * @return Normal NTSTATUS return.
720 NTSTATUS rpc_info_internals(struct net_context *c,
721 const struct dom_sid *domain_sid,
722 const char *domain_name,
723 struct cli_state *cli,
724 struct rpc_pipe_client *pipe_hnd,
725 TALLOC_CTX *mem_ctx,
726 int argc,
727 const char **argv)
729 struct policy_handle connect_pol, domain_pol;
730 NTSTATUS status, result;
731 union samr_DomainInfo *info = NULL;
732 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
734 /* Get sam policy handle */
735 status = dcerpc_samr_Connect2(b, mem_ctx,
736 pipe_hnd->desthost,
737 MAXIMUM_ALLOWED_ACCESS,
738 &connect_pol,
739 &result);
740 if (!NT_STATUS_IS_OK(status)) {
741 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
742 nt_errstr(status));
743 goto done;
746 if (!NT_STATUS_IS_OK(result)) {
747 status = result;
748 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
749 nt_errstr(result));
750 goto done;
753 /* Get domain policy handle */
754 status = dcerpc_samr_OpenDomain(b, mem_ctx,
755 &connect_pol,
756 MAXIMUM_ALLOWED_ACCESS,
757 discard_const_p(struct dom_sid2, domain_sid),
758 &domain_pol,
759 &result);
760 if (!NT_STATUS_IS_OK(status)) {
761 d_fprintf(stderr, _("Could not open domain: %s\n"),
762 nt_errstr(status));
763 goto done;
765 if (!NT_STATUS_IS_OK(result)) {
766 status = result;
767 d_fprintf(stderr, _("Could not open domain: %s\n"),
768 nt_errstr(result));
769 goto done;
772 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
773 &domain_pol,
775 &info,
776 &result);
777 if (!NT_STATUS_IS_OK(status)) {
778 goto done;
780 status = result;
781 if (NT_STATUS_IS_OK(result)) {
782 struct dom_sid_buf sid_str;
784 d_printf(_("Domain Name: %s\n"),
785 info->general.domain_name.string);
786 d_printf(_("Domain SID: %s\n"),
787 dom_sid_str_buf(domain_sid, &sid_str));
788 d_printf(_("Sequence number: %llu\n"),
789 (unsigned long long)info->general.sequence_num);
790 d_printf(_("Num users: %u\n"), info->general.num_users);
791 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
792 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
795 done:
796 return status;
800 * 'net rpc info' entrypoint.
801 * @param argc Standard main() style argc.
802 * @param argv Standard main() style argv. Initial components are already
803 * stripped.
806 int net_rpc_info(struct net_context *c, int argc, const char **argv)
808 if (c->display_usage) {
809 d_printf( "%s\n"
810 "net rpc info\n"
811 " %s\n",
812 _("Usage:"),
813 _("Display information about the domain"));
814 return 0;
817 return run_rpc_command(c, NULL, &ndr_table_samr,
818 NET_FLAGS_PDC, rpc_info_internals,
819 argc, argv);
823 * Fetch domain SID into the local secrets.tdb.
825 * All parameters are provided by the run_rpc_command function, except for
826 * argc, argv which are passed through.
828 * @param domain_sid The domain sid acquired from the remote server.
829 * @param cli A cli_state connected to the server.
830 * @param mem_ctx Talloc context, destroyed on completion of the function.
831 * @param argc Standard main() style argc.
832 * @param argv Standard main() style argv. Initial components are already
833 * stripped.
835 * @return Normal NTSTATUS return.
838 static NTSTATUS rpc_getsid_internals(struct net_context *c,
839 const struct dom_sid *domain_sid,
840 const char *domain_name,
841 struct cli_state *cli,
842 struct rpc_pipe_client *pipe_hnd,
843 TALLOC_CTX *mem_ctx,
844 int argc,
845 const char **argv)
847 struct dom_sid_buf sid_str;
849 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
850 dom_sid_str_buf(domain_sid, &sid_str),
851 domain_name);
853 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
854 DEBUG(0,("Can't store domain SID\n"));
855 return NT_STATUS_UNSUCCESSFUL;
858 return NT_STATUS_OK;
862 * 'net rpc getsid' entrypoint.
863 * @param argc Standard main() style argc.
864 * @param argv Standard main() style argv. Initial components are already
865 * stripped.
868 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
870 int conn_flags = NET_FLAGS_PDC;
872 if (!c->opt_user_specified && !c->opt_kerberos) {
873 conn_flags |= NET_FLAGS_ANONYMOUS;
876 if (c->display_usage) {
877 d_printf( "%s\n"
878 "net rpc getsid\n"
879 " %s\n",
880 _("Usage:"),
881 _("Fetch domain SID into local secrets.tdb"));
882 return 0;
885 return run_rpc_command(c, NULL, &ndr_table_samr,
886 conn_flags,
887 rpc_getsid_internals,
888 argc, argv);
891 /****************************************************************************/
894 * Basic usage function for 'net rpc user'.
895 * @param argc Standard main() style argc.
896 * @param argv Standard main() style argv. Initial components are already
897 * stripped.
900 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
902 return net_user_usage(c, argc, argv);
906 * Add a new user to a remote RPC server.
908 * @param argc Standard main() style argc.
909 * @param argv Standard main() style argv. Initial components are already
910 * stripped.
912 * @return A shell status integer (0 for success).
915 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
917 NET_API_STATUS status;
918 struct USER_INFO_1 info1;
919 uint32_t parm_error = 0;
921 if (argc < 1 || c->display_usage) {
922 rpc_user_usage(c, argc, argv);
923 return 0;
926 ZERO_STRUCT(info1);
928 info1.usri1_name = argv[0];
929 if (argc == 2) {
930 info1.usri1_password = argv[1];
933 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
935 if (status != 0) {
936 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
937 argv[0], libnetapi_get_error_string(c->netapi_ctx,
938 status));
939 return -1;
940 } else {
941 d_printf(_("Added user '%s'.\n"), argv[0]);
944 return 0;
948 * Rename a user on a remote RPC server.
950 * @param argc Standard main() style argc.
951 * @param argv Standard main() style argv. Initial components are already
952 * stripped.
954 * @return A shell status integer (0 for success).
957 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
959 NET_API_STATUS status;
960 struct USER_INFO_0 u0;
961 uint32_t parm_err = 0;
963 if (argc != 2 || c->display_usage) {
964 rpc_user_usage(c, argc, argv);
965 return 0;
968 u0.usri0_name = argv[1];
970 status = NetUserSetInfo(c->opt_host, argv[0],
971 0, (uint8_t *)&u0, &parm_err);
972 if (status) {
973 d_fprintf(stderr,
974 _("Failed to rename user from %s to %s - %s\n"),
975 argv[0], argv[1],
976 libnetapi_get_error_string(c->netapi_ctx, status));
977 } else {
978 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
981 return status;
985 * Set a user's primary group
987 * @param argc Standard main() style argc.
988 * @param argv Standard main() style argv. Initial components are already
989 * stripped.
991 * @return A shell status integer (0 for success).
994 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
995 const char **argv)
997 NET_API_STATUS status;
998 uint8_t *buffer;
999 struct GROUP_INFO_2 *g2;
1000 struct USER_INFO_1051 u1051;
1001 uint32_t parm_err = 0;
1003 if (argc != 2 || c->display_usage) {
1004 rpc_user_usage(c, argc, argv);
1005 return 0;
1008 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
1009 if (status) {
1010 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
1011 argv[1],
1012 libnetapi_get_error_string(c->netapi_ctx, status));
1013 return status;
1015 g2 = (struct GROUP_INFO_2 *)buffer;
1017 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
1019 NetApiBufferFree(buffer);
1021 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
1022 (uint8_t *)&u1051, &parm_err);
1023 if (status) {
1024 d_fprintf(stderr,
1025 _("Failed to set user's primary group %s to %s - "
1026 "%s\n"), argv[0], argv[1],
1027 libnetapi_get_error_string(c->netapi_ctx, status));
1028 } else {
1029 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
1030 argv[1]);
1032 return status;
1036 * Delete a user from a remote RPC server.
1038 * @param argc Standard main() style argc.
1039 * @param argv Standard main() style argv. Initial components are already
1040 * stripped.
1042 * @return A shell status integer (0 for success).
1045 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
1047 NET_API_STATUS status;
1049 if (argc < 1 || c->display_usage) {
1050 rpc_user_usage(c, argc, argv);
1051 return 0;
1054 status = NetUserDel(c->opt_host, argv[0]);
1056 if (status != 0) {
1057 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
1058 argv[0],
1059 libnetapi_get_error_string(c->netapi_ctx, status));
1060 return -1;
1061 } else {
1062 d_printf(_("Deleted user '%s'.\n"), argv[0]);
1065 return 0;
1069 * Set a user's password on a remote RPC server.
1071 * @param argc Standard main() style argc.
1072 * @param argv Standard main() style argv. Initial components are already
1073 * stripped.
1075 * @return A shell status integer (0 for success).
1078 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
1080 NET_API_STATUS status;
1081 char *prompt = NULL;
1082 struct USER_INFO_1003 u1003;
1083 uint32_t parm_err = 0;
1084 int ret;
1086 if (argc < 1 || c->display_usage) {
1087 rpc_user_usage(c, argc, argv);
1088 return 0;
1091 if (argv[1]) {
1092 u1003.usri1003_password = argv[1];
1093 } else {
1094 char pwd[256] = {0};
1095 ret = asprintf(&prompt, _("Enter new password for %s:"),
1096 argv[0]);
1097 if (ret == -1) {
1098 return -1;
1101 ret = samba_getpass(prompt, pwd, sizeof(pwd), false, false);
1102 SAFE_FREE(prompt);
1103 if (ret < 0) {
1104 return -1;
1107 u1003.usri1003_password = talloc_strdup(c, pwd);
1108 if (u1003.usri1003_password == NULL) {
1109 return -1;
1113 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
1115 /* Display results */
1116 if (status != 0) {
1117 d_fprintf(stderr,
1118 _("Failed to set password for '%s' with error: %s.\n"),
1119 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1120 status));
1121 return -1;
1124 return 0;
1128 * List a user's groups from a remote RPC server.
1130 * @param argc Standard main() style argc.
1131 * @param argv Standard main() style argv. Initial components are already
1132 * stripped.
1134 * @return A shell status integer (0 for success)
1137 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
1140 NET_API_STATUS status;
1141 struct GROUP_USERS_INFO_0 *u0 = NULL;
1142 uint32_t entries_read = 0;
1143 uint32_t total_entries = 0;
1144 int i;
1147 if (argc < 1 || c->display_usage) {
1148 rpc_user_usage(c, argc, argv);
1149 return 0;
1152 status = NetUserGetGroups(c->opt_host,
1153 argv[0],
1155 (uint8_t **)(void *)&u0,
1156 (uint32_t)-1,
1157 &entries_read,
1158 &total_entries);
1159 if (status != 0) {
1160 d_fprintf(stderr,
1161 _("Failed to get groups for '%s' with error: %s.\n"),
1162 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1163 status));
1164 return -1;
1167 for (i=0; i < entries_read; i++) {
1168 printf("%s\n", u0->grui0_name);
1169 u0++;
1172 return 0;
1176 * List users on a remote RPC server.
1178 * All parameters are provided by the run_rpc_command function, except for
1179 * argc, argv which are passed through.
1181 * @param domain_sid The domain sid acquired from the remote server.
1182 * @param cli A cli_state connected to the server.
1183 * @param mem_ctx Talloc context, destroyed on completion of the function.
1184 * @param argc Standard main() style argc.
1185 * @param argv Standard main() style argv. Initial components are already
1186 * stripped.
1188 * @return Normal NTSTATUS return.
1191 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
1193 NET_API_STATUS status;
1194 uint32_t start_idx=0, num_entries, i, loop_count = 0;
1195 struct NET_DISPLAY_USER *info = NULL;
1196 void *buffer = NULL;
1198 /* Query domain users */
1199 if (c->opt_long_list_entries)
1200 d_printf(_("\nUser name Comment"
1201 "\n-----------------------------\n"));
1202 do {
1203 uint32_t max_entries, max_size;
1205 dcerpc_get_query_dispinfo_params(
1206 loop_count, &max_entries, &max_size);
1208 status = NetQueryDisplayInformation(c->opt_host,
1210 start_idx,
1211 max_entries,
1212 max_size,
1213 &num_entries,
1214 &buffer);
1215 if (status != 0 && status != ERROR_MORE_DATA) {
1216 return status;
1219 info = (struct NET_DISPLAY_USER *)buffer;
1221 for (i = 0; i < num_entries; i++) {
1223 if (c->opt_long_list_entries)
1224 printf("%-21.21s %s\n", info->usri1_name,
1225 info->usri1_comment);
1226 else
1227 printf("%s\n", info->usri1_name);
1228 info++;
1231 NetApiBufferFree(buffer);
1233 loop_count++;
1234 start_idx += num_entries;
1236 } while (status == ERROR_MORE_DATA);
1238 return status;
1242 * 'net rpc user' entrypoint.
1243 * @param argc Standard main() style argc.
1244 * @param argv Standard main() style argv. Initial components are already
1245 * stripped.
1248 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1250 NET_API_STATUS status;
1252 struct functable func[] = {
1254 "add",
1255 rpc_user_add,
1256 NET_TRANSPORT_RPC,
1257 N_("Add specified user"),
1258 N_("net rpc user add\n"
1259 " Add specified user")
1262 "info",
1263 rpc_user_info,
1264 NET_TRANSPORT_RPC,
1265 N_("List domain groups of user"),
1266 N_("net rpc user info\n"
1267 " List domain groups of user")
1270 "delete",
1271 rpc_user_delete,
1272 NET_TRANSPORT_RPC,
1273 N_("Remove specified user"),
1274 N_("net rpc user delete\n"
1275 " Remove specified user")
1278 "password",
1279 rpc_user_password,
1280 NET_TRANSPORT_RPC,
1281 N_("Change user password"),
1282 N_("net rpc user password\n"
1283 " Change user password")
1286 "rename",
1287 rpc_user_rename,
1288 NET_TRANSPORT_RPC,
1289 N_("Rename specified user"),
1290 N_("net rpc user rename\n"
1291 " Rename specified user")
1294 "setprimarygroup",
1295 rpc_user_setprimarygroup,
1296 NET_TRANSPORT_RPC,
1297 "Set a user's primary group",
1298 "net rpc user setprimarygroup\n"
1299 " Set a user's primary group"
1301 {NULL, NULL, 0, NULL, NULL}
1304 status = libnetapi_net_init(&c->netapi_ctx);
1305 if (status != 0) {
1306 return -1;
1308 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1309 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1310 if (c->opt_kerberos) {
1311 libnetapi_set_use_kerberos(c->netapi_ctx);
1314 if (argc == 0) {
1315 if (c->display_usage) {
1316 d_printf( "%s\n"
1317 "net rpc user\n"
1318 " %s\n",
1319 _("Usage:"),
1320 _("List all users"));
1321 net_display_usage_from_functable(func);
1322 return 0;
1325 return rpc_user_list(c, argc, argv);
1328 return net_run_function(c, argc, argv, "net rpc user", func);
1331 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1332 TALLOC_CTX *mem_ctx,
1333 struct rpc_sh_ctx *ctx,
1334 struct rpc_pipe_client *pipe_hnd,
1335 int argc, const char **argv)
1337 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1340 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1341 TALLOC_CTX *mem_ctx,
1342 struct rpc_sh_ctx *ctx,
1343 struct rpc_pipe_client *pipe_hnd,
1344 int argc, const char **argv)
1346 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1349 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1350 TALLOC_CTX *mem_ctx,
1351 struct rpc_sh_ctx *ctx,
1352 struct rpc_pipe_client *pipe_hnd,
1353 int argc, const char **argv,
1354 NTSTATUS (*fn)(
1355 struct net_context *c,
1356 TALLOC_CTX *mem_ctx,
1357 struct rpc_sh_ctx *ctx,
1358 struct rpc_pipe_client *pipe_hnd,
1359 struct policy_handle *user_hnd,
1360 int argc, const char **argv))
1362 struct policy_handle connect_pol, domain_pol, user_pol;
1363 NTSTATUS status, result;
1364 struct dom_sid sid;
1365 uint32_t rid;
1366 enum lsa_SidType type;
1367 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1369 if (argc == 0) {
1370 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1371 ctx->whoami);
1372 return NT_STATUS_INVALID_PARAMETER;
1375 ZERO_STRUCT(connect_pol);
1376 ZERO_STRUCT(domain_pol);
1377 ZERO_STRUCT(user_pol);
1379 status = net_rpc_lookup_name(c, mem_ctx, ctx->cli,
1380 argv[0], NULL, NULL, &sid, &type);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1383 nt_errstr(status));
1384 goto done;
1387 if (type != SID_NAME_USER) {
1388 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1389 sid_type_lookup(type));
1390 status = NT_STATUS_NO_SUCH_USER;
1391 goto done;
1394 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1395 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1396 status = NT_STATUS_NO_SUCH_USER;
1397 goto done;
1400 status = dcerpc_samr_Connect2(b, mem_ctx,
1401 pipe_hnd->desthost,
1402 MAXIMUM_ALLOWED_ACCESS,
1403 &connect_pol,
1404 &result);
1405 if (!NT_STATUS_IS_OK(status)) {
1406 goto done;
1408 if (!NT_STATUS_IS_OK(result)) {
1409 status = result;
1410 goto done;
1413 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1414 &connect_pol,
1415 MAXIMUM_ALLOWED_ACCESS,
1416 ctx->domain_sid,
1417 &domain_pol,
1418 &result);
1419 if (!NT_STATUS_IS_OK(status)) {
1420 goto done;
1422 if (!NT_STATUS_IS_OK(result)) {
1423 status = result;
1424 goto done;
1427 status = dcerpc_samr_OpenUser(b, mem_ctx,
1428 &domain_pol,
1429 MAXIMUM_ALLOWED_ACCESS,
1430 rid,
1431 &user_pol,
1432 &result);
1433 if (!NT_STATUS_IS_OK(status)) {
1434 goto done;
1436 if (!NT_STATUS_IS_OK(result)) {
1437 status = result;
1438 goto done;
1441 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1443 done:
1444 if (is_valid_policy_hnd(&user_pol)) {
1445 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1447 if (is_valid_policy_hnd(&domain_pol)) {
1448 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1450 if (is_valid_policy_hnd(&connect_pol)) {
1451 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1453 return status;
1456 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1457 TALLOC_CTX *mem_ctx,
1458 struct rpc_sh_ctx *ctx,
1459 struct rpc_pipe_client *pipe_hnd,
1460 struct policy_handle *user_hnd,
1461 int argc, const char **argv)
1463 NTSTATUS status, result;
1464 union samr_UserInfo *info = NULL;
1465 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1467 if (argc != 0) {
1468 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1469 ctx->whoami);
1470 return NT_STATUS_INVALID_PARAMETER;
1473 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1474 user_hnd,
1476 &info,
1477 &result);
1478 if (!NT_STATUS_IS_OK(status)) {
1479 return status;
1481 if (!NT_STATUS_IS_OK(result)) {
1482 return result;
1485 d_printf(_("user rid: %d, group rid: %d\n"),
1486 info->info21.rid,
1487 info->info21.primary_gid);
1489 return result;
1492 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1493 TALLOC_CTX *mem_ctx,
1494 struct rpc_sh_ctx *ctx,
1495 struct rpc_pipe_client *pipe_hnd,
1496 int argc, const char **argv)
1498 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1499 rpc_sh_user_show_internals);
1502 #define FETCHSTR(name, rec) \
1503 do { if (strequal(ctx->thiscmd, name)) { \
1504 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1505 } while (0);
1507 #define SETSTR(name, rec, flag) \
1508 do { if (strequal(ctx->thiscmd, name)) { \
1509 init_lsa_String(&(info->info21.rec), argv[0]); \
1510 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1511 } while (0);
1513 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1514 TALLOC_CTX *mem_ctx,
1515 struct rpc_sh_ctx *ctx,
1516 struct rpc_pipe_client *pipe_hnd,
1517 struct policy_handle *user_hnd,
1518 int argc, const char **argv)
1520 NTSTATUS status, result;
1521 const char *username;
1522 const char *oldval = "";
1523 union samr_UserInfo *info = NULL;
1524 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1526 if (argc > 1) {
1527 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1528 _("Usage:"), ctx->whoami);
1529 return NT_STATUS_INVALID_PARAMETER;
1532 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1533 user_hnd,
1535 &info,
1536 &result);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 return status;
1540 if (!NT_STATUS_IS_OK(result)) {
1541 return result;
1544 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1546 FETCHSTR("fullname", full_name);
1547 FETCHSTR("homedir", home_directory);
1548 FETCHSTR("homedrive", home_drive);
1549 FETCHSTR("logonscript", logon_script);
1550 FETCHSTR("profilepath", profile_path);
1551 FETCHSTR("description", description);
1553 if (argc == 0) {
1554 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1555 goto done;
1558 if (strcmp(argv[0], "NULL") == 0) {
1559 argv[0] = "";
1562 ZERO_STRUCT(info->info21);
1564 SETSTR("fullname", full_name, FULL_NAME);
1565 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1566 SETSTR("homedrive", home_drive, HOME_DRIVE);
1567 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1568 SETSTR("profilepath", profile_path, PROFILE_PATH);
1569 SETSTR("description", description, DESCRIPTION);
1571 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1572 user_hnd,
1574 info,
1575 &result);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 return status;
1580 status = result;
1582 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1583 ctx->thiscmd, oldval, argv[0]);
1585 done:
1587 return status;
1590 #define HANDLEFLG(name, rec) \
1591 do { if (strequal(ctx->thiscmd, name)) { \
1592 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1593 if (newval) { \
1594 newflags = oldflags | ACB_##rec; \
1595 } else { \
1596 newflags = oldflags & ~ACB_##rec; \
1597 } } } while (0);
1599 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1600 TALLOC_CTX *mem_ctx,
1601 struct rpc_sh_ctx *ctx,
1602 struct rpc_pipe_client *pipe_hnd,
1603 int argc, const char **argv)
1605 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1606 rpc_sh_user_str_edit_internals);
1609 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1610 TALLOC_CTX *mem_ctx,
1611 struct rpc_sh_ctx *ctx,
1612 struct rpc_pipe_client *pipe_hnd,
1613 struct policy_handle *user_hnd,
1614 int argc, const char **argv)
1616 NTSTATUS status, result;
1617 const char *username;
1618 const char *oldval = "unknown";
1619 uint32_t oldflags, newflags;
1620 bool newval;
1621 union samr_UserInfo *info = NULL;
1622 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1624 if ((argc > 1) ||
1625 ((argc == 1) && !strequal(argv[0], "yes") &&
1626 !strequal(argv[0], "no"))) {
1627 /* TRANSATORS: The yes|no here are program keywords. Please do
1628 not translate. */
1629 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1630 ctx->whoami);
1631 return NT_STATUS_INVALID_PARAMETER;
1634 newval = strequal(argv[0], "yes");
1636 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1637 user_hnd,
1639 &info,
1640 &result);
1641 if (!NT_STATUS_IS_OK(status)) {
1642 return status;
1644 if (!NT_STATUS_IS_OK(result)) {
1645 return result;
1648 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1649 oldflags = info->info21.acct_flags;
1650 newflags = info->info21.acct_flags;
1652 HANDLEFLG("disabled", DISABLED);
1653 HANDLEFLG("pwnotreq", PWNOTREQ);
1654 HANDLEFLG("autolock", AUTOLOCK);
1655 HANDLEFLG("pwnoexp", PWNOEXP);
1657 if (argc == 0) {
1658 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1659 oldval);
1660 goto done;
1663 ZERO_STRUCT(info->info21);
1665 info->info21.acct_flags = newflags;
1666 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1668 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1669 user_hnd,
1671 info,
1672 &result);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 goto done;
1676 status = result;
1677 if (NT_STATUS_IS_OK(result)) {
1678 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1679 ctx->thiscmd, oldval, argv[0]);
1682 done:
1684 return status;
1687 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1688 TALLOC_CTX *mem_ctx,
1689 struct rpc_sh_ctx *ctx,
1690 struct rpc_pipe_client *pipe_hnd,
1691 int argc, const char **argv)
1693 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1694 rpc_sh_user_flag_edit_internals);
1697 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1698 TALLOC_CTX *mem_ctx,
1699 struct rpc_sh_ctx *ctx)
1701 static struct rpc_sh_cmd cmds[] = {
1703 { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1704 N_("Show/Set a user's full name") },
1706 { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1707 N_("Show/Set a user's home directory") },
1709 { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1710 N_("Show/Set a user's home drive") },
1712 { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1713 N_("Show/Set a user's logon script") },
1715 { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1716 N_("Show/Set a user's profile path") },
1718 { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1719 N_("Show/Set a user's description") },
1721 { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1722 N_("Show/Set whether a user is disabled") },
1724 { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1725 N_("Show/Set whether a user locked out") },
1727 { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1728 N_("Show/Set whether a user does not need a password") },
1730 { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1731 N_("Show/Set whether a user's password does not expire") },
1733 { NULL, NULL, 0, NULL, NULL }
1736 return cmds;
1739 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1740 TALLOC_CTX *mem_ctx,
1741 struct rpc_sh_ctx *ctx)
1743 static struct rpc_sh_cmd cmds[] = {
1745 { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1746 N_("List available users") },
1748 { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1749 N_("List the domain groups a user is member of") },
1751 { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1752 N_("Show info about a user") },
1754 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1755 N_("Show/Modify a user's fields") },
1757 { NULL, NULL, 0, NULL, NULL }
1760 return cmds;
1763 /****************************************************************************/
1766 * Basic usage function for 'net rpc group'.
1767 * @param argc Standard main() style argc.
1768 * @param argv Standard main() style argv. Initial components are already
1769 * stripped.
1772 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1774 return net_group_usage(c, argc, argv);
1778 * Delete group on a remote RPC server.
1780 * All parameters are provided by the run_rpc_command function, except for
1781 * argc, argv which are passed through.
1783 * @param domain_sid The domain sid acquired from the remote server.
1784 * @param cli A cli_state connected to the server.
1785 * @param mem_ctx Talloc context, destroyed on completion of the function.
1786 * @param argc Standard main() style argc.
1787 * @param argv Standard main() style argv. Initial components are already
1788 * stripped.
1790 * @return Normal NTSTATUS return.
1793 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1794 const struct dom_sid *domain_sid,
1795 const char *domain_name,
1796 struct cli_state *cli,
1797 struct rpc_pipe_client *pipe_hnd,
1798 TALLOC_CTX *mem_ctx,
1799 int argc,
1800 const char **argv)
1802 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1803 bool group_is_primary = false;
1804 NTSTATUS status, result;
1805 uint32_t group_rid;
1806 struct samr_RidAttrArray *rids = NULL;
1807 /* char **names; */
1808 int i;
1809 /* struct samr_RidWithAttribute *user_gids; */
1810 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1812 struct samr_Ids group_rids, name_types;
1813 struct lsa_String lsa_acct_name;
1814 union samr_UserInfo *info = NULL;
1816 if (argc < 1 || c->display_usage) {
1817 rpc_group_usage(c, argc,argv);
1818 return NT_STATUS_OK; /* ok? */
1821 status = dcerpc_samr_Connect2(b, mem_ctx,
1822 pipe_hnd->desthost,
1823 MAXIMUM_ALLOWED_ACCESS,
1824 &connect_pol,
1825 &result);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1828 goto done;
1831 if (!NT_STATUS_IS_OK(result)) {
1832 status = result;
1833 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1834 goto done;
1837 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1838 &connect_pol,
1839 MAXIMUM_ALLOWED_ACCESS,
1840 discard_const_p(struct dom_sid2, domain_sid),
1841 &domain_pol,
1842 &result);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 d_fprintf(stderr, _("Request open_domain failed\n"));
1845 goto done;
1848 if (!NT_STATUS_IS_OK(result)) {
1849 status = result;
1850 d_fprintf(stderr, _("Request open_domain failed\n"));
1851 goto done;
1854 init_lsa_String(&lsa_acct_name, argv[0]);
1856 status = dcerpc_samr_LookupNames(b, mem_ctx,
1857 &domain_pol,
1859 &lsa_acct_name,
1860 &group_rids,
1861 &name_types,
1862 &result);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1865 goto done;
1868 if (!NT_STATUS_IS_OK(result)) {
1869 status = result;
1870 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1871 goto done;
1873 if (group_rids.count != 1) {
1874 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1875 goto done;
1877 if (name_types.count != 1) {
1878 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1879 goto done;
1882 switch (name_types.ids[0])
1884 case SID_NAME_DOM_GRP:
1885 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1886 &domain_pol,
1887 MAXIMUM_ALLOWED_ACCESS,
1888 group_rids.ids[0],
1889 &group_pol,
1890 &result);
1891 if (!NT_STATUS_IS_OK(status)) {
1892 d_fprintf(stderr, _("Request open_group failed"));
1893 goto done;
1896 if (!NT_STATUS_IS_OK(result)) {
1897 status = result;
1898 d_fprintf(stderr, _("Request open_group failed"));
1899 goto done;
1902 group_rid = group_rids.ids[0];
1904 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1905 &group_pol,
1906 &rids,
1907 &result);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 d_fprintf(stderr,
1910 _("Unable to query group members of %s"),
1911 argv[0]);
1912 goto done;
1915 if (!NT_STATUS_IS_OK(result)) {
1916 status = result;
1917 d_fprintf(stderr,
1918 _("Unable to query group members of %s"),
1919 argv[0]);
1920 goto done;
1923 if (c->opt_verbose) {
1924 d_printf(
1925 _("Domain Group %s (rid: %d) has %d members\n"),
1926 argv[0],group_rid, rids->count);
1929 /* Check if group is anyone's primary group */
1930 for (i = 0; i < rids->count; i++)
1932 status = dcerpc_samr_OpenUser(b, mem_ctx,
1933 &domain_pol,
1934 MAXIMUM_ALLOWED_ACCESS,
1935 rids->rids[i],
1936 &user_pol,
1937 &result);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 d_fprintf(stderr,
1940 _("Unable to open group member %d\n"),
1941 rids->rids[i]);
1942 goto done;
1945 if (!NT_STATUS_IS_OK(result)) {
1946 status = result;
1947 d_fprintf(stderr,
1948 _("Unable to open group member %d\n"),
1949 rids->rids[i]);
1950 goto done;
1953 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1954 &user_pol,
1956 &info,
1957 &result);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 d_fprintf(stderr,
1960 _("Unable to lookup userinfo for group "
1961 "member %d\n"),
1962 rids->rids[i]);
1963 goto done;
1966 if (!NT_STATUS_IS_OK(result)) {
1967 status = result;
1968 d_fprintf(stderr,
1969 _("Unable to lookup userinfo for group "
1970 "member %d\n"),
1971 rids->rids[i]);
1972 goto done;
1975 if (info->info21.primary_gid == group_rid) {
1976 if (c->opt_verbose) {
1977 d_printf(_("Group is primary group "
1978 "of %s\n"),
1979 info->info21.account_name.string);
1981 group_is_primary = true;
1984 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1987 if (group_is_primary) {
1988 d_fprintf(stderr, _("Unable to delete group because "
1989 "some of it's members have it as primary "
1990 "group\n"));
1991 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1992 goto done;
1995 /* remove all group members */
1996 for (i = 0; i < rids->count; i++)
1998 if (c->opt_verbose)
1999 d_printf(_("Remove group member %d..."),
2000 rids->rids[i]);
2001 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2002 &group_pol,
2003 rids->rids[i],
2004 &result);
2005 if (!NT_STATUS_IS_OK(status)) {
2006 goto done;
2008 status = result;
2009 if (NT_STATUS_IS_OK(result)) {
2010 if (c->opt_verbose)
2011 d_printf(_("ok\n"));
2012 } else {
2013 if (c->opt_verbose)
2014 d_printf("%s\n", _("failed"));
2015 goto done;
2019 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
2020 &group_pol,
2021 &result);
2022 if (!NT_STATUS_IS_OK(status)) {
2023 break;
2026 status = result;
2028 break;
2029 /* removing a local group is easier... */
2030 case SID_NAME_ALIAS:
2031 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2032 &domain_pol,
2033 MAXIMUM_ALLOWED_ACCESS,
2034 group_rids.ids[0],
2035 &group_pol,
2036 &result);
2037 if (!NT_STATUS_IS_OK(status)) {
2038 d_fprintf(stderr, _("Request open_alias failed\n"));
2039 goto done;
2041 if (!NT_STATUS_IS_OK(result)) {
2042 status = result;
2043 d_fprintf(stderr, _("Request open_alias failed\n"));
2044 goto done;
2047 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
2048 &group_pol,
2049 &result);
2050 if (!NT_STATUS_IS_OK(status)) {
2051 break;
2054 status = result;
2056 break;
2057 default:
2058 d_fprintf(stderr, _("%s is of type %s. This command is only "
2059 "for deleting local or global groups\n"),
2060 argv[0],sid_type_lookup(name_types.ids[0]));
2061 status = NT_STATUS_UNSUCCESSFUL;
2062 goto done;
2065 if (NT_STATUS_IS_OK(status)) {
2066 if (c->opt_verbose)
2067 d_printf(_("Deleted %s '%s'\n"),
2068 sid_type_lookup(name_types.ids[0]), argv[0]);
2069 } else {
2070 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
2071 get_friendly_nt_error_msg(status));
2074 done:
2075 return status;
2079 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
2081 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2082 rpc_group_delete_internals, argc,argv);
2085 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
2087 NET_API_STATUS status;
2088 struct GROUP_INFO_1 info1;
2089 uint32_t parm_error = 0;
2091 if (argc != 1 || c->display_usage) {
2092 rpc_group_usage(c, argc, argv);
2093 return 0;
2096 ZERO_STRUCT(info1);
2098 info1.grpi1_name = argv[0];
2099 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2100 info1.grpi1_comment = c->opt_comment;
2103 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2105 if (status != 0) {
2106 d_fprintf(stderr,
2107 _("Failed to add group '%s' with error: %s.\n"),
2108 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2109 status));
2110 return -1;
2111 } else {
2112 d_printf(_("Added group '%s'.\n"), argv[0]);
2115 return 0;
2118 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
2120 NET_API_STATUS status;
2121 struct LOCALGROUP_INFO_1 info1;
2122 uint32_t parm_error = 0;
2124 if (argc != 1 || c->display_usage) {
2125 rpc_group_usage(c, argc, argv);
2126 return 0;
2129 ZERO_STRUCT(info1);
2131 info1.lgrpi1_name = argv[0];
2132 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2133 info1.lgrpi1_comment = c->opt_comment;
2136 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2138 if (status != 0) {
2139 d_fprintf(stderr,
2140 _("Failed to add alias '%s' with error: %s.\n"),
2141 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2142 status));
2143 return -1;
2144 } else {
2145 d_printf(_("Added alias '%s'.\n"), argv[0]);
2148 return 0;
2151 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
2153 if (c->opt_localgroup)
2154 return rpc_alias_add_internals(c, argc, argv);
2156 return rpc_group_add_internals(c, argc, argv);
2159 static NTSTATUS get_sid_from_name(struct cli_state *cli,
2160 TALLOC_CTX *mem_ctx,
2161 const char *name,
2162 struct dom_sid *sid,
2163 enum lsa_SidType *type)
2165 struct dom_sid *sids = NULL;
2166 enum lsa_SidType *types = NULL;
2167 struct rpc_pipe_client *pipe_hnd = NULL;
2168 struct policy_handle lsa_pol;
2169 NTSTATUS status, result;
2170 struct dcerpc_binding_handle *b;
2172 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
2173 &pipe_hnd);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 goto done;
2178 b = pipe_hnd->binding_handle;
2180 status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
2181 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2183 if (!NT_STATUS_IS_OK(status)) {
2184 goto done;
2187 status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2188 &name, NULL, 1, &sids, &types);
2190 if (NT_STATUS_IS_OK(status)) {
2191 sid_copy(sid, &sids[0]);
2192 *type = types[0];
2195 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
2197 done:
2198 if (pipe_hnd) {
2199 TALLOC_FREE(pipe_hnd);
2202 if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
2204 /* Try as S-1-5-whatever */
2206 struct dom_sid tmp_sid;
2208 if (string_to_sid(&tmp_sid, name)) {
2209 sid_copy(sid, &tmp_sid);
2210 *type = SID_NAME_UNKNOWN;
2211 status = NT_STATUS_OK;
2215 return status;
2218 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2219 TALLOC_CTX *mem_ctx,
2220 const struct dom_sid *group_sid,
2221 const char *member)
2223 struct policy_handle connect_pol, domain_pol;
2224 NTSTATUS status, result;
2225 uint32_t group_rid;
2226 struct policy_handle group_pol;
2227 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2229 struct samr_Ids rids, rid_types;
2230 struct lsa_String lsa_acct_name;
2232 struct dom_sid sid;
2234 sid_copy(&sid, group_sid);
2236 if (!sid_split_rid(&sid, &group_rid)) {
2237 return NT_STATUS_UNSUCCESSFUL;
2240 /* Get sam policy handle */
2241 status = dcerpc_samr_Connect2(b, mem_ctx,
2242 pipe_hnd->desthost,
2243 MAXIMUM_ALLOWED_ACCESS,
2244 &connect_pol,
2245 &result);
2246 if (!NT_STATUS_IS_OK(status)) {
2247 return status;
2249 if (!NT_STATUS_IS_OK(result)) {
2250 return result;
2253 /* Get domain policy handle */
2254 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2255 &connect_pol,
2256 MAXIMUM_ALLOWED_ACCESS,
2257 &sid,
2258 &domain_pol,
2259 &result);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 return status;
2263 if (!NT_STATUS_IS_OK(result)) {
2264 return result;
2267 init_lsa_String(&lsa_acct_name, member);
2269 status = dcerpc_samr_LookupNames(b, mem_ctx,
2270 &domain_pol,
2272 &lsa_acct_name,
2273 &rids,
2274 &rid_types,
2275 &result);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2278 member);
2279 goto done;
2282 if (!NT_STATUS_IS_OK(result)) {
2283 status = result;
2284 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2285 member);
2286 goto done;
2288 if (rids.count != 1) {
2289 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2290 goto done;
2292 if (rid_types.count != 1) {
2293 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2294 goto done;
2297 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2298 &domain_pol,
2299 MAXIMUM_ALLOWED_ACCESS,
2300 group_rid,
2301 &group_pol,
2302 &result);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 goto done;
2307 if (!NT_STATUS_IS_OK(result)) {
2308 status = result;
2309 goto done;
2312 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2313 &group_pol,
2314 rids.ids[0],
2315 0x0005, /* unknown flags */
2316 &result);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 goto done;
2321 status = result;
2323 done:
2324 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2325 return status;
2328 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2329 struct cli_state *cli,
2330 TALLOC_CTX *mem_ctx,
2331 const struct dom_sid *alias_sid,
2332 const char *member)
2334 struct policy_handle connect_pol, domain_pol;
2335 NTSTATUS status, result;
2336 uint32_t alias_rid;
2337 struct policy_handle alias_pol;
2338 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2340 struct dom_sid member_sid;
2341 enum lsa_SidType member_type;
2343 struct dom_sid sid;
2345 sid_copy(&sid, alias_sid);
2347 if (!sid_split_rid(&sid, &alias_rid)) {
2348 return NT_STATUS_UNSUCCESSFUL;
2351 result = get_sid_from_name(cli, mem_ctx,
2352 member, &member_sid, &member_type);
2354 if (!NT_STATUS_IS_OK(result)) {
2355 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2356 member);
2357 return result;
2360 /* Get sam policy handle */
2361 status = dcerpc_samr_Connect2(b, mem_ctx,
2362 pipe_hnd->desthost,
2363 MAXIMUM_ALLOWED_ACCESS,
2364 &connect_pol,
2365 &result);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 goto done;
2369 if (!NT_STATUS_IS_OK(result)) {
2370 status = result;
2371 goto done;
2374 /* Get domain policy handle */
2375 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2376 &connect_pol,
2377 MAXIMUM_ALLOWED_ACCESS,
2378 &sid,
2379 &domain_pol,
2380 &result);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 goto done;
2384 if (!NT_STATUS_IS_OK(result)) {
2385 status = result;
2386 goto done;
2389 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2390 &domain_pol,
2391 MAXIMUM_ALLOWED_ACCESS,
2392 alias_rid,
2393 &alias_pol,
2394 &result);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 return status;
2398 if (!NT_STATUS_IS_OK(result)) {
2399 return result;
2402 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2403 &alias_pol,
2404 &member_sid,
2405 &result);
2406 if (!NT_STATUS_IS_OK(status)) {
2407 return status;
2410 status = result;
2412 done:
2413 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2414 return status;
2417 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2418 const struct dom_sid *domain_sid,
2419 const char *domain_name,
2420 struct cli_state *cli,
2421 struct rpc_pipe_client *pipe_hnd,
2422 TALLOC_CTX *mem_ctx,
2423 int argc,
2424 const char **argv)
2426 struct dom_sid group_sid;
2427 enum lsa_SidType group_type;
2429 if (argc != 2 || c->display_usage) {
2430 d_printf("%s\n%s",
2431 _("Usage:"),
2432 _("net rpc group addmem <group> <member>\n"
2433 " Add a member to a group\n"
2434 " group\tGroup to add member to\n"
2435 " member\tMember to add to group\n"));
2436 return NT_STATUS_UNSUCCESSFUL;
2439 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2440 &group_sid, &group_type))) {
2441 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2442 argv[0]);
2443 return NT_STATUS_UNSUCCESSFUL;
2446 if (group_type == SID_NAME_DOM_GRP) {
2447 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2448 &group_sid, argv[1]);
2450 if (!NT_STATUS_IS_OK(result)) {
2451 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2452 argv[1], argv[0], nt_errstr(result));
2454 return result;
2457 if (group_type == SID_NAME_ALIAS) {
2458 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, cli, mem_ctx,
2459 &group_sid, argv[1]);
2461 if (!NT_STATUS_IS_OK(result)) {
2462 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2463 argv[1], argv[0], nt_errstr(result));
2465 return result;
2468 d_fprintf(stderr, _("Can only add members to global or local groups "
2469 "which %s is not\n"), argv[0]);
2471 return NT_STATUS_UNSUCCESSFUL;
2474 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2476 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2477 rpc_group_addmem_internals,
2478 argc, argv);
2481 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2482 struct rpc_pipe_client *pipe_hnd,
2483 TALLOC_CTX *mem_ctx,
2484 const struct dom_sid *group_sid,
2485 const char *member)
2487 struct policy_handle connect_pol, domain_pol;
2488 NTSTATUS status, result;
2489 uint32_t group_rid;
2490 struct policy_handle group_pol;
2491 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2493 struct samr_Ids rids, rid_types;
2494 struct lsa_String lsa_acct_name;
2496 struct dom_sid sid;
2498 sid_copy(&sid, group_sid);
2500 if (!sid_split_rid(&sid, &group_rid))
2501 return NT_STATUS_UNSUCCESSFUL;
2503 /* Get sam policy handle */
2504 status = dcerpc_samr_Connect2(b, mem_ctx,
2505 pipe_hnd->desthost,
2506 MAXIMUM_ALLOWED_ACCESS,
2507 &connect_pol,
2508 &result);
2509 if (!NT_STATUS_IS_OK(status)) {
2510 return status;
2512 if (!NT_STATUS_IS_OK(result)) {
2513 return result;
2517 /* Get domain policy handle */
2518 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2519 &connect_pol,
2520 MAXIMUM_ALLOWED_ACCESS,
2521 &sid,
2522 &domain_pol,
2523 &result);
2524 if (!NT_STATUS_IS_OK(status)) {
2525 return status;
2527 if (!NT_STATUS_IS_OK(result)) {
2528 return result;
2531 init_lsa_String(&lsa_acct_name, member);
2533 status = dcerpc_samr_LookupNames(b, mem_ctx,
2534 &domain_pol,
2536 &lsa_acct_name,
2537 &rids,
2538 &rid_types,
2539 &result);
2540 if (!NT_STATUS_IS_OK(status)) {
2541 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2542 member);
2543 goto done;
2546 if (!NT_STATUS_IS_OK(result)) {
2547 status = result;
2548 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2549 member);
2550 goto done;
2552 if (rids.count != 1) {
2553 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2554 goto done;
2556 if (rid_types.count != 1) {
2557 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2558 goto done;
2561 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2562 &domain_pol,
2563 MAXIMUM_ALLOWED_ACCESS,
2564 group_rid,
2565 &group_pol,
2566 &result);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 goto done;
2570 if (!NT_STATUS_IS_OK(result)) {
2571 status = result;
2572 goto done;
2575 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2576 &group_pol,
2577 rids.ids[0],
2578 &result);
2579 if (!NT_STATUS_IS_OK(status)) {
2580 goto done;
2583 status = result;
2584 done:
2585 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2586 return status;
2589 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2590 struct cli_state *cli,
2591 TALLOC_CTX *mem_ctx,
2592 const struct dom_sid *alias_sid,
2593 const char *member)
2595 struct policy_handle connect_pol, domain_pol;
2596 NTSTATUS status, result;
2597 uint32_t alias_rid;
2598 struct policy_handle alias_pol;
2599 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2601 struct dom_sid member_sid;
2602 enum lsa_SidType member_type;
2604 struct dom_sid sid;
2606 sid_copy(&sid, alias_sid);
2608 if (!sid_split_rid(&sid, &alias_rid))
2609 return NT_STATUS_UNSUCCESSFUL;
2611 result = get_sid_from_name(cli, mem_ctx,
2612 member, &member_sid, &member_type);
2614 if (!NT_STATUS_IS_OK(result)) {
2615 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2616 member);
2617 return result;
2620 /* Get sam policy handle */
2621 status = dcerpc_samr_Connect2(b, mem_ctx,
2622 pipe_hnd->desthost,
2623 MAXIMUM_ALLOWED_ACCESS,
2624 &connect_pol,
2625 &result);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 goto done;
2629 if (!NT_STATUS_IS_OK(result)) {
2630 status = result;
2631 goto done;
2634 /* Get domain policy handle */
2635 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2636 &connect_pol,
2637 MAXIMUM_ALLOWED_ACCESS,
2638 &sid,
2639 &domain_pol,
2640 &result);
2641 if (!NT_STATUS_IS_OK(status)) {
2642 goto done;
2644 if (!NT_STATUS_IS_OK(result)) {
2645 status = result;
2646 goto done;
2649 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2650 &domain_pol,
2651 MAXIMUM_ALLOWED_ACCESS,
2652 alias_rid,
2653 &alias_pol,
2654 &result);
2655 if (!NT_STATUS_IS_OK(status)) {
2656 return status;
2659 if (!NT_STATUS_IS_OK(result)) {
2660 return result;
2663 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2664 &alias_pol,
2665 &member_sid,
2666 &result);
2668 if (!NT_STATUS_IS_OK(status)) {
2669 return status;
2672 status = result;
2674 done:
2675 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2676 return status;
2679 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2680 const struct dom_sid *domain_sid,
2681 const char *domain_name,
2682 struct cli_state *cli,
2683 struct rpc_pipe_client *pipe_hnd,
2684 TALLOC_CTX *mem_ctx,
2685 int argc,
2686 const char **argv)
2688 struct dom_sid group_sid;
2689 enum lsa_SidType group_type;
2691 if (argc != 2 || c->display_usage) {
2692 d_printf("%s\n%s",
2693 _("Usage:"),
2694 _("net rpc group delmem <group> <member>\n"
2695 " Delete a member from a group\n"
2696 " group\tGroup to delete member from\n"
2697 " member\tMember to delete from group\n"));
2698 return NT_STATUS_UNSUCCESSFUL;
2701 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2702 &group_sid, &group_type))) {
2703 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2704 argv[0]);
2705 return NT_STATUS_UNSUCCESSFUL;
2708 if (group_type == SID_NAME_DOM_GRP) {
2709 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2710 &group_sid, argv[1]);
2712 if (!NT_STATUS_IS_OK(result)) {
2713 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2714 argv[1], argv[0], nt_errstr(result));
2716 return result;
2719 if (group_type == SID_NAME_ALIAS) {
2720 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, cli, mem_ctx,
2721 &group_sid, argv[1]);
2723 if (!NT_STATUS_IS_OK(result)) {
2724 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2725 argv[1], argv[0], nt_errstr(result));
2727 return result;
2730 d_fprintf(stderr, _("Can only delete members from global or local "
2731 "groups which %s is not\n"), argv[0]);
2733 return NT_STATUS_UNSUCCESSFUL;
2736 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2738 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2739 rpc_group_delmem_internals,
2740 argc, argv);
2744 * List groups on a remote RPC server.
2746 * All parameters are provided by the run_rpc_command function, except for
2747 * argc, argv which are passes through.
2749 * @param domain_sid The domain sid acquired from the remote server.
2750 * @param cli A cli_state connected to the server.
2751 * @param mem_ctx Talloc context, destroyed on completion of the function.
2752 * @param argc Standard main() style argc.
2753 * @param argv Standard main() style argv. Initial components are already
2754 * stripped.
2756 * @return Normal NTSTATUS return.
2759 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2760 const struct dom_sid *domain_sid,
2761 const char *domain_name,
2762 struct cli_state *cli,
2763 struct rpc_pipe_client *pipe_hnd,
2764 TALLOC_CTX *mem_ctx,
2765 int argc,
2766 const char **argv)
2768 struct policy_handle connect_pol, domain_pol;
2769 NTSTATUS status, result;
2770 uint32_t start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2771 struct samr_SamArray *groups = NULL;
2772 bool global = false;
2773 bool local = false;
2774 bool builtin = false;
2775 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2777 if (c->display_usage) {
2778 d_printf("%s\n%s",
2779 _("Usage:"),
2780 _("net rpc group list [global] [local] [builtin]\n"
2781 " List groups on RPC server\n"
2782 " global\tList global groups\n"
2783 " local\tList local groups\n"
2784 " builtin\tList builtin groups\n"
2785 " If none of global, local or builtin is "
2786 "specified, all three options are considered "
2787 "set\n"));
2788 return NT_STATUS_OK;
2791 if (argc == 0) {
2792 global = true;
2793 local = true;
2794 builtin = true;
2797 for (i=0; i<argc; i++) {
2798 if (strequal(argv[i], "global"))
2799 global = true;
2801 if (strequal(argv[i], "local"))
2802 local = true;
2804 if (strequal(argv[i], "builtin"))
2805 builtin = true;
2808 /* Get sam policy handle */
2810 status = dcerpc_samr_Connect2(b, mem_ctx,
2811 pipe_hnd->desthost,
2812 MAXIMUM_ALLOWED_ACCESS,
2813 &connect_pol,
2814 &result);
2815 if (!NT_STATUS_IS_OK(status)) {
2816 goto done;
2818 if (!NT_STATUS_IS_OK(result)) {
2819 status = result;
2820 goto done;
2823 /* Get domain policy handle */
2825 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2826 &connect_pol,
2827 MAXIMUM_ALLOWED_ACCESS,
2828 discard_const_p(struct dom_sid2, domain_sid),
2829 &domain_pol,
2830 &result);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 goto done;
2834 if (!NT_STATUS_IS_OK(result)) {
2835 status = result;
2836 goto done;
2839 /* Query domain groups */
2840 if (c->opt_long_list_entries)
2841 d_printf(_("\nGroup name Comment"
2842 "\n-----------------------------\n"));
2843 do {
2844 uint32_t max_size, total_size, returned_size;
2845 union samr_DispInfo info;
2847 if (!global) break;
2849 dcerpc_get_query_dispinfo_params(
2850 loop_count, &max_entries, &max_size);
2852 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2853 &domain_pol,
2855 start_idx,
2856 max_entries,
2857 max_size,
2858 &total_size,
2859 &returned_size,
2860 &info,
2861 &result);
2862 if (!NT_STATUS_IS_OK(status)) {
2863 goto done;
2865 num_entries = info.info3.count;
2866 start_idx += info.info3.count;
2868 if (!NT_STATUS_IS_OK(result) &&
2869 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2870 break;
2872 for (i = 0; i < num_entries; i++) {
2874 const char *group = NULL;
2875 const char *desc = NULL;
2877 group = info.info3.entries[i].account_name.string;
2878 desc = info.info3.entries[i].description.string;
2880 if (c->opt_long_list_entries)
2881 printf("%-21.21s %-50.50s\n",
2882 group, desc);
2883 else
2884 printf("%s\n", group);
2886 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2887 /* query domain aliases */
2888 start_idx = 0;
2889 do {
2890 if (!local) break;
2892 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2893 &domain_pol,
2894 &start_idx,
2895 &groups,
2896 0xffff,
2897 &num_entries,
2898 &result);
2899 if (!NT_STATUS_IS_OK(status)) {
2900 goto done;
2902 if (!NT_STATUS_IS_OK(result) &&
2903 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2904 break;
2906 for (i = 0; i < num_entries; i++) {
2908 const char *description = NULL;
2910 if (c->opt_long_list_entries) {
2912 struct policy_handle alias_pol;
2913 union samr_AliasInfo *info = NULL;
2914 NTSTATUS _result;
2916 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2917 &domain_pol,
2918 0x8,
2919 groups->entries[i].idx,
2920 &alias_pol,
2921 &_result);
2922 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2923 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2924 &alias_pol,
2926 &info,
2927 &_result);
2928 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2929 status = dcerpc_samr_Close(b, mem_ctx,
2930 &alias_pol,
2931 &_result);
2932 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2933 description = info->description.string;
2939 if (description != NULL) {
2940 printf("%-21.21s %-50.50s\n",
2941 groups->entries[i].name.string,
2942 description);
2943 } else {
2944 printf("%s\n", groups->entries[i].name.string);
2947 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2948 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2949 /* Get builtin policy handle */
2951 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2952 &connect_pol,
2953 MAXIMUM_ALLOWED_ACCESS,
2954 discard_const_p(struct dom_sid2, &global_sid_Builtin),
2955 &domain_pol,
2956 &result);
2957 if (!NT_STATUS_IS_OK(status)) {
2958 goto done;
2960 if (!NT_STATUS_IS_OK(result)) {
2961 status = result;
2962 goto done;
2965 /* query builtin aliases */
2966 start_idx = 0;
2967 do {
2968 if (!builtin) break;
2970 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2971 &domain_pol,
2972 &start_idx,
2973 &groups,
2974 max_entries,
2975 &num_entries,
2976 &result);
2977 if (!NT_STATUS_IS_OK(status)) {
2978 break;
2980 if (!NT_STATUS_IS_OK(result) &&
2981 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2982 status = result;
2983 break;
2986 for (i = 0; i < num_entries; i++) {
2988 const char *description = NULL;
2990 if (c->opt_long_list_entries) {
2992 struct policy_handle alias_pol;
2993 union samr_AliasInfo *info = NULL;
2994 NTSTATUS _result;
2996 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2997 &domain_pol,
2998 0x8,
2999 groups->entries[i].idx,
3000 &alias_pol,
3001 &_result);
3002 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3003 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
3004 &alias_pol,
3006 &info,
3007 &_result);
3008 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3009 status = dcerpc_samr_Close(b, mem_ctx,
3010 &alias_pol,
3011 &_result);
3012 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3013 description = info->description.string;
3019 if (description != NULL) {
3020 printf("%-21.21s %-50.50s\n",
3021 groups->entries[i].name.string,
3022 description);
3023 } else {
3024 printf("%s\n", groups->entries[i].name.string);
3027 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3029 status = result;
3031 done:
3032 return status;
3035 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
3037 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3038 rpc_group_list_internals,
3039 argc, argv);
3042 static NTSTATUS rpc_list_group_members(struct net_context *c,
3043 struct rpc_pipe_client *pipe_hnd,
3044 TALLOC_CTX *mem_ctx,
3045 const char *domain_name,
3046 const struct dom_sid *domain_sid,
3047 struct policy_handle *domain_pol,
3048 uint32_t rid)
3050 NTSTATUS result, status;
3051 struct policy_handle group_pol;
3052 uint32_t num_members, *group_rids;
3053 int i;
3054 struct samr_RidAttrArray *rids = NULL;
3055 struct lsa_Strings names;
3056 struct samr_Ids types;
3057 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3059 status = dcerpc_samr_OpenGroup(b, mem_ctx,
3060 domain_pol,
3061 MAXIMUM_ALLOWED_ACCESS,
3062 rid,
3063 &group_pol,
3064 &result);
3065 if (!NT_STATUS_IS_OK(status)) {
3066 return status;
3068 if (!NT_STATUS_IS_OK(result)) {
3069 return result;
3072 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
3073 &group_pol,
3074 &rids,
3075 &result);
3076 if (!NT_STATUS_IS_OK(status)) {
3077 return status;
3079 if (!NT_STATUS_IS_OK(result)) {
3080 return result;
3083 num_members = rids->count;
3084 group_rids = rids->rids;
3086 while (num_members > 0) {
3087 int this_time = 512;
3089 if (num_members < this_time)
3090 this_time = num_members;
3092 status = dcerpc_samr_LookupRids(b, mem_ctx,
3093 domain_pol,
3094 this_time,
3095 group_rids,
3096 &names,
3097 &types,
3098 &result);
3099 if (!NT_STATUS_IS_OK(status)) {
3100 return status;
3102 if (!NT_STATUS_IS_OK(result)) {
3103 return result;
3105 if (names.count != this_time) {
3106 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3108 if (types.count != this_time) {
3109 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3111 /* We only have users as members, but make the output
3112 the same as the output of alias members */
3114 for (i = 0; i < this_time; i++) {
3116 if (c->opt_long_list_entries) {
3117 struct dom_sid sid;
3118 struct dom_sid_buf sid_str;
3120 sid_compose(&sid, domain_sid, group_rids[i]);
3122 printf("%s %s\\%s %d\n",
3123 dom_sid_str_buf(&sid, &sid_str),
3124 domain_name,
3125 names.names[i].string,
3126 SID_NAME_USER);
3127 } else {
3128 printf("%s\\%s\n", domain_name,
3129 names.names[i].string);
3133 num_members -= this_time;
3134 group_rids += 512;
3137 return NT_STATUS_OK;
3140 static NTSTATUS rpc_list_alias_members(struct net_context *c,
3141 struct rpc_pipe_client *pipe_hnd,
3142 struct cli_state *cli,
3143 TALLOC_CTX *mem_ctx,
3144 struct policy_handle *domain_pol,
3145 uint32_t rid)
3147 NTSTATUS result, status;
3148 struct rpc_pipe_client *lsa_pipe;
3149 struct policy_handle alias_pol, lsa_pol;
3150 uint32_t num_members;
3151 struct dom_sid *alias_sids;
3152 char **domains;
3153 char **names;
3154 enum lsa_SidType *types;
3155 int i;
3156 struct lsa_SidArray sid_array;
3157 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3159 status = dcerpc_samr_OpenAlias(b, mem_ctx,
3160 domain_pol,
3161 MAXIMUM_ALLOWED_ACCESS,
3162 rid,
3163 &alias_pol,
3164 &result);
3165 if (!NT_STATUS_IS_OK(status)) {
3166 return status;
3168 if (!NT_STATUS_IS_OK(result)) {
3169 return result;
3172 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
3173 &alias_pol,
3174 &sid_array,
3175 &result);
3176 if (!NT_STATUS_IS_OK(status)) {
3177 d_fprintf(stderr, _("Couldn't list alias members\n"));
3178 return status;
3180 if (!NT_STATUS_IS_OK(result)) {
3181 d_fprintf(stderr, _("Couldn't list alias members\n"));
3182 return result;
3185 num_members = sid_array.num_sids;
3187 if (num_members == 0) {
3188 return NT_STATUS_OK;
3191 result = cli_rpc_pipe_open_noauth(cli,
3192 &ndr_table_lsarpc,
3193 &lsa_pipe);
3194 if (!NT_STATUS_IS_OK(result)) {
3195 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
3196 nt_errstr(result) );
3197 return result;
3200 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
3201 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
3203 if (!NT_STATUS_IS_OK(result)) {
3204 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
3205 TALLOC_FREE(lsa_pipe);
3206 return result;
3209 alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
3210 if (!alias_sids) {
3211 d_fprintf(stderr, _("Out of memory\n"));
3212 TALLOC_FREE(lsa_pipe);
3213 return NT_STATUS_NO_MEMORY;
3216 for (i=0; i<num_members; i++) {
3217 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
3220 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
3221 num_members, alias_sids,
3222 &domains, &names, &types);
3224 if (!NT_STATUS_IS_OK(result) &&
3225 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3226 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
3227 TALLOC_FREE(lsa_pipe);
3228 return result;
3231 for (i = 0; i < num_members; i++) {
3232 struct dom_sid_buf sid_str;
3233 dom_sid_str_buf(&alias_sids[i], &sid_str);
3235 if (c->opt_long_list_entries) {
3236 printf("%s %s\\%s %d\n", sid_str.buf,
3237 domains[i] ? domains[i] : _("*unknown*"),
3238 names[i] ? names[i] : _("*unknown*"), types[i]);
3239 } else {
3240 if (domains[i])
3241 printf("%s\\%s\n", domains[i], names[i]);
3242 else
3243 printf("%s\n", sid_str.buf);
3247 TALLOC_FREE(lsa_pipe);
3248 return NT_STATUS_OK;
3251 static NTSTATUS rpc_group_members_internals(struct net_context *c,
3252 const struct dom_sid *domain_sid,
3253 const char *domain_name,
3254 struct cli_state *cli,
3255 struct rpc_pipe_client *pipe_hnd,
3256 TALLOC_CTX *mem_ctx,
3257 int argc,
3258 const char **argv)
3260 NTSTATUS result, status;
3261 struct policy_handle connect_pol, domain_pol;
3262 struct samr_Ids rids, rid_types;
3263 struct lsa_String lsa_acct_name;
3264 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3266 /* Get sam policy handle */
3268 status = dcerpc_samr_Connect2(b, mem_ctx,
3269 pipe_hnd->desthost,
3270 MAXIMUM_ALLOWED_ACCESS,
3271 &connect_pol,
3272 &result);
3273 if (!NT_STATUS_IS_OK(status)) {
3274 return status;
3276 if (!NT_STATUS_IS_OK(result)) {
3277 return result;
3280 /* Get domain policy handle */
3282 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3283 &connect_pol,
3284 MAXIMUM_ALLOWED_ACCESS,
3285 discard_const_p(struct dom_sid2, domain_sid),
3286 &domain_pol,
3287 &result);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 return status;
3291 if (!NT_STATUS_IS_OK(result)) {
3292 return result;
3295 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3297 status = dcerpc_samr_LookupNames(b, mem_ctx,
3298 &domain_pol,
3300 &lsa_acct_name,
3301 &rids,
3302 &rid_types,
3303 &result);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 return status;
3308 if (!NT_STATUS_IS_OK(result)) {
3310 /* Ok, did not find it in the global sam, try with builtin */
3312 struct dom_sid sid_Builtin;
3314 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3316 sid_copy(&sid_Builtin, &global_sid_Builtin);
3318 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3319 &connect_pol,
3320 MAXIMUM_ALLOWED_ACCESS,
3321 &sid_Builtin,
3322 &domain_pol,
3323 &result);
3324 if (!NT_STATUS_IS_OK(status)) {
3325 return status;
3327 if (!NT_STATUS_IS_OK(result)) {
3328 d_fprintf(stderr, _("Couldn't find group %s\n"),
3329 argv[0]);
3330 return result;
3333 status = dcerpc_samr_LookupNames(b, mem_ctx,
3334 &domain_pol,
3336 &lsa_acct_name,
3337 &rids,
3338 &rid_types,
3339 &result);
3340 if (!NT_STATUS_IS_OK(status)) {
3341 return status;
3343 if (!NT_STATUS_IS_OK(result)) {
3344 d_fprintf(stderr, _("Couldn't find group %s\n"),
3345 argv[0]);
3346 return result;
3350 if (rids.count != 1) {
3351 d_fprintf(stderr, _("Couldn't find group %s\n"),
3352 argv[0]);
3353 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3355 if (rid_types.count != 1) {
3356 d_fprintf(stderr, _("Couldn't find group %s\n"),
3357 argv[0]);
3358 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3362 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3363 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3364 domain_sid, &domain_pol,
3365 rids.ids[0]);
3368 if (rid_types.ids[0] == SID_NAME_ALIAS) {
3369 return rpc_list_alias_members(c, pipe_hnd, cli, mem_ctx, &domain_pol,
3370 rids.ids[0]);
3373 return NT_STATUS_NO_SUCH_GROUP;
3376 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3378 if (argc != 1 || c->display_usage) {
3379 return rpc_group_usage(c, argc, argv);
3382 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3383 rpc_group_members_internals,
3384 argc, argv);
3387 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3389 NET_API_STATUS status;
3390 struct GROUP_INFO_0 g0;
3391 uint32_t parm_err;
3393 if (argc != 2) {
3394 d_printf(_("Usage:\n"));
3395 d_printf("net rpc group rename group newname\n");
3396 return -1;
3399 g0.grpi0_name = argv[1];
3401 status = NetGroupSetInfo(c->opt_host,
3402 argv[0],
3404 (uint8_t *)&g0,
3405 &parm_err);
3407 if (status != 0) {
3408 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3409 argv[0], libnetapi_get_error_string(c->netapi_ctx,
3410 status));
3411 return -1;
3414 return 0;
3417 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3419 if (argc != 2 || c->display_usage) {
3420 return rpc_group_usage(c, argc, argv);
3423 return rpc_group_rename_internals(c, argc, argv);
3427 * 'net rpc group' entrypoint.
3428 * @param argc Standard main() style argc.
3429 * @param argv Standard main() style argv. Initial components are already
3430 * stripped.
3433 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3435 NET_API_STATUS status;
3437 struct functable func[] = {
3439 "add",
3440 rpc_group_add,
3441 NET_TRANSPORT_RPC,
3442 N_("Create specified group"),
3443 N_("net rpc group add\n"
3444 " Create specified group")
3447 "delete",
3448 rpc_group_delete,
3449 NET_TRANSPORT_RPC,
3450 N_("Delete specified group"),
3451 N_("net rpc group delete\n"
3452 " Delete specified group")
3455 "addmem",
3456 rpc_group_addmem,
3457 NET_TRANSPORT_RPC,
3458 N_("Add member to group"),
3459 N_("net rpc group addmem\n"
3460 " Add member to group")
3463 "delmem",
3464 rpc_group_delmem,
3465 NET_TRANSPORT_RPC,
3466 N_("Remove member from group"),
3467 N_("net rpc group delmem\n"
3468 " Remove member from group")
3471 "list",
3472 rpc_group_list,
3473 NET_TRANSPORT_RPC,
3474 N_("List groups"),
3475 N_("net rpc group list\n"
3476 " List groups")
3479 "members",
3480 rpc_group_members,
3481 NET_TRANSPORT_RPC,
3482 N_("List group members"),
3483 N_("net rpc group members\n"
3484 " List group members")
3487 "rename",
3488 rpc_group_rename,
3489 NET_TRANSPORT_RPC,
3490 N_("Rename group"),
3491 N_("net rpc group rename\n"
3492 " Rename group")
3494 {NULL, NULL, 0, NULL, NULL}
3497 status = libnetapi_net_init(&c->netapi_ctx);
3498 if (status != 0) {
3499 return -1;
3501 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3502 libnetapi_set_password(c->netapi_ctx, c->opt_password);
3503 if (c->opt_kerberos) {
3504 libnetapi_set_use_kerberos(c->netapi_ctx);
3507 if (argc == 0) {
3508 if (c->display_usage) {
3509 d_printf(_("Usage:\n"));
3510 d_printf(_("net rpc group\n"
3511 " Alias for net rpc group list global "
3512 "local builtin\n"));
3513 net_display_usage_from_functable(func);
3514 return 0;
3517 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3518 rpc_group_list_internals,
3519 argc, argv);
3522 return net_run_function(c, argc, argv, "net rpc group", func);
3525 /****************************************************************************/
3527 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3529 return net_share_usage(c, argc, argv);
3533 * Add a share on a remote RPC server.
3535 * @param argc Standard main() style argc.
3536 * @param argv Standard main() style argv. Initial components are already
3537 * stripped.
3539 * @return A shell status integer (0 for success).
3542 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3544 NET_API_STATUS status;
3545 char *sharename;
3546 char *path;
3547 uint32_t type = STYPE_DISKTREE; /* only allow disk shares to be added */
3548 uint32_t num_users=0, perms=0;
3549 char *password=NULL; /* don't allow a share password */
3550 struct SHARE_INFO_2 i2;
3551 uint32_t parm_error = 0;
3553 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3554 return rpc_share_usage(c, argc, argv);
3557 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3558 return -1;
3561 path = strchr(sharename, '=');
3562 if (!path) {
3563 return -1;
3566 *path++ = '\0';
3568 i2.shi2_netname = sharename;
3569 i2.shi2_type = type;
3570 i2.shi2_remark = c->opt_comment;
3571 i2.shi2_permissions = perms;
3572 i2.shi2_max_uses = c->opt_maxusers;
3573 i2.shi2_current_uses = num_users;
3574 i2.shi2_path = path;
3575 i2.shi2_passwd = password;
3577 status = NetShareAdd(c->opt_host,
3579 (uint8_t *)&i2,
3580 &parm_error);
3581 if (status != 0) {
3582 printf(_("NetShareAdd failed with: %s\n"),
3583 libnetapi_get_error_string(c->netapi_ctx, status));
3586 return status;
3590 * Delete a share on a remote RPC server.
3592 * @param domain_sid The domain sid acquired from the remote server.
3593 * @param argc Standard main() style argc.
3594 * @param argv Standard main() style argv. Initial components are already
3595 * stripped.
3597 * @return A shell status integer (0 for success).
3599 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3601 if (argc < 1 || c->display_usage) {
3602 return rpc_share_usage(c, argc, argv);
3605 return NetShareDel(c->opt_host, argv[0], 0);
3609 * Formatted print of share info
3611 * @param r pointer to SHARE_INFO_1 to format
3614 static void display_share_info_1(struct net_context *c,
3615 struct SHARE_INFO_1 *r)
3617 if (c->opt_long_list_entries) {
3618 d_printf("%-12s %-8.8s %-50s\n",
3619 r->shi1_netname,
3620 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3621 r->shi1_remark);
3622 } else {
3623 d_printf("%s\n", r->shi1_netname);
3627 static WERROR get_share_info(struct net_context *c,
3628 struct rpc_pipe_client *pipe_hnd,
3629 TALLOC_CTX *mem_ctx,
3630 uint32_t level,
3631 int argc,
3632 const char **argv,
3633 struct srvsvc_NetShareInfoCtr *info_ctr)
3635 WERROR result;
3636 NTSTATUS status;
3637 union srvsvc_NetShareInfo info;
3638 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3640 /* no specific share requested, enumerate all */
3641 if (argc == 0) {
3643 uint32_t preferred_len = 0xffffffff;
3644 uint32_t total_entries = 0;
3645 uint32_t resume_handle = 0;
3647 info_ctr->level = level;
3649 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3650 pipe_hnd->desthost,
3651 info_ctr,
3652 preferred_len,
3653 &total_entries,
3654 &resume_handle,
3655 &result);
3656 if (!NT_STATUS_IS_OK(status)) {
3657 return ntstatus_to_werror(status);
3659 return result;
3662 /* request just one share */
3663 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3664 pipe_hnd->desthost,
3665 argv[0],
3666 level,
3667 &info,
3668 &result);
3670 if (!NT_STATUS_IS_OK(status)) {
3671 result = ntstatus_to_werror(status);
3672 goto done;
3675 if (!W_ERROR_IS_OK(result)) {
3676 goto done;
3679 /* construct ctr */
3680 ZERO_STRUCTP(info_ctr);
3682 info_ctr->level = level;
3684 switch (level) {
3685 case 1:
3687 struct srvsvc_NetShareCtr1 *ctr1;
3689 ctr1 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr1);
3690 W_ERROR_HAVE_NO_MEMORY(ctr1);
3692 ctr1->count = 1;
3693 ctr1->array = info.info1;
3695 info_ctr->ctr.ctr1 = ctr1;
3697 break;
3699 case 2:
3701 struct srvsvc_NetShareCtr2 *ctr2;
3703 ctr2 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr2);
3704 W_ERROR_HAVE_NO_MEMORY(ctr2);
3706 ctr2->count = 1;
3707 ctr2->array = info.info2;
3709 info_ctr->ctr.ctr2 = ctr2;
3711 break;
3713 case 502:
3715 struct srvsvc_NetShareCtr502 *ctr502;
3717 ctr502 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr502);
3718 W_ERROR_HAVE_NO_MEMORY(ctr502);
3720 ctr502->count = 1;
3721 ctr502->array = info.info502;
3723 info_ctr->ctr.ctr502 = ctr502;
3725 break;
3727 } /* switch */
3728 done:
3729 return result;
3732 /***
3733 * 'net rpc share list' entrypoint.
3734 * @param argc Standard main() style argc.
3735 * @param argv Standard main() style argv. Initial components are already
3736 * stripped.
3738 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3740 NET_API_STATUS status;
3741 struct SHARE_INFO_1 *i1 = NULL;
3742 uint32_t entries_read = 0;
3743 uint32_t total_entries = 0;
3744 uint32_t resume_handle = 0;
3745 uint32_t i, level = 1;
3747 if (c->display_usage) {
3748 d_printf( "%s\n"
3749 "net rpc share list\n"
3750 " %s\n",
3751 _("Usage:"),
3752 _("List shares on remote server"));
3753 return 0;
3756 status = NetShareEnum(c->opt_host,
3757 level,
3758 (uint8_t **)(void *)&i1,
3759 (uint32_t)-1,
3760 &entries_read,
3761 &total_entries,
3762 &resume_handle);
3763 if (status != 0) {
3764 goto done;
3767 /* Display results */
3769 if (c->opt_long_list_entries) {
3770 d_printf(_(
3771 "\nEnumerating shared resources (exports) on remote server:\n\n"
3772 "\nShare name Type Description\n"
3773 "---------- ---- -----------\n"));
3775 for (i = 0; i < entries_read; i++)
3776 display_share_info_1(c, &i1[i]);
3777 done:
3778 return status;
3781 static bool check_share_availability(struct cli_state *cli, const char *netname)
3783 NTSTATUS status;
3785 status = cli_tree_connect(cli, netname, "A:", NULL);
3786 if (!NT_STATUS_IS_OK(status)) {
3787 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3788 return false;
3791 status = cli_tdis(cli);
3792 if (!NT_STATUS_IS_OK(status)) {
3793 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3794 return false;
3797 return true;
3800 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3801 const char *netname, uint32_t type)
3803 /* only support disk shares */
3804 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3805 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3806 type);
3807 return false;
3810 /* skip builtin shares */
3811 /* FIXME: should print$ be added too ? */
3812 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3813 strequal(netname,"global"))
3814 return false;
3816 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3817 printf(_("excluding [%s]\n"), netname);
3818 return false;
3821 return check_share_availability(cli, netname);
3825 * Migrate shares from a remote RPC server to the local RPC server.
3827 * All parameters are provided by the run_rpc_command function, except for
3828 * argc, argv which are passed through.
3830 * @param domain_sid The domain sid acquired from the remote server.
3831 * @param cli A cli_state connected to the server.
3832 * @param mem_ctx Talloc context, destroyed on completion of the function.
3833 * @param argc Standard main() style argc.
3834 * @param argv Standard main() style argv. Initial components are already
3835 * stripped.
3837 * @return Normal NTSTATUS return.
3840 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3841 const struct dom_sid *domain_sid,
3842 const char *domain_name,
3843 struct cli_state *cli,
3844 struct rpc_pipe_client *pipe_hnd,
3845 TALLOC_CTX *mem_ctx,
3846 int argc,
3847 const char **argv)
3849 WERROR result;
3850 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3851 struct srvsvc_NetShareInfoCtr ctr_src;
3852 uint32_t i;
3853 struct rpc_pipe_client *srvsvc_pipe = NULL;
3854 struct cli_state *cli_dst = NULL;
3855 uint32_t level = 502; /* includes secdesc */
3856 uint32_t parm_error = 0;
3857 struct dcerpc_binding_handle *b;
3859 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3860 &ctr_src);
3861 if (!W_ERROR_IS_OK(result))
3862 goto done;
3864 /* connect destination PI_SRVSVC */
3865 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3866 &ndr_table_srvsvc);
3867 if (!NT_STATUS_IS_OK(nt_status))
3868 return nt_status;
3870 b = srvsvc_pipe->binding_handle;
3872 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3874 union srvsvc_NetShareInfo info;
3875 struct srvsvc_NetShareInfo502 info502 =
3876 ctr_src.ctr.ctr502->array[i];
3878 /* reset error-code */
3879 nt_status = NT_STATUS_UNSUCCESSFUL;
3881 if (!check_share_sanity(c, cli, info502.name, info502.type))
3882 continue;
3884 /* finally add the share on the dst server */
3886 printf(_("migrating: [%s], path: %s, comment: %s, without "
3887 "share-ACLs\n"),
3888 info502.name, info502.path, info502.comment);
3890 info.info502 = &info502;
3892 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3893 srvsvc_pipe->desthost,
3894 502,
3895 &info,
3896 &parm_error,
3897 &result);
3898 if (!NT_STATUS_IS_OK(nt_status)) {
3899 printf(_("cannot add share: %s\n"),
3900 nt_errstr(nt_status));
3901 goto done;
3903 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3904 printf(_(" [%s] does already exist\n"),
3905 info502.name);
3906 continue;
3909 if (!W_ERROR_IS_OK(result)) {
3910 nt_status = werror_to_ntstatus(result);
3911 printf(_("cannot add share: %s\n"),
3912 win_errstr(result));
3913 goto done;
3918 nt_status = NT_STATUS_OK;
3920 done:
3921 if (cli_dst) {
3922 cli_shutdown(cli_dst);
3925 return nt_status;
3930 * Migrate shares from a RPC server to another.
3932 * @param argc Standard main() style argc.
3933 * @param argv Standard main() style argv. Initial components are already
3934 * stripped.
3936 * @return A shell status integer (0 for success).
3938 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3939 const char **argv)
3941 if (c->display_usage) {
3942 d_printf( "%s\n"
3943 "net rpc share migrate shares\n"
3944 " %s\n",
3945 _("Usage:"),
3946 _("Migrate shares to local server"));
3947 return 0;
3950 if (!c->opt_host) {
3951 printf(_("no server to migrate\n"));
3952 return -1;
3955 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
3956 rpc_share_migrate_shares_internals,
3957 argc, argv);
3961 * Copy a file/dir
3963 * @param f file_info
3964 * @param mask current search mask
3965 * @param state arg-pointer
3968 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3969 const char *mask, void *state)
3971 static NTSTATUS nt_status;
3972 static struct copy_clistate *local_state;
3973 static fstring filename, new_mask;
3974 fstring dir;
3975 char *old_dir;
3976 struct net_context *c;
3978 local_state = (struct copy_clistate *)state;
3979 nt_status = NT_STATUS_UNSUCCESSFUL;
3981 c = local_state->c;
3983 if (strequal(f->name, ".") || strequal(f->name, ".."))
3984 return NT_STATUS_OK;
3986 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3988 /* DIRECTORY */
3989 if (f->mode & FILE_ATTRIBUTE_DIRECTORY) {
3991 DEBUG(3,("got dir: %s\n", f->name));
3993 fstrcpy(dir, local_state->cwd);
3994 fstrcat(dir, "\\");
3995 fstrcat(dir, f->name);
3997 switch (net_mode_share)
3999 case NET_MODE_SHARE_MIGRATE:
4000 /* create that directory */
4001 nt_status = net_copy_file(c, local_state->mem_ctx,
4002 local_state->cli_share_src,
4003 local_state->cli_share_dst,
4004 dir, dir,
4005 c->opt_acls? true : false,
4006 c->opt_attrs? true : false,
4007 c->opt_timestamps? true:false,
4008 false);
4009 break;
4010 default:
4011 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
4012 return NT_STATUS_INTERNAL_ERROR;
4015 if (!NT_STATUS_IS_OK(nt_status)) {
4016 printf(_("could not handle dir %s: %s\n"),
4017 dir, nt_errstr(nt_status));
4018 return nt_status;
4021 /* search below that directory */
4022 if (strlcpy(new_mask, dir, sizeof(new_mask)) >= sizeof(new_mask)) {
4023 return NT_STATUS_NO_MEMORY;
4025 if (strlcat(new_mask, "\\*", sizeof(new_mask)) >= sizeof(new_mask)) {
4026 return NT_STATUS_NO_MEMORY;
4029 old_dir = local_state->cwd;
4030 local_state->cwd = dir;
4031 nt_status = sync_files(local_state, new_mask);
4032 if (!NT_STATUS_IS_OK(nt_status)) {
4033 printf(_("could not handle files\n"));
4035 local_state->cwd = old_dir;
4037 return nt_status;
4041 /* FILE */
4042 fstrcpy(filename, local_state->cwd);
4043 fstrcat(filename, "\\");
4044 fstrcat(filename, f->name);
4046 DEBUG(3,("got file: %s\n", filename));
4048 switch (net_mode_share)
4050 case NET_MODE_SHARE_MIGRATE:
4051 nt_status = net_copy_file(c, local_state->mem_ctx,
4052 local_state->cli_share_src,
4053 local_state->cli_share_dst,
4054 filename, filename,
4055 c->opt_acls? true : false,
4056 c->opt_attrs? true : false,
4057 c->opt_timestamps? true: false,
4058 true);
4059 break;
4060 default:
4061 d_fprintf(stderr, _("Unsupported file mode %d\n"),
4062 net_mode_share);
4063 return NT_STATUS_INTERNAL_ERROR;
4066 if (!NT_STATUS_IS_OK(nt_status))
4067 printf(_("could not handle file %s: %s\n"),
4068 filename, nt_errstr(nt_status));
4069 return nt_status;
4073 * sync files, can be called recursively to list files
4074 * and then call copy_fn for each file
4076 * @param cp_clistate pointer to the copy_clistate we work with
4077 * @param mask the current search mask
4079 * @return Boolean result
4081 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
4083 struct cli_state *targetcli;
4084 char *targetpath = NULL;
4085 NTSTATUS status;
4087 DEBUG(3,("calling cli_list with mask: %s\n", mask));
4089 status = cli_resolve_path(talloc_tos(), "", NULL,
4090 cp_clistate->cli_share_src,
4091 mask, &targetcli, &targetpath);
4092 if (!NT_STATUS_IS_OK(status)) {
4093 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
4094 "%s\n"),
4095 mask, nt_errstr(status));
4096 return status;
4099 status = cli_list(targetcli, targetpath, cp_clistate->attribute,
4100 copy_fn, cp_clistate);
4101 if (!NT_STATUS_IS_OK(status)) {
4102 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
4103 mask, nt_errstr(status));
4106 return status;
4111 * Set the top level directory permissions before we do any further copies.
4112 * Should set up ACL inheritance.
4115 bool copy_top_level_perms(struct net_context *c,
4116 struct copy_clistate *cp_clistate,
4117 const char *sharename)
4119 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4121 switch (net_mode_share) {
4122 case NET_MODE_SHARE_MIGRATE:
4123 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
4124 nt_status = net_copy_fileattr(c,
4125 cp_clistate->mem_ctx,
4126 cp_clistate->cli_share_src,
4127 cp_clistate->cli_share_dst,
4128 "\\", "\\",
4129 c->opt_acls? true : false,
4130 c->opt_attrs? true : false,
4131 c->opt_timestamps? true: false,
4132 false);
4133 break;
4134 default:
4135 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
4136 break;
4139 if (!NT_STATUS_IS_OK(nt_status)) {
4140 printf(_("Could handle directory attributes for top level "
4141 "directory of share %s. Error %s\n"),
4142 sharename, nt_errstr(nt_status));
4143 return false;
4146 return true;
4150 * Sync all files inside a remote share to another share (over smb).
4152 * All parameters are provided by the run_rpc_command function, except for
4153 * argc, argv which are passed through.
4155 * @param domain_sid The domain sid acquired from the remote server.
4156 * @param cli A cli_state connected to the server.
4157 * @param mem_ctx Talloc context, destroyed on completion of the function.
4158 * @param argc Standard main() style argc.
4159 * @param argv Standard main() style argv. Initial components are already
4160 * stripped.
4162 * @return Normal NTSTATUS return.
4165 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
4166 const struct dom_sid *domain_sid,
4167 const char *domain_name,
4168 struct cli_state *cli,
4169 struct rpc_pipe_client *pipe_hnd,
4170 TALLOC_CTX *mem_ctx,
4171 int argc,
4172 const char **argv)
4174 WERROR result;
4175 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4176 struct srvsvc_NetShareInfoCtr ctr_src;
4177 uint32_t i;
4178 uint32_t level = 502;
4179 struct copy_clistate cp_clistate;
4180 bool got_src_share = false;
4181 bool got_dst_share = false;
4182 const char *mask = "\\*";
4183 char *dst = NULL;
4185 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
4186 if (dst == NULL) {
4187 nt_status = NT_STATUS_NO_MEMORY;
4188 goto done;
4191 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4192 &ctr_src);
4194 if (!W_ERROR_IS_OK(result))
4195 goto done;
4197 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4199 struct srvsvc_NetShareInfo502 info502 =
4200 ctr_src.ctr.ctr502->array[i];
4202 if (!check_share_sanity(c, cli, info502.name, info502.type))
4203 continue;
4205 /* one might not want to mirror whole discs :) */
4206 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
4207 d_printf(_("skipping [%s]: builtin/hidden share\n"),
4208 info502.name);
4209 continue;
4212 switch (net_mode_share)
4214 case NET_MODE_SHARE_MIGRATE:
4215 printf("syncing");
4216 break;
4217 default:
4218 d_fprintf(stderr, _("Unsupported mode %d\n"),
4219 net_mode_share);
4220 break;
4222 printf(_(" [%s] files and directories %s ACLs, %s DOS "
4223 "Attributes %s\n"),
4224 info502.name,
4225 c->opt_acls ? _("including") : _("without"),
4226 c->opt_attrs ? _("including") : _("without"),
4227 c->opt_timestamps ? _("(preserving timestamps)") : "");
4229 cp_clistate.mem_ctx = mem_ctx;
4230 cp_clistate.cli_share_src = NULL;
4231 cp_clistate.cli_share_dst = NULL;
4232 cp_clistate.cwd = NULL;
4233 cp_clistate.attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
4234 cp_clistate.c = c;
4236 /* open share source */
4237 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
4238 smbXcli_conn_remote_sockaddr(cli->conn),
4239 smbXcli_conn_remote_name(cli->conn),
4240 info502.name, "A:");
4241 if (!NT_STATUS_IS_OK(nt_status))
4242 goto done;
4244 got_src_share = true;
4246 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
4247 /* open share destination */
4248 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
4249 NULL, dst, info502.name, "A:");
4250 if (!NT_STATUS_IS_OK(nt_status))
4251 goto done;
4253 got_dst_share = true;
4256 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
4257 d_fprintf(stderr, _("Could not handle the top level "
4258 "directory permissions for the "
4259 "share: %s\n"), info502.name);
4260 nt_status = NT_STATUS_UNSUCCESSFUL;
4261 goto done;
4264 nt_status = sync_files(&cp_clistate, mask);
4265 if (!NT_STATUS_IS_OK(nt_status)) {
4266 d_fprintf(stderr, _("could not handle files for share: "
4267 "%s\n"), info502.name);
4268 goto done;
4272 nt_status = NT_STATUS_OK;
4274 done:
4276 if (got_src_share)
4277 cli_shutdown(cp_clistate.cli_share_src);
4279 if (got_dst_share)
4280 cli_shutdown(cp_clistate.cli_share_dst);
4282 SAFE_FREE(dst);
4283 return nt_status;
4287 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
4289 if (c->display_usage) {
4290 d_printf( "%s\n"
4291 "net share migrate files\n"
4292 " %s\n",
4293 _("Usage:"),
4294 _("Migrate files to local server"));
4295 return 0;
4298 if (!c->opt_host) {
4299 d_printf(_("no server to migrate\n"));
4300 return -1;
4303 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4304 rpc_share_migrate_files_internals,
4305 argc, argv);
4309 * Migrate share-ACLs from a remote RPC server to the local RPC server.
4311 * All parameters are provided by the run_rpc_command function, except for
4312 * argc, argv which are passed through.
4314 * @param domain_sid The domain sid acquired from the remote server.
4315 * @param cli A cli_state connected to the server.
4316 * @param mem_ctx Talloc context, destroyed on completion of the function.
4317 * @param argc Standard main() style argc.
4318 * @param argv Standard main() style argv. Initial components are already
4319 * stripped.
4321 * @return Normal NTSTATUS return.
4324 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
4325 const struct dom_sid *domain_sid,
4326 const char *domain_name,
4327 struct cli_state *cli,
4328 struct rpc_pipe_client *pipe_hnd,
4329 TALLOC_CTX *mem_ctx,
4330 int argc,
4331 const char **argv)
4333 WERROR result;
4334 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4335 struct srvsvc_NetShareInfoCtr ctr_src;
4336 union srvsvc_NetShareInfo info;
4337 uint32_t i;
4338 struct rpc_pipe_client *srvsvc_pipe = NULL;
4339 struct cli_state *cli_dst = NULL;
4340 uint32_t level = 502; /* includes secdesc */
4341 uint32_t parm_error = 0;
4342 struct dcerpc_binding_handle *b;
4344 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4345 &ctr_src);
4347 if (!W_ERROR_IS_OK(result))
4348 goto done;
4350 /* connect destination PI_SRVSVC */
4351 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
4352 &ndr_table_srvsvc);
4353 if (!NT_STATUS_IS_OK(nt_status))
4354 return nt_status;
4356 b = srvsvc_pipe->binding_handle;
4358 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4360 struct srvsvc_NetShareInfo502 info502 =
4361 ctr_src.ctr.ctr502->array[i];
4363 /* reset error-code */
4364 nt_status = NT_STATUS_UNSUCCESSFUL;
4366 if (!check_share_sanity(c, cli, info502.name, info502.type))
4367 continue;
4369 printf(_("migrating: [%s], path: %s, comment: %s, including "
4370 "share-ACLs\n"),
4371 info502.name, info502.path, info502.comment);
4373 if (c->opt_verbose)
4374 display_sec_desc(info502.sd_buf.sd);
4376 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4377 info.info502 = &info502;
4379 /* finally modify the share on the dst server */
4380 nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
4381 srvsvc_pipe->desthost,
4382 info502.name,
4383 level,
4384 &info,
4385 &parm_error,
4386 &result);
4387 if (!NT_STATUS_IS_OK(nt_status)) {
4388 printf(_("cannot set share-acl: %s\n"),
4389 nt_errstr(nt_status));
4390 goto done;
4392 if (!W_ERROR_IS_OK(result)) {
4393 nt_status = werror_to_ntstatus(result);
4394 printf(_("cannot set share-acl: %s\n"),
4395 win_errstr(result));
4396 goto done;
4401 nt_status = NT_STATUS_OK;
4403 done:
4404 if (cli_dst) {
4405 cli_shutdown(cli_dst);
4408 return nt_status;
4413 * Migrate share-acls from a RPC server to another.
4415 * @param argc Standard main() style argc.
4416 * @param argv Standard main() style argv. Initial components are already
4417 * stripped.
4419 * @return A shell status integer (0 for success).
4421 static int rpc_share_migrate_security(struct net_context *c, int argc,
4422 const char **argv)
4424 if (c->display_usage) {
4425 d_printf( "%s\n"
4426 "net rpc share migrate security\n"
4427 " %s\n",
4428 _("Usage:"),
4429 _("Migrate share-acls to local server"));
4430 return 0;
4433 if (!c->opt_host) {
4434 d_printf(_("no server to migrate\n"));
4435 return -1;
4438 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4439 rpc_share_migrate_security_internals,
4440 argc, argv);
4444 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4445 * from one server to another.
4447 * @param argc Standard main() style argc.
4448 * @param argv Standard main() style argv. Initial components are already
4449 * stripped.
4451 * @return A shell status integer (0 for success).
4454 static int rpc_share_migrate_all(struct net_context *c, int argc,
4455 const char **argv)
4457 int ret;
4459 if (c->display_usage) {
4460 d_printf( "%s\n"
4461 "net rpc share migrate all\n"
4462 " %s\n",
4463 _("Usage:"),
4464 _("Migrates shares including all share settings"));
4465 return 0;
4468 if (!c->opt_host) {
4469 d_printf(_("no server to migrate\n"));
4470 return -1;
4473 /* order is important. we don't want to be locked out by the share-acl
4474 * before copying files - gd */
4476 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4477 rpc_share_migrate_shares_internals, argc, argv);
4478 if (ret)
4479 return ret;
4481 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4482 rpc_share_migrate_files_internals, argc, argv);
4483 if (ret)
4484 return ret;
4486 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4487 rpc_share_migrate_security_internals, argc,
4488 argv);
4493 * 'net rpc share migrate' entrypoint.
4494 * @param argc Standard main() style argc.
4495 * @param argv Standard main() style argv. Initial components are already
4496 * stripped.
4498 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4501 struct functable func[] = {
4503 "all",
4504 rpc_share_migrate_all,
4505 NET_TRANSPORT_RPC,
4506 N_("Migrate shares from remote to local server"),
4507 N_("net rpc share migrate all\n"
4508 " Migrate shares from remote to local server")
4511 "files",
4512 rpc_share_migrate_files,
4513 NET_TRANSPORT_RPC,
4514 N_("Migrate files from remote to local server"),
4515 N_("net rpc share migrate files\n"
4516 " Migrate files from remote to local server")
4519 "security",
4520 rpc_share_migrate_security,
4521 NET_TRANSPORT_RPC,
4522 N_("Migrate share-ACLs from remote to local server"),
4523 N_("net rpc share migrate security\n"
4524 " Migrate share-ACLs from remote to local server")
4527 "shares",
4528 rpc_share_migrate_shares,
4529 NET_TRANSPORT_RPC,
4530 N_("Migrate shares from remote to local server"),
4531 N_("net rpc share migrate shares\n"
4532 " Migrate shares from remote to local server")
4534 {NULL, NULL, 0, NULL, NULL}
4537 net_mode_share = NET_MODE_SHARE_MIGRATE;
4539 return net_run_function(c, argc, argv, "net rpc share migrate", func);
4542 struct full_alias {
4543 struct dom_sid sid;
4544 uint32_t num_members;
4545 struct dom_sid *members;
4548 static int num_server_aliases;
4549 static struct full_alias *server_aliases;
4552 * Add an alias to the static list.
4554 static void push_alias(struct full_alias *alias)
4556 size_t array_size;
4558 if (server_aliases == NULL) {
4559 server_aliases = talloc_array(NULL, struct full_alias, 100);
4560 if (server_aliases == NULL) {
4561 smb_panic("talloc_array failed");
4565 array_size = talloc_array_length(server_aliases);
4566 if (array_size == num_server_aliases) {
4567 server_aliases = talloc_realloc(NULL, server_aliases,
4568 struct full_alias, array_size + 100);
4569 if (server_aliases == NULL) {
4570 smb_panic("talloc_realloc failed");
4574 server_aliases[num_server_aliases] = *alias;
4575 num_server_aliases += 1;
4579 * For a specific domain on the server, fetch all the aliases
4580 * and their members. Add all of them to the server_aliases.
4583 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4584 TALLOC_CTX *mem_ctx,
4585 struct policy_handle *connect_pol,
4586 const struct dom_sid *domain_sid)
4588 uint32_t start_idx, max_entries, num_entries, i;
4589 struct samr_SamArray *groups = NULL;
4590 NTSTATUS result, status;
4591 struct policy_handle domain_pol;
4592 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4594 /* Get domain policy handle */
4596 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4597 connect_pol,
4598 MAXIMUM_ALLOWED_ACCESS,
4599 discard_const_p(struct dom_sid2, domain_sid),
4600 &domain_pol,
4601 &result);
4602 if (!NT_STATUS_IS_OK(status)) {
4603 return status;
4605 if (!NT_STATUS_IS_OK(result)) {
4606 return result;
4609 start_idx = 0;
4610 max_entries = 250;
4612 do {
4613 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
4614 &domain_pol,
4615 &start_idx,
4616 &groups,
4617 max_entries,
4618 &num_entries,
4619 &result);
4620 if (!NT_STATUS_IS_OK(status)) {
4621 goto done;
4623 for (i = 0; i < num_entries; i++) {
4625 struct policy_handle alias_pol;
4626 struct full_alias alias;
4627 struct lsa_SidArray sid_array;
4628 int j;
4629 NTSTATUS _result;
4631 status = dcerpc_samr_OpenAlias(b, mem_ctx,
4632 &domain_pol,
4633 MAXIMUM_ALLOWED_ACCESS,
4634 groups->entries[i].idx,
4635 &alias_pol,
4636 &_result);
4637 if (!NT_STATUS_IS_OK(status)) {
4638 goto done;
4640 if (!NT_STATUS_IS_OK(_result)) {
4641 status = _result;
4642 goto done;
4645 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
4646 &alias_pol,
4647 &sid_array,
4648 &_result);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 goto done;
4652 if (!NT_STATUS_IS_OK(_result)) {
4653 status = _result;
4654 goto done;
4657 alias.num_members = sid_array.num_sids;
4659 status = dcerpc_samr_Close(b, mem_ctx, &alias_pol, &_result);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 goto done;
4663 if (!NT_STATUS_IS_OK(_result)) {
4664 status = _result;
4665 goto done;
4668 alias.members = NULL;
4670 if (alias.num_members > 0) {
4671 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4672 if (alias.members == NULL) {
4673 status = NT_STATUS_NO_MEMORY;
4674 goto done;
4677 for (j = 0; j < alias.num_members; j++)
4678 sid_copy(&alias.members[j],
4679 sid_array.sids[j].sid);
4682 sid_compose(&alias.sid, domain_sid,
4683 groups->entries[i].idx);
4685 push_alias(&alias);
4687 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4689 status = NT_STATUS_OK;
4691 done:
4692 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
4694 return status;
4698 * Dump server_aliases as names for debugging purposes.
4701 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4702 const struct dom_sid *domain_sid,
4703 const char *domain_name,
4704 struct cli_state *cli,
4705 struct rpc_pipe_client *pipe_hnd,
4706 TALLOC_CTX *mem_ctx,
4707 int argc,
4708 const char **argv)
4710 int i;
4711 NTSTATUS result;
4712 struct policy_handle lsa_pol;
4713 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4715 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4716 SEC_FLAG_MAXIMUM_ALLOWED,
4717 &lsa_pol);
4718 if (!NT_STATUS_IS_OK(result))
4719 return result;
4721 for (i=0; i<num_server_aliases; i++) {
4722 char **names;
4723 char **domains;
4724 enum lsa_SidType *types;
4725 int j;
4727 struct full_alias *alias = &server_aliases[i];
4729 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4730 &alias->sid,
4731 &domains, &names, &types);
4732 if (!NT_STATUS_IS_OK(result))
4733 continue;
4735 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4737 if (alias->num_members == 0) {
4738 DEBUG(1, ("\n"));
4739 continue;
4742 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4743 alias->num_members,
4744 alias->members,
4745 &domains, &names, &types);
4747 if (!NT_STATUS_IS_OK(result) &&
4748 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4749 continue;
4751 for (j=0; j<alias->num_members; j++)
4752 DEBUG(1, ("%s\\%s (%d); ",
4753 domains[j] ? domains[j] : "*unknown*",
4754 names[j] ? names[j] : "*unknown*",types[j]));
4755 DEBUG(1, ("\n"));
4758 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
4760 return NT_STATUS_OK;
4764 * Fetch a list of all server aliases and their members into
4765 * server_aliases.
4768 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4769 const struct dom_sid *domain_sid,
4770 const char *domain_name,
4771 struct cli_state *cli,
4772 struct rpc_pipe_client *pipe_hnd,
4773 TALLOC_CTX *mem_ctx,
4774 int argc,
4775 const char **argv)
4777 NTSTATUS result, status;
4778 struct policy_handle connect_pol;
4779 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4781 status = dcerpc_samr_Connect2(b, mem_ctx,
4782 pipe_hnd->desthost,
4783 MAXIMUM_ALLOWED_ACCESS,
4784 &connect_pol,
4785 &result);
4786 if (!NT_STATUS_IS_OK(status)) {
4787 goto done;
4789 if (!NT_STATUS_IS_OK(result)) {
4790 status = result;
4791 goto done;
4794 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4795 &global_sid_Builtin);
4796 if (!NT_STATUS_IS_OK(status)) {
4797 goto done;
4800 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4801 domain_sid);
4803 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
4804 done:
4805 return status;
4808 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4810 token->num_sids = 4;
4812 if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4813 d_fprintf(stderr, "malloc %s\n",_("failed"));
4814 token->num_sids = 0;
4815 return;
4818 token->sids[0] = *user_sid;
4819 sid_copy(&token->sids[1], &global_sid_World);
4820 sid_copy(&token->sids[2], &global_sid_Network);
4821 sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4824 static void free_user_token(struct security_token *token)
4826 SAFE_FREE(token->sids);
4829 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4831 if (security_token_has_sid(token, sid))
4832 return;
4834 token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4835 if (!token->sids) {
4836 return;
4839 sid_copy(&token->sids[token->num_sids], sid);
4841 token->num_sids += 1;
4844 struct user_token {
4845 fstring name;
4846 struct security_token token;
4849 static void dump_user_token(struct user_token *token)
4851 int i;
4853 d_printf("%s\n", token->name);
4855 for (i=0; i<token->token.num_sids; i++) {
4856 struct dom_sid_buf buf;
4857 d_printf(" %s\n",
4858 dom_sid_str_buf(&token->token.sids[i], &buf));
4862 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4864 int i;
4866 for (i=0; i<alias->num_members; i++) {
4867 if (dom_sid_equal(sid, &alias->members[i])) {
4868 return true;
4872 return false;
4875 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4877 int i;
4879 for (i=0; i<num_server_aliases; i++) {
4880 if (is_alias_member(&sid, &server_aliases[i]))
4881 add_sid_to_token(token, &server_aliases[i].sid);
4886 * We got a user token with all the SIDs we can know about without asking the
4887 * server directly. These are the user and domain group sids. All of these can
4888 * be members of aliases. So scan the list of aliases for each of the SIDs and
4889 * add them to the token.
4892 static void collect_alias_memberships(struct security_token *token)
4894 int num_global_sids = token->num_sids;
4895 int i;
4897 for (i=0; i<num_global_sids; i++) {
4898 collect_sid_memberships(token, token->sids[i]);
4902 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4904 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4905 enum wbcSidType type;
4906 fstring full_name;
4907 struct wbcDomainSid wsid;
4908 char sid_str[WBC_SID_STRING_BUFLEN];
4909 struct dom_sid user_sid;
4910 uint32_t num_groups;
4911 gid_t *groups = NULL;
4912 uint32_t i;
4914 fstr_sprintf(full_name, "%s%c%s",
4915 domain, *lp_winbind_separator(), user);
4917 /* First let's find out the user sid */
4919 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4921 if (!WBC_ERROR_IS_OK(wbc_status)) {
4922 DEBUG(1, ("winbind could not find %s: %s\n",
4923 full_name, wbcErrorString(wbc_status)));
4924 return false;
4927 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4929 if (type != WBC_SID_NAME_USER) {
4930 DEBUG(1, ("%s is not a user\n", full_name));
4931 return false;
4934 if (!string_to_sid(&user_sid, sid_str)) {
4935 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4936 return false;
4939 init_user_token(token, &user_sid);
4941 /* And now the groups winbind knows about */
4943 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4944 if (!WBC_ERROR_IS_OK(wbc_status)) {
4945 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4946 full_name, wbcErrorString(wbc_status)));
4947 return false;
4950 for (i = 0; i < num_groups; i++) {
4951 gid_t gid = groups[i];
4952 struct dom_sid sid;
4953 bool ok;
4955 wbc_status = wbcGidToSid(gid, &wsid);
4956 if (!WBC_ERROR_IS_OK(wbc_status)) {
4957 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4958 (unsigned int)gid, wbcErrorString(wbc_status)));
4959 wbcFreeMemory(groups);
4960 return false;
4963 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4965 DEBUG(3, (" %s\n", sid_str));
4967 ok = string_to_sid(&sid, sid_str);
4968 if (!ok) {
4969 DEBUG(1, ("Failed to convert string to SID\n"));
4970 wbcFreeMemory(groups);
4971 return false;
4973 add_sid_to_token(token, &sid);
4975 wbcFreeMemory(groups);
4977 return true;
4981 * Get a list of all user tokens we want to look at
4984 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4985 struct user_token **user_tokens)
4987 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4988 uint32_t i, num_users;
4989 const char **users;
4990 struct user_token *result;
4991 TALLOC_CTX *frame = NULL;
4993 if (lp_winbind_use_default_domain() &&
4994 (c->opt_target_workgroup == NULL)) {
4995 d_fprintf(stderr, _("winbind use default domain = yes set, "
4996 "please specify a workgroup\n"));
4997 return false;
5000 /* Send request to winbind daemon */
5002 wbc_status = wbcListUsers(NULL, &num_users, &users);
5003 if (!WBC_ERROR_IS_OK(wbc_status)) {
5004 DEBUG(1, (_("winbind could not list users: %s\n"),
5005 wbcErrorString(wbc_status)));
5006 return false;
5009 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
5011 if (result == NULL) {
5012 DEBUG(1, ("Could not malloc sid array\n"));
5013 wbcFreeMemory(users);
5014 return false;
5017 frame = talloc_stackframe();
5018 for (i=0; i < num_users; i++) {
5019 fstring domain, user;
5020 char *p;
5022 fstrcpy(result[i].name, users[i]);
5024 p = strchr(users[i], *lp_winbind_separator());
5026 DEBUG(3, ("%s\n", users[i]));
5028 if (p == NULL) {
5029 fstrcpy(domain, c->opt_target_workgroup);
5030 fstrcpy(user, users[i]);
5031 } else {
5032 *p++ = '\0';
5033 fstrcpy(domain, users[i]);
5034 if (!strupper_m(domain)) {
5035 DEBUG(1, ("strupper_m %s failed\n", domain));
5036 wbcFreeMemory(users);
5037 return false;
5039 fstrcpy(user, p);
5042 get_user_sids(domain, user, &(result[i].token));
5044 TALLOC_FREE(frame);
5045 wbcFreeMemory(users);
5047 *num_tokens = num_users;
5048 *user_tokens = result;
5050 return true;
5053 static bool get_user_tokens_from_file(FILE *f,
5054 int *num_tokens,
5055 struct user_token **tokens)
5057 struct user_token *token = NULL;
5059 while (!feof(f)) {
5060 fstring line;
5062 if (fgets(line, sizeof(line)-1, f) == NULL) {
5063 return true;
5066 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
5067 line[strlen(line)-1] = '\0';
5070 if (line[0] == ' ') {
5071 /* We have a SID */
5073 struct dom_sid sid;
5074 if(!string_to_sid(&sid, &line[1])) {
5075 DEBUG(1,("get_user_tokens_from_file: Could "
5076 "not convert sid %s \n",&line[1]));
5077 return false;
5080 if (token == NULL) {
5081 DEBUG(0, ("File does not begin with username"));
5082 return false;
5085 add_sid_to_token(&token->token, &sid);
5086 continue;
5089 /* And a new user... */
5091 *num_tokens += 1;
5092 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
5093 if (*tokens == NULL) {
5094 DEBUG(0, ("Could not realloc tokens\n"));
5095 return false;
5098 token = &((*tokens)[*num_tokens-1]);
5100 if (strlcpy(token->name, line, sizeof(token->name)) >= sizeof(token->name)) {
5101 return false;
5103 token->token.num_sids = 0;
5104 token->token.sids = NULL;
5105 continue;
5108 return false;
5113 * Show the list of all users that have access to a share
5116 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
5117 struct cli_state *cli,
5118 TALLOC_CTX *mem_ctx,
5119 const char *netname,
5120 int num_tokens,
5121 struct user_token *tokens)
5123 uint16_t fnum;
5124 struct security_descriptor *share_sd = NULL;
5125 struct security_descriptor *root_sd = NULL;
5126 int i;
5127 union srvsvc_NetShareInfo info;
5128 WERROR result;
5129 NTSTATUS status;
5130 struct smbXcli_tcon *orig_tcon = NULL;
5131 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5133 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5134 pipe_hnd->desthost,
5135 netname,
5136 502,
5137 &info,
5138 &result);
5140 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
5141 DEBUG(1, ("Could not query secdesc for share %s\n",
5142 netname));
5143 return;
5146 share_sd = info.info502->sd_buf.sd;
5147 if (share_sd == NULL) {
5148 DEBUG(1, ("Got no secdesc for share %s\n",
5149 netname));
5152 if (cli_state_has_tcon(cli)) {
5153 orig_tcon = cli_state_save_tcon(cli);
5154 if (orig_tcon == NULL) {
5155 return;
5159 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", NULL))) {
5160 cli_state_restore_tcon(cli, orig_tcon);
5161 return;
5164 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
5165 FILE_SHARE_READ|FILE_SHARE_WRITE,
5166 FILE_OPEN, 0x0, 0x0, &fnum, NULL))) {
5167 cli_query_secdesc(cli, fnum, mem_ctx, &root_sd);
5170 for (i=0; i<num_tokens; i++) {
5171 uint32_t acc_granted;
5173 if (share_sd != NULL) {
5174 status = se_access_check(share_sd, &tokens[i].token,
5175 1, &acc_granted);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 DEBUG(1, ("Could not check share_sd for "
5179 "user %s\n",
5180 tokens[i].name));
5181 continue;
5185 if (root_sd == NULL) {
5186 d_printf(" %s\n", tokens[i].name);
5187 continue;
5190 status = se_access_check(root_sd, &tokens[i].token,
5191 1, &acc_granted);
5192 if (!NT_STATUS_IS_OK(status)) {
5193 DEBUG(1, ("Could not check root_sd for user %s\n",
5194 tokens[i].name));
5195 continue;
5197 d_printf(" %s\n", tokens[i].name);
5200 if (fnum != (uint16_t)-1)
5201 cli_close(cli, fnum);
5202 cli_tdis(cli);
5203 cli_state_restore_tcon(cli, orig_tcon);
5205 return;
5209 * List shares on a remote RPC server, including the security descriptors.
5211 * All parameters are provided by the run_rpc_command function, except for
5212 * argc, argv which are passed through.
5214 * @param domain_sid The domain sid acquired from the remote server.
5215 * @param cli A cli_state connected to the server.
5216 * @param mem_ctx Talloc context, destroyed on completion of the function.
5217 * @param argc Standard main() style argc.
5218 * @param argv Standard main() style argv. Initial components are already
5219 * stripped.
5221 * @return Normal NTSTATUS return.
5224 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
5225 const struct dom_sid *domain_sid,
5226 const char *domain_name,
5227 struct cli_state *cli,
5228 struct rpc_pipe_client *pipe_hnd,
5229 TALLOC_CTX *mem_ctx,
5230 int argc,
5231 const char **argv)
5233 bool r;
5234 FILE *f;
5235 NTSTATUS nt_status = NT_STATUS_OK;
5236 uint32_t total_entries = 0;
5237 uint32_t resume_handle = 0;
5238 uint32_t preferred_len = 0xffffffff;
5239 uint32_t i;
5240 struct dcerpc_binding_handle *b = NULL;
5241 struct srvsvc_NetShareInfoCtr info_ctr;
5242 struct srvsvc_NetShareCtr1 ctr1;
5243 WERROR result;
5245 struct user_token *tokens = NULL;
5246 int num_tokens = 0;
5248 if (argc == 0) {
5249 f = stdin;
5250 } else {
5251 if (strequal(argv[0], "-")) {
5252 f = stdin;
5253 } else {
5254 f = fopen(argv[0], "r");
5256 argv++;
5257 argc--;
5260 if (f == NULL) {
5261 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
5262 return NT_STATUS_UNSUCCESSFUL;
5265 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
5267 if (f != stdin)
5268 fclose(f);
5270 if (!r) {
5271 DEBUG(0, ("Could not read users from file\n"));
5272 return NT_STATUS_UNSUCCESSFUL;
5275 for (i=0; i<num_tokens; i++)
5276 collect_alias_memberships(&tokens[i].token);
5278 ZERO_STRUCT(info_ctr);
5279 ZERO_STRUCT(ctr1);
5281 info_ctr.level = 1;
5282 info_ctr.ctr.ctr1 = &ctr1;
5284 b = pipe_hnd->binding_handle;
5286 if (argc != 0) {
5287 /* Show results only for shares listed on the command line. */
5288 while (*argv) {
5289 const char *netname = *argv++;
5290 d_printf("%s\n", netname);
5291 show_userlist(pipe_hnd, cli, mem_ctx, netname,
5292 num_tokens, tokens);
5294 goto done;
5297 /* Issue the NetShareEnum RPC call and retrieve the response */
5298 nt_status = dcerpc_srvsvc_NetShareEnumAll(b,
5299 talloc_tos(),
5300 pipe_hnd->desthost,
5301 &info_ctr,
5302 preferred_len,
5303 &total_entries,
5304 &resume_handle,
5305 &result);
5307 /* Was it successful? */
5308 if (!NT_STATUS_IS_OK(nt_status)) {
5309 /* Nope. Go clean up. */
5310 goto done;
5313 if (!W_ERROR_IS_OK(result)) {
5314 /* Nope. Go clean up. */
5315 nt_status = werror_to_ntstatus(result);
5316 goto done;
5319 if (total_entries == 0) {
5320 goto done;
5323 /* For each returned entry... */
5324 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
5325 const char *netname = info_ctr.ctr.ctr1->array[i].name;
5327 if (info_ctr.ctr.ctr1->array[i].type != STYPE_DISKTREE) {
5328 continue;
5331 d_printf("%s\n", netname);
5333 show_userlist(pipe_hnd, cli, mem_ctx, netname,
5334 num_tokens, tokens);
5336 done:
5337 for (i=0; i<num_tokens; i++) {
5338 free_user_token(&tokens[i].token);
5340 SAFE_FREE(tokens);
5341 TALLOC_FREE(server_aliases);
5343 return nt_status;
5346 static int rpc_share_allowedusers(struct net_context *c, int argc,
5347 const char **argv)
5349 int result;
5351 if (c->display_usage) {
5352 d_printf( "%s\n"
5353 "net rpc share allowedusers\n"
5354 " %s\n",
5355 _("Usage:"),
5356 _("List allowed users"));
5357 return 0;
5360 result = run_rpc_command(c, NULL, &ndr_table_samr, 0,
5361 rpc_aliaslist_internals,
5362 argc, argv);
5363 if (result != 0)
5364 return result;
5366 result = run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
5367 rpc_aliaslist_dump,
5368 argc, argv);
5369 if (result != 0)
5370 return result;
5372 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
5373 rpc_share_allowedusers_internals,
5374 argc, argv);
5377 int net_usersidlist(struct net_context *c, int argc, const char **argv)
5379 int num_tokens = 0;
5380 struct user_token *tokens = NULL;
5381 int i;
5383 if (argc != 0) {
5384 net_usersidlist_usage(c, argc, argv);
5385 return 0;
5388 if (!get_user_tokens(c, &num_tokens, &tokens)) {
5389 DEBUG(0, ("Could not get the user/sid list\n"));
5390 return -1;
5393 for (i=0; i<num_tokens; i++) {
5394 dump_user_token(&tokens[i]);
5395 free_user_token(&tokens[i].token);
5398 SAFE_FREE(tokens);
5399 return 0;
5402 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
5404 d_printf(_("net usersidlist\n"
5405 "\tprints out a list of all users the running winbind knows\n"
5406 "\tabout, together with all their SIDs. This is used as\n"
5407 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
5409 net_common_flags_usage(c, argc, argv);
5410 return -1;
5414 * 'net rpc share' entrypoint.
5415 * @param argc Standard main() style argc.
5416 * @param argv Standard main() style argv. Initial components are already
5417 * stripped.
5420 int net_rpc_share(struct net_context *c, int argc, const char **argv)
5422 NET_API_STATUS status;
5424 struct functable func[] = {
5426 "add",
5427 rpc_share_add,
5428 NET_TRANSPORT_RPC,
5429 N_("Add share"),
5430 N_("net rpc share add\n"
5431 " Add share")
5434 "delete",
5435 rpc_share_delete,
5436 NET_TRANSPORT_RPC,
5437 N_("Remove share"),
5438 N_("net rpc share delete\n"
5439 " Remove share")
5442 "allowedusers",
5443 rpc_share_allowedusers,
5444 NET_TRANSPORT_RPC,
5445 N_("List allowed users"),
5446 N_("net rpc share allowedusers\n"
5447 " List allowed users")
5450 "migrate",
5451 rpc_share_migrate,
5452 NET_TRANSPORT_RPC,
5453 N_("Migrate share to local server"),
5454 N_("net rpc share migrate\n"
5455 " Migrate share to local server")
5458 "list",
5459 rpc_share_list,
5460 NET_TRANSPORT_RPC,
5461 N_("List shares"),
5462 N_("net rpc share list\n"
5463 " List shares")
5465 {NULL, NULL, 0, NULL, NULL}
5468 status = libnetapi_net_init(&c->netapi_ctx);
5469 if (status != 0) {
5470 return -1;
5472 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5473 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5474 if (c->opt_kerberos) {
5475 libnetapi_set_use_kerberos(c->netapi_ctx);
5478 if (argc == 0) {
5479 if (c->display_usage) {
5480 d_printf("%s\n%s",
5481 _("Usage:"),
5482 _("net rpc share\n"
5483 " List shares\n"
5484 " Alias for net rpc share list\n"));
5485 net_display_usage_from_functable(func);
5486 return 0;
5489 return rpc_share_list(c, argc, argv);
5492 return net_run_function(c, argc, argv, "net rpc share", func);
5495 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5496 TALLOC_CTX *mem_ctx,
5497 struct rpc_sh_ctx *ctx,
5498 struct rpc_pipe_client *pipe_hnd,
5499 int argc, const char **argv)
5502 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5505 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5506 TALLOC_CTX *mem_ctx,
5507 struct rpc_sh_ctx *ctx,
5508 struct rpc_pipe_client *pipe_hnd,
5509 int argc, const char **argv)
5511 NET_API_STATUS status;
5512 uint32_t parm_err = 0;
5513 struct SHARE_INFO_2 i2;
5515 if ((argc < 2) || (argc > 3)) {
5516 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5517 ctx->whoami);
5518 return NT_STATUS_INVALID_PARAMETER;
5521 i2.shi2_netname = argv[0];
5522 i2.shi2_type = STYPE_DISKTREE;
5523 i2.shi2_remark = (argc == 3) ? argv[2] : "";
5524 i2.shi2_permissions = 0;
5525 i2.shi2_max_uses = 0;
5526 i2.shi2_current_uses = 0;
5527 i2.shi2_path = argv[1];
5528 i2.shi2_passwd = NULL;
5530 status = NetShareAdd(pipe_hnd->desthost,
5532 (uint8_t *)&i2,
5533 &parm_err);
5535 return werror_to_ntstatus(W_ERROR(status));
5538 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5539 TALLOC_CTX *mem_ctx,
5540 struct rpc_sh_ctx *ctx,
5541 struct rpc_pipe_client *pipe_hnd,
5542 int argc, const char **argv)
5544 if (argc != 1) {
5545 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5546 return NT_STATUS_INVALID_PARAMETER;
5549 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5552 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5553 TALLOC_CTX *mem_ctx,
5554 struct rpc_sh_ctx *ctx,
5555 struct rpc_pipe_client *pipe_hnd,
5556 int argc, const char **argv)
5558 union srvsvc_NetShareInfo info;
5559 WERROR result;
5560 NTSTATUS status;
5561 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5563 if (argc != 1) {
5564 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5565 return NT_STATUS_INVALID_PARAMETER;
5568 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5569 pipe_hnd->desthost,
5570 argv[0],
5572 &info,
5573 &result);
5574 if (!NT_STATUS_IS_OK(status)) {
5575 result = ntstatus_to_werror(status);
5576 goto done;
5578 if (!W_ERROR_IS_OK(result)) {
5579 goto done;
5582 d_printf(_("Name: %s\n"), info.info2->name);
5583 d_printf(_("Comment: %s\n"), info.info2->comment);
5584 d_printf(_("Path: %s\n"), info.info2->path);
5585 d_printf(_("Password: %s\n"), info.info2->password);
5587 done:
5588 return werror_to_ntstatus(result);
5591 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5592 struct rpc_sh_ctx *ctx)
5594 static struct rpc_sh_cmd cmds[] = {
5596 { "list", NULL, &ndr_table_srvsvc, rpc_sh_share_list,
5597 N_("List available shares") },
5599 { "add", NULL, &ndr_table_srvsvc, rpc_sh_share_add,
5600 N_("Add a share") },
5602 { "delete", NULL, &ndr_table_srvsvc, rpc_sh_share_delete,
5603 N_("Delete a share") },
5605 { "info", NULL, &ndr_table_srvsvc, rpc_sh_share_info,
5606 N_("Get information about a share") },
5608 { NULL, NULL, 0, NULL, NULL }
5611 return cmds;
5614 /****************************************************************************/
5616 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5618 return net_file_usage(c, argc, argv);
5622 * Close a file on a remote RPC server.
5624 * @param argc Standard main() style argc.
5625 * @param argv Standard main() style argv. Initial components are already
5626 * stripped.
5628 * @return A shell status integer (0 for success).
5630 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5632 if (argc < 1 || c->display_usage) {
5633 return rpc_file_usage(c, argc, argv);
5636 return NetFileClose(c->opt_host, atoi(argv[0]));
5640 * Formatted print of open file info
5642 * @param r struct FILE_INFO_3 contents
5645 static void display_file_info_3(struct FILE_INFO_3 *r)
5647 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5648 r->fi3_id, r->fi3_username, r->fi3_permissions,
5649 r->fi3_num_locks, r->fi3_pathname);
5653 * List files for a user on a remote RPC server.
5655 * @param argc Standard main() style argc.
5656 * @param argv Standard main() style argv. Initial components are already
5657 * stripped.
5659 * @return A shell status integer (0 for success)..
5662 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5664 NET_API_STATUS status;
5665 uint32_t preferred_len = 0xffffffff, i;
5666 char *username=NULL;
5667 uint32_t total_entries = 0;
5668 uint32_t entries_read = 0;
5669 uint32_t resume_handle = 0;
5670 struct FILE_INFO_3 *i3 = NULL;
5672 if (c->display_usage) {
5673 return rpc_file_usage(c, argc, argv);
5676 /* if argc > 0, must be user command */
5677 if (argc > 0) {
5678 username = smb_xstrdup(argv[0]);
5681 status = NetFileEnum(c->opt_host,
5682 NULL,
5683 username,
5685 (uint8_t **)(void *)&i3,
5686 preferred_len,
5687 &entries_read,
5688 &total_entries,
5689 &resume_handle);
5691 if (status != 0) {
5692 goto done;
5695 /* Display results */
5697 d_printf(_(
5698 "\nEnumerating open files on remote server:\n\n"
5699 "\nFileId Opened by Perms Locks Path"
5700 "\n------ --------- ----- ----- ---- \n"));
5701 for (i = 0; i < entries_read; i++) {
5702 display_file_info_3(&i3[i]);
5704 done:
5705 SAFE_FREE(username);
5706 return status;
5710 * 'net rpc file' entrypoint.
5711 * @param argc Standard main() style argc.
5712 * @param argv Standard main() style argv. Initial components are already
5713 * stripped.
5716 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5718 NET_API_STATUS status;
5720 struct functable func[] = {
5722 "close",
5723 rpc_file_close,
5724 NET_TRANSPORT_RPC,
5725 N_("Close opened file"),
5726 N_("net rpc file close\n"
5727 " Close opened file")
5730 "user",
5731 rpc_file_user,
5732 NET_TRANSPORT_RPC,
5733 N_("List files opened by user"),
5734 N_("net rpc file user\n"
5735 " List files opened by user")
5737 #if 0
5739 "info",
5740 rpc_file_info,
5741 NET_TRANSPORT_RPC,
5742 N_("Display information about opened file"),
5743 N_("net rpc file info\n"
5744 " Display information about opened file")
5746 #endif
5747 {NULL, NULL, 0, NULL, NULL}
5750 status = libnetapi_net_init(&c->netapi_ctx);
5751 if (status != 0) {
5752 return -1;
5754 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5755 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5756 if (c->opt_kerberos) {
5757 libnetapi_set_use_kerberos(c->netapi_ctx);
5760 if (argc == 0) {
5761 if (c->display_usage) {
5762 d_printf(_("Usage:\n"));
5763 d_printf(_("net rpc file\n"
5764 " List opened files\n"));
5765 net_display_usage_from_functable(func);
5766 return 0;
5769 return rpc_file_user(c, argc, argv);
5772 return net_run_function(c, argc, argv, "net rpc file", func);
5776 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5778 * All parameters are provided by the run_rpc_command function, except for
5779 * argc, argv which are passed through.
5781 * @param c A net_context structure.
5782 * @param domain_sid The domain sid acquired from the remote server.
5783 * @param cli A cli_state connected to the server.
5784 * @param mem_ctx Talloc context, destroyed on completion of the function.
5785 * @param argc Standard main() style argc.
5786 * @param argv Standard main() style argv. Initial components are already
5787 * stripped.
5789 * @return Normal NTSTATUS return.
5792 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5793 const struct dom_sid *domain_sid,
5794 const char *domain_name,
5795 struct cli_state *cli,
5796 struct rpc_pipe_client *pipe_hnd,
5797 TALLOC_CTX *mem_ctx,
5798 int argc,
5799 const char **argv)
5801 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5802 WERROR result;
5803 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5805 status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5806 if (!NT_STATUS_IS_OK(status)) {
5807 return status;
5809 if (W_ERROR_IS_OK(result)) {
5810 d_printf(_("\nShutdown successfully aborted\n"));
5811 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5812 } else
5813 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5815 return werror_to_ntstatus(result);
5819 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5821 * All parameters are provided by the run_rpc_command function, except for
5822 * argc, argv which are passed through.
5824 * @param c A net_context structure.
5825 * @param domain_sid The domain sid acquired from the remote server.
5826 * @param cli A cli_state connected to the server.
5827 * @param mem_ctx Talloc context, destroyed on completion of the function.
5828 * @param argc Standard main() style argc.
5829 * @param argv Standard main() style argv. Initial components are already
5830 * stripped.
5832 * @return Normal NTSTATUS return.
5835 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5836 const struct dom_sid *domain_sid,
5837 const char *domain_name,
5838 struct cli_state *cli,
5839 struct rpc_pipe_client *pipe_hnd,
5840 TALLOC_CTX *mem_ctx,
5841 int argc,
5842 const char **argv)
5844 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5845 WERROR werr;
5846 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5848 result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5850 if (!NT_STATUS_IS_OK(result)) {
5851 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5852 return result;
5854 if (W_ERROR_IS_OK(werr)) {
5855 d_printf(_("\nShutdown successfully aborted\n"));
5856 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5857 } else
5858 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5860 return werror_to_ntstatus(werr);
5864 * ABORT the shutdown of a remote RPC server.
5866 * @param argc Standard main() style argc.
5867 * @param argv Standard main() style argv. Initial components are already
5868 * stripped.
5870 * @return A shell status integer (0 for success).
5873 static int rpc_shutdown_abort(struct net_context *c, int argc,
5874 const char **argv)
5876 int rc = -1;
5878 if (c->display_usage) {
5879 d_printf( "%s\n"
5880 "net rpc abortshutdown\n"
5881 " %s\n",
5882 _("Usage:"),
5883 _("Abort a scheduled shutdown"));
5884 return 0;
5887 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5888 rpc_shutdown_abort_internals, argc, argv);
5890 if (rc == 0)
5891 return rc;
5893 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5895 return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5896 rpc_reg_shutdown_abort_internals,
5897 argc, argv);
5901 * Shut down a remote RPC Server via initshutdown pipe.
5903 * All parameters are provided by the run_rpc_command function, except for
5904 * argc, argv which are passed through.
5906 * @param c A net_context structure.
5907 * @param domain_sid The domain sid acquired from the remote server.
5908 * @param cli A cli_state connected to the server.
5909 * @param mem_ctx Talloc context, destroyed on completion of the function.
5910 * @param argc Standard main() style argc.
5911 * @param argv Standard main() style argv. Initial components are already
5912 * stripped.
5914 * @return Normal NTSTATUS return.
5917 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5918 const struct dom_sid *domain_sid,
5919 const char *domain_name,
5920 struct cli_state *cli,
5921 struct rpc_pipe_client *pipe_hnd,
5922 TALLOC_CTX *mem_ctx,
5923 int argc,
5924 const char **argv)
5926 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5927 WERROR result;
5928 const char *msg = N_("This machine will be shutdown shortly");
5929 uint32_t timeout = 20;
5930 struct lsa_StringLarge msg_string;
5931 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5933 if (c->opt_comment) {
5934 msg = c->opt_comment;
5936 if (c->opt_timeout) {
5937 timeout = c->opt_timeout;
5940 msg_string.string = msg;
5942 /* create an entry */
5943 status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5944 &msg_string, timeout, c->opt_force, c->opt_reboot,
5945 &result);
5946 if (!NT_STATUS_IS_OK(status)) {
5947 return status;
5949 if (W_ERROR_IS_OK(result)) {
5950 d_printf(_("\nShutdown of remote machine succeeded\n"));
5951 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5952 } else {
5953 DEBUG(1,("Shutdown of remote machine failed!\n"));
5955 return werror_to_ntstatus(result);
5959 * Shut down a remote RPC Server via winreg pipe.
5961 * All parameters are provided by the run_rpc_command function, except for
5962 * argc, argv which are passed through.
5964 * @param c A net_context structure.
5965 * @param domain_sid The domain sid acquired from the remote server.
5966 * @param cli A cli_state connected to the server.
5967 * @param mem_ctx Talloc context, destroyed on completion of the function.
5968 * @param argc Standard main() style argc.
5969 * @param argv Standard main() style argv. Initial components are already
5970 * stripped.
5972 * @return Normal NTSTATUS return.
5975 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5976 const struct dom_sid *domain_sid,
5977 const char *domain_name,
5978 struct cli_state *cli,
5979 struct rpc_pipe_client *pipe_hnd,
5980 TALLOC_CTX *mem_ctx,
5981 int argc,
5982 const char **argv)
5984 const char *msg = N_("This machine will be shutdown shortly");
5985 uint32_t timeout = 20;
5986 struct lsa_StringLarge msg_string;
5987 NTSTATUS result;
5988 WERROR werr;
5989 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5991 if (c->opt_comment) {
5992 msg = c->opt_comment;
5994 msg_string.string = msg;
5996 if (c->opt_timeout) {
5997 timeout = c->opt_timeout;
6000 /* create an entry */
6001 result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
6002 &msg_string, timeout, c->opt_force, c->opt_reboot,
6003 &werr);
6004 if (!NT_STATUS_IS_OK(result)) {
6005 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
6006 return result;
6009 if (W_ERROR_IS_OK(werr)) {
6010 d_printf(_("\nShutdown of remote machine succeeded\n"));
6011 } else {
6012 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
6013 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
6014 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
6015 else
6016 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
6019 return werror_to_ntstatus(werr);
6023 * Shut down a remote RPC server.
6025 * @param argc Standard main() style argc.
6026 * @param argv Standard main() style argv. Initial components are already
6027 * stripped.
6029 * @return A shell status integer (0 for success).
6032 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
6034 int rc = -1;
6036 if (c->display_usage) {
6037 d_printf( "%s\n"
6038 "net rpc shutdown\n"
6039 " %s\n",
6040 _("Usage:"),
6041 _("Shut down a remote RPC server"));
6042 return 0;
6045 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
6046 rpc_init_shutdown_internals, argc, argv);
6048 if (rc) {
6049 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
6050 rc = run_rpc_command(c, NULL, &ndr_table_winreg, 0,
6051 rpc_reg_shutdown_internals, argc, argv);
6054 return rc;
6057 /***************************************************************************
6058 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
6059 ***************************************************************************/
6062 * Add interdomain trust account to the RPC server.
6063 * All parameters (except for argc and argv) are passed by run_rpc_command
6064 * function.
6066 * @param c A net_context structure.
6067 * @param domain_sid The domain sid acquired from the server.
6068 * @param cli A cli_state connected to the server.
6069 * @param mem_ctx Talloc context, destroyed on completion of the function.
6070 * @param argc Standard main() style argc.
6071 * @param argv Standard main() style argv. Initial components are already
6072 * stripped.
6074 * @return normal NTSTATUS return code.
6077 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
6078 const struct dom_sid *domain_sid,
6079 const char *domain_name,
6080 struct cli_state *cli,
6081 struct rpc_pipe_client *pipe_hnd,
6082 TALLOC_CTX *mem_ctx,
6083 int argc,
6084 const char **argv)
6086 struct policy_handle connect_pol, domain_pol, user_pol;
6087 NTSTATUS status, result;
6088 char *acct_name;
6089 struct lsa_String lsa_acct_name;
6090 uint32_t acb_info;
6091 uint32_t acct_flags=0;
6092 uint32_t user_rid;
6093 uint32_t access_granted = 0;
6094 union samr_UserInfo info;
6095 unsigned int orig_timeout;
6096 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6097 DATA_BLOB session_key = data_blob_null;
6098 TALLOC_CTX *frame = NULL;
6100 if (argc != 2) {
6101 d_printf("%s\n%s",
6102 _("Usage:"),
6103 _(" net rpc trustdom add <domain_name> "
6104 "<trust password>\n"));
6105 return NT_STATUS_INVALID_PARAMETER;
6108 frame = talloc_stackframe();
6111 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6114 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
6115 status = NT_STATUS_NO_MEMORY;
6118 if (!strupper_m(acct_name)) {
6119 status = NT_STATUS_INVALID_PARAMETER;
6120 goto done;
6123 init_lsa_String(&lsa_acct_name, acct_name);
6125 status = cli_get_session_key(frame, pipe_hnd, &session_key);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
6128 nt_errstr(status)));
6129 goto done;
6132 /* Get samr policy handle */
6133 status = dcerpc_samr_Connect2(b, frame,
6134 pipe_hnd->desthost,
6135 MAXIMUM_ALLOWED_ACCESS,
6136 &connect_pol,
6137 &result);
6138 if (!NT_STATUS_IS_OK(status)) {
6139 goto done;
6141 if (!NT_STATUS_IS_OK(result)) {
6142 status = result;
6143 goto done;
6146 /* Get domain policy handle */
6147 status = dcerpc_samr_OpenDomain(b, frame,
6148 &connect_pol,
6149 MAXIMUM_ALLOWED_ACCESS,
6150 discard_const_p(struct dom_sid2, domain_sid),
6151 &domain_pol,
6152 &result);
6153 if (!NT_STATUS_IS_OK(status)) {
6154 goto done;
6156 if (!NT_STATUS_IS_OK(result)) {
6157 status = result;
6158 goto done;
6161 /* This call can take a long time - allow the server to time out.
6162 * 35 seconds should do it. */
6164 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
6166 /* Create trusting domain's account */
6167 acb_info = ACB_NORMAL;
6168 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
6169 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
6170 SAMR_USER_ACCESS_SET_PASSWORD |
6171 SAMR_USER_ACCESS_GET_ATTRIBUTES |
6172 SAMR_USER_ACCESS_SET_ATTRIBUTES;
6174 status = dcerpc_samr_CreateUser2(b, frame,
6175 &domain_pol,
6176 &lsa_acct_name,
6177 acb_info,
6178 acct_flags,
6179 &user_pol,
6180 &access_granted,
6181 &user_rid,
6182 &result);
6183 if (!NT_STATUS_IS_OK(status)) {
6184 goto done;
6186 /* And restore our original timeout. */
6187 rpccli_set_timeout(pipe_hnd, orig_timeout);
6189 if (!NT_STATUS_IS_OK(result)) {
6190 status = result;
6191 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
6192 acct_name, nt_errstr(result));
6193 goto done;
6197 struct samr_CryptPassword crypt_pwd;
6199 ZERO_STRUCT(info.info23);
6201 status = init_samr_CryptPassword(argv[1],
6202 &session_key,
6203 &crypt_pwd);
6204 if (!NT_STATUS_IS_OK(status)) {
6205 goto done;
6208 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
6209 SAMR_FIELD_NT_PASSWORD_PRESENT;
6210 info.info23.info.acct_flags = ACB_DOMTRUST;
6211 info.info23.password = crypt_pwd;
6213 status = dcerpc_samr_SetUserInfo2(b, frame,
6214 &user_pol,
6216 &info,
6217 &result);
6218 if (!NT_STATUS_IS_OK(status)) {
6219 goto done;
6222 if (!NT_STATUS_IS_OK(result)) {
6223 status = result;
6224 DEBUG(0,("Could not set trust account password: %s\n",
6225 nt_errstr(result)));
6226 goto done;
6230 status = NT_STATUS_OK;
6231 done:
6232 SAFE_FREE(acct_name);
6233 data_blob_clear_free(&session_key);
6234 TALLOC_FREE(frame);
6235 return status;
6239 * Create interdomain trust account for a remote domain.
6241 * @param argc Standard argc.
6242 * @param argv Standard argv without initial components.
6244 * @return Integer status (0 means success).
6247 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
6249 if (argc > 0 && !c->display_usage) {
6250 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6251 rpc_trustdom_add_internals, argc, argv);
6252 } else {
6253 d_printf("%s\n%s",
6254 _("Usage:"),
6255 _("net rpc trustdom add <domain_name> <trust "
6256 "password>\n"));
6257 return -1;
6263 * Remove interdomain trust account from the RPC server.
6264 * All parameters (except for argc and argv) are passed by run_rpc_command
6265 * function.
6267 * @param c A net_context structure.
6268 * @param domain_sid The domain sid acquired from the server.
6269 * @param cli A cli_state connected to the server.
6270 * @param mem_ctx Talloc context, destroyed on completion of the function.
6271 * @param argc Standard main() style argc.
6272 * @param argv Standard main() style argv. Initial components are already
6273 * stripped.
6275 * @return normal NTSTATUS return code.
6278 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
6279 const struct dom_sid *domain_sid,
6280 const char *domain_name,
6281 struct cli_state *cli,
6282 struct rpc_pipe_client *pipe_hnd,
6283 TALLOC_CTX *mem_ctx,
6284 int argc,
6285 const char **argv)
6287 struct policy_handle connect_pol, domain_pol, user_pol;
6288 NTSTATUS status, result;
6289 char *acct_name;
6290 struct dom_sid trust_acct_sid;
6291 struct samr_Ids user_rids, name_types;
6292 struct lsa_String lsa_acct_name;
6293 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6295 if (argc != 1) {
6296 d_printf("%s\n%s",
6297 _("Usage:"),
6298 _(" net rpc trustdom del <domain_name>\n"));
6299 return NT_STATUS_INVALID_PARAMETER;
6303 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6305 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
6307 if (acct_name == NULL)
6308 return NT_STATUS_NO_MEMORY;
6310 if (!strupper_m(acct_name)) {
6311 TALLOC_FREE(acct_name);
6312 return NT_STATUS_INVALID_PARAMETER;
6315 /* Get samr policy handle */
6316 status = dcerpc_samr_Connect2(b, mem_ctx,
6317 pipe_hnd->desthost,
6318 MAXIMUM_ALLOWED_ACCESS,
6319 &connect_pol,
6320 &result);
6321 if (!NT_STATUS_IS_OK(status)) {
6322 goto done;
6324 if (!NT_STATUS_IS_OK(result)) {
6325 status = result;
6326 goto done;
6329 /* Get domain policy handle */
6330 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6331 &connect_pol,
6332 MAXIMUM_ALLOWED_ACCESS,
6333 discard_const_p(struct dom_sid2, domain_sid),
6334 &domain_pol,
6335 &result);
6336 if (!NT_STATUS_IS_OK(status)) {
6337 goto done;
6339 if (!NT_STATUS_IS_OK(result)) {
6340 status = result;
6341 goto done;
6344 init_lsa_String(&lsa_acct_name, acct_name);
6346 status = dcerpc_samr_LookupNames(b, mem_ctx,
6347 &domain_pol,
6349 &lsa_acct_name,
6350 &user_rids,
6351 &name_types,
6352 &result);
6353 if (!NT_STATUS_IS_OK(status)) {
6354 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6355 "failed %s\n"),
6356 acct_name, nt_errstr(status));
6357 goto done;
6359 if (!NT_STATUS_IS_OK(result)) {
6360 status = result;
6361 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6362 "failed %s\n"),
6363 acct_name, nt_errstr(result) );
6364 goto done;
6366 if (user_rids.count != 1) {
6367 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6368 goto done;
6370 if (name_types.count != 1) {
6371 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6372 goto done;
6375 status = dcerpc_samr_OpenUser(b, mem_ctx,
6376 &domain_pol,
6377 MAXIMUM_ALLOWED_ACCESS,
6378 user_rids.ids[0],
6379 &user_pol,
6380 &result);
6381 if (!NT_STATUS_IS_OK(status)) {
6382 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6383 "%s\n"),
6384 acct_name, nt_errstr(status) );
6385 goto done;
6388 if (!NT_STATUS_IS_OK(result)) {
6389 status = result;
6390 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6391 "%s\n"),
6392 acct_name, nt_errstr(result) );
6393 goto done;
6396 /* append the rid to the domain sid */
6397 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6398 goto done;
6401 /* remove the sid */
6403 status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6404 &user_pol,
6405 &trust_acct_sid,
6406 &result);
6407 if (!NT_STATUS_IS_OK(status)) {
6408 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6409 " on user %s failed %s\n"),
6410 acct_name, nt_errstr(status));
6411 goto done;
6413 if (!NT_STATUS_IS_OK(result)) {
6414 status = result;
6415 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6416 " on user %s failed %s\n"),
6417 acct_name, nt_errstr(result) );
6418 goto done;
6422 /* Delete user */
6424 status = dcerpc_samr_DeleteUser(b, mem_ctx,
6425 &user_pol,
6426 &result);
6427 if (!NT_STATUS_IS_OK(status)) {
6428 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6429 "%s\n"),
6430 acct_name, nt_errstr(status));
6431 goto done;
6434 if (!NT_STATUS_IS_OK(result)) {
6435 result = status;
6436 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6437 "%s\n"),
6438 acct_name, nt_errstr(result) );
6439 goto done;
6442 if (!NT_STATUS_IS_OK(result)) {
6443 d_printf(_("Could not set trust account password: %s\n"),
6444 nt_errstr(result));
6445 goto done;
6448 done:
6449 return status;
6453 * Delete interdomain trust account for a remote domain.
6455 * @param argc Standard argc.
6456 * @param argv Standard argv without initial components.
6458 * @return Integer status (0 means success).
6461 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6463 if (argc > 0 && !c->display_usage) {
6464 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6465 rpc_trustdom_del_internals, argc, argv);
6466 } else {
6467 d_printf("%s\n%s",
6468 _("Usage:"),
6469 _("net rpc trustdom del <domain>\n"));
6470 return -1;
6474 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6475 struct cli_state *cli,
6476 TALLOC_CTX *mem_ctx,
6477 const char *domain_name)
6479 char *dc_name = NULL;
6480 const char *buffer = NULL;
6481 struct rpc_pipe_client *netr;
6482 NTSTATUS status;
6483 WERROR result;
6484 struct dcerpc_binding_handle *b;
6486 /* Use NetServerEnum2 */
6488 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6489 SAFE_FREE(dc_name);
6490 return NT_STATUS_OK;
6493 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6494 for domain %s\n", domain_name));
6496 /* Try netr_GetDcName */
6498 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon,
6499 &netr);
6500 if (!NT_STATUS_IS_OK(status)) {
6501 return status;
6504 b = netr->binding_handle;
6506 status = dcerpc_netr_GetDcName(b, mem_ctx,
6507 netr->desthost,
6508 domain_name,
6509 &buffer,
6510 &result);
6511 TALLOC_FREE(netr);
6513 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6514 return status;
6517 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6518 for domain %s\n", domain_name));
6520 if (!NT_STATUS_IS_OK(status)) {
6521 return status;
6524 return werror_to_ntstatus(result);
6528 * Establish trust relationship to a trusting domain.
6529 * Interdomain account must already be created on remote PDC.
6531 * @param c A net_context structure.
6532 * @param argc Standard argc.
6533 * @param argv Standard argv without initial components.
6535 * @return Integer status (0 means success).
6538 static int rpc_trustdom_establish(struct net_context *c, int argc,
6539 const char **argv)
6541 struct cli_state *cli = NULL;
6542 struct sockaddr_storage server_ss;
6543 struct rpc_pipe_client *pipe_hnd = NULL;
6544 struct policy_handle connect_hnd;
6545 TALLOC_CTX *mem_ctx;
6546 NTSTATUS nt_status, result;
6547 struct dom_sid *domain_sid;
6549 char* domain_name;
6550 char* acct_name;
6551 fstring pdc_name;
6552 union lsa_PolicyInformation *info = NULL;
6553 struct dcerpc_binding_handle *b;
6556 * Connect to \\server\ipc$ as 'our domain' account with password
6559 if (argc != 1 || c->display_usage) {
6560 d_printf("%s\n%s",
6561 _("Usage:"),
6562 _("net rpc trustdom establish <domain_name>\n"));
6563 return -1;
6566 domain_name = smb_xstrdup(argv[0]);
6567 if (!strupper_m(domain_name)) {
6568 SAFE_FREE(domain_name);
6569 return -1;
6572 /* account name used at first is our domain's name with '$' */
6573 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6574 return -1;
6576 if (!strupper_m(acct_name)) {
6577 SAFE_FREE(domain_name);
6578 SAFE_FREE(acct_name);
6579 return -1;
6583 * opt_workgroup will be used by connection functions further,
6584 * hence it should be set to remote domain name instead of ours
6586 if (c->opt_workgroup) {
6587 c->opt_workgroup = smb_xstrdup(domain_name);
6590 c->opt_user_name = acct_name;
6592 /* find the domain controller */
6593 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6594 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6595 return -1;
6598 /* connect to ipc$ as username/password */
6599 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6600 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6602 /* Is it trusting domain account for sure ? */
6603 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6604 nt_errstr(nt_status)));
6605 return -1;
6608 /* store who we connected to */
6610 saf_store( domain_name, pdc_name );
6613 * Connect to \\server\ipc$ again (this time anonymously)
6616 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6617 (char*)pdc_name);
6619 if (NT_STATUS_IS_ERR(nt_status)) {
6620 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6621 domain_name, nt_errstr(nt_status)));
6622 return -1;
6625 if (!(mem_ctx = talloc_init("establishing trust relationship to "
6626 "domain %s", domain_name))) {
6627 DEBUG(0, ("talloc_init() failed\n"));
6628 cli_shutdown(cli);
6629 return -1;
6632 /* Make sure we're talking to a proper server */
6634 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6635 if (!NT_STATUS_IS_OK(nt_status)) {
6636 cli_shutdown(cli);
6637 talloc_destroy(mem_ctx);
6638 return -1;
6642 * Call LsaOpenPolicy and LsaQueryInfo
6645 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6646 &pipe_hnd);
6647 if (!NT_STATUS_IS_OK(nt_status)) {
6648 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6649 cli_shutdown(cli);
6650 talloc_destroy(mem_ctx);
6651 return -1;
6654 b = pipe_hnd->binding_handle;
6656 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6657 &connect_hnd);
6658 if (NT_STATUS_IS_ERR(nt_status)) {
6659 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6660 nt_errstr(nt_status)));
6661 cli_shutdown(cli);
6662 talloc_destroy(mem_ctx);
6663 return -1;
6666 /* Querying info level 5 */
6668 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6669 &connect_hnd,
6670 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6671 &info,
6672 &result);
6673 if (NT_STATUS_IS_ERR(nt_status)) {
6674 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6675 nt_errstr(nt_status)));
6676 cli_shutdown(cli);
6677 talloc_destroy(mem_ctx);
6678 return -1;
6680 if (NT_STATUS_IS_ERR(result)) {
6681 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6682 nt_errstr(result)));
6683 cli_shutdown(cli);
6684 talloc_destroy(mem_ctx);
6685 return -1;
6688 domain_sid = info->account_domain.sid;
6690 /* There should be actually query info level 3 (following nt serv behaviour),
6691 but I still don't know if it's _really_ necessary */
6694 * Store the password in secrets db
6697 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6698 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6699 cli_shutdown(cli);
6700 talloc_destroy(mem_ctx);
6701 return -1;
6705 * Close the pipes and clean up
6708 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6709 if (NT_STATUS_IS_ERR(nt_status)) {
6710 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6711 nt_errstr(nt_status)));
6712 cli_shutdown(cli);
6713 talloc_destroy(mem_ctx);
6714 return -1;
6717 cli_shutdown(cli);
6719 talloc_destroy(mem_ctx);
6721 d_printf(_("Trust to domain %s established\n"), domain_name);
6722 return 0;
6726 * Revoke trust relationship to the remote domain.
6728 * @param c A net_context structure.
6729 * @param argc Standard argc.
6730 * @param argv Standard argv without initial components.
6732 * @return Integer status (0 means success).
6735 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6736 const char **argv)
6738 char* domain_name;
6739 int rc = -1;
6741 if (argc < 1 || c->display_usage) {
6742 d_printf("%s\n%s",
6743 _("Usage:"),
6744 _("net rpc trustdom revoke <domain_name>\n"
6745 " Revoke trust relationship\n"
6746 " domain_name\tName of domain to revoke trust\n"));
6747 return -1;
6750 /* generate upper cased domain name */
6751 domain_name = smb_xstrdup(argv[0]);
6752 if (!strupper_m(domain_name)) {
6753 SAFE_FREE(domain_name);
6754 return -1;
6757 /* delete password of the trust */
6758 if (!pdb_del_trusteddom_pw(domain_name)) {
6759 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6760 domain_name));
6761 goto done;
6764 rc = 0;
6765 done:
6766 SAFE_FREE(domain_name);
6767 return rc;
6770 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6771 const struct dom_sid *domain_sid,
6772 const char *domain_name,
6773 struct cli_state *cli,
6774 struct rpc_pipe_client *pipe_hnd,
6775 TALLOC_CTX *mem_ctx,
6776 int argc,
6777 const char **argv)
6779 struct dom_sid_buf sid_str;
6780 d_printf("%s\n", dom_sid_str_buf(domain_sid, &sid_str));
6781 return NT_STATUS_OK;
6784 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6786 struct dom_sid_buf sid_str;
6788 d_printf("%-20s%s\n",
6789 trusted_dom_name,
6790 dom_sid_str_buf(dom_sid, &sid_str));
6793 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6794 TALLOC_CTX *mem_ctx,
6795 struct policy_handle *pol,
6796 struct dom_sid dom_sid,
6797 const char *trusted_dom_name)
6799 NTSTATUS nt_status, result;
6800 union lsa_TrustedDomainInfo *info = NULL;
6801 char *cleartextpwd = NULL;
6802 DATA_BLOB session_key;
6803 DATA_BLOB data = data_blob_null;
6804 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6806 nt_status = dcerpc_lsa_QueryTrustedDomainInfoBySid(b, mem_ctx,
6807 pol,
6808 &dom_sid,
6809 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6810 &info,
6811 &result);
6812 if (NT_STATUS_IS_ERR(nt_status)) {
6813 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6814 nt_errstr(nt_status)));
6815 goto done;
6817 if (NT_STATUS_IS_ERR(result)) {
6818 nt_status = result;
6819 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6820 nt_errstr(result)));
6821 goto done;
6824 data = data_blob(info->password.password->data,
6825 info->password.password->length);
6827 nt_status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6828 if (!NT_STATUS_IS_OK(nt_status)) {
6829 DEBUG(0, ("Could not retrieve session key: %s\n", nt_errstr(nt_status)));
6830 goto done;
6833 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key);
6834 data_blob_free(&session_key);
6836 if (cleartextpwd == NULL) {
6837 DEBUG(0,("retrieved NULL password\n"));
6838 nt_status = NT_STATUS_UNSUCCESSFUL;
6839 goto done;
6842 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6843 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6844 nt_status = NT_STATUS_UNSUCCESSFUL;
6845 goto done;
6848 #ifdef DEBUG_PASSWORD
6850 struct dom_sid_buf buf;
6851 DEBUG(100,("successfully vampired trusted domain [%s], "
6852 "sid: [%s], password: [%s]\n",
6853 trusted_dom_name,
6854 dom_sid_str_buf(&dom_sid, &buf),
6855 cleartextpwd));
6857 #endif
6859 done:
6860 SAFE_FREE(cleartextpwd);
6861 data_blob_free(&data);
6863 return nt_status;
6866 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6867 const char **argv)
6869 /* common variables */
6870 TALLOC_CTX* mem_ctx;
6871 struct cli_state *cli = NULL;
6872 struct rpc_pipe_client *pipe_hnd = NULL;
6873 NTSTATUS nt_status, result;
6874 const char *domain_name = NULL;
6875 struct policy_handle connect_hnd;
6876 union lsa_PolicyInformation *info = NULL;
6878 /* trusted domains listing variables */
6879 unsigned int enum_ctx = 0;
6880 int i;
6881 struct lsa_DomainList dom_list;
6882 fstring pdc_name;
6883 struct dcerpc_binding_handle *b;
6885 if (c->display_usage) {
6886 d_printf( "%s\n"
6887 "net rpc trustdom vampire\n"
6888 " %s\n",
6889 _("Usage:"),
6890 _("Vampire trust relationship from remote server"));
6891 return 0;
6895 * Listing trusted domains (stored in secrets.tdb, if local)
6898 mem_ctx = talloc_init("trust relationships vampire");
6901 * set domain and pdc name to local samba server (default)
6902 * or to remote one given in command line
6905 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6906 domain_name = c->opt_workgroup;
6907 c->opt_target_workgroup = c->opt_workgroup;
6908 } else {
6909 fstrcpy(pdc_name, lp_netbios_name());
6910 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6911 c->opt_target_workgroup = domain_name;
6914 /* open \PIPE\lsarpc and open policy handle */
6915 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6916 if (!NT_STATUS_IS_OK(nt_status)) {
6917 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6918 nt_errstr(nt_status)));
6919 talloc_destroy(mem_ctx);
6920 return -1;
6923 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6924 &pipe_hnd);
6925 if (!NT_STATUS_IS_OK(nt_status)) {
6926 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6927 nt_errstr(nt_status) ));
6928 cli_shutdown(cli);
6929 talloc_destroy(mem_ctx);
6930 return -1;
6933 b = pipe_hnd->binding_handle;
6935 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6936 &connect_hnd);
6937 if (NT_STATUS_IS_ERR(nt_status)) {
6938 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6939 nt_errstr(nt_status)));
6940 cli_shutdown(cli);
6941 talloc_destroy(mem_ctx);
6942 return -1;
6945 /* query info level 5 to obtain sid of a domain being queried */
6946 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6947 &connect_hnd,
6948 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6949 &info,
6950 &result);
6952 if (NT_STATUS_IS_ERR(nt_status)) {
6953 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6954 nt_errstr(nt_status)));
6955 cli_shutdown(cli);
6956 talloc_destroy(mem_ctx);
6957 return -1;
6959 if (NT_STATUS_IS_ERR(result)) {
6960 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6961 nt_errstr(result)));
6962 cli_shutdown(cli);
6963 talloc_destroy(mem_ctx);
6964 return -1;
6968 * Keep calling LsaEnumTrustdom over opened pipe until
6969 * the end of enumeration is reached
6972 d_printf(_("Vampire trusted domains:\n\n"));
6974 do {
6975 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6976 &connect_hnd,
6977 &enum_ctx,
6978 &dom_list,
6979 (uint32_t)-1,
6980 &result);
6981 if (NT_STATUS_IS_ERR(nt_status)) {
6982 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6983 nt_errstr(nt_status)));
6984 cli_shutdown(cli);
6985 talloc_destroy(mem_ctx);
6986 return -1;
6988 if (NT_STATUS_IS_ERR(result)) {
6989 nt_status = result;
6990 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6991 nt_errstr(result)));
6992 cli_shutdown(cli);
6993 talloc_destroy(mem_ctx);
6994 return -1;
6998 for (i = 0; i < dom_list.count; i++) {
7000 print_trusted_domain(dom_list.domains[i].sid,
7001 dom_list.domains[i].name.string);
7003 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
7004 *dom_list.domains[i].sid,
7005 dom_list.domains[i].name.string);
7006 if (!NT_STATUS_IS_OK(nt_status)) {
7007 cli_shutdown(cli);
7008 talloc_destroy(mem_ctx);
7009 return -1;
7014 * in case of no trusted domains say something rather
7015 * than just display blank line
7017 if (!dom_list.count) d_printf(_("none\n"));
7019 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
7021 /* close this connection before doing next one */
7022 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
7023 if (NT_STATUS_IS_ERR(nt_status)) {
7024 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
7025 nt_errstr(nt_status)));
7026 cli_shutdown(cli);
7027 talloc_destroy(mem_ctx);
7028 return -1;
7031 /* close lsarpc pipe and connection to IPC$ */
7032 cli_shutdown(cli);
7034 talloc_destroy(mem_ctx);
7035 return 0;
7038 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
7040 /* common variables */
7041 TALLOC_CTX* mem_ctx;
7042 struct cli_state *cli = NULL, *remote_cli = NULL;
7043 struct rpc_pipe_client *pipe_hnd = NULL;
7044 NTSTATUS nt_status, result;
7045 const char *domain_name = NULL;
7046 struct dom_sid *queried_dom_sid;
7047 int ascii_dom_name_len;
7048 struct policy_handle connect_hnd;
7049 union lsa_PolicyInformation *info = NULL;
7050 struct dcerpc_binding_handle *b = NULL;
7052 /* trusted domains listing variables */
7053 unsigned int num_domains, enum_ctx = 0;
7054 int i;
7055 struct lsa_DomainList dom_list;
7056 fstring pdc_name;
7057 bool found_domain;
7059 /* trusting domains listing variables */
7060 struct policy_handle domain_hnd;
7061 struct samr_SamArray *trusts = NULL;
7063 if (c->display_usage) {
7064 d_printf( "%s\n"
7065 "net rpc trustdom list\n"
7066 " %s\n",
7067 _("Usage:"),
7068 _("List incoming and outgoing trust relationships"));
7069 return 0;
7073 * Listing trusted domains (stored in secrets.tdb, if local)
7076 mem_ctx = talloc_init("trust relationships listing");
7079 * set domain and pdc name to local samba server (default)
7080 * or to remote one given in command line
7083 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
7084 domain_name = c->opt_workgroup;
7085 c->opt_target_workgroup = c->opt_workgroup;
7086 } else {
7087 fstrcpy(pdc_name, lp_netbios_name());
7088 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
7089 c->opt_target_workgroup = domain_name;
7092 /* open \PIPE\lsarpc and open policy handle */
7093 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
7094 if (!NT_STATUS_IS_OK(nt_status)) {
7095 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
7096 nt_errstr(nt_status)));
7097 talloc_destroy(mem_ctx);
7098 return -1;
7101 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
7102 &pipe_hnd);
7103 if (!NT_STATUS_IS_OK(nt_status)) {
7104 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
7105 nt_errstr(nt_status) ));
7106 cli_shutdown(cli);
7107 talloc_destroy(mem_ctx);
7108 return -1;
7111 b = pipe_hnd->binding_handle;
7113 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
7114 &connect_hnd);
7115 if (NT_STATUS_IS_ERR(nt_status)) {
7116 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
7117 nt_errstr(nt_status)));
7118 cli_shutdown(cli);
7119 talloc_destroy(mem_ctx);
7120 return -1;
7123 /* query info level 5 to obtain sid of a domain being queried */
7124 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
7125 &connect_hnd,
7126 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
7127 &info,
7128 &result);
7130 if (NT_STATUS_IS_ERR(nt_status)) {
7131 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7132 nt_errstr(nt_status)));
7133 cli_shutdown(cli);
7134 talloc_destroy(mem_ctx);
7135 return -1;
7137 if (NT_STATUS_IS_ERR(result)) {
7138 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7139 nt_errstr(result)));
7140 cli_shutdown(cli);
7141 talloc_destroy(mem_ctx);
7142 return -1;
7145 queried_dom_sid = info->account_domain.sid;
7148 * Keep calling LsaEnumTrustdom over opened pipe until
7149 * the end of enumeration is reached
7152 d_printf(_("Trusted domains list:\n\n"));
7154 found_domain = false;
7156 do {
7157 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
7158 &connect_hnd,
7159 &enum_ctx,
7160 &dom_list,
7161 (uint32_t)-1,
7162 &result);
7163 if (NT_STATUS_IS_ERR(nt_status)) {
7164 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7165 nt_errstr(nt_status)));
7166 cli_shutdown(cli);
7167 talloc_destroy(mem_ctx);
7168 return -1;
7170 if (NT_STATUS_IS_ERR(result)) {
7171 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7172 nt_errstr(result)));
7173 cli_shutdown(cli);
7174 talloc_destroy(mem_ctx);
7175 return -1;
7179 for (i = 0; i < dom_list.count; i++) {
7180 print_trusted_domain(dom_list.domains[i].sid,
7181 dom_list.domains[i].name.string);
7182 found_domain = true;
7186 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
7189 * in case of no trusted domains say something rather
7190 * than just display blank line
7192 if (!found_domain) {
7193 d_printf(_("none\n"));
7196 /* close this connection before doing next one */
7197 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
7198 if (NT_STATUS_IS_ERR(nt_status)) {
7199 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
7200 nt_errstr(nt_status)));
7201 cli_shutdown(cli);
7202 talloc_destroy(mem_ctx);
7203 return -1;
7206 TALLOC_FREE(pipe_hnd);
7209 * Listing trusting domains (stored in passdb backend, if local)
7212 d_printf(_("\nTrusting domains list:\n\n"));
7215 * Open \PIPE\samr and get needed policy handles
7217 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
7218 &pipe_hnd);
7219 if (!NT_STATUS_IS_OK(nt_status)) {
7220 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
7221 cli_shutdown(cli);
7222 talloc_destroy(mem_ctx);
7223 return -1;
7226 b = pipe_hnd->binding_handle;
7228 /* SamrConnect2 */
7229 nt_status = dcerpc_samr_Connect2(b, mem_ctx,
7230 pipe_hnd->desthost,
7231 SAMR_ACCESS_LOOKUP_DOMAIN,
7232 &connect_hnd,
7233 &result);
7234 if (!NT_STATUS_IS_OK(nt_status)) {
7235 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7236 nt_errstr(nt_status)));
7237 cli_shutdown(cli);
7238 talloc_destroy(mem_ctx);
7239 return -1;
7241 if (!NT_STATUS_IS_OK(result)) {
7242 nt_status = result;
7243 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7244 nt_errstr(result)));
7245 cli_shutdown(cli);
7246 talloc_destroy(mem_ctx);
7247 return -1;
7250 /* SamrOpenDomain - we have to open domain policy handle in order to be
7251 able to enumerate accounts*/
7252 nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
7253 &connect_hnd,
7254 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
7255 queried_dom_sid,
7256 &domain_hnd,
7257 &result);
7258 if (!NT_STATUS_IS_OK(nt_status)) {
7259 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7260 nt_errstr(nt_status)));
7261 cli_shutdown(cli);
7262 talloc_destroy(mem_ctx);
7263 return -1;
7265 if (!NT_STATUS_IS_OK(result)) {
7266 nt_status = result;
7267 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7268 nt_errstr(result)));
7269 cli_shutdown(cli);
7270 talloc_destroy(mem_ctx);
7271 return -1;
7275 * perform actual enumeration
7278 found_domain = false;
7280 enum_ctx = 0; /* reset enumeration context from last enumeration */
7281 do {
7283 nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
7284 &domain_hnd,
7285 &enum_ctx,
7286 ACB_DOMTRUST,
7287 &trusts,
7288 0xffff,
7289 &num_domains,
7290 &result);
7291 if (NT_STATUS_IS_ERR(nt_status)) {
7292 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7293 nt_errstr(nt_status)));
7294 cli_shutdown(cli);
7295 talloc_destroy(mem_ctx);
7296 return -1;
7298 if (NT_STATUS_IS_ERR(result)) {
7299 nt_status = result;
7300 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7301 nt_errstr(result)));
7302 cli_shutdown(cli);
7303 talloc_destroy(mem_ctx);
7304 return -1;
7307 for (i = 0; i < num_domains; i++) {
7309 char *str = discard_const_p(char, trusts->entries[i].name.string);
7311 found_domain = true;
7314 * get each single domain's sid (do we _really_ need this ?):
7315 * 1) connect to domain's pdc
7316 * 2) query the pdc for domain's sid
7319 /* get rid of '$' tail */
7320 ascii_dom_name_len = strlen(str);
7321 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
7322 str[ascii_dom_name_len - 1] = '\0';
7324 /* set opt_* variables to remote domain */
7325 if (!strupper_m(str)) {
7326 cli_shutdown(cli);
7327 talloc_destroy(mem_ctx);
7328 return -1;
7330 c->opt_workgroup = talloc_strdup(mem_ctx, str);
7331 c->opt_target_workgroup = c->opt_workgroup;
7333 d_printf("%-20s", str);
7335 /* connect to remote domain controller */
7336 nt_status = net_make_ipc_connection(c,
7337 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
7338 &remote_cli);
7339 if (NT_STATUS_IS_OK(nt_status)) {
7340 /* query for domain's sid */
7341 if (run_rpc_command(
7342 c, remote_cli,
7343 &ndr_table_lsarpc, 0,
7344 rpc_query_domain_sid, argc,
7345 argv))
7346 d_printf(_("strange - couldn't get domain's sid\n"));
7348 cli_shutdown(remote_cli);
7350 } else {
7351 d_fprintf(stderr, _("domain controller is not "
7352 "responding: %s\n"),
7353 nt_errstr(nt_status));
7354 d_printf(_("couldn't get domain's sid\n"));
7358 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
7360 if (!found_domain) {
7361 d_printf("none\n");
7364 /* close opened samr and domain policy handles */
7365 nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
7366 if (!NT_STATUS_IS_OK(nt_status)) {
7367 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
7370 nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
7371 if (!NT_STATUS_IS_OK(nt_status)) {
7372 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
7375 /* close samr pipe and connection to IPC$ */
7376 cli_shutdown(cli);
7378 talloc_destroy(mem_ctx);
7379 return 0;
7383 * Entrypoint for 'net rpc trustdom' code.
7385 * @param argc Standard argc.
7386 * @param argv Standard argv without initial components.
7388 * @return Integer status (0 means success).
7391 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
7393 struct functable func[] = {
7395 "add",
7396 rpc_trustdom_add,
7397 NET_TRANSPORT_RPC,
7398 N_("Add trusting domain's account"),
7399 N_("net rpc trustdom add\n"
7400 " Add trusting domain's account")
7403 "del",
7404 rpc_trustdom_del,
7405 NET_TRANSPORT_RPC,
7406 N_("Remove trusting domain's account"),
7407 N_("net rpc trustdom del\n"
7408 " Remove trusting domain's account")
7411 "establish",
7412 rpc_trustdom_establish,
7413 NET_TRANSPORT_RPC,
7414 N_("Establish outgoing trust relationship"),
7415 N_("net rpc trustdom establish\n"
7416 " Establish outgoing trust relationship")
7419 "revoke",
7420 rpc_trustdom_revoke,
7421 NET_TRANSPORT_RPC,
7422 N_("Revoke outgoing trust relationship"),
7423 N_("net rpc trustdom revoke\n"
7424 " Revoke outgoing trust relationship")
7427 "list",
7428 rpc_trustdom_list,
7429 NET_TRANSPORT_RPC,
7430 N_("List in- and outgoing domain trusts"),
7431 N_("net rpc trustdom list\n"
7432 " List in- and outgoing domain trusts")
7435 "vampire",
7436 rpc_trustdom_vampire,
7437 NET_TRANSPORT_RPC,
7438 N_("Vampire trusts from remote server"),
7439 N_("net rpc trustdom vampire\n"
7440 " Vampire trusts from remote server")
7442 {NULL, NULL, 0, NULL, NULL}
7445 return net_run_function(c, argc, argv, "net rpc trustdom", func);
7449 * Check if a server will take rpc commands
7450 * @param flags Type of server to connect to (PDC, DMB, localhost)
7451 * if the host is not explicitly specified
7452 * @return bool (true means rpc supported)
7454 bool net_rpc_check(struct net_context *c, unsigned flags)
7456 struct cli_state *cli;
7457 bool ret = false;
7458 struct sockaddr_storage server_ss;
7459 char *server_name = NULL;
7460 NTSTATUS status;
7462 /* flags (i.e. server type) may depend on command */
7463 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7464 return false;
7466 status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
7467 lp_netbios_name(), SMB_SIGNING_IPC_DEFAULT,
7468 0, &cli);
7469 if (!NT_STATUS_IS_OK(status)) {
7470 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
7471 DBG_ERR("NetBIOS support disabled, unable to connect\n");
7473 return false;
7475 status = smbXcli_negprot(cli->conn, cli->timeout,
7476 lp_client_min_protocol(),
7477 lp_client_max_protocol());
7478 if (!NT_STATUS_IS_OK(status))
7479 goto done;
7480 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1)
7481 goto done;
7483 ret = true;
7484 done:
7485 cli_shutdown(cli);
7486 return ret;
7489 /* syncronise sam database via samsync rpc calls */
7490 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7492 struct functable func[] = {
7494 "keytab",
7495 rpc_vampire_keytab,
7496 NET_TRANSPORT_RPC,
7497 N_("Dump remote SAM database to Kerberos Keytab"),
7498 N_("net rpc vampire keytab\n"
7499 " Dump remote SAM database to Kerberos keytab "
7500 "file")
7503 "passdb",
7504 rpc_vampire_passdb,
7505 NET_TRANSPORT_RPC,
7506 N_("Dump remote SAM database to passdb"),
7507 N_("net rpc vampire passdb\n"
7508 " Dump remote SAM database to passdb")
7511 {NULL, NULL, 0, NULL, NULL}
7514 if (argc == 0) {
7515 if (c->display_usage) {
7516 d_printf( "%s\n"
7517 "net rpc vampire\n"
7518 " %s\n",
7519 _("Usage:"),
7520 _("Vampire remote SAM database"));
7521 return 0;
7524 return rpc_vampire_passdb(c, argc, argv);
7527 return net_run_function(c, argc, argv, "net rpc vampire", func);
7531 * Migrate everything from a print server.
7533 * @param c A net_context structure.
7534 * @param argc Standard main() style argc.
7535 * @param argv Standard main() style argv. Initial components are already
7536 * stripped.
7538 * @return A shell status integer (0 for success).
7540 * The order is important !
7541 * To successfully add drivers the print queues have to exist !
7542 * Applying ACLs should be the last step, because you're easily locked out.
7545 static int rpc_printer_migrate_all(struct net_context *c, int argc,
7546 const char **argv)
7548 int ret;
7550 if (c->display_usage) {
7551 d_printf( "%s\n"
7552 "net rpc printer migrate all\n"
7553 " %s\n",
7554 _("Usage:"),
7555 _("Migrate everything from a print server"));
7556 return 0;
7559 if (!c->opt_host) {
7560 d_printf(_("no server to migrate\n"));
7561 return -1;
7564 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7565 rpc_printer_migrate_printers_internals, argc,
7566 argv);
7567 if (ret)
7568 return ret;
7570 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7571 rpc_printer_migrate_drivers_internals, argc,
7572 argv);
7573 if (ret)
7574 return ret;
7576 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7577 rpc_printer_migrate_forms_internals, argc, argv);
7578 if (ret)
7579 return ret;
7581 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7582 rpc_printer_migrate_settings_internals, argc,
7583 argv);
7584 if (ret)
7585 return ret;
7587 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7588 rpc_printer_migrate_security_internals, argc,
7589 argv);
7594 * Migrate print drivers from a print server.
7596 * @param c A net_context structure.
7597 * @param argc Standard main() style argc.
7598 * @param argv Standard main() style argv. Initial components are already
7599 * stripped.
7601 * @return A shell status integer (0 for success).
7603 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7604 const char **argv)
7606 if (c->display_usage) {
7607 d_printf( "%s\n"
7608 "net rpc printer migrate drivers\n"
7609 " %s\n",
7610 _("Usage:"),
7611 _("Migrate print-drivers from a print-server"));
7612 return 0;
7615 if (!c->opt_host) {
7616 d_printf(_("no server to migrate\n"));
7617 return -1;
7620 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7621 rpc_printer_migrate_drivers_internals,
7622 argc, argv);
7626 * Migrate print-forms from a print-server.
7628 * @param c A net_context structure.
7629 * @param argc Standard main() style argc.
7630 * @param argv Standard main() style argv. Initial components are already
7631 * stripped.
7633 * @return A shell status integer (0 for success).
7635 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7636 const char **argv)
7638 if (c->display_usage) {
7639 d_printf( "%s\n"
7640 "net rpc printer migrate forms\n"
7641 " %s\n",
7642 _("Usage:"),
7643 _("Migrate print-forms from a print-server"));
7644 return 0;
7647 if (!c->opt_host) {
7648 d_printf(_("no server to migrate\n"));
7649 return -1;
7652 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7653 rpc_printer_migrate_forms_internals,
7654 argc, argv);
7658 * Migrate printers from a print-server.
7660 * @param c A net_context structure.
7661 * @param argc Standard main() style argc.
7662 * @param argv Standard main() style argv. Initial components are already
7663 * stripped.
7665 * @return A shell status integer (0 for success).
7667 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7668 const char **argv)
7670 if (c->display_usage) {
7671 d_printf( "%s\n"
7672 "net rpc printer migrate printers\n"
7673 " %s\n",
7674 _("Usage:"),
7675 _("Migrate printers from a print-server"));
7676 return 0;
7679 if (!c->opt_host) {
7680 d_printf(_("no server to migrate\n"));
7681 return -1;
7684 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7685 rpc_printer_migrate_printers_internals,
7686 argc, argv);
7690 * Migrate printer-ACLs from a print-server
7692 * @param c A net_context structure.
7693 * @param argc Standard main() style argc.
7694 * @param argv Standard main() style argv. Initial components are already
7695 * stripped.
7697 * @return A shell status integer (0 for success).
7699 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7700 const char **argv)
7702 if (c->display_usage) {
7703 d_printf( "%s\n"
7704 "net rpc printer migrate security\n"
7705 " %s\n",
7706 _("Usage:"),
7707 _("Migrate printer-ACLs from a print-server"));
7708 return 0;
7711 if (!c->opt_host) {
7712 d_printf(_("no server to migrate\n"));
7713 return -1;
7716 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7717 rpc_printer_migrate_security_internals,
7718 argc, argv);
7722 * Migrate printer-settings from a print-server.
7724 * @param c A net_context structure.
7725 * @param argc Standard main() style argc.
7726 * @param argv Standard main() style argv. Initial components are already
7727 * stripped.
7729 * @return A shell status integer (0 for success).
7731 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7732 const char **argv)
7734 if (c->display_usage) {
7735 d_printf( "%s\n"
7736 "net rpc printer migrate settings\n"
7737 " %s\n",
7738 _("Usage:"),
7739 _("Migrate printer-settings from a "
7740 "print-server"));
7741 return 0;
7744 if (!c->opt_host) {
7745 d_printf(_("no server to migrate\n"));
7746 return -1;
7749 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7750 rpc_printer_migrate_settings_internals,
7751 argc, argv);
7755 * 'net rpc printer' entrypoint.
7757 * @param c A net_context structure.
7758 * @param argc Standard main() style argc.
7759 * @param argv Standard main() style argv. Initial components are already
7760 * stripped.
7763 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7766 /* ouch: when addriver and setdriver are called from within
7767 rpc_printer_migrate_drivers_internals, the printer-queue already
7768 *has* to exist */
7770 struct functable func[] = {
7772 "all",
7773 rpc_printer_migrate_all,
7774 NET_TRANSPORT_RPC,
7775 N_("Migrate all from remote to local print server"),
7776 N_("net rpc printer migrate all\n"
7777 " Migrate all from remote to local print server")
7780 "drivers",
7781 rpc_printer_migrate_drivers,
7782 NET_TRANSPORT_RPC,
7783 N_("Migrate drivers to local server"),
7784 N_("net rpc printer migrate drivers\n"
7785 " Migrate drivers to local server")
7788 "forms",
7789 rpc_printer_migrate_forms,
7790 NET_TRANSPORT_RPC,
7791 N_("Migrate froms to local server"),
7792 N_("net rpc printer migrate forms\n"
7793 " Migrate froms to local server")
7796 "printers",
7797 rpc_printer_migrate_printers,
7798 NET_TRANSPORT_RPC,
7799 N_("Migrate printers to local server"),
7800 N_("net rpc printer migrate printers\n"
7801 " Migrate printers to local server")
7804 "security",
7805 rpc_printer_migrate_security,
7806 NET_TRANSPORT_RPC,
7807 N_("Migrate printer ACLs to local server"),
7808 N_("net rpc printer migrate security\n"
7809 " Migrate printer ACLs to local server")
7812 "settings",
7813 rpc_printer_migrate_settings,
7814 NET_TRANSPORT_RPC,
7815 N_("Migrate printer settings to local server"),
7816 N_("net rpc printer migrate settings\n"
7817 " Migrate printer settings to local server")
7819 {NULL, NULL, 0, NULL, NULL}
7822 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7827 * List printers on a remote RPC server.
7829 * @param c A net_context structure.
7830 * @param argc Standard main() style argc.
7831 * @param argv Standard main() style argv. Initial components are already
7832 * stripped.
7834 * @return A shell status integer (0 for success).
7836 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7838 if (c->display_usage) {
7839 d_printf( "%s\n"
7840 "net rpc printer list\n"
7841 " %s\n",
7842 _("Usage:"),
7843 _("List printers on a remote RPC server"));
7844 return 0;
7847 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7848 rpc_printer_list_internals,
7849 argc, argv);
7853 * List printer-drivers on a remote RPC server.
7855 * @param c A net_context structure.
7856 * @param argc Standard main() style argc.
7857 * @param argv Standard main() style argv. Initial components are already
7858 * stripped.
7860 * @return A shell status integer (0 for success).
7862 static int rpc_printer_driver_list(struct net_context *c, int argc,
7863 const char **argv)
7865 if (c->display_usage) {
7866 d_printf( "%s\n"
7867 "net rpc printer driver\n"
7868 " %s\n",
7869 _("Usage:"),
7870 _("List printer-drivers on a remote RPC server"));
7871 return 0;
7874 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7875 rpc_printer_driver_list_internals,
7876 argc, argv);
7880 * Publish printer in ADS via MSRPC.
7882 * @param c A net_context structure.
7883 * @param argc Standard main() style argc.
7884 * @param argv Standard main() style argv. Initial components are already
7885 * stripped.
7887 * @return A shell status integer (0 for success).
7889 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7890 const char **argv)
7892 if (c->display_usage) {
7893 d_printf( "%s\n"
7894 "net rpc printer publish publish\n"
7895 " %s\n",
7896 _("Usage:"),
7897 _("Publish printer in ADS via MSRPC"));
7898 return 0;
7901 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7902 rpc_printer_publish_publish_internals,
7903 argc, argv);
7907 * Update printer in ADS via MSRPC.
7909 * @param c A net_context structure.
7910 * @param argc Standard main() style argc.
7911 * @param argv Standard main() style argv. Initial components are already
7912 * stripped.
7914 * @return A shell status integer (0 for success).
7916 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7918 if (c->display_usage) {
7919 d_printf( "%s\n"
7920 "net rpc printer publish update\n"
7921 " %s\n",
7922 _("Usage:"),
7923 _("Update printer in ADS via MSRPC"));
7924 return 0;
7927 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7928 rpc_printer_publish_update_internals,
7929 argc, argv);
7933 * UnPublish printer in ADS via MSRPC.
7935 * @param c A net_context structure.
7936 * @param argc Standard main() style argc.
7937 * @param argv Standard main() style argv. Initial components are already
7938 * stripped.
7940 * @return A shell status integer (0 for success).
7942 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7943 const char **argv)
7945 if (c->display_usage) {
7946 d_printf( "%s\n"
7947 "net rpc printer publish unpublish\n"
7948 " %s\n",
7949 _("Usage:\n"),
7950 _("UnPublish printer in ADS via MSRPC"));
7951 return 0;
7954 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7955 rpc_printer_publish_unpublish_internals,
7956 argc, argv);
7960 * List published printers via MSRPC.
7962 * @param c A net_context structure.
7963 * @param argc Standard main() style argc.
7964 * @param argv Standard main() style argv. Initial components are already
7965 * stripped.
7967 * @return A shell status integer (0 for success).
7969 static int rpc_printer_publish_list(struct net_context *c, int argc,
7970 const char **argv)
7972 if (c->display_usage) {
7973 d_printf( "%s\n"
7974 "net rpc printer publish list\n"
7975 " %s\n",
7976 _("Usage:"),
7977 _("List published printers via MSRPC"));
7978 return 0;
7981 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7982 rpc_printer_publish_list_internals,
7983 argc, argv);
7988 * Publish printer in ADS.
7990 * @param c A net_context structure.
7991 * @param argc Standard main() style argc.
7992 * @param argv Standard main() style argv. Initial components are already
7993 * stripped.
7995 * @return A shell status integer (0 for success).
7997 static int rpc_printer_publish(struct net_context *c, int argc,
7998 const char **argv)
8001 struct functable func[] = {
8003 "publish",
8004 rpc_printer_publish_publish,
8005 NET_TRANSPORT_RPC,
8006 N_("Publish printer in AD"),
8007 N_("net rpc printer publish publish\n"
8008 " Publish printer in AD")
8011 "update",
8012 rpc_printer_publish_update,
8013 NET_TRANSPORT_RPC,
8014 N_("Update printer in AD"),
8015 N_("net rpc printer publish update\n"
8016 " Update printer in AD")
8019 "unpublish",
8020 rpc_printer_publish_unpublish,
8021 NET_TRANSPORT_RPC,
8022 N_("Unpublish printer"),
8023 N_("net rpc printer publish unpublish\n"
8024 " Unpublish printer")
8027 "list",
8028 rpc_printer_publish_list,
8029 NET_TRANSPORT_RPC,
8030 N_("List published printers"),
8031 N_("net rpc printer publish list\n"
8032 " List published printers")
8034 {NULL, NULL, 0, NULL, NULL}
8037 if (argc == 0) {
8038 if (c->display_usage) {
8039 d_printf(_("Usage:\n"));
8040 d_printf(_("net rpc printer publish\n"
8041 " List published printers\n"
8042 " Alias of net rpc printer publish "
8043 "list\n"));
8044 net_display_usage_from_functable(func);
8045 return 0;
8047 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8048 rpc_printer_publish_list_internals,
8049 argc, argv);
8052 return net_run_function(c, argc, argv, "net rpc printer publish",func);
8058 * Display rpc printer help page.
8060 * @param c A net_context structure.
8061 * @param argc Standard main() style argc.
8062 * @param argv Standard main() style argv. Initial components are already
8063 * stripped.
8065 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
8067 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
8068 "\tlists all printers on print-server\n\n"));
8069 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
8070 "\tlists all printer-drivers on print-server\n\n"));
8071 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
8072 "\tpublishes printer settings in Active Directory\n"
8073 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
8074 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
8075 "\n\tmigrates printers from remote to local server\n\n"));
8076 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
8077 "\n\tmigrates printer-settings from remote to local server\n\n"));
8078 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
8079 "\n\tmigrates printer-drivers from remote to local server\n\n"));
8080 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
8081 "\n\tmigrates printer-forms from remote to local server\n\n"));
8082 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
8083 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
8084 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
8085 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
8086 "\tremote to local print-server\n\n"));
8087 net_common_methods_usage(c, argc, argv);
8088 net_common_flags_usage(c, argc, argv);
8089 d_printf(_(
8090 "\t-v or --verbose\t\t\tgive verbose output\n"
8091 "\t --destination\t\tmigration target server (default: localhost)\n"));
8093 return -1;
8097 * 'net rpc printer' entrypoint.
8099 * @param c A net_context structure.
8100 * @param argc Standard main() style argc.
8101 * @param argv Standard main() style argv. Initial components are already
8102 * stripped.
8104 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
8106 struct functable func[] = {
8108 "list",
8109 rpc_printer_list,
8110 NET_TRANSPORT_RPC,
8111 N_("List all printers on print server"),
8112 N_("net rpc printer list\n"
8113 " List all printers on print server")
8116 "migrate",
8117 rpc_printer_migrate,
8118 NET_TRANSPORT_RPC,
8119 N_("Migrate printer to local server"),
8120 N_("net rpc printer migrate\n"
8121 " Migrate printer to local server")
8124 "driver",
8125 rpc_printer_driver_list,
8126 NET_TRANSPORT_RPC,
8127 N_("List printer drivers"),
8128 N_("net rpc printer driver\n"
8129 " List printer drivers")
8132 "publish",
8133 rpc_printer_publish,
8134 NET_TRANSPORT_RPC,
8135 N_("Publish printer in AD"),
8136 N_("net rpc printer publish\n"
8137 " Publish printer in AD")
8139 {NULL, NULL, 0, NULL, NULL}
8142 if (argc == 0) {
8143 if (c->display_usage) {
8144 d_printf(_("Usage:\n"));
8145 d_printf(_("net rpc printer\n"
8146 " List printers\n"));
8147 net_display_usage_from_functable(func);
8148 return 0;
8150 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8151 rpc_printer_list_internals,
8152 argc, argv);
8155 return net_run_function(c, argc, argv, "net rpc printer", func);
8159 * 'net rpc' entrypoint.
8161 * @param c A net_context structure.
8162 * @param argc Standard main() style argc.
8163 * @param argv Standard main() style argv. Initial components are already
8164 * stripped.
8167 int net_rpc(struct net_context *c, int argc, const char **argv)
8169 NET_API_STATUS status;
8171 struct functable func[] = {
8173 "audit",
8174 net_rpc_audit,
8175 NET_TRANSPORT_RPC,
8176 N_("Modify global audit settings"),
8177 N_("net rpc audit\n"
8178 " Modify global audit settings")
8181 "info",
8182 net_rpc_info,
8183 NET_TRANSPORT_RPC,
8184 N_("Show basic info about a domain"),
8185 N_("net rpc info\n"
8186 " Show basic info about a domain")
8189 "join",
8190 net_rpc_join,
8191 NET_TRANSPORT_RPC,
8192 N_("Join a domain"),
8193 N_("net rpc join\n"
8194 " Join a domain")
8197 "oldjoin",
8198 net_rpc_oldjoin,
8199 NET_TRANSPORT_RPC,
8200 N_("Join a domain created in server manager"),
8201 N_("net rpc oldjoin\n"
8202 " Join a domain created in server manager")
8205 "testjoin",
8206 net_rpc_testjoin,
8207 NET_TRANSPORT_RPC,
8208 N_("Test that a join is valid"),
8209 N_("net rpc testjoin\n"
8210 " Test that a join is valid")
8213 "user",
8214 net_rpc_user,
8215 NET_TRANSPORT_RPC,
8216 N_("List/modify users"),
8217 N_("net rpc user\n"
8218 " List/modify users")
8221 "password",
8222 rpc_user_password,
8223 NET_TRANSPORT_RPC,
8224 N_("Change a user password"),
8225 N_("net rpc password\n"
8226 " Change a user password\n"
8227 " Alias for net rpc user password")
8230 "group",
8231 net_rpc_group,
8232 NET_TRANSPORT_RPC,
8233 N_("List/modify groups"),
8234 N_("net rpc group\n"
8235 " List/modify groups")
8238 "share",
8239 net_rpc_share,
8240 NET_TRANSPORT_RPC,
8241 N_("List/modify shares"),
8242 N_("net rpc share\n"
8243 " List/modify shares")
8246 "file",
8247 net_rpc_file,
8248 NET_TRANSPORT_RPC,
8249 N_("List open files"),
8250 N_("net rpc file\n"
8251 " List open files")
8254 "printer",
8255 net_rpc_printer,
8256 NET_TRANSPORT_RPC,
8257 N_("List/modify printers"),
8258 N_("net rpc printer\n"
8259 " List/modify printers")
8262 "changetrustpw",
8263 net_rpc_changetrustpw,
8264 NET_TRANSPORT_RPC,
8265 N_("Change trust account password"),
8266 N_("net rpc changetrustpw\n"
8267 " Change trust account password")
8270 "trustdom",
8271 rpc_trustdom,
8272 NET_TRANSPORT_RPC,
8273 N_("Modify domain trusts"),
8274 N_("net rpc trustdom\n"
8275 " Modify domain trusts")
8278 "abortshutdown",
8279 rpc_shutdown_abort,
8280 NET_TRANSPORT_RPC,
8281 N_("Abort a remote shutdown"),
8282 N_("net rpc abortshutdown\n"
8283 " Abort a remote shutdown")
8286 "shutdown",
8287 rpc_shutdown,
8288 NET_TRANSPORT_RPC,
8289 N_("Shutdown a remote server"),
8290 N_("net rpc shutdown\n"
8291 " Shutdown a remote server")
8294 "vampire",
8295 rpc_vampire,
8296 NET_TRANSPORT_RPC,
8297 N_("Sync a remote NT PDC's data into local passdb"),
8298 N_("net rpc vampire\n"
8299 " Sync a remote NT PDC's data into local passdb")
8302 "getsid",
8303 net_rpc_getsid,
8304 NET_TRANSPORT_RPC,
8305 N_("Fetch the domain sid into local secrets.tdb"),
8306 N_("net rpc getsid\n"
8307 " Fetch the domain sid into local secrets.tdb")
8310 "rights",
8311 net_rpc_rights,
8312 NET_TRANSPORT_RPC,
8313 N_("Manage privileges assigned to SID"),
8314 N_("net rpc rights\n"
8315 " Manage privileges assigned to SID")
8318 "service",
8319 net_rpc_service,
8320 NET_TRANSPORT_RPC,
8321 N_("Start/stop/query remote services"),
8322 N_("net rpc service\n"
8323 " Start/stop/query remote services")
8326 "registry",
8327 net_rpc_registry,
8328 NET_TRANSPORT_RPC,
8329 N_("Manage registry hives"),
8330 N_("net rpc registry\n"
8331 " Manage registry hives")
8334 "shell",
8335 net_rpc_shell,
8336 NET_TRANSPORT_RPC,
8337 N_("Open interactive shell on remote server"),
8338 N_("net rpc shell\n"
8339 " Open interactive shell on remote server")
8342 "trust",
8343 net_rpc_trust,
8344 NET_TRANSPORT_RPC,
8345 N_("Manage trusts"),
8346 N_("net rpc trust\n"
8347 " Manage trusts")
8350 "conf",
8351 net_rpc_conf,
8352 NET_TRANSPORT_RPC,
8353 N_("Configure a remote samba server"),
8354 N_("net rpc conf\n"
8355 " Configure a remote samba server")
8357 {NULL, NULL, 0, NULL, NULL}
8360 status = libnetapi_net_init(&c->netapi_ctx);
8361 if (status != 0) {
8362 return -1;
8364 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
8365 libnetapi_set_password(c->netapi_ctx, c->opt_password);
8366 if (c->opt_kerberos) {
8367 libnetapi_set_use_kerberos(c->netapi_ctx);
8369 if (c->opt_ccache) {
8370 libnetapi_set_use_ccache(c->netapi_ctx);
8373 return net_run_function(c, argc, argv, "net rpc", func);