CVE-2013-4408:s3:Ensure LookupNames replies arrays are range checked.
[Samba.git] / source3 / utils / net_rpc.c
blobe0c8eeacce5f79f1a1989821de61f76b0294f11d
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 "rpc_client/cli_pipe.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/cli_samr.h"
29 #include "rpc_client/init_samr.h"
30 #include "../librpc/gen_ndr/ndr_lsa_c.h"
31 #include "rpc_client/cli_lsarpc.h"
32 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
33 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
34 #include "../librpc/gen_ndr/ndr_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_initshutdown_c.h"
36 #include "../librpc/gen_ndr/ndr_winreg_c.h"
37 #include "secrets.h"
38 #include "lib/netapi/netapi.h"
39 #include "lib/netapi/netapi_net.h"
40 #include "rpc_client/init_lsa.h"
41 #include "../libcli/security/security.h"
42 #include "libsmb/libsmb.h"
43 #include "libsmb/clirap.h"
44 #include "nsswitch/libwbclient/wbclient.h"
45 #include "passdb.h"
46 #include "../libcli/smb/smbXcli_base.h"
48 static int net_mode_share;
49 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
51 /**
52 * @file net_rpc.c
54 * @brief RPC based subcommands for the 'net' utility.
56 * This file should contain much of the functionality that used to
57 * be found in rpcclient, execpt that the commands should change
58 * less often, and the fucntionality should be sane (the user is not
59 * expected to know a rid/sid before they conduct an operation etc.)
61 * @todo Perhaps eventually these should be split out into a number
62 * of files, as this could get quite big.
63 **/
66 /**
67 * Many of the RPC functions need the domain sid. This function gets
68 * it at the start of every run
70 * @param cli A cli_state already connected to the remote machine
72 * @return The Domain SID of the remote machine.
73 **/
75 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
76 struct dom_sid **domain_sid,
77 const char **domain_name)
79 struct rpc_pipe_client *lsa_pipe = NULL;
80 struct policy_handle pol;
81 NTSTATUS status, result;
82 union lsa_PolicyInformation *info = NULL;
83 struct dcerpc_binding_handle *b;
85 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
86 &lsa_pipe);
87 if (!NT_STATUS_IS_OK(status)) {
88 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
89 return status;
92 b = lsa_pipe->binding_handle;
94 status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
95 SEC_FLAG_MAXIMUM_ALLOWED,
96 &pol);
97 if (!NT_STATUS_IS_OK(status)) {
98 d_fprintf(stderr, "open_policy %s: %s\n",
99 _("failed"),
100 nt_errstr(status));
101 return status;
104 status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
105 &pol,
106 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
107 &info,
108 &result);
109 if (!NT_STATUS_IS_OK(status)) {
110 d_fprintf(stderr, "lsaquery %s: %s\n",
111 _("failed"),
112 nt_errstr(status));
113 return status;
115 if (!NT_STATUS_IS_OK(result)) {
116 d_fprintf(stderr, "lsaquery %s: %s\n",
117 _("failed"),
118 nt_errstr(result));
119 return result;
122 *domain_name = info->account_domain.name.string;
123 *domain_sid = info->account_domain.sid;
125 dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
126 TALLOC_FREE(lsa_pipe);
128 return NT_STATUS_OK;
132 * Run a single RPC command, from start to finish.
134 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
135 * @param conn_flag a NET_FLAG_ combination. Passed to
136 * net_make_ipc_connection.
137 * @param argc Standard main() style argc.
138 * @param argv Standard main() style argv. Initial components are already
139 * stripped.
140 * @return A shell status integer (0 for success).
143 int run_rpc_command(struct net_context *c,
144 struct cli_state *cli_arg,
145 const struct ndr_interface_table *table,
146 int conn_flags,
147 rpc_command_fn fn,
148 int argc,
149 const char **argv)
151 struct cli_state *cli = NULL;
152 struct rpc_pipe_client *pipe_hnd = NULL;
153 TALLOC_CTX *mem_ctx;
154 NTSTATUS nt_status;
155 struct dom_sid *domain_sid;
156 const char *domain_name;
157 int ret = -1;
159 /* make use of cli_state handed over as an argument, if possible */
160 if (!cli_arg) {
161 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
162 if (!NT_STATUS_IS_OK(nt_status)) {
163 DEBUG(1, ("failed to make ipc connection: %s\n",
164 nt_errstr(nt_status)));
165 return -1;
167 } else {
168 cli = cli_arg;
171 if (!cli) {
172 return -1;
175 /* Create mem_ctx */
177 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
178 DEBUG(0, ("talloc_init() failed\n"));
179 goto fail;
182 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
183 &domain_name);
184 if (!NT_STATUS_IS_OK(nt_status)) {
185 goto fail;
188 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
189 if (lp_client_schannel()
190 && (ndr_syntax_id_equal(&table->syntax_id,
191 &ndr_table_netlogon.syntax_id))) {
192 /* Always try and create an schannel netlogon pipe. */
193 nt_status = cli_rpc_pipe_open_schannel(
194 cli, &table->syntax_id, NCACN_NP,
195 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
196 &pipe_hnd);
197 if (!NT_STATUS_IS_OK(nt_status)) {
198 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
199 nt_errstr(nt_status) ));
200 goto fail;
202 } else {
203 if (conn_flags & NET_FLAGS_SEAL) {
204 nt_status = cli_rpc_pipe_open_generic_auth(
205 cli, table,
206 (conn_flags & NET_FLAGS_TCP) ?
207 NCACN_IP_TCP : NCACN_NP,
208 DCERPC_AUTH_TYPE_NTLMSSP,
209 DCERPC_AUTH_LEVEL_PRIVACY,
210 smbXcli_conn_remote_name(cli->conn),
211 lp_workgroup(), c->opt_user_name,
212 c->opt_password, &pipe_hnd);
213 } else {
214 nt_status = cli_rpc_pipe_open_noauth(
215 cli, &table->syntax_id,
216 &pipe_hnd);
218 if (!NT_STATUS_IS_OK(nt_status)) {
219 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
220 table->name,
221 nt_errstr(nt_status) ));
222 goto fail;
227 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
229 if (!NT_STATUS_IS_OK(nt_status)) {
230 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
231 } else {
232 ret = 0;
233 DEBUG(5, ("rpc command function succedded\n"));
236 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
237 if (pipe_hnd) {
238 TALLOC_FREE(pipe_hnd);
242 fail:
243 /* close the connection only if it was opened here */
244 if (!cli_arg) {
245 cli_shutdown(cli);
248 talloc_destroy(mem_ctx);
249 return ret;
253 * Force a change of the trust acccount password.
255 * All parameters are provided by the run_rpc_command function, except for
256 * argc, argv which are passed through.
258 * @param domain_sid The domain sid acquired from the remote server.
259 * @param cli A cli_state connected to the server.
260 * @param mem_ctx Talloc context, destroyed on completion of the function.
261 * @param argc Standard main() style argc.
262 * @param argv Standard main() style argv. Initial components are already
263 * stripped.
265 * @return Normal NTSTATUS return.
268 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
269 const struct dom_sid *domain_sid,
270 const char *domain_name,
271 struct cli_state *cli,
272 struct rpc_pipe_client *pipe_hnd,
273 TALLOC_CTX *mem_ctx,
274 int argc,
275 const char **argv)
277 NTSTATUS status;
279 status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
280 if (!NT_STATUS_IS_OK(status)) {
281 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
282 nt_errstr(status));
283 return status;
286 return NT_STATUS_OK;
290 * Force a change of the trust acccount password.
292 * @param argc Standard main() style argc.
293 * @param argv Standard main() style argv. Initial components are already
294 * stripped.
296 * @return A shell status integer (0 for success).
299 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
301 if (c->display_usage) {
302 d_printf( "%s\n"
303 "net rpc changetrustpw\n"
304 " %s\n",
305 _("Usage:"),
306 _("Change the machine trust password"));
307 return 0;
310 return run_rpc_command(c, NULL, &ndr_table_netlogon,
311 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
312 rpc_changetrustpw_internals,
313 argc, argv);
317 * Join a domain, the old way.
319 * This uses 'machinename' as the inital password, and changes it.
321 * The password should be created with 'server manager' or equiv first.
323 * All parameters are provided by the run_rpc_command function, except for
324 * argc, argv which are passed through.
326 * @param domain_sid The domain sid acquired from the remote server.
327 * @param cli A cli_state connected to the server.
328 * @param mem_ctx Talloc context, destroyed on completion of the function.
329 * @param argc Standard main() style argc.
330 * @param argv Standard main() style argv. Initial components are already
331 * stripped.
333 * @return Normal NTSTATUS return.
336 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
337 const struct dom_sid *domain_sid,
338 const char *domain_name,
339 struct cli_state *cli,
340 struct rpc_pipe_client *pipe_hnd,
341 TALLOC_CTX *mem_ctx,
342 int argc,
343 const char **argv)
346 fstring trust_passwd;
347 unsigned char orig_trust_passwd_hash[16];
348 NTSTATUS result;
349 enum netr_SchannelType sec_channel_type;
351 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
352 &pipe_hnd);
353 if (!NT_STATUS_IS_OK(result)) {
354 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
355 "error was %s\n",
356 smbXcli_conn_remote_name(cli->conn),
357 nt_errstr(result) ));
358 return result;
362 check what type of join - if the user want's to join as
363 a BDC, the server must agree that we are a BDC.
365 if (argc >= 0) {
366 sec_channel_type = get_sec_channel_type(argv[0]);
367 } else {
368 sec_channel_type = get_sec_channel_type(NULL);
371 fstrcpy(trust_passwd, lp_netbios_name());
372 if (!strlower_m(trust_passwd)) {
373 return NT_STATUS_UNSUCCESSFUL;
377 * Machine names can be 15 characters, but the max length on
378 * a password is 14. --jerry
381 trust_passwd[14] = '\0';
383 E_md4hash(trust_passwd, orig_trust_passwd_hash);
385 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
386 lp_netbios_name(),
387 orig_trust_passwd_hash,
388 sec_channel_type);
390 if (NT_STATUS_IS_OK(result))
391 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
394 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
395 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
396 result = NT_STATUS_UNSUCCESSFUL;
399 return result;
403 * Join a domain, the old way.
405 * @param argc Standard main() style argc.
406 * @param argv Standard main() style argv. Initial components are already
407 * stripped.
409 * @return A shell status integer (0 for success).
412 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
414 return run_rpc_command(c, NULL, &ndr_table_netlogon,
415 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
416 rpc_oldjoin_internals,
417 argc, argv);
421 * Join a domain, the old way. This function exists to allow
422 * the message to be displayed when oldjoin was explicitly
423 * requested, but not when it was implied by "net rpc join".
425 * @param argc Standard main() style argc.
426 * @param argv Standard main() style argv. Initial components are already
427 * stripped.
429 * @return A shell status integer (0 for success).
432 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
434 int rc = -1;
436 if (c->display_usage) {
437 d_printf( "%s\n"
438 "net rpc oldjoin\n"
439 " %s\n",
440 _("Usage:"),
441 _("Join a domain the old way"));
442 return 0;
445 rc = net_rpc_perform_oldjoin(c, argc, argv);
447 if (rc) {
448 d_fprintf(stderr, _("Failed to join domain\n"));
451 return rc;
455 * 'net rpc join' entrypoint.
456 * @param argc Standard main() style argc.
457 * @param argv Standard main() style argv. Initial components are already
458 * stripped
460 * Main 'net_rpc_join()' (where the admin username/password is used) is
461 * in net_rpc_join.c.
462 * Try to just change the password, but if that doesn't work, use/prompt
463 * for a username/password.
466 int net_rpc_join(struct net_context *c, int argc, const char **argv)
468 if (c->display_usage) {
469 d_printf("%s\n%s",
470 _("Usage:"),
471 _("net rpc join -U <username>[%%password] <type>\n"
472 " Join a domain\n"
473 " username\tName of the admin user"
474 " password\tPassword of the admin user, will "
475 "prompt if not specified\n"
476 " type\tCan be one of the following:\n"
477 "\t\tMEMBER\tJoin as member server (default)\n"
478 "\t\tBDC\tJoin as BDC\n"
479 "\t\tPDC\tJoin as PDC\n"));
480 return 0;
483 if (lp_server_role() == ROLE_STANDALONE) {
484 d_printf(_("cannot join as standalone machine\n"));
485 return -1;
488 if (strlen(lp_netbios_name()) > 15) {
489 d_printf(_("Our netbios name can be at most 15 chars long, "
490 "\"%s\" is %u chars long\n"),
491 lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
492 return -1;
495 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
496 return 0;
498 return net_rpc_join_newstyle(c, argc, argv);
502 * display info about a rpc domain
504 * All parameters are provided by the run_rpc_command function, except for
505 * argc, argv which are passed through.
507 * @param domain_sid The domain sid acquired from the remote server
508 * @param cli A cli_state connected to the server.
509 * @param mem_ctx Talloc context, destroyed on completion of the function.
510 * @param argc Standard main() style argc.
511 * @param argv Standard main() style argv. Initial components are already
512 * stripped.
514 * @return Normal NTSTATUS return.
517 NTSTATUS rpc_info_internals(struct net_context *c,
518 const struct dom_sid *domain_sid,
519 const char *domain_name,
520 struct cli_state *cli,
521 struct rpc_pipe_client *pipe_hnd,
522 TALLOC_CTX *mem_ctx,
523 int argc,
524 const char **argv)
526 struct policy_handle connect_pol, domain_pol;
527 NTSTATUS status, result;
528 union samr_DomainInfo *info = NULL;
529 fstring sid_str;
530 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
532 sid_to_fstring(sid_str, domain_sid);
534 /* Get sam policy handle */
535 status = dcerpc_samr_Connect2(b, mem_ctx,
536 pipe_hnd->desthost,
537 MAXIMUM_ALLOWED_ACCESS,
538 &connect_pol,
539 &result);
540 if (!NT_STATUS_IS_OK(status)) {
541 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
542 nt_errstr(status));
543 goto done;
546 if (!NT_STATUS_IS_OK(result)) {
547 status = result;
548 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
549 nt_errstr(result));
550 goto done;
553 /* Get domain policy handle */
554 status = dcerpc_samr_OpenDomain(b, mem_ctx,
555 &connect_pol,
556 MAXIMUM_ALLOWED_ACCESS,
557 discard_const_p(struct dom_sid2, domain_sid),
558 &domain_pol,
559 &result);
560 if (!NT_STATUS_IS_OK(status)) {
561 d_fprintf(stderr, _("Could not open domain: %s\n"),
562 nt_errstr(status));
563 goto done;
565 if (!NT_STATUS_IS_OK(result)) {
566 status = result;
567 d_fprintf(stderr, _("Could not open domain: %s\n"),
568 nt_errstr(result));
569 goto done;
572 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
573 &domain_pol,
575 &info,
576 &result);
577 if (!NT_STATUS_IS_OK(status)) {
578 goto done;
580 status = result;
581 if (NT_STATUS_IS_OK(result)) {
582 d_printf(_("Domain Name: %s\n"),
583 info->general.domain_name.string);
584 d_printf(_("Domain SID: %s\n"), sid_str);
585 d_printf(_("Sequence number: %llu\n"),
586 (unsigned long long)info->general.sequence_num);
587 d_printf(_("Num users: %u\n"), info->general.num_users);
588 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
589 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
592 done:
593 return status;
597 * 'net rpc info' entrypoint.
598 * @param argc Standard main() style argc.
599 * @param argv Standard main() style argv. Initial components are already
600 * stripped.
603 int net_rpc_info(struct net_context *c, int argc, const char **argv)
605 if (c->display_usage) {
606 d_printf( "%s\n"
607 "net rpc info\n"
608 " %s\n",
609 _("Usage:"),
610 _("Display information about the domain"));
611 return 0;
614 return run_rpc_command(c, NULL, &ndr_table_samr,
615 NET_FLAGS_PDC, rpc_info_internals,
616 argc, argv);
620 * Fetch domain SID into the local secrets.tdb.
622 * All parameters are provided by the run_rpc_command function, except for
623 * argc, argv which are passed through.
625 * @param domain_sid The domain sid acquired from the remote server.
626 * @param cli A cli_state connected to the server.
627 * @param mem_ctx Talloc context, destroyed on completion of the function.
628 * @param argc Standard main() style argc.
629 * @param argv Standard main() style argv. Initial components are already
630 * stripped.
632 * @return Normal NTSTATUS return.
635 static NTSTATUS rpc_getsid_internals(struct net_context *c,
636 const struct dom_sid *domain_sid,
637 const char *domain_name,
638 struct cli_state *cli,
639 struct rpc_pipe_client *pipe_hnd,
640 TALLOC_CTX *mem_ctx,
641 int argc,
642 const char **argv)
644 fstring sid_str;
646 sid_to_fstring(sid_str, domain_sid);
647 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
648 sid_str, domain_name);
650 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
651 DEBUG(0,("Can't store domain SID\n"));
652 return NT_STATUS_UNSUCCESSFUL;
655 return NT_STATUS_OK;
659 * 'net rpc getsid' entrypoint.
660 * @param argc Standard main() style argc.
661 * @param argv Standard main() style argv. Initial components are already
662 * stripped.
665 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
667 int conn_flags = NET_FLAGS_PDC;
669 if (!c->opt_user_specified) {
670 conn_flags |= NET_FLAGS_ANONYMOUS;
673 if (c->display_usage) {
674 d_printf( "%s\n"
675 "net rpc getsid\n"
676 " %s\n",
677 _("Usage:"),
678 _("Fetch domain SID into local secrets.tdb"));
679 return 0;
682 return run_rpc_command(c, NULL, &ndr_table_samr,
683 conn_flags,
684 rpc_getsid_internals,
685 argc, argv);
688 /****************************************************************************/
691 * Basic usage function for 'net rpc user'.
692 * @param argc Standard main() style argc.
693 * @param argv Standard main() style argv. Initial components are already
694 * stripped.
697 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
699 return net_user_usage(c, argc, argv);
703 * Add a new user to a remote RPC server.
705 * @param argc Standard main() style argc.
706 * @param argv Standard main() style argv. Initial components are already
707 * stripped.
709 * @return A shell status integer (0 for success).
712 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
714 NET_API_STATUS status;
715 struct USER_INFO_1 info1;
716 uint32_t parm_error = 0;
718 if (argc < 1 || c->display_usage) {
719 rpc_user_usage(c, argc, argv);
720 return 0;
723 ZERO_STRUCT(info1);
725 info1.usri1_name = argv[0];
726 if (argc == 2) {
727 info1.usri1_password = argv[1];
730 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
732 if (status != 0) {
733 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
734 argv[0], libnetapi_get_error_string(c->netapi_ctx,
735 status));
736 return -1;
737 } else {
738 d_printf(_("Added user '%s'.\n"), argv[0]);
741 return 0;
745 * Rename a user on a remote RPC server.
747 * @param argc Standard main() style argc.
748 * @param argv Standard main() style argv. Initial components are already
749 * stripped.
751 * @return A shell status integer (0 for success).
754 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
756 NET_API_STATUS status;
757 struct USER_INFO_0 u0;
758 uint32_t parm_err = 0;
760 if (argc != 2 || c->display_usage) {
761 rpc_user_usage(c, argc, argv);
762 return 0;
765 u0.usri0_name = argv[1];
767 status = NetUserSetInfo(c->opt_host, argv[0],
768 0, (uint8_t *)&u0, &parm_err);
769 if (status) {
770 d_fprintf(stderr,
771 _("Failed to rename user from %s to %s - %s\n"),
772 argv[0], argv[1],
773 libnetapi_get_error_string(c->netapi_ctx, status));
774 } else {
775 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
778 return status;
782 * Set a user's primary group
784 * @param argc Standard main() style argc.
785 * @param argv Standard main() style argv. Initial components are already
786 * stripped.
788 * @return A shell status integer (0 for success).
791 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
792 const char **argv)
794 NET_API_STATUS status;
795 uint8_t *buffer;
796 struct GROUP_INFO_2 *g2;
797 struct USER_INFO_1051 u1051;
798 uint32_t parm_err = 0;
800 if (argc != 2 || c->display_usage) {
801 rpc_user_usage(c, argc, argv);
802 return 0;
805 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
806 if (status) {
807 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
808 argv[1],
809 libnetapi_get_error_string(c->netapi_ctx, status));
810 return status;
812 g2 = (struct GROUP_INFO_2 *)buffer;
814 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
816 NetApiBufferFree(buffer);
818 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
819 (uint8_t *)&u1051, &parm_err);
820 if (status) {
821 d_fprintf(stderr,
822 _("Failed to set user's primary group %s to %s - "
823 "%s\n"), argv[0], argv[1],
824 libnetapi_get_error_string(c->netapi_ctx, status));
825 } else {
826 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
827 argv[1]);
829 return status;
833 * Delete a user from a remote RPC server.
835 * @param argc Standard main() style argc.
836 * @param argv Standard main() style argv. Initial components are already
837 * stripped.
839 * @return A shell status integer (0 for success).
842 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
844 NET_API_STATUS status;
846 if (argc < 1 || c->display_usage) {
847 rpc_user_usage(c, argc, argv);
848 return 0;
851 status = NetUserDel(c->opt_host, argv[0]);
853 if (status != 0) {
854 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
855 argv[0],
856 libnetapi_get_error_string(c->netapi_ctx, status));
857 return -1;
858 } else {
859 d_printf(_("Deleted user '%s'.\n"), argv[0]);
862 return 0;
866 * Set a user's password on a remote RPC server.
868 * @param argc Standard main() style argc.
869 * @param argv Standard main() style argv. Initial components are already
870 * stripped.
872 * @return A shell status integer (0 for success).
875 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
877 NET_API_STATUS status;
878 char *prompt = NULL;
879 struct USER_INFO_1003 u1003;
880 uint32_t parm_err = 0;
881 int ret;
883 if (argc < 1 || c->display_usage) {
884 rpc_user_usage(c, argc, argv);
885 return 0;
888 if (argv[1]) {
889 u1003.usri1003_password = argv[1];
890 } else {
891 char pwd[256] = {0};
892 ret = asprintf(&prompt, _("Enter new password for %s:"),
893 argv[0]);
894 if (ret == -1) {
895 return -1;
898 ret = samba_getpass(prompt, pwd, sizeof(pwd), false, false);
899 SAFE_FREE(prompt);
900 if (ret < 0) {
901 return -1;
904 u1003.usri1003_password = talloc_strdup(c, pwd);
905 if (u1003.usri1003_password == NULL) {
906 return -1;
910 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
912 /* Display results */
913 if (status != 0) {
914 d_fprintf(stderr,
915 _("Failed to set password for '%s' with error: %s.\n"),
916 argv[0], libnetapi_get_error_string(c->netapi_ctx,
917 status));
918 return -1;
921 return 0;
925 * List a user's groups from a remote RPC server.
927 * @param argc Standard main() style argc.
928 * @param argv Standard main() style argv. Initial components are already
929 * stripped.
931 * @return A shell status integer (0 for success)
934 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
937 NET_API_STATUS status;
938 struct GROUP_USERS_INFO_0 *u0 = NULL;
939 uint32_t entries_read = 0;
940 uint32_t total_entries = 0;
941 int i;
944 if (argc < 1 || c->display_usage) {
945 rpc_user_usage(c, argc, argv);
946 return 0;
949 status = NetUserGetGroups(c->opt_host,
950 argv[0],
952 (uint8_t **)(void *)&u0,
953 (uint32_t)-1,
954 &entries_read,
955 &total_entries);
956 if (status != 0) {
957 d_fprintf(stderr,
958 _("Failed to get groups for '%s' with error: %s.\n"),
959 argv[0], libnetapi_get_error_string(c->netapi_ctx,
960 status));
961 return -1;
964 for (i=0; i < entries_read; i++) {
965 printf("%s\n", u0->grui0_name);
966 u0++;
969 return 0;
973 * List users on a remote RPC server.
975 * All parameters are provided by the run_rpc_command function, except for
976 * argc, argv which are passed through.
978 * @param domain_sid The domain sid acquired from the remote server.
979 * @param cli A cli_state connected to the server.
980 * @param mem_ctx Talloc context, destroyed on completion of the function.
981 * @param argc Standard main() style argc.
982 * @param argv Standard main() style argv. Initial components are already
983 * stripped.
985 * @return Normal NTSTATUS return.
988 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
990 NET_API_STATUS status;
991 uint32_t start_idx=0, num_entries, i, loop_count = 0;
992 struct NET_DISPLAY_USER *info = NULL;
993 void *buffer = NULL;
995 /* Query domain users */
996 if (c->opt_long_list_entries)
997 d_printf(_("\nUser name Comment"
998 "\n-----------------------------\n"));
999 do {
1000 uint32_t max_entries, max_size;
1002 dcerpc_get_query_dispinfo_params(
1003 loop_count, &max_entries, &max_size);
1005 status = NetQueryDisplayInformation(c->opt_host,
1007 start_idx,
1008 max_entries,
1009 max_size,
1010 &num_entries,
1011 &buffer);
1012 if (status != 0 && status != ERROR_MORE_DATA) {
1013 return status;
1016 info = (struct NET_DISPLAY_USER *)buffer;
1018 for (i = 0; i < num_entries; i++) {
1020 if (c->opt_long_list_entries)
1021 printf("%-21.21s %s\n", info->usri1_name,
1022 info->usri1_comment);
1023 else
1024 printf("%s\n", info->usri1_name);
1025 info++;
1028 NetApiBufferFree(buffer);
1030 loop_count++;
1031 start_idx += num_entries;
1033 } while (status == ERROR_MORE_DATA);
1035 return status;
1039 * 'net rpc user' entrypoint.
1040 * @param argc Standard main() style argc.
1041 * @param argv Standard main() style argv. Initial components are already
1042 * stripped.
1045 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1047 NET_API_STATUS status;
1049 struct functable func[] = {
1051 "add",
1052 rpc_user_add,
1053 NET_TRANSPORT_RPC,
1054 N_("Add specified user"),
1055 N_("net rpc user add\n"
1056 " Add specified user")
1059 "info",
1060 rpc_user_info,
1061 NET_TRANSPORT_RPC,
1062 N_("List domain groups of user"),
1063 N_("net rpc user info\n"
1064 " List domain groups of user")
1067 "delete",
1068 rpc_user_delete,
1069 NET_TRANSPORT_RPC,
1070 N_("Remove specified user"),
1071 N_("net rpc user delete\n"
1072 " Remove specified user")
1075 "password",
1076 rpc_user_password,
1077 NET_TRANSPORT_RPC,
1078 N_("Change user password"),
1079 N_("net rpc user password\n"
1080 " Change user password")
1083 "rename",
1084 rpc_user_rename,
1085 NET_TRANSPORT_RPC,
1086 N_("Rename specified user"),
1087 N_("net rpc user rename\n"
1088 " Rename specified user")
1091 "setprimarygroup",
1092 rpc_user_setprimarygroup,
1093 NET_TRANSPORT_RPC,
1094 "Set a user's primary group",
1095 "net rpc user setprimarygroup\n"
1096 " Set a user's primary group"
1098 {NULL, NULL, 0, NULL, NULL}
1101 status = libnetapi_net_init(&c->netapi_ctx);
1102 if (status != 0) {
1103 return -1;
1105 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1106 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1107 if (c->opt_kerberos) {
1108 libnetapi_set_use_kerberos(c->netapi_ctx);
1111 if (argc == 0) {
1112 if (c->display_usage) {
1113 d_printf( "%s\n"
1114 "net rpc user\n"
1115 " %s\n",
1116 _("Usage:"),
1117 _("List all users"));
1118 net_display_usage_from_functable(func);
1119 return 0;
1122 return rpc_user_list(c, argc, argv);
1125 return net_run_function(c, argc, argv, "net rpc user", func);
1128 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1129 TALLOC_CTX *mem_ctx,
1130 struct rpc_sh_ctx *ctx,
1131 struct rpc_pipe_client *pipe_hnd,
1132 int argc, const char **argv)
1134 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1137 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1138 TALLOC_CTX *mem_ctx,
1139 struct rpc_sh_ctx *ctx,
1140 struct rpc_pipe_client *pipe_hnd,
1141 int argc, const char **argv)
1143 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1146 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1147 TALLOC_CTX *mem_ctx,
1148 struct rpc_sh_ctx *ctx,
1149 struct rpc_pipe_client *pipe_hnd,
1150 int argc, const char **argv,
1151 NTSTATUS (*fn)(
1152 struct net_context *c,
1153 TALLOC_CTX *mem_ctx,
1154 struct rpc_sh_ctx *ctx,
1155 struct rpc_pipe_client *pipe_hnd,
1156 struct policy_handle *user_hnd,
1157 int argc, const char **argv))
1159 struct policy_handle connect_pol, domain_pol, user_pol;
1160 NTSTATUS status, result;
1161 struct dom_sid sid;
1162 uint32 rid;
1163 enum lsa_SidType type;
1164 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1166 if (argc == 0) {
1167 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1168 ctx->whoami);
1169 return NT_STATUS_INVALID_PARAMETER;
1172 ZERO_STRUCT(connect_pol);
1173 ZERO_STRUCT(domain_pol);
1174 ZERO_STRUCT(user_pol);
1176 status = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1177 argv[0], NULL, NULL, &sid, &type);
1178 if (!NT_STATUS_IS_OK(status)) {
1179 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1180 nt_errstr(status));
1181 goto done;
1184 if (type != SID_NAME_USER) {
1185 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1186 sid_type_lookup(type));
1187 status = NT_STATUS_NO_SUCH_USER;
1188 goto done;
1191 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1192 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1193 status = NT_STATUS_NO_SUCH_USER;
1194 goto done;
1197 status = dcerpc_samr_Connect2(b, mem_ctx,
1198 pipe_hnd->desthost,
1199 MAXIMUM_ALLOWED_ACCESS,
1200 &connect_pol,
1201 &result);
1202 if (!NT_STATUS_IS_OK(status)) {
1203 goto done;
1205 if (!NT_STATUS_IS_OK(result)) {
1206 status = result;
1207 goto done;
1210 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1211 &connect_pol,
1212 MAXIMUM_ALLOWED_ACCESS,
1213 ctx->domain_sid,
1214 &domain_pol,
1215 &result);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 goto done;
1219 if (!NT_STATUS_IS_OK(result)) {
1220 status = result;
1221 goto done;
1224 status = dcerpc_samr_OpenUser(b, mem_ctx,
1225 &domain_pol,
1226 MAXIMUM_ALLOWED_ACCESS,
1227 rid,
1228 &user_pol,
1229 &result);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 goto done;
1233 if (!NT_STATUS_IS_OK(result)) {
1234 status = result;
1235 goto done;
1238 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1240 done:
1241 if (is_valid_policy_hnd(&user_pol)) {
1242 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1244 if (is_valid_policy_hnd(&domain_pol)) {
1245 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1247 if (is_valid_policy_hnd(&connect_pol)) {
1248 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1250 return status;
1253 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1254 TALLOC_CTX *mem_ctx,
1255 struct rpc_sh_ctx *ctx,
1256 struct rpc_pipe_client *pipe_hnd,
1257 struct policy_handle *user_hnd,
1258 int argc, const char **argv)
1260 NTSTATUS status, result;
1261 union samr_UserInfo *info = NULL;
1262 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1264 if (argc != 0) {
1265 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1266 ctx->whoami);
1267 return NT_STATUS_INVALID_PARAMETER;
1270 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1271 user_hnd,
1273 &info,
1274 &result);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 return status;
1278 if (!NT_STATUS_IS_OK(result)) {
1279 return result;
1282 d_printf(_("user rid: %d, group rid: %d\n"),
1283 info->info21.rid,
1284 info->info21.primary_gid);
1286 return result;
1289 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1290 TALLOC_CTX *mem_ctx,
1291 struct rpc_sh_ctx *ctx,
1292 struct rpc_pipe_client *pipe_hnd,
1293 int argc, const char **argv)
1295 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1296 rpc_sh_user_show_internals);
1299 #define FETCHSTR(name, rec) \
1300 do { if (strequal(ctx->thiscmd, name)) { \
1301 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1302 } while (0);
1304 #define SETSTR(name, rec, flag) \
1305 do { if (strequal(ctx->thiscmd, name)) { \
1306 init_lsa_String(&(info->info21.rec), argv[0]); \
1307 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1308 } while (0);
1310 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1311 TALLOC_CTX *mem_ctx,
1312 struct rpc_sh_ctx *ctx,
1313 struct rpc_pipe_client *pipe_hnd,
1314 struct policy_handle *user_hnd,
1315 int argc, const char **argv)
1317 NTSTATUS status, result;
1318 const char *username;
1319 const char *oldval = "";
1320 union samr_UserInfo *info = NULL;
1321 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1323 if (argc > 1) {
1324 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1325 _("Usage:"), ctx->whoami);
1326 return NT_STATUS_INVALID_PARAMETER;
1329 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1330 user_hnd,
1332 &info,
1333 &result);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 return status;
1337 if (!NT_STATUS_IS_OK(result)) {
1338 return result;
1341 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1343 FETCHSTR("fullname", full_name);
1344 FETCHSTR("homedir", home_directory);
1345 FETCHSTR("homedrive", home_drive);
1346 FETCHSTR("logonscript", logon_script);
1347 FETCHSTR("profilepath", profile_path);
1348 FETCHSTR("description", description);
1350 if (argc == 0) {
1351 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1352 goto done;
1355 if (strcmp(argv[0], "NULL") == 0) {
1356 argv[0] = "";
1359 ZERO_STRUCT(info->info21);
1361 SETSTR("fullname", full_name, FULL_NAME);
1362 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1363 SETSTR("homedrive", home_drive, HOME_DRIVE);
1364 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1365 SETSTR("profilepath", profile_path, PROFILE_PATH);
1366 SETSTR("description", description, DESCRIPTION);
1368 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1369 user_hnd,
1371 info,
1372 &result);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 return status;
1377 status = result;
1379 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1380 ctx->thiscmd, oldval, argv[0]);
1382 done:
1384 return status;
1387 #define HANDLEFLG(name, rec) \
1388 do { if (strequal(ctx->thiscmd, name)) { \
1389 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1390 if (newval) { \
1391 newflags = oldflags | ACB_##rec; \
1392 } else { \
1393 newflags = oldflags & ~ACB_##rec; \
1394 } } } while (0);
1396 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1397 TALLOC_CTX *mem_ctx,
1398 struct rpc_sh_ctx *ctx,
1399 struct rpc_pipe_client *pipe_hnd,
1400 int argc, const char **argv)
1402 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1403 rpc_sh_user_str_edit_internals);
1406 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1407 TALLOC_CTX *mem_ctx,
1408 struct rpc_sh_ctx *ctx,
1409 struct rpc_pipe_client *pipe_hnd,
1410 struct policy_handle *user_hnd,
1411 int argc, const char **argv)
1413 NTSTATUS status, result;
1414 const char *username;
1415 const char *oldval = "unknown";
1416 uint32 oldflags, newflags;
1417 bool newval;
1418 union samr_UserInfo *info = NULL;
1419 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1421 if ((argc > 1) ||
1422 ((argc == 1) && !strequal(argv[0], "yes") &&
1423 !strequal(argv[0], "no"))) {
1424 /* TRANSATORS: The yes|no here are program keywords. Please do
1425 not translate. */
1426 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1427 ctx->whoami);
1428 return NT_STATUS_INVALID_PARAMETER;
1431 newval = strequal(argv[0], "yes");
1433 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1434 user_hnd,
1436 &info,
1437 &result);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 return status;
1441 if (!NT_STATUS_IS_OK(result)) {
1442 return result;
1445 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1446 oldflags = info->info21.acct_flags;
1447 newflags = info->info21.acct_flags;
1449 HANDLEFLG("disabled", DISABLED);
1450 HANDLEFLG("pwnotreq", PWNOTREQ);
1451 HANDLEFLG("autolock", AUTOLOCK);
1452 HANDLEFLG("pwnoexp", PWNOEXP);
1454 if (argc == 0) {
1455 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1456 oldval);
1457 goto done;
1460 ZERO_STRUCT(info->info21);
1462 info->info21.acct_flags = newflags;
1463 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1465 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1466 user_hnd,
1468 info,
1469 &result);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 goto done;
1473 status = result;
1474 if (NT_STATUS_IS_OK(result)) {
1475 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1476 ctx->thiscmd, oldval, argv[0]);
1479 done:
1481 return status;
1484 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1485 TALLOC_CTX *mem_ctx,
1486 struct rpc_sh_ctx *ctx,
1487 struct rpc_pipe_client *pipe_hnd,
1488 int argc, const char **argv)
1490 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1491 rpc_sh_user_flag_edit_internals);
1494 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1495 TALLOC_CTX *mem_ctx,
1496 struct rpc_sh_ctx *ctx)
1498 static struct rpc_sh_cmd cmds[] = {
1500 { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1501 N_("Show/Set a user's full name") },
1503 { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1504 N_("Show/Set a user's home directory") },
1506 { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1507 N_("Show/Set a user's home drive") },
1509 { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1510 N_("Show/Set a user's logon script") },
1512 { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1513 N_("Show/Set a user's profile path") },
1515 { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1516 N_("Show/Set a user's description") },
1518 { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1519 N_("Show/Set whether a user is disabled") },
1521 { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1522 N_("Show/Set whether a user locked out") },
1524 { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1525 N_("Show/Set whether a user does not need a password") },
1527 { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1528 N_("Show/Set whether a user's password does not expire") },
1530 { NULL, NULL, 0, NULL, NULL }
1533 return cmds;
1536 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1537 TALLOC_CTX *mem_ctx,
1538 struct rpc_sh_ctx *ctx)
1540 static struct rpc_sh_cmd cmds[] = {
1542 { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1543 N_("List available users") },
1545 { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1546 N_("List the domain groups a user is member of") },
1548 { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1549 N_("Show info about a user") },
1551 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1552 N_("Show/Modify a user's fields") },
1554 { NULL, NULL, 0, NULL, NULL }
1557 return cmds;
1560 /****************************************************************************/
1563 * Basic usage function for 'net rpc group'.
1564 * @param argc Standard main() style argc.
1565 * @param argv Standard main() style argv. Initial components are already
1566 * stripped.
1569 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1571 return net_group_usage(c, argc, argv);
1575 * Delete group on a remote RPC server.
1577 * All parameters are provided by the run_rpc_command function, except for
1578 * argc, argv which are passed through.
1580 * @param domain_sid The domain sid acquired from the remote server.
1581 * @param cli A cli_state connected to the server.
1582 * @param mem_ctx Talloc context, destroyed on completion of the function.
1583 * @param argc Standard main() style argc.
1584 * @param argv Standard main() style argv. Initial components are already
1585 * stripped.
1587 * @return Normal NTSTATUS return.
1590 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1591 const struct dom_sid *domain_sid,
1592 const char *domain_name,
1593 struct cli_state *cli,
1594 struct rpc_pipe_client *pipe_hnd,
1595 TALLOC_CTX *mem_ctx,
1596 int argc,
1597 const char **argv)
1599 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1600 bool group_is_primary = false;
1601 NTSTATUS status, result;
1602 uint32_t group_rid;
1603 struct samr_RidAttrArray *rids = NULL;
1604 /* char **names; */
1605 int i;
1606 /* struct samr_RidWithAttribute *user_gids; */
1607 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1609 struct samr_Ids group_rids, name_types;
1610 struct lsa_String lsa_acct_name;
1611 union samr_UserInfo *info = NULL;
1613 if (argc < 1 || c->display_usage) {
1614 rpc_group_usage(c, argc,argv);
1615 return NT_STATUS_OK; /* ok? */
1618 status = dcerpc_samr_Connect2(b, mem_ctx,
1619 pipe_hnd->desthost,
1620 MAXIMUM_ALLOWED_ACCESS,
1621 &connect_pol,
1622 &result);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1625 goto done;
1628 if (!NT_STATUS_IS_OK(result)) {
1629 status = result;
1630 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1631 goto done;
1634 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1635 &connect_pol,
1636 MAXIMUM_ALLOWED_ACCESS,
1637 discard_const_p(struct dom_sid2, domain_sid),
1638 &domain_pol,
1639 &result);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 d_fprintf(stderr, _("Request open_domain failed\n"));
1642 goto done;
1645 if (!NT_STATUS_IS_OK(result)) {
1646 status = result;
1647 d_fprintf(stderr, _("Request open_domain failed\n"));
1648 goto done;
1651 init_lsa_String(&lsa_acct_name, argv[0]);
1653 status = dcerpc_samr_LookupNames(b, mem_ctx,
1654 &domain_pol,
1656 &lsa_acct_name,
1657 &group_rids,
1658 &name_types,
1659 &result);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1662 goto done;
1665 if (!NT_STATUS_IS_OK(result)) {
1666 status = result;
1667 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1668 goto done;
1670 if (group_rids.count != 1) {
1671 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1672 goto done;
1674 if (name_types.count != 1) {
1675 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1676 goto done;
1679 switch (name_types.ids[0])
1681 case SID_NAME_DOM_GRP:
1682 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1683 &domain_pol,
1684 MAXIMUM_ALLOWED_ACCESS,
1685 group_rids.ids[0],
1686 &group_pol,
1687 &result);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 d_fprintf(stderr, _("Request open_group failed"));
1690 goto done;
1693 if (!NT_STATUS_IS_OK(result)) {
1694 status = result;
1695 d_fprintf(stderr, _("Request open_group failed"));
1696 goto done;
1699 group_rid = group_rids.ids[0];
1701 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1702 &group_pol,
1703 &rids,
1704 &result);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 d_fprintf(stderr,
1707 _("Unable to query group members of %s"),
1708 argv[0]);
1709 goto done;
1712 if (!NT_STATUS_IS_OK(result)) {
1713 status = result;
1714 d_fprintf(stderr,
1715 _("Unable to query group members of %s"),
1716 argv[0]);
1717 goto done;
1720 if (c->opt_verbose) {
1721 d_printf(
1722 _("Domain Group %s (rid: %d) has %d members\n"),
1723 argv[0],group_rid, rids->count);
1726 /* Check if group is anyone's primary group */
1727 for (i = 0; i < rids->count; i++)
1729 status = dcerpc_samr_OpenUser(b, mem_ctx,
1730 &domain_pol,
1731 MAXIMUM_ALLOWED_ACCESS,
1732 rids->rids[i],
1733 &user_pol,
1734 &result);
1735 if (!NT_STATUS_IS_OK(status)) {
1736 d_fprintf(stderr,
1737 _("Unable to open group member %d\n"),
1738 rids->rids[i]);
1739 goto done;
1742 if (!NT_STATUS_IS_OK(result)) {
1743 status = result;
1744 d_fprintf(stderr,
1745 _("Unable to open group member %d\n"),
1746 rids->rids[i]);
1747 goto done;
1750 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1751 &user_pol,
1753 &info,
1754 &result);
1755 if (!NT_STATUS_IS_OK(status)) {
1756 d_fprintf(stderr,
1757 _("Unable to lookup userinfo for group "
1758 "member %d\n"),
1759 rids->rids[i]);
1760 goto done;
1763 if (!NT_STATUS_IS_OK(result)) {
1764 status = result;
1765 d_fprintf(stderr,
1766 _("Unable to lookup userinfo for group "
1767 "member %d\n"),
1768 rids->rids[i]);
1769 goto done;
1772 if (info->info21.primary_gid == group_rid) {
1773 if (c->opt_verbose) {
1774 d_printf(_("Group is primary group "
1775 "of %s\n"),
1776 info->info21.account_name.string);
1778 group_is_primary = true;
1781 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1784 if (group_is_primary) {
1785 d_fprintf(stderr, _("Unable to delete group because "
1786 "some of it's members have it as primary "
1787 "group\n"));
1788 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1789 goto done;
1792 /* remove all group members */
1793 for (i = 0; i < rids->count; i++)
1795 if (c->opt_verbose)
1796 d_printf(_("Remove group member %d..."),
1797 rids->rids[i]);
1798 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
1799 &group_pol,
1800 rids->rids[i],
1801 &result);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 goto done;
1805 status = result;
1806 if (NT_STATUS_IS_OK(result)) {
1807 if (c->opt_verbose)
1808 d_printf(_("ok\n"));
1809 } else {
1810 if (c->opt_verbose)
1811 d_printf("%s\n", _("failed"));
1812 goto done;
1816 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
1817 &group_pol,
1818 &result);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 break;
1823 status = result;
1825 break;
1826 /* removing a local group is easier... */
1827 case SID_NAME_ALIAS:
1828 status = dcerpc_samr_OpenAlias(b, mem_ctx,
1829 &domain_pol,
1830 MAXIMUM_ALLOWED_ACCESS,
1831 group_rids.ids[0],
1832 &group_pol,
1833 &result);
1834 if (!NT_STATUS_IS_OK(status)) {
1835 d_fprintf(stderr, _("Request open_alias failed\n"));
1836 goto done;
1838 if (!NT_STATUS_IS_OK(result)) {
1839 status = result;
1840 d_fprintf(stderr, _("Request open_alias failed\n"));
1841 goto done;
1844 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
1845 &group_pol,
1846 &result);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 break;
1851 status = result;
1853 break;
1854 default:
1855 d_fprintf(stderr, _("%s is of type %s. This command is only "
1856 "for deleting local or global groups\n"),
1857 argv[0],sid_type_lookup(name_types.ids[0]));
1858 status = NT_STATUS_UNSUCCESSFUL;
1859 goto done;
1862 if (NT_STATUS_IS_OK(status)) {
1863 if (c->opt_verbose)
1864 d_printf(_("Deleted %s '%s'\n"),
1865 sid_type_lookup(name_types.ids[0]), argv[0]);
1866 } else {
1867 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1868 get_friendly_nt_error_msg(status));
1871 done:
1872 return status;
1876 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1878 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
1879 rpc_group_delete_internals, argc,argv);
1882 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1884 NET_API_STATUS status;
1885 struct GROUP_INFO_1 info1;
1886 uint32_t parm_error = 0;
1888 if (argc != 1 || c->display_usage) {
1889 rpc_group_usage(c, argc, argv);
1890 return 0;
1893 ZERO_STRUCT(info1);
1895 info1.grpi1_name = argv[0];
1896 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1897 info1.grpi1_comment = c->opt_comment;
1900 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1902 if (status != 0) {
1903 d_fprintf(stderr,
1904 _("Failed to add group '%s' with error: %s.\n"),
1905 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1906 status));
1907 return -1;
1908 } else {
1909 d_printf(_("Added group '%s'.\n"), argv[0]);
1912 return 0;
1915 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1917 NET_API_STATUS status;
1918 struct LOCALGROUP_INFO_1 info1;
1919 uint32_t parm_error = 0;
1921 if (argc != 1 || c->display_usage) {
1922 rpc_group_usage(c, argc, argv);
1923 return 0;
1926 ZERO_STRUCT(info1);
1928 info1.lgrpi1_name = argv[0];
1929 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1930 info1.lgrpi1_comment = c->opt_comment;
1933 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1935 if (status != 0) {
1936 d_fprintf(stderr,
1937 _("Failed to add alias '%s' with error: %s.\n"),
1938 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1939 status));
1940 return -1;
1941 } else {
1942 d_printf(_("Added alias '%s'.\n"), argv[0]);
1945 return 0;
1948 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1950 if (c->opt_localgroup)
1951 return rpc_alias_add_internals(c, argc, argv);
1953 return rpc_group_add_internals(c, argc, argv);
1956 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1957 TALLOC_CTX *mem_ctx,
1958 const char *name,
1959 struct dom_sid *sid,
1960 enum lsa_SidType *type)
1962 struct dom_sid *sids = NULL;
1963 enum lsa_SidType *types = NULL;
1964 struct rpc_pipe_client *pipe_hnd = NULL;
1965 struct policy_handle lsa_pol;
1966 NTSTATUS status, result;
1967 struct dcerpc_binding_handle *b;
1969 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1970 &pipe_hnd);
1971 if (!NT_STATUS_IS_OK(status)) {
1972 goto done;
1975 b = pipe_hnd->binding_handle;
1977 status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1978 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1980 if (!NT_STATUS_IS_OK(status)) {
1981 goto done;
1984 status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1985 &name, NULL, 1, &sids, &types);
1987 if (NT_STATUS_IS_OK(status)) {
1988 sid_copy(sid, &sids[0]);
1989 *type = types[0];
1992 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
1994 done:
1995 if (pipe_hnd) {
1996 TALLOC_FREE(pipe_hnd);
1999 if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
2001 /* Try as S-1-5-whatever */
2003 struct dom_sid tmp_sid;
2005 if (string_to_sid(&tmp_sid, name)) {
2006 sid_copy(sid, &tmp_sid);
2007 *type = SID_NAME_UNKNOWN;
2008 status = NT_STATUS_OK;
2012 return status;
2015 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2016 TALLOC_CTX *mem_ctx,
2017 const struct dom_sid *group_sid,
2018 const char *member)
2020 struct policy_handle connect_pol, domain_pol;
2021 NTSTATUS status, result;
2022 uint32 group_rid;
2023 struct policy_handle group_pol;
2024 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2026 struct samr_Ids rids, rid_types;
2027 struct lsa_String lsa_acct_name;
2029 struct dom_sid sid;
2031 sid_copy(&sid, group_sid);
2033 if (!sid_split_rid(&sid, &group_rid)) {
2034 return NT_STATUS_UNSUCCESSFUL;
2037 /* Get sam policy handle */
2038 status = dcerpc_samr_Connect2(b, mem_ctx,
2039 pipe_hnd->desthost,
2040 MAXIMUM_ALLOWED_ACCESS,
2041 &connect_pol,
2042 &result);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 return status;
2046 if (!NT_STATUS_IS_OK(result)) {
2047 return result;
2050 /* Get domain policy handle */
2051 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2052 &connect_pol,
2053 MAXIMUM_ALLOWED_ACCESS,
2054 &sid,
2055 &domain_pol,
2056 &result);
2057 if (!NT_STATUS_IS_OK(status)) {
2058 return status;
2060 if (!NT_STATUS_IS_OK(result)) {
2061 return result;
2064 init_lsa_String(&lsa_acct_name, member);
2066 status = dcerpc_samr_LookupNames(b, mem_ctx,
2067 &domain_pol,
2069 &lsa_acct_name,
2070 &rids,
2071 &rid_types,
2072 &result);
2073 if (!NT_STATUS_IS_OK(status)) {
2074 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2075 member);
2076 goto done;
2079 if (!NT_STATUS_IS_OK(result)) {
2080 status = result;
2081 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2082 member);
2083 goto done;
2085 if (rids.count != 1) {
2086 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2087 goto done;
2089 if (rid_types.count != 1) {
2090 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2091 goto done;
2094 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2095 &domain_pol,
2096 MAXIMUM_ALLOWED_ACCESS,
2097 group_rid,
2098 &group_pol,
2099 &result);
2100 if (!NT_STATUS_IS_OK(status)) {
2101 goto done;
2104 if (!NT_STATUS_IS_OK(result)) {
2105 status = result;
2106 goto done;
2109 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2110 &group_pol,
2111 rids.ids[0],
2112 0x0005, /* unknown flags */
2113 &result);
2114 if (!NT_STATUS_IS_OK(status)) {
2115 goto done;
2118 status = result;
2120 done:
2121 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2122 return status;
2125 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2126 TALLOC_CTX *mem_ctx,
2127 const struct dom_sid *alias_sid,
2128 const char *member)
2130 struct policy_handle connect_pol, domain_pol;
2131 NTSTATUS status, result;
2132 uint32 alias_rid;
2133 struct policy_handle alias_pol;
2134 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2136 struct dom_sid member_sid;
2137 enum lsa_SidType member_type;
2139 struct dom_sid sid;
2141 sid_copy(&sid, alias_sid);
2143 if (!sid_split_rid(&sid, &alias_rid)) {
2144 return NT_STATUS_UNSUCCESSFUL;
2147 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2148 member, &member_sid, &member_type);
2150 if (!NT_STATUS_IS_OK(result)) {
2151 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2152 member);
2153 return result;
2156 /* Get sam policy handle */
2157 status = dcerpc_samr_Connect2(b, mem_ctx,
2158 pipe_hnd->desthost,
2159 MAXIMUM_ALLOWED_ACCESS,
2160 &connect_pol,
2161 &result);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 goto done;
2165 if (!NT_STATUS_IS_OK(result)) {
2166 status = result;
2167 goto done;
2170 /* Get domain policy handle */
2171 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2172 &connect_pol,
2173 MAXIMUM_ALLOWED_ACCESS,
2174 &sid,
2175 &domain_pol,
2176 &result);
2177 if (!NT_STATUS_IS_OK(status)) {
2178 goto done;
2180 if (!NT_STATUS_IS_OK(result)) {
2181 status = result;
2182 goto done;
2185 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2186 &domain_pol,
2187 MAXIMUM_ALLOWED_ACCESS,
2188 alias_rid,
2189 &alias_pol,
2190 &result);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 return status;
2194 if (!NT_STATUS_IS_OK(result)) {
2195 return result;
2198 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2199 &alias_pol,
2200 &member_sid,
2201 &result);
2202 if (!NT_STATUS_IS_OK(status)) {
2203 return status;
2206 status = result;
2208 done:
2209 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2210 return status;
2213 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2214 const struct dom_sid *domain_sid,
2215 const char *domain_name,
2216 struct cli_state *cli,
2217 struct rpc_pipe_client *pipe_hnd,
2218 TALLOC_CTX *mem_ctx,
2219 int argc,
2220 const char **argv)
2222 struct dom_sid group_sid;
2223 enum lsa_SidType group_type;
2225 if (argc != 2 || c->display_usage) {
2226 d_printf("%s\n%s",
2227 _("Usage:"),
2228 _("net rpc group addmem <group> <member>\n"
2229 " Add a member to a group\n"
2230 " group\tGroup to add member to\n"
2231 " member\tMember to add to group\n"));
2232 return NT_STATUS_UNSUCCESSFUL;
2235 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2236 &group_sid, &group_type))) {
2237 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2238 argv[0]);
2239 return NT_STATUS_UNSUCCESSFUL;
2242 if (group_type == SID_NAME_DOM_GRP) {
2243 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2244 &group_sid, argv[1]);
2246 if (!NT_STATUS_IS_OK(result)) {
2247 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2248 argv[1], argv[0], nt_errstr(result));
2250 return result;
2253 if (group_type == SID_NAME_ALIAS) {
2254 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2255 &group_sid, argv[1]);
2257 if (!NT_STATUS_IS_OK(result)) {
2258 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2259 argv[1], argv[0], nt_errstr(result));
2261 return result;
2264 d_fprintf(stderr, _("Can only add members to global or local groups "
2265 "which %s is not\n"), argv[0]);
2267 return NT_STATUS_UNSUCCESSFUL;
2270 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2272 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2273 rpc_group_addmem_internals,
2274 argc, argv);
2277 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2278 struct rpc_pipe_client *pipe_hnd,
2279 TALLOC_CTX *mem_ctx,
2280 const struct dom_sid *group_sid,
2281 const char *member)
2283 struct policy_handle connect_pol, domain_pol;
2284 NTSTATUS status, result;
2285 uint32 group_rid;
2286 struct policy_handle group_pol;
2287 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2289 struct samr_Ids rids, rid_types;
2290 struct lsa_String lsa_acct_name;
2292 struct dom_sid sid;
2294 sid_copy(&sid, group_sid);
2296 if (!sid_split_rid(&sid, &group_rid))
2297 return NT_STATUS_UNSUCCESSFUL;
2299 /* Get sam policy handle */
2300 status = dcerpc_samr_Connect2(b, mem_ctx,
2301 pipe_hnd->desthost,
2302 MAXIMUM_ALLOWED_ACCESS,
2303 &connect_pol,
2304 &result);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 return status;
2308 if (!NT_STATUS_IS_OK(result)) {
2309 return result;
2313 /* Get domain policy handle */
2314 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2315 &connect_pol,
2316 MAXIMUM_ALLOWED_ACCESS,
2317 &sid,
2318 &domain_pol,
2319 &result);
2320 if (!NT_STATUS_IS_OK(status)) {
2321 return status;
2323 if (!NT_STATUS_IS_OK(result)) {
2324 return result;
2327 init_lsa_String(&lsa_acct_name, member);
2329 status = dcerpc_samr_LookupNames(b, mem_ctx,
2330 &domain_pol,
2332 &lsa_acct_name,
2333 &rids,
2334 &rid_types,
2335 &result);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2338 member);
2339 goto done;
2342 if (!NT_STATUS_IS_OK(result)) {
2343 status = result;
2344 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2345 member);
2346 goto done;
2348 if (rids.count != 1) {
2349 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2350 goto done;
2352 if (rid_types.count != 1) {
2353 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2354 goto done;
2357 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2358 &domain_pol,
2359 MAXIMUM_ALLOWED_ACCESS,
2360 group_rid,
2361 &group_pol,
2362 &result);
2363 if (!NT_STATUS_IS_OK(status)) {
2364 goto done;
2366 if (!NT_STATUS_IS_OK(result)) {
2367 status = result;
2368 goto done;
2371 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2372 &group_pol,
2373 rids.ids[0],
2374 &result);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 goto done;
2379 status = result;
2380 done:
2381 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2382 return status;
2385 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2386 TALLOC_CTX *mem_ctx,
2387 const struct dom_sid *alias_sid,
2388 const char *member)
2390 struct policy_handle connect_pol, domain_pol;
2391 NTSTATUS status, result;
2392 uint32 alias_rid;
2393 struct policy_handle alias_pol;
2394 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2396 struct dom_sid member_sid;
2397 enum lsa_SidType member_type;
2399 struct dom_sid sid;
2401 sid_copy(&sid, alias_sid);
2403 if (!sid_split_rid(&sid, &alias_rid))
2404 return NT_STATUS_UNSUCCESSFUL;
2406 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2407 member, &member_sid, &member_type);
2409 if (!NT_STATUS_IS_OK(result)) {
2410 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2411 member);
2412 return result;
2415 /* Get sam policy handle */
2416 status = dcerpc_samr_Connect2(b, mem_ctx,
2417 pipe_hnd->desthost,
2418 MAXIMUM_ALLOWED_ACCESS,
2419 &connect_pol,
2420 &result);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 goto done;
2424 if (!NT_STATUS_IS_OK(result)) {
2425 status = result;
2426 goto done;
2429 /* Get domain policy handle */
2430 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2431 &connect_pol,
2432 MAXIMUM_ALLOWED_ACCESS,
2433 &sid,
2434 &domain_pol,
2435 &result);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 goto done;
2439 if (!NT_STATUS_IS_OK(result)) {
2440 status = result;
2441 goto done;
2444 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2445 &domain_pol,
2446 MAXIMUM_ALLOWED_ACCESS,
2447 alias_rid,
2448 &alias_pol,
2449 &result);
2450 if (!NT_STATUS_IS_OK(status)) {
2451 return status;
2454 if (!NT_STATUS_IS_OK(result)) {
2455 return result;
2458 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2459 &alias_pol,
2460 &member_sid,
2461 &result);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 return status;
2467 status = result;
2469 done:
2470 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2471 return status;
2474 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2475 const struct dom_sid *domain_sid,
2476 const char *domain_name,
2477 struct cli_state *cli,
2478 struct rpc_pipe_client *pipe_hnd,
2479 TALLOC_CTX *mem_ctx,
2480 int argc,
2481 const char **argv)
2483 struct dom_sid group_sid;
2484 enum lsa_SidType group_type;
2486 if (argc != 2 || c->display_usage) {
2487 d_printf("%s\n%s",
2488 _("Usage:"),
2489 _("net rpc group delmem <group> <member>\n"
2490 " Delete a member from a group\n"
2491 " group\tGroup to delete member from\n"
2492 " member\tMember to delete from group\n"));
2493 return NT_STATUS_UNSUCCESSFUL;
2496 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2497 &group_sid, &group_type))) {
2498 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2499 argv[0]);
2500 return NT_STATUS_UNSUCCESSFUL;
2503 if (group_type == SID_NAME_DOM_GRP) {
2504 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2505 &group_sid, argv[1]);
2507 if (!NT_STATUS_IS_OK(result)) {
2508 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2509 argv[1], argv[0], nt_errstr(result));
2511 return result;
2514 if (group_type == SID_NAME_ALIAS) {
2515 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2516 &group_sid, argv[1]);
2518 if (!NT_STATUS_IS_OK(result)) {
2519 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2520 argv[1], argv[0], nt_errstr(result));
2522 return result;
2525 d_fprintf(stderr, _("Can only delete members from global or local "
2526 "groups which %s is not\n"), argv[0]);
2528 return NT_STATUS_UNSUCCESSFUL;
2531 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2533 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2534 rpc_group_delmem_internals,
2535 argc, argv);
2539 * List groups on a remote RPC server.
2541 * All parameters are provided by the run_rpc_command function, except for
2542 * argc, argv which are passes through.
2544 * @param domain_sid The domain sid acquired from the remote server.
2545 * @param cli A cli_state connected to the server.
2546 * @param mem_ctx Talloc context, destroyed on completion of the function.
2547 * @param argc Standard main() style argc.
2548 * @param argv Standard main() style argv. Initial components are already
2549 * stripped.
2551 * @return Normal NTSTATUS return.
2554 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2555 const struct dom_sid *domain_sid,
2556 const char *domain_name,
2557 struct cli_state *cli,
2558 struct rpc_pipe_client *pipe_hnd,
2559 TALLOC_CTX *mem_ctx,
2560 int argc,
2561 const char **argv)
2563 struct policy_handle connect_pol, domain_pol;
2564 NTSTATUS status, result;
2565 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2566 struct samr_SamArray *groups = NULL;
2567 bool global = false;
2568 bool local = false;
2569 bool builtin = false;
2570 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2572 if (c->display_usage) {
2573 d_printf("%s\n%s",
2574 _("Usage:"),
2575 _("net rpc group list [global] [local] [builtin]\n"
2576 " List groups on RPC server\n"
2577 " global\tList global groups\n"
2578 " local\tList local groups\n"
2579 " builtin\tList builtin groups\n"
2580 " If none of global, local or builtin is "
2581 "specified, all three options are considered "
2582 "set\n"));
2583 return NT_STATUS_OK;
2586 if (argc == 0) {
2587 global = true;
2588 local = true;
2589 builtin = true;
2592 for (i=0; i<argc; i++) {
2593 if (strequal(argv[i], "global"))
2594 global = true;
2596 if (strequal(argv[i], "local"))
2597 local = true;
2599 if (strequal(argv[i], "builtin"))
2600 builtin = true;
2603 /* Get sam policy handle */
2605 status = dcerpc_samr_Connect2(b, mem_ctx,
2606 pipe_hnd->desthost,
2607 MAXIMUM_ALLOWED_ACCESS,
2608 &connect_pol,
2609 &result);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 goto done;
2613 if (!NT_STATUS_IS_OK(result)) {
2614 status = result;
2615 goto done;
2618 /* Get domain policy handle */
2620 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2621 &connect_pol,
2622 MAXIMUM_ALLOWED_ACCESS,
2623 discard_const_p(struct dom_sid2, domain_sid),
2624 &domain_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 /* Query domain groups */
2635 if (c->opt_long_list_entries)
2636 d_printf(_("\nGroup name Comment"
2637 "\n-----------------------------\n"));
2638 do {
2639 uint32_t max_size, total_size, returned_size;
2640 union samr_DispInfo info;
2642 if (!global) break;
2644 dcerpc_get_query_dispinfo_params(
2645 loop_count, &max_entries, &max_size);
2647 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2648 &domain_pol,
2650 start_idx,
2651 max_entries,
2652 max_size,
2653 &total_size,
2654 &returned_size,
2655 &info,
2656 &result);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 goto done;
2660 num_entries = info.info3.count;
2661 start_idx += info.info3.count;
2663 if (!NT_STATUS_IS_OK(result) &&
2664 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2665 break;
2667 for (i = 0; i < num_entries; i++) {
2669 const char *group = NULL;
2670 const char *desc = NULL;
2672 group = info.info3.entries[i].account_name.string;
2673 desc = info.info3.entries[i].description.string;
2675 if (c->opt_long_list_entries)
2676 printf("%-21.21s %-50.50s\n",
2677 group, desc);
2678 else
2679 printf("%s\n", group);
2681 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2682 /* query domain aliases */
2683 start_idx = 0;
2684 do {
2685 if (!local) break;
2687 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2688 &domain_pol,
2689 &start_idx,
2690 &groups,
2691 0xffff,
2692 &num_entries,
2693 &result);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 goto done;
2697 if (!NT_STATUS_IS_OK(result) &&
2698 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2699 break;
2701 for (i = 0; i < num_entries; i++) {
2703 const char *description = NULL;
2705 if (c->opt_long_list_entries) {
2707 struct policy_handle alias_pol;
2708 union samr_AliasInfo *info = NULL;
2709 NTSTATUS _result;
2711 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2712 &domain_pol,
2713 0x8,
2714 groups->entries[i].idx,
2715 &alias_pol,
2716 &_result);
2717 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2718 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2719 &alias_pol,
2721 &info,
2722 &_result);
2723 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2724 status = dcerpc_samr_Close(b, mem_ctx,
2725 &alias_pol,
2726 &_result);
2727 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2728 description = info->description.string;
2734 if (description != NULL) {
2735 printf("%-21.21s %-50.50s\n",
2736 groups->entries[i].name.string,
2737 description);
2738 } else {
2739 printf("%s\n", groups->entries[i].name.string);
2742 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2743 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2744 /* Get builtin policy handle */
2746 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2747 &connect_pol,
2748 MAXIMUM_ALLOWED_ACCESS,
2749 discard_const_p(struct dom_sid2, &global_sid_Builtin),
2750 &domain_pol,
2751 &result);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 goto done;
2755 if (!NT_STATUS_IS_OK(result)) {
2756 status = result;
2757 goto done;
2760 /* query builtin aliases */
2761 start_idx = 0;
2762 do {
2763 if (!builtin) break;
2765 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2766 &domain_pol,
2767 &start_idx,
2768 &groups,
2769 max_entries,
2770 &num_entries,
2771 &result);
2772 if (!NT_STATUS_IS_OK(status)) {
2773 break;
2775 if (!NT_STATUS_IS_OK(result) &&
2776 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2777 status = result;
2778 break;
2781 for (i = 0; i < num_entries; i++) {
2783 const char *description = NULL;
2785 if (c->opt_long_list_entries) {
2787 struct policy_handle alias_pol;
2788 union samr_AliasInfo *info = NULL;
2789 NTSTATUS _result;
2791 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2792 &domain_pol,
2793 0x8,
2794 groups->entries[i].idx,
2795 &alias_pol,
2796 &_result);
2797 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2798 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2799 &alias_pol,
2801 &info,
2802 &_result);
2803 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2804 status = dcerpc_samr_Close(b, mem_ctx,
2805 &alias_pol,
2806 &_result);
2807 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2808 description = info->description.string;
2814 if (description != NULL) {
2815 printf("%-21.21s %-50.50s\n",
2816 groups->entries[i].name.string,
2817 description);
2818 } else {
2819 printf("%s\n", groups->entries[i].name.string);
2822 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2824 status = result;
2826 done:
2827 return status;
2830 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2832 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2833 rpc_group_list_internals,
2834 argc, argv);
2837 static NTSTATUS rpc_list_group_members(struct net_context *c,
2838 struct rpc_pipe_client *pipe_hnd,
2839 TALLOC_CTX *mem_ctx,
2840 const char *domain_name,
2841 const struct dom_sid *domain_sid,
2842 struct policy_handle *domain_pol,
2843 uint32 rid)
2845 NTSTATUS result, status;
2846 struct policy_handle group_pol;
2847 uint32 num_members, *group_rids;
2848 int i;
2849 struct samr_RidAttrArray *rids = NULL;
2850 struct lsa_Strings names;
2851 struct samr_Ids types;
2852 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2854 fstring sid_str;
2855 sid_to_fstring(sid_str, domain_sid);
2857 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2858 domain_pol,
2859 MAXIMUM_ALLOWED_ACCESS,
2860 rid,
2861 &group_pol,
2862 &result);
2863 if (!NT_STATUS_IS_OK(status)) {
2864 return status;
2866 if (!NT_STATUS_IS_OK(result)) {
2867 return result;
2870 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
2871 &group_pol,
2872 &rids,
2873 &result);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 return status;
2877 if (!NT_STATUS_IS_OK(result)) {
2878 return result;
2881 num_members = rids->count;
2882 group_rids = rids->rids;
2884 while (num_members > 0) {
2885 int this_time = 512;
2887 if (num_members < this_time)
2888 this_time = num_members;
2890 status = dcerpc_samr_LookupRids(b, mem_ctx,
2891 domain_pol,
2892 this_time,
2893 group_rids,
2894 &names,
2895 &types,
2896 &result);
2897 if (!NT_STATUS_IS_OK(status)) {
2898 return status;
2900 if (!NT_STATUS_IS_OK(result)) {
2901 return result;
2904 /* We only have users as members, but make the output
2905 the same as the output of alias members */
2907 for (i = 0; i < this_time; i++) {
2909 if (c->opt_long_list_entries) {
2910 printf("%s-%d %s\\%s %d\n", sid_str,
2911 group_rids[i], domain_name,
2912 names.names[i].string,
2913 SID_NAME_USER);
2914 } else {
2915 printf("%s\\%s\n", domain_name,
2916 names.names[i].string);
2920 num_members -= this_time;
2921 group_rids += 512;
2924 return NT_STATUS_OK;
2927 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2928 struct rpc_pipe_client *pipe_hnd,
2929 TALLOC_CTX *mem_ctx,
2930 struct policy_handle *domain_pol,
2931 uint32 rid)
2933 NTSTATUS result, status;
2934 struct rpc_pipe_client *lsa_pipe;
2935 struct policy_handle alias_pol, lsa_pol;
2936 uint32 num_members;
2937 struct dom_sid *alias_sids;
2938 char **domains;
2939 char **names;
2940 enum lsa_SidType *types;
2941 int i;
2942 struct lsa_SidArray sid_array;
2943 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2945 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2946 domain_pol,
2947 MAXIMUM_ALLOWED_ACCESS,
2948 rid,
2949 &alias_pol,
2950 &result);
2951 if (!NT_STATUS_IS_OK(status)) {
2952 return status;
2954 if (!NT_STATUS_IS_OK(result)) {
2955 return result;
2958 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
2959 &alias_pol,
2960 &sid_array,
2961 &result);
2962 if (!NT_STATUS_IS_OK(status)) {
2963 d_fprintf(stderr, _("Couldn't list alias members\n"));
2964 return status;
2966 if (!NT_STATUS_IS_OK(result)) {
2967 d_fprintf(stderr, _("Couldn't list alias members\n"));
2968 return result;
2971 num_members = sid_array.num_sids;
2973 if (num_members == 0) {
2974 return NT_STATUS_OK;
2977 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2978 &ndr_table_lsarpc.syntax_id,
2979 &lsa_pipe);
2980 if (!NT_STATUS_IS_OK(result)) {
2981 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2982 nt_errstr(result) );
2983 return result;
2986 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2987 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2989 if (!NT_STATUS_IS_OK(result)) {
2990 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2991 TALLOC_FREE(lsa_pipe);
2992 return result;
2995 alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
2996 if (!alias_sids) {
2997 d_fprintf(stderr, _("Out of memory\n"));
2998 TALLOC_FREE(lsa_pipe);
2999 return NT_STATUS_NO_MEMORY;
3002 for (i=0; i<num_members; i++) {
3003 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
3006 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
3007 num_members, alias_sids,
3008 &domains, &names, &types);
3010 if (!NT_STATUS_IS_OK(result) &&
3011 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3012 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
3013 TALLOC_FREE(lsa_pipe);
3014 return result;
3017 for (i = 0; i < num_members; i++) {
3018 fstring sid_str;
3019 sid_to_fstring(sid_str, &alias_sids[i]);
3021 if (c->opt_long_list_entries) {
3022 printf("%s %s\\%s %d\n", sid_str,
3023 domains[i] ? domains[i] : _("*unknown*"),
3024 names[i] ? names[i] : _("*unknown*"), types[i]);
3025 } else {
3026 if (domains[i])
3027 printf("%s\\%s\n", domains[i], names[i]);
3028 else
3029 printf("%s\n", sid_str);
3033 TALLOC_FREE(lsa_pipe);
3034 return NT_STATUS_OK;
3037 static NTSTATUS rpc_group_members_internals(struct net_context *c,
3038 const struct dom_sid *domain_sid,
3039 const char *domain_name,
3040 struct cli_state *cli,
3041 struct rpc_pipe_client *pipe_hnd,
3042 TALLOC_CTX *mem_ctx,
3043 int argc,
3044 const char **argv)
3046 NTSTATUS result, status;
3047 struct policy_handle connect_pol, domain_pol;
3048 struct samr_Ids rids, rid_types;
3049 struct lsa_String lsa_acct_name;
3050 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3052 /* Get sam policy handle */
3054 status = dcerpc_samr_Connect2(b, mem_ctx,
3055 pipe_hnd->desthost,
3056 MAXIMUM_ALLOWED_ACCESS,
3057 &connect_pol,
3058 &result);
3059 if (!NT_STATUS_IS_OK(status)) {
3060 return status;
3062 if (!NT_STATUS_IS_OK(result)) {
3063 return result;
3066 /* Get domain policy handle */
3068 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3069 &connect_pol,
3070 MAXIMUM_ALLOWED_ACCESS,
3071 discard_const_p(struct dom_sid2, domain_sid),
3072 &domain_pol,
3073 &result);
3074 if (!NT_STATUS_IS_OK(status)) {
3075 return status;
3077 if (!NT_STATUS_IS_OK(result)) {
3078 return result;
3081 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3083 status = dcerpc_samr_LookupNames(b, mem_ctx,
3084 &domain_pol,
3086 &lsa_acct_name,
3087 &rids,
3088 &rid_types,
3089 &result);
3090 if (!NT_STATUS_IS_OK(status)) {
3091 return status;
3094 if (!NT_STATUS_IS_OK(result)) {
3096 /* Ok, did not find it in the global sam, try with builtin */
3098 struct dom_sid sid_Builtin;
3100 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3102 sid_copy(&sid_Builtin, &global_sid_Builtin);
3104 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3105 &connect_pol,
3106 MAXIMUM_ALLOWED_ACCESS,
3107 &sid_Builtin,
3108 &domain_pol,
3109 &result);
3110 if (!NT_STATUS_IS_OK(status)) {
3111 return status;
3113 if (!NT_STATUS_IS_OK(result)) {
3114 d_fprintf(stderr, _("Couldn't find group %s\n"),
3115 argv[0]);
3116 return result;
3119 status = dcerpc_samr_LookupNames(b, mem_ctx,
3120 &domain_pol,
3122 &lsa_acct_name,
3123 &rids,
3124 &rid_types,
3125 &result);
3126 if (!NT_STATUS_IS_OK(status)) {
3127 return status;
3129 if (!NT_STATUS_IS_OK(result)) {
3130 d_fprintf(stderr, _("Couldn't find group %s\n"),
3131 argv[0]);
3132 return result;
3136 if (rids.count != 1) {
3137 d_fprintf(stderr, _("Couldn't find group %s\n"),
3138 argv[0]);
3139 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3141 if (rid_types.count != 1) {
3142 d_fprintf(stderr, _("Couldn't find group %s\n"),
3143 argv[0]);
3144 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3148 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3149 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3150 domain_sid, &domain_pol,
3151 rids.ids[0]);
3154 if (rid_types.ids[0] == SID_NAME_ALIAS) {
3155 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
3156 rids.ids[0]);
3159 return NT_STATUS_NO_SUCH_GROUP;
3162 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3164 if (argc != 1 || c->display_usage) {
3165 return rpc_group_usage(c, argc, argv);
3168 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3169 rpc_group_members_internals,
3170 argc, argv);
3173 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3175 NET_API_STATUS status;
3176 struct GROUP_INFO_0 g0;
3177 uint32_t parm_err;
3179 if (argc != 2) {
3180 d_printf(_("Usage:\n"));
3181 d_printf("net rpc group rename group newname\n");
3182 return -1;
3185 g0.grpi0_name = argv[1];
3187 status = NetGroupSetInfo(c->opt_host,
3188 argv[0],
3190 (uint8_t *)&g0,
3191 &parm_err);
3193 if (status != 0) {
3194 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3195 argv[0], libnetapi_get_error_string(c->netapi_ctx,
3196 status));
3197 return -1;
3200 return 0;
3203 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3205 if (argc != 2 || c->display_usage) {
3206 return rpc_group_usage(c, argc, argv);
3209 return rpc_group_rename_internals(c, argc, argv);
3213 * 'net rpc group' entrypoint.
3214 * @param argc Standard main() style argc.
3215 * @param argv Standard main() style argv. Initial components are already
3216 * stripped.
3219 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3221 NET_API_STATUS status;
3223 struct functable func[] = {
3225 "add",
3226 rpc_group_add,
3227 NET_TRANSPORT_RPC,
3228 N_("Create specified group"),
3229 N_("net rpc group add\n"
3230 " Create specified group")
3233 "delete",
3234 rpc_group_delete,
3235 NET_TRANSPORT_RPC,
3236 N_("Delete specified group"),
3237 N_("net rpc group delete\n"
3238 " Delete specified group")
3241 "addmem",
3242 rpc_group_addmem,
3243 NET_TRANSPORT_RPC,
3244 N_("Add member to group"),
3245 N_("net rpc group addmem\n"
3246 " Add member to group")
3249 "delmem",
3250 rpc_group_delmem,
3251 NET_TRANSPORT_RPC,
3252 N_("Remove member from group"),
3253 N_("net rpc group delmem\n"
3254 " Remove member from group")
3257 "list",
3258 rpc_group_list,
3259 NET_TRANSPORT_RPC,
3260 N_("List groups"),
3261 N_("net rpc group list\n"
3262 " List groups")
3265 "members",
3266 rpc_group_members,
3267 NET_TRANSPORT_RPC,
3268 N_("List group members"),
3269 N_("net rpc group members\n"
3270 " List group members")
3273 "rename",
3274 rpc_group_rename,
3275 NET_TRANSPORT_RPC,
3276 N_("Rename group"),
3277 N_("net rpc group rename\n"
3278 " Rename group")
3280 {NULL, NULL, 0, NULL, NULL}
3283 status = libnetapi_net_init(&c->netapi_ctx);
3284 if (status != 0) {
3285 return -1;
3287 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3288 libnetapi_set_password(c->netapi_ctx, c->opt_password);
3289 if (c->opt_kerberos) {
3290 libnetapi_set_use_kerberos(c->netapi_ctx);
3293 if (argc == 0) {
3294 if (c->display_usage) {
3295 d_printf(_("Usage:\n"));
3296 d_printf(_("net rpc group\n"
3297 " Alias for net rpc group list global "
3298 "local builtin\n"));
3299 net_display_usage_from_functable(func);
3300 return 0;
3303 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3304 rpc_group_list_internals,
3305 argc, argv);
3308 return net_run_function(c, argc, argv, "net rpc group", func);
3311 /****************************************************************************/
3313 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3315 return net_share_usage(c, argc, argv);
3319 * Add a share on a remote RPC server.
3321 * @param argc Standard main() style argc.
3322 * @param argv Standard main() style argv. Initial components are already
3323 * stripped.
3325 * @return A shell status integer (0 for success).
3328 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3330 NET_API_STATUS status;
3331 char *sharename;
3332 char *path;
3333 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3334 uint32 num_users=0, perms=0;
3335 char *password=NULL; /* don't allow a share password */
3336 struct SHARE_INFO_2 i2;
3337 uint32_t parm_error = 0;
3339 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3340 return rpc_share_usage(c, argc, argv);
3343 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3344 return -1;
3347 path = strchr(sharename, '=');
3348 if (!path) {
3349 return -1;
3352 *path++ = '\0';
3354 i2.shi2_netname = sharename;
3355 i2.shi2_type = type;
3356 i2.shi2_remark = c->opt_comment;
3357 i2.shi2_permissions = perms;
3358 i2.shi2_max_uses = c->opt_maxusers;
3359 i2.shi2_current_uses = num_users;
3360 i2.shi2_path = path;
3361 i2.shi2_passwd = password;
3363 status = NetShareAdd(c->opt_host,
3365 (uint8_t *)&i2,
3366 &parm_error);
3367 if (status != 0) {
3368 printf(_("NetShareAdd failed with: %s\n"),
3369 libnetapi_get_error_string(c->netapi_ctx, status));
3372 return status;
3376 * Delete a share on a remote RPC server.
3378 * @param domain_sid The domain sid acquired from the remote server.
3379 * @param argc Standard main() style argc.
3380 * @param argv Standard main() style argv. Initial components are already
3381 * stripped.
3383 * @return A shell status integer (0 for success).
3385 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3387 if (argc < 1 || c->display_usage) {
3388 return rpc_share_usage(c, argc, argv);
3391 return NetShareDel(c->opt_host, argv[0], 0);
3395 * Formatted print of share info
3397 * @param r pointer to SHARE_INFO_1 to format
3400 static void display_share_info_1(struct net_context *c,
3401 struct SHARE_INFO_1 *r)
3403 if (c->opt_long_list_entries) {
3404 d_printf("%-12s %-8.8s %-50s\n",
3405 r->shi1_netname,
3406 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3407 r->shi1_remark);
3408 } else {
3409 d_printf("%s\n", r->shi1_netname);
3413 static WERROR get_share_info(struct net_context *c,
3414 struct rpc_pipe_client *pipe_hnd,
3415 TALLOC_CTX *mem_ctx,
3416 uint32 level,
3417 int argc,
3418 const char **argv,
3419 struct srvsvc_NetShareInfoCtr *info_ctr)
3421 WERROR result;
3422 NTSTATUS status;
3423 union srvsvc_NetShareInfo info;
3424 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3426 /* no specific share requested, enumerate all */
3427 if (argc == 0) {
3429 uint32_t preferred_len = 0xffffffff;
3430 uint32_t total_entries = 0;
3431 uint32_t resume_handle = 0;
3433 info_ctr->level = level;
3435 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3436 pipe_hnd->desthost,
3437 info_ctr,
3438 preferred_len,
3439 &total_entries,
3440 &resume_handle,
3441 &result);
3442 if (!NT_STATUS_IS_OK(status)) {
3443 return ntstatus_to_werror(status);
3445 return result;
3448 /* request just one share */
3449 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3450 pipe_hnd->desthost,
3451 argv[0],
3452 level,
3453 &info,
3454 &result);
3456 if (!NT_STATUS_IS_OK(status)) {
3457 result = ntstatus_to_werror(status);
3458 goto done;
3461 if (!W_ERROR_IS_OK(result)) {
3462 goto done;
3465 /* construct ctr */
3466 ZERO_STRUCTP(info_ctr);
3468 info_ctr->level = level;
3470 switch (level) {
3471 case 1:
3473 struct srvsvc_NetShareCtr1 *ctr1;
3475 ctr1 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr1);
3476 W_ERROR_HAVE_NO_MEMORY(ctr1);
3478 ctr1->count = 1;
3479 ctr1->array = info.info1;
3481 info_ctr->ctr.ctr1 = ctr1;
3483 break;
3485 case 2:
3487 struct srvsvc_NetShareCtr2 *ctr2;
3489 ctr2 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr2);
3490 W_ERROR_HAVE_NO_MEMORY(ctr2);
3492 ctr2->count = 1;
3493 ctr2->array = info.info2;
3495 info_ctr->ctr.ctr2 = ctr2;
3497 break;
3499 case 502:
3501 struct srvsvc_NetShareCtr502 *ctr502;
3503 ctr502 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr502);
3504 W_ERROR_HAVE_NO_MEMORY(ctr502);
3506 ctr502->count = 1;
3507 ctr502->array = info.info502;
3509 info_ctr->ctr.ctr502 = ctr502;
3511 break;
3513 } /* switch */
3514 done:
3515 return result;
3518 /***
3519 * 'net rpc share list' entrypoint.
3520 * @param argc Standard main() style argc.
3521 * @param argv Standard main() style argv. Initial components are already
3522 * stripped.
3524 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3526 NET_API_STATUS status;
3527 struct SHARE_INFO_1 *i1 = NULL;
3528 uint32_t entries_read = 0;
3529 uint32_t total_entries = 0;
3530 uint32_t resume_handle = 0;
3531 uint32_t i, level = 1;
3533 if (c->display_usage) {
3534 d_printf( "%s\n"
3535 "net rpc share list\n"
3536 " %s\n",
3537 _("Usage:"),
3538 _("List shares on remote server"));
3539 return 0;
3542 status = NetShareEnum(c->opt_host,
3543 level,
3544 (uint8_t **)(void *)&i1,
3545 (uint32_t)-1,
3546 &entries_read,
3547 &total_entries,
3548 &resume_handle);
3549 if (status != 0) {
3550 goto done;
3553 /* Display results */
3555 if (c->opt_long_list_entries) {
3556 d_printf(_(
3557 "\nEnumerating shared resources (exports) on remote server:\n\n"
3558 "\nShare name Type Description\n"
3559 "---------- ---- -----------\n"));
3561 for (i = 0; i < entries_read; i++)
3562 display_share_info_1(c, &i1[i]);
3563 done:
3564 return status;
3567 static bool check_share_availability(struct cli_state *cli, const char *netname)
3569 NTSTATUS status;
3571 status = cli_tree_connect(cli, netname, "A:", "", 0);
3572 if (!NT_STATUS_IS_OK(status)) {
3573 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3574 return false;
3577 status = cli_tdis(cli);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3580 return false;
3583 return true;
3586 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3587 const char *netname, uint32 type)
3589 /* only support disk shares */
3590 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3591 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3592 type);
3593 return false;
3596 /* skip builtin shares */
3597 /* FIXME: should print$ be added too ? */
3598 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3599 strequal(netname,"global"))
3600 return false;
3602 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3603 printf(_("excluding [%s]\n"), netname);
3604 return false;
3607 return check_share_availability(cli, netname);
3611 * Migrate shares from a remote RPC server to the local RPC server.
3613 * All parameters are provided by the run_rpc_command function, except for
3614 * argc, argv which are passed through.
3616 * @param domain_sid The domain sid acquired from the remote server.
3617 * @param cli A cli_state connected to the server.
3618 * @param mem_ctx Talloc context, destroyed on completion of the function.
3619 * @param argc Standard main() style argc.
3620 * @param argv Standard main() style argv. Initial components are already
3621 * stripped.
3623 * @return Normal NTSTATUS return.
3626 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3627 const struct dom_sid *domain_sid,
3628 const char *domain_name,
3629 struct cli_state *cli,
3630 struct rpc_pipe_client *pipe_hnd,
3631 TALLOC_CTX *mem_ctx,
3632 int argc,
3633 const char **argv)
3635 WERROR result;
3636 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3637 struct srvsvc_NetShareInfoCtr ctr_src;
3638 uint32 i;
3639 struct rpc_pipe_client *srvsvc_pipe = NULL;
3640 struct cli_state *cli_dst = NULL;
3641 uint32 level = 502; /* includes secdesc */
3642 uint32_t parm_error = 0;
3643 struct dcerpc_binding_handle *b;
3645 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3646 &ctr_src);
3647 if (!W_ERROR_IS_OK(result))
3648 goto done;
3650 /* connect destination PI_SRVSVC */
3651 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3652 &ndr_table_srvsvc.syntax_id);
3653 if (!NT_STATUS_IS_OK(nt_status))
3654 return nt_status;
3656 b = srvsvc_pipe->binding_handle;
3658 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3660 union srvsvc_NetShareInfo info;
3661 struct srvsvc_NetShareInfo502 info502 =
3662 ctr_src.ctr.ctr502->array[i];
3664 /* reset error-code */
3665 nt_status = NT_STATUS_UNSUCCESSFUL;
3667 if (!check_share_sanity(c, cli, info502.name, info502.type))
3668 continue;
3670 /* finally add the share on the dst server */
3672 printf(_("migrating: [%s], path: %s, comment: %s, without "
3673 "share-ACLs\n"),
3674 info502.name, info502.path, info502.comment);
3676 info.info502 = &info502;
3678 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3679 srvsvc_pipe->desthost,
3680 502,
3681 &info,
3682 &parm_error,
3683 &result);
3684 if (!NT_STATUS_IS_OK(nt_status)) {
3685 printf(_("cannot add share: %s\n"),
3686 nt_errstr(nt_status));
3687 goto done;
3689 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3690 printf(_(" [%s] does already exist\n"),
3691 info502.name);
3692 continue;
3695 if (!W_ERROR_IS_OK(result)) {
3696 nt_status = werror_to_ntstatus(result);
3697 printf(_("cannot add share: %s\n"),
3698 win_errstr(result));
3699 goto done;
3704 nt_status = NT_STATUS_OK;
3706 done:
3707 if (cli_dst) {
3708 cli_shutdown(cli_dst);
3711 return nt_status;
3716 * Migrate shares from a RPC server to another.
3718 * @param argc Standard main() style argc.
3719 * @param argv Standard main() style argv. Initial components are already
3720 * stripped.
3722 * @return A shell status integer (0 for success).
3724 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3725 const char **argv)
3727 if (c->display_usage) {
3728 d_printf( "%s\n"
3729 "net rpc share migrate shares\n"
3730 " %s\n",
3731 _("Usage:"),
3732 _("Migrate shares to local server"));
3733 return 0;
3736 if (!c->opt_host) {
3737 printf(_("no server to migrate\n"));
3738 return -1;
3741 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
3742 rpc_share_migrate_shares_internals,
3743 argc, argv);
3747 * Copy a file/dir
3749 * @param f file_info
3750 * @param mask current search mask
3751 * @param state arg-pointer
3754 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3755 const char *mask, void *state)
3757 static NTSTATUS nt_status;
3758 static struct copy_clistate *local_state;
3759 static fstring filename, new_mask;
3760 fstring dir;
3761 char *old_dir;
3762 struct net_context *c;
3764 local_state = (struct copy_clistate *)state;
3765 nt_status = NT_STATUS_UNSUCCESSFUL;
3767 c = local_state->c;
3769 if (strequal(f->name, ".") || strequal(f->name, ".."))
3770 return NT_STATUS_OK;
3772 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3774 /* DIRECTORY */
3775 if (f->mode & FILE_ATTRIBUTE_DIRECTORY) {
3777 DEBUG(3,("got dir: %s\n", f->name));
3779 fstrcpy(dir, local_state->cwd);
3780 fstrcat(dir, "\\");
3781 fstrcat(dir, f->name);
3783 switch (net_mode_share)
3785 case NET_MODE_SHARE_MIGRATE:
3786 /* create that directory */
3787 nt_status = net_copy_file(c, local_state->mem_ctx,
3788 local_state->cli_share_src,
3789 local_state->cli_share_dst,
3790 dir, dir,
3791 c->opt_acls? true : false,
3792 c->opt_attrs? true : false,
3793 c->opt_timestamps? true:false,
3794 false);
3795 break;
3796 default:
3797 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3798 return NT_STATUS_INTERNAL_ERROR;
3801 if (!NT_STATUS_IS_OK(nt_status)) {
3802 printf(_("could not handle dir %s: %s\n"),
3803 dir, nt_errstr(nt_status));
3804 return nt_status;
3807 /* search below that directory */
3808 if (strlcpy(new_mask, dir, sizeof(new_mask)) >= sizeof(new_mask)) {
3809 return NT_STATUS_NO_MEMORY;
3811 if (strlcat(new_mask, "\\*", sizeof(new_mask)) >= sizeof(new_mask)) {
3812 return NT_STATUS_NO_MEMORY;
3815 old_dir = local_state->cwd;
3816 local_state->cwd = dir;
3817 nt_status = sync_files(local_state, new_mask);
3818 if (!NT_STATUS_IS_OK(nt_status)) {
3819 printf(_("could not handle files\n"));
3821 local_state->cwd = old_dir;
3823 return nt_status;
3827 /* FILE */
3828 fstrcpy(filename, local_state->cwd);
3829 fstrcat(filename, "\\");
3830 fstrcat(filename, f->name);
3832 DEBUG(3,("got file: %s\n", filename));
3834 switch (net_mode_share)
3836 case NET_MODE_SHARE_MIGRATE:
3837 nt_status = net_copy_file(c, local_state->mem_ctx,
3838 local_state->cli_share_src,
3839 local_state->cli_share_dst,
3840 filename, filename,
3841 c->opt_acls? true : false,
3842 c->opt_attrs? true : false,
3843 c->opt_timestamps? true: false,
3844 true);
3845 break;
3846 default:
3847 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3848 net_mode_share);
3849 return NT_STATUS_INTERNAL_ERROR;
3852 if (!NT_STATUS_IS_OK(nt_status))
3853 printf(_("could not handle file %s: %s\n"),
3854 filename, nt_errstr(nt_status));
3855 return nt_status;
3859 * sync files, can be called recursivly to list files
3860 * and then call copy_fn for each file
3862 * @param cp_clistate pointer to the copy_clistate we work with
3863 * @param mask the current search mask
3865 * @return Boolean result
3867 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
3869 struct cli_state *targetcli;
3870 char *targetpath = NULL;
3871 NTSTATUS status;
3873 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3875 status = cli_resolve_path(talloc_tos(), "", NULL,
3876 cp_clistate->cli_share_src,
3877 mask, &targetcli, &targetpath);
3878 if (!NT_STATUS_IS_OK(status)) {
3879 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3880 "%s\n"),
3881 mask, nt_errstr(status));
3882 return status;
3885 status = cli_list(targetcli, targetpath, cp_clistate->attribute,
3886 copy_fn, cp_clistate);
3887 if (!NT_STATUS_IS_OK(status)) {
3888 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3889 mask, nt_errstr(status));
3892 return status;
3897 * Set the top level directory permissions before we do any further copies.
3898 * Should set up ACL inheritance.
3901 bool copy_top_level_perms(struct net_context *c,
3902 struct copy_clistate *cp_clistate,
3903 const char *sharename)
3905 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3907 switch (net_mode_share) {
3908 case NET_MODE_SHARE_MIGRATE:
3909 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3910 nt_status = net_copy_fileattr(c,
3911 cp_clistate->mem_ctx,
3912 cp_clistate->cli_share_src,
3913 cp_clistate->cli_share_dst,
3914 "\\", "\\",
3915 c->opt_acls? true : false,
3916 c->opt_attrs? true : false,
3917 c->opt_timestamps? true: false,
3918 false);
3919 break;
3920 default:
3921 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3922 break;
3925 if (!NT_STATUS_IS_OK(nt_status)) {
3926 printf(_("Could handle directory attributes for top level "
3927 "directory of share %s. Error %s\n"),
3928 sharename, nt_errstr(nt_status));
3929 return false;
3932 return true;
3936 * Sync all files inside a remote share to another share (over smb).
3938 * All parameters are provided by the run_rpc_command function, except for
3939 * argc, argv which are passed through.
3941 * @param domain_sid The domain sid acquired from the remote server.
3942 * @param cli A cli_state connected to the server.
3943 * @param mem_ctx Talloc context, destroyed on completion of the function.
3944 * @param argc Standard main() style argc.
3945 * @param argv Standard main() style argv. Initial components are already
3946 * stripped.
3948 * @return Normal NTSTATUS return.
3951 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3952 const struct dom_sid *domain_sid,
3953 const char *domain_name,
3954 struct cli_state *cli,
3955 struct rpc_pipe_client *pipe_hnd,
3956 TALLOC_CTX *mem_ctx,
3957 int argc,
3958 const char **argv)
3960 WERROR result;
3961 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3962 struct srvsvc_NetShareInfoCtr ctr_src;
3963 uint32 i;
3964 uint32 level = 502;
3965 struct copy_clistate cp_clistate;
3966 bool got_src_share = false;
3967 bool got_dst_share = false;
3968 const char *mask = "\\*";
3969 char *dst = NULL;
3971 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3972 if (dst == NULL) {
3973 nt_status = NT_STATUS_NO_MEMORY;
3974 goto done;
3977 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3978 &ctr_src);
3980 if (!W_ERROR_IS_OK(result))
3981 goto done;
3983 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3985 struct srvsvc_NetShareInfo502 info502 =
3986 ctr_src.ctr.ctr502->array[i];
3988 if (!check_share_sanity(c, cli, info502.name, info502.type))
3989 continue;
3991 /* one might not want to mirror whole discs :) */
3992 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3993 d_printf(_("skipping [%s]: builtin/hidden share\n"),
3994 info502.name);
3995 continue;
3998 switch (net_mode_share)
4000 case NET_MODE_SHARE_MIGRATE:
4001 printf("syncing");
4002 break;
4003 default:
4004 d_fprintf(stderr, _("Unsupported mode %d\n"),
4005 net_mode_share);
4006 break;
4008 printf(_(" [%s] files and directories %s ACLs, %s DOS "
4009 "Attributes %s\n"),
4010 info502.name,
4011 c->opt_acls ? _("including") : _("without"),
4012 c->opt_attrs ? _("including") : _("without"),
4013 c->opt_timestamps ? _("(preserving timestamps)") : "");
4015 cp_clistate.mem_ctx = mem_ctx;
4016 cp_clistate.cli_share_src = NULL;
4017 cp_clistate.cli_share_dst = NULL;
4018 cp_clistate.cwd = NULL;
4019 cp_clistate.attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
4020 cp_clistate.c = c;
4022 /* open share source */
4023 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
4024 smbXcli_conn_remote_sockaddr(cli->conn),
4025 smbXcli_conn_remote_name(cli->conn),
4026 info502.name, "A:");
4027 if (!NT_STATUS_IS_OK(nt_status))
4028 goto done;
4030 got_src_share = true;
4032 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
4033 /* open share destination */
4034 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
4035 NULL, dst, info502.name, "A:");
4036 if (!NT_STATUS_IS_OK(nt_status))
4037 goto done;
4039 got_dst_share = true;
4042 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
4043 d_fprintf(stderr, _("Could not handle the top level "
4044 "directory permissions for the "
4045 "share: %s\n"), info502.name);
4046 nt_status = NT_STATUS_UNSUCCESSFUL;
4047 goto done;
4050 nt_status = sync_files(&cp_clistate, mask);
4051 if (!NT_STATUS_IS_OK(nt_status)) {
4052 d_fprintf(stderr, _("could not handle files for share: "
4053 "%s\n"), info502.name);
4054 goto done;
4058 nt_status = NT_STATUS_OK;
4060 done:
4062 if (got_src_share)
4063 cli_shutdown(cp_clistate.cli_share_src);
4065 if (got_dst_share)
4066 cli_shutdown(cp_clistate.cli_share_dst);
4068 SAFE_FREE(dst);
4069 return nt_status;
4073 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
4075 if (c->display_usage) {
4076 d_printf( "%s\n"
4077 "net share migrate files\n"
4078 " %s\n",
4079 _("Usage:"),
4080 _("Migrate files to local server"));
4081 return 0;
4084 if (!c->opt_host) {
4085 d_printf(_("no server to migrate\n"));
4086 return -1;
4089 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4090 rpc_share_migrate_files_internals,
4091 argc, argv);
4095 * Migrate share-ACLs from a remote RPC server to the local RPC server.
4097 * All parameters are provided by the run_rpc_command function, except for
4098 * argc, argv which are passed through.
4100 * @param domain_sid The domain sid acquired from the remote server.
4101 * @param cli A cli_state connected to the server.
4102 * @param mem_ctx Talloc context, destroyed on completion of the function.
4103 * @param argc Standard main() style argc.
4104 * @param argv Standard main() style argv. Initial components are already
4105 * stripped.
4107 * @return Normal NTSTATUS return.
4110 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
4111 const struct dom_sid *domain_sid,
4112 const char *domain_name,
4113 struct cli_state *cli,
4114 struct rpc_pipe_client *pipe_hnd,
4115 TALLOC_CTX *mem_ctx,
4116 int argc,
4117 const char **argv)
4119 WERROR result;
4120 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4121 struct srvsvc_NetShareInfoCtr ctr_src;
4122 union srvsvc_NetShareInfo info;
4123 uint32 i;
4124 struct rpc_pipe_client *srvsvc_pipe = NULL;
4125 struct cli_state *cli_dst = NULL;
4126 uint32 level = 502; /* includes secdesc */
4127 uint32_t parm_error = 0;
4128 struct dcerpc_binding_handle *b;
4130 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4131 &ctr_src);
4133 if (!W_ERROR_IS_OK(result))
4134 goto done;
4136 /* connect destination PI_SRVSVC */
4137 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
4138 &ndr_table_srvsvc.syntax_id);
4139 if (!NT_STATUS_IS_OK(nt_status))
4140 return nt_status;
4142 b = srvsvc_pipe->binding_handle;
4144 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4146 struct srvsvc_NetShareInfo502 info502 =
4147 ctr_src.ctr.ctr502->array[i];
4149 /* reset error-code */
4150 nt_status = NT_STATUS_UNSUCCESSFUL;
4152 if (!check_share_sanity(c, cli, info502.name, info502.type))
4153 continue;
4155 printf(_("migrating: [%s], path: %s, comment: %s, including "
4156 "share-ACLs\n"),
4157 info502.name, info502.path, info502.comment);
4159 if (c->opt_verbose)
4160 display_sec_desc(info502.sd_buf.sd);
4162 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4163 info.info502 = &info502;
4165 /* finally modify the share on the dst server */
4166 nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
4167 srvsvc_pipe->desthost,
4168 info502.name,
4169 level,
4170 &info,
4171 &parm_error,
4172 &result);
4173 if (!NT_STATUS_IS_OK(nt_status)) {
4174 printf(_("cannot set share-acl: %s\n"),
4175 nt_errstr(nt_status));
4176 goto done;
4178 if (!W_ERROR_IS_OK(result)) {
4179 nt_status = werror_to_ntstatus(result);
4180 printf(_("cannot set share-acl: %s\n"),
4181 win_errstr(result));
4182 goto done;
4187 nt_status = NT_STATUS_OK;
4189 done:
4190 if (cli_dst) {
4191 cli_shutdown(cli_dst);
4194 return nt_status;
4199 * Migrate share-acls from a RPC server to another.
4201 * @param argc Standard main() style argc.
4202 * @param argv Standard main() style argv. Initial components are already
4203 * stripped.
4205 * @return A shell status integer (0 for success).
4207 static int rpc_share_migrate_security(struct net_context *c, int argc,
4208 const char **argv)
4210 if (c->display_usage) {
4211 d_printf( "%s\n"
4212 "net rpc share migrate security\n"
4213 " %s\n",
4214 _("Usage:"),
4215 _("Migrate share-acls to local server"));
4216 return 0;
4219 if (!c->opt_host) {
4220 d_printf(_("no server to migrate\n"));
4221 return -1;
4224 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4225 rpc_share_migrate_security_internals,
4226 argc, argv);
4230 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4231 * from one server to another.
4233 * @param argc Standard main() style argc.
4234 * @param argv Standard main() style argv. Initial components are already
4235 * stripped.
4237 * @return A shell status integer (0 for success).
4240 static int rpc_share_migrate_all(struct net_context *c, int argc,
4241 const char **argv)
4243 int ret;
4245 if (c->display_usage) {
4246 d_printf( "%s\n"
4247 "net rpc share migrate all\n"
4248 " %s\n",
4249 _("Usage:"),
4250 _("Migrates shares including all share settings"));
4251 return 0;
4254 if (!c->opt_host) {
4255 d_printf(_("no server to migrate\n"));
4256 return -1;
4259 /* order is important. we don't want to be locked out by the share-acl
4260 * before copying files - gd */
4262 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4263 rpc_share_migrate_shares_internals, argc, argv);
4264 if (ret)
4265 return ret;
4267 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4268 rpc_share_migrate_files_internals, argc, argv);
4269 if (ret)
4270 return ret;
4272 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4273 rpc_share_migrate_security_internals, argc,
4274 argv);
4279 * 'net rpc share migrate' entrypoint.
4280 * @param argc Standard main() style argc.
4281 * @param argv Standard main() style argv. Initial components are already
4282 * stripped.
4284 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4287 struct functable func[] = {
4289 "all",
4290 rpc_share_migrate_all,
4291 NET_TRANSPORT_RPC,
4292 N_("Migrate shares from remote to local server"),
4293 N_("net rpc share migrate all\n"
4294 " Migrate shares from remote to local server")
4297 "files",
4298 rpc_share_migrate_files,
4299 NET_TRANSPORT_RPC,
4300 N_("Migrate files from remote to local server"),
4301 N_("net rpc share migrate files\n"
4302 " Migrate files from remote to local server")
4305 "security",
4306 rpc_share_migrate_security,
4307 NET_TRANSPORT_RPC,
4308 N_("Migrate share-ACLs from remote to local server"),
4309 N_("net rpc share migrate security\n"
4310 " Migrate share-ACLs from remote to local server")
4313 "shares",
4314 rpc_share_migrate_shares,
4315 NET_TRANSPORT_RPC,
4316 N_("Migrate shares from remote to local server"),
4317 N_("net rpc share migrate shares\n"
4318 " Migrate shares from remote to local server")
4320 {NULL, NULL, 0, NULL, NULL}
4323 net_mode_share = NET_MODE_SHARE_MIGRATE;
4325 return net_run_function(c, argc, argv, "net rpc share migrate", func);
4328 struct full_alias {
4329 struct dom_sid sid;
4330 uint32 num_members;
4331 struct dom_sid *members;
4334 static int num_server_aliases;
4335 static struct full_alias *server_aliases;
4338 * Add an alias to the static list.
4340 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4342 if (server_aliases == NULL)
4343 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4345 server_aliases[num_server_aliases] = *alias;
4346 num_server_aliases += 1;
4350 * For a specific domain on the server, fetch all the aliases
4351 * and their members. Add all of them to the server_aliases.
4354 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4355 TALLOC_CTX *mem_ctx,
4356 struct policy_handle *connect_pol,
4357 const struct dom_sid *domain_sid)
4359 uint32 start_idx, max_entries, num_entries, i;
4360 struct samr_SamArray *groups = NULL;
4361 NTSTATUS result, status;
4362 struct policy_handle domain_pol;
4363 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4365 /* Get domain policy handle */
4367 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4368 connect_pol,
4369 MAXIMUM_ALLOWED_ACCESS,
4370 discard_const_p(struct dom_sid2, domain_sid),
4371 &domain_pol,
4372 &result);
4373 if (!NT_STATUS_IS_OK(status)) {
4374 return status;
4376 if (!NT_STATUS_IS_OK(result)) {
4377 return result;
4380 start_idx = 0;
4381 max_entries = 250;
4383 do {
4384 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
4385 &domain_pol,
4386 &start_idx,
4387 &groups,
4388 max_entries,
4389 &num_entries,
4390 &result);
4391 if (!NT_STATUS_IS_OK(status)) {
4392 goto done;
4394 for (i = 0; i < num_entries; i++) {
4396 struct policy_handle alias_pol;
4397 struct full_alias alias;
4398 struct lsa_SidArray sid_array;
4399 int j;
4400 NTSTATUS _result;
4402 status = dcerpc_samr_OpenAlias(b, mem_ctx,
4403 &domain_pol,
4404 MAXIMUM_ALLOWED_ACCESS,
4405 groups->entries[i].idx,
4406 &alias_pol,
4407 &_result);
4408 if (!NT_STATUS_IS_OK(status)) {
4409 goto done;
4411 if (!NT_STATUS_IS_OK(_result)) {
4412 status = _result;
4413 goto done;
4416 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
4417 &alias_pol,
4418 &sid_array,
4419 &_result);
4420 if (!NT_STATUS_IS_OK(status)) {
4421 goto done;
4423 if (!NT_STATUS_IS_OK(_result)) {
4424 status = _result;
4425 goto done;
4428 alias.num_members = sid_array.num_sids;
4430 status = dcerpc_samr_Close(b, mem_ctx, &alias_pol, &_result);
4431 if (!NT_STATUS_IS_OK(status)) {
4432 goto done;
4434 if (!NT_STATUS_IS_OK(_result)) {
4435 status = _result;
4436 goto done;
4439 alias.members = NULL;
4441 if (alias.num_members > 0) {
4442 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4444 for (j = 0; j < alias.num_members; j++)
4445 sid_copy(&alias.members[j],
4446 sid_array.sids[j].sid);
4449 sid_compose(&alias.sid, domain_sid,
4450 groups->entries[i].idx);
4452 push_alias(mem_ctx, &alias);
4454 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4456 status = NT_STATUS_OK;
4458 done:
4459 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
4461 return status;
4465 * Dump server_aliases as names for debugging purposes.
4468 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4469 const struct dom_sid *domain_sid,
4470 const char *domain_name,
4471 struct cli_state *cli,
4472 struct rpc_pipe_client *pipe_hnd,
4473 TALLOC_CTX *mem_ctx,
4474 int argc,
4475 const char **argv)
4477 int i;
4478 NTSTATUS result;
4479 struct policy_handle lsa_pol;
4480 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4482 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4483 SEC_FLAG_MAXIMUM_ALLOWED,
4484 &lsa_pol);
4485 if (!NT_STATUS_IS_OK(result))
4486 return result;
4488 for (i=0; i<num_server_aliases; i++) {
4489 char **names;
4490 char **domains;
4491 enum lsa_SidType *types;
4492 int j;
4494 struct full_alias *alias = &server_aliases[i];
4496 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4497 &alias->sid,
4498 &domains, &names, &types);
4499 if (!NT_STATUS_IS_OK(result))
4500 continue;
4502 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4504 if (alias->num_members == 0) {
4505 DEBUG(1, ("\n"));
4506 continue;
4509 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4510 alias->num_members,
4511 alias->members,
4512 &domains, &names, &types);
4514 if (!NT_STATUS_IS_OK(result) &&
4515 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4516 continue;
4518 for (j=0; j<alias->num_members; j++)
4519 DEBUG(1, ("%s\\%s (%d); ",
4520 domains[j] ? domains[j] : "*unknown*",
4521 names[j] ? names[j] : "*unknown*",types[j]));
4522 DEBUG(1, ("\n"));
4525 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
4527 return NT_STATUS_OK;
4531 * Fetch a list of all server aliases and their members into
4532 * server_aliases.
4535 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4536 const struct dom_sid *domain_sid,
4537 const char *domain_name,
4538 struct cli_state *cli,
4539 struct rpc_pipe_client *pipe_hnd,
4540 TALLOC_CTX *mem_ctx,
4541 int argc,
4542 const char **argv)
4544 NTSTATUS result, status;
4545 struct policy_handle connect_pol;
4546 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4548 status = dcerpc_samr_Connect2(b, mem_ctx,
4549 pipe_hnd->desthost,
4550 MAXIMUM_ALLOWED_ACCESS,
4551 &connect_pol,
4552 &result);
4553 if (!NT_STATUS_IS_OK(status)) {
4554 goto done;
4556 if (!NT_STATUS_IS_OK(result)) {
4557 status = result;
4558 goto done;
4561 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4562 &global_sid_Builtin);
4563 if (!NT_STATUS_IS_OK(status)) {
4564 goto done;
4567 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4568 domain_sid);
4570 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
4571 done:
4572 return status;
4575 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4577 token->num_sids = 4;
4579 if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4580 d_fprintf(stderr, "malloc %s\n",_("failed"));
4581 token->num_sids = 0;
4582 return;
4585 token->sids[0] = *user_sid;
4586 sid_copy(&token->sids[1], &global_sid_World);
4587 sid_copy(&token->sids[2], &global_sid_Network);
4588 sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4591 static void free_user_token(struct security_token *token)
4593 SAFE_FREE(token->sids);
4596 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4598 if (security_token_has_sid(token, sid))
4599 return;
4601 token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4602 if (!token->sids) {
4603 return;
4606 sid_copy(&token->sids[token->num_sids], sid);
4608 token->num_sids += 1;
4611 struct user_token {
4612 fstring name;
4613 struct security_token token;
4616 static void dump_user_token(struct user_token *token)
4618 int i;
4620 d_printf("%s\n", token->name);
4622 for (i=0; i<token->token.num_sids; i++) {
4623 d_printf(" %s\n", sid_string_tos(&token->token.sids[i]));
4627 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4629 int i;
4631 for (i=0; i<alias->num_members; i++) {
4632 if (dom_sid_compare(sid, &alias->members[i]) == 0)
4633 return true;
4636 return false;
4639 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4641 int i;
4643 for (i=0; i<num_server_aliases; i++) {
4644 if (is_alias_member(&sid, &server_aliases[i]))
4645 add_sid_to_token(token, &server_aliases[i].sid);
4650 * We got a user token with all the SIDs we can know about without asking the
4651 * server directly. These are the user and domain group sids. All of these can
4652 * be members of aliases. So scan the list of aliases for each of the SIDs and
4653 * add them to the token.
4656 static void collect_alias_memberships(struct security_token *token)
4658 int num_global_sids = token->num_sids;
4659 int i;
4661 for (i=0; i<num_global_sids; i++) {
4662 collect_sid_memberships(token, token->sids[i]);
4666 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4668 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4669 enum wbcSidType type;
4670 fstring full_name;
4671 struct wbcDomainSid wsid;
4672 char sid_str[WBC_SID_STRING_BUFLEN];
4673 struct dom_sid user_sid;
4674 uint32_t num_groups;
4675 gid_t *groups = NULL;
4676 uint32_t i;
4678 fstr_sprintf(full_name, "%s%c%s",
4679 domain, *lp_winbind_separator(), user);
4681 /* First let's find out the user sid */
4683 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4685 if (!WBC_ERROR_IS_OK(wbc_status)) {
4686 DEBUG(1, ("winbind could not find %s: %s\n",
4687 full_name, wbcErrorString(wbc_status)));
4688 return false;
4691 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4693 if (type != WBC_SID_NAME_USER) {
4694 DEBUG(1, ("%s is not a user\n", full_name));
4695 return false;
4698 if (!string_to_sid(&user_sid, sid_str)) {
4699 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4700 return false;
4703 init_user_token(token, &user_sid);
4705 /* And now the groups winbind knows about */
4707 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4708 if (!WBC_ERROR_IS_OK(wbc_status)) {
4709 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4710 full_name, wbcErrorString(wbc_status)));
4711 return false;
4714 for (i = 0; i < num_groups; i++) {
4715 gid_t gid = groups[i];
4716 struct dom_sid sid;
4717 bool ok;
4719 wbc_status = wbcGidToSid(gid, &wsid);
4720 if (!WBC_ERROR_IS_OK(wbc_status)) {
4721 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4722 (unsigned int)gid, wbcErrorString(wbc_status)));
4723 wbcFreeMemory(groups);
4724 return false;
4727 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4729 DEBUG(3, (" %s\n", sid_str));
4731 ok = string_to_sid(&sid, sid_str);
4732 if (!ok) {
4733 DEBUG(1, ("Failed to convert string to SID\n"));
4734 wbcFreeMemory(groups);
4735 return false;
4737 add_sid_to_token(token, &sid);
4739 wbcFreeMemory(groups);
4741 return true;
4745 * Get a list of all user tokens we want to look at
4748 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4749 struct user_token **user_tokens)
4751 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4752 uint32_t i, num_users;
4753 const char **users;
4754 struct user_token *result;
4755 TALLOC_CTX *frame = NULL;
4757 if (lp_winbind_use_default_domain() &&
4758 (c->opt_target_workgroup == NULL)) {
4759 d_fprintf(stderr, _("winbind use default domain = yes set, "
4760 "please specify a workgroup\n"));
4761 return false;
4764 /* Send request to winbind daemon */
4766 wbc_status = wbcListUsers(NULL, &num_users, &users);
4767 if (!WBC_ERROR_IS_OK(wbc_status)) {
4768 DEBUG(1, (_("winbind could not list users: %s\n"),
4769 wbcErrorString(wbc_status)));
4770 return false;
4773 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4775 if (result == NULL) {
4776 DEBUG(1, ("Could not malloc sid array\n"));
4777 wbcFreeMemory(users);
4778 return false;
4781 frame = talloc_stackframe();
4782 for (i=0; i < num_users; i++) {
4783 fstring domain, user;
4784 char *p;
4786 fstrcpy(result[i].name, users[i]);
4788 p = strchr(users[i], *lp_winbind_separator());
4790 DEBUG(3, ("%s\n", users[i]));
4792 if (p == NULL) {
4793 fstrcpy(domain, c->opt_target_workgroup);
4794 fstrcpy(user, users[i]);
4795 } else {
4796 *p++ = '\0';
4797 fstrcpy(domain, users[i]);
4798 if (!strupper_m(domain)) {
4799 DEBUG(1, ("strupper_m %s failed\n", domain));
4800 wbcFreeMemory(users);
4801 return false;
4803 fstrcpy(user, p);
4806 get_user_sids(domain, user, &(result[i].token));
4808 TALLOC_FREE(frame);
4809 wbcFreeMemory(users);
4811 *num_tokens = num_users;
4812 *user_tokens = result;
4814 return true;
4817 static bool get_user_tokens_from_file(FILE *f,
4818 int *num_tokens,
4819 struct user_token **tokens)
4821 struct user_token *token = NULL;
4823 while (!feof(f)) {
4824 fstring line;
4826 if (fgets(line, sizeof(line)-1, f) == NULL) {
4827 return true;
4830 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
4831 line[strlen(line)-1] = '\0';
4834 if (line[0] == ' ') {
4835 /* We have a SID */
4837 struct dom_sid sid;
4838 if(!string_to_sid(&sid, &line[1])) {
4839 DEBUG(1,("get_user_tokens_from_file: Could "
4840 "not convert sid %s \n",&line[1]));
4841 return false;
4844 if (token == NULL) {
4845 DEBUG(0, ("File does not begin with username"));
4846 return false;
4849 add_sid_to_token(&token->token, &sid);
4850 continue;
4853 /* And a new user... */
4855 *num_tokens += 1;
4856 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4857 if (*tokens == NULL) {
4858 DEBUG(0, ("Could not realloc tokens\n"));
4859 return false;
4862 token = &((*tokens)[*num_tokens-1]);
4864 if (strlcpy(token->name, line, sizeof(token->name)) >= sizeof(token->name)) {
4865 return false;
4867 token->token.num_sids = 0;
4868 token->token.sids = NULL;
4869 continue;
4872 return false;
4877 * Show the list of all users that have access to a share
4880 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4881 TALLOC_CTX *mem_ctx,
4882 const char *netname,
4883 int num_tokens,
4884 struct user_token *tokens)
4886 uint16_t fnum;
4887 struct security_descriptor *share_sd = NULL;
4888 struct security_descriptor *root_sd = NULL;
4889 struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4890 int i;
4891 union srvsvc_NetShareInfo info;
4892 WERROR result;
4893 NTSTATUS status;
4894 uint16 cnum;
4895 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4897 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
4898 pipe_hnd->desthost,
4899 netname,
4900 502,
4901 &info,
4902 &result);
4904 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4905 DEBUG(1, ("Coult not query secdesc for share %s\n",
4906 netname));
4907 return;
4910 share_sd = info.info502->sd_buf.sd;
4911 if (share_sd == NULL) {
4912 DEBUG(1, ("Got no secdesc for share %s\n",
4913 netname));
4916 cnum = cli_state_get_tid(cli);
4918 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", "", 0))) {
4919 return;
4922 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4923 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
4924 cli_query_secdesc(cli, fnum, mem_ctx, &root_sd);
4927 for (i=0; i<num_tokens; i++) {
4928 uint32 acc_granted;
4930 if (share_sd != NULL) {
4931 status = se_access_check(share_sd, &tokens[i].token,
4932 1, &acc_granted);
4934 if (!NT_STATUS_IS_OK(status)) {
4935 DEBUG(1, ("Could not check share_sd for "
4936 "user %s\n",
4937 tokens[i].name));
4938 continue;
4942 if (root_sd == NULL) {
4943 d_printf(" %s\n", tokens[i].name);
4944 continue;
4947 status = se_access_check(root_sd, &tokens[i].token,
4948 1, &acc_granted);
4949 if (!NT_STATUS_IS_OK(status)) {
4950 DEBUG(1, ("Could not check root_sd for user %s\n",
4951 tokens[i].name));
4952 continue;
4954 d_printf(" %s\n", tokens[i].name);
4957 if (fnum != (uint16_t)-1)
4958 cli_close(cli, fnum);
4959 cli_tdis(cli);
4960 cli_state_set_tid(cli, cnum);
4962 return;
4966 * List shares on a remote RPC server, including the security descriptors.
4968 * All parameters are provided by the run_rpc_command function, except for
4969 * argc, argv which are passed through.
4971 * @param domain_sid The domain sid acquired from the remote server.
4972 * @param cli A cli_state connected to the server.
4973 * @param mem_ctx Talloc context, destroyed on completion of the function.
4974 * @param argc Standard main() style argc.
4975 * @param argv Standard main() style argv. Initial components are already
4976 * stripped.
4978 * @return Normal NTSTATUS return.
4981 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4982 const struct dom_sid *domain_sid,
4983 const char *domain_name,
4984 struct cli_state *cli,
4985 struct rpc_pipe_client *pipe_hnd,
4986 TALLOC_CTX *mem_ctx,
4987 int argc,
4988 const char **argv)
4990 bool r;
4991 FILE *f;
4992 NTSTATUS nt_status = NT_STATUS_OK;
4993 uint32_t total_entries = 0;
4994 uint32_t resume_handle = 0;
4995 uint32_t preferred_len = 0xffffffff;
4996 uint32_t i;
4997 struct dcerpc_binding_handle *b = NULL;
4998 struct srvsvc_NetShareInfoCtr info_ctr;
4999 struct srvsvc_NetShareCtr1 ctr1;
5000 WERROR result;
5002 struct user_token *tokens = NULL;
5003 int num_tokens = 0;
5005 if (argc == 0) {
5006 f = stdin;
5007 } else {
5008 f = fopen(argv[0], "r");
5011 if (f == NULL) {
5012 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
5013 return NT_STATUS_UNSUCCESSFUL;
5016 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
5018 if (f != stdin)
5019 fclose(f);
5021 if (!r) {
5022 DEBUG(0, ("Could not read users from file\n"));
5023 return NT_STATUS_UNSUCCESSFUL;
5026 for (i=0; i<num_tokens; i++)
5027 collect_alias_memberships(&tokens[i].token);
5029 ZERO_STRUCT(info_ctr);
5030 ZERO_STRUCT(ctr1);
5032 info_ctr.level = 1;
5033 info_ctr.ctr.ctr1 = &ctr1;
5035 b = pipe_hnd->binding_handle;
5037 /* Issue the NetShareEnum RPC call and retrieve the response */
5038 nt_status = dcerpc_srvsvc_NetShareEnumAll(b,
5039 talloc_tos(),
5040 pipe_hnd->desthost,
5041 &info_ctr,
5042 preferred_len,
5043 &total_entries,
5044 &resume_handle,
5045 &result);
5047 /* Was it successful? */
5048 if (!NT_STATUS_IS_OK(nt_status)) {
5049 /* Nope. Go clean up. */
5050 goto done;
5053 if (!W_ERROR_IS_OK(result)) {
5054 /* Nope. Go clean up. */
5055 nt_status = werror_to_ntstatus(result);
5056 goto done;
5059 if (total_entries == 0) {
5060 goto done;
5063 /* For each returned entry... */
5064 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
5065 const char *netname = info_ctr.ctr.ctr1->array[i].name;
5067 if (info_ctr.ctr.ctr1->array[i].type != STYPE_DISKTREE) {
5068 continue;
5071 d_printf("%s\n", netname);
5073 show_userlist(pipe_hnd, mem_ctx, netname,
5074 num_tokens, tokens);
5076 done:
5077 for (i=0; i<num_tokens; i++) {
5078 free_user_token(&tokens[i].token);
5080 SAFE_FREE(tokens);
5082 return nt_status;
5085 static int rpc_share_allowedusers(struct net_context *c, int argc,
5086 const char **argv)
5088 int result;
5090 if (c->display_usage) {
5091 d_printf( "%s\n"
5092 "net rpc share allowedusers\n"
5093 " %s\n",
5094 _("Usage:"),
5095 _("List allowed users"));
5096 return 0;
5099 result = run_rpc_command(c, NULL, &ndr_table_samr, 0,
5100 rpc_aliaslist_internals,
5101 argc, argv);
5102 if (result != 0)
5103 return result;
5105 result = run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
5106 rpc_aliaslist_dump,
5107 argc, argv);
5108 if (result != 0)
5109 return result;
5111 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
5112 rpc_share_allowedusers_internals,
5113 argc, argv);
5116 int net_usersidlist(struct net_context *c, int argc, const char **argv)
5118 int num_tokens = 0;
5119 struct user_token *tokens = NULL;
5120 int i;
5122 if (argc != 0) {
5123 net_usersidlist_usage(c, argc, argv);
5124 return 0;
5127 if (!get_user_tokens(c, &num_tokens, &tokens)) {
5128 DEBUG(0, ("Could not get the user/sid list\n"));
5129 return -1;
5132 for (i=0; i<num_tokens; i++) {
5133 dump_user_token(&tokens[i]);
5134 free_user_token(&tokens[i].token);
5137 SAFE_FREE(tokens);
5138 return 0;
5141 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
5143 d_printf(_("net usersidlist\n"
5144 "\tprints out a list of all users the running winbind knows\n"
5145 "\tabout, together with all their SIDs. This is used as\n"
5146 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
5148 net_common_flags_usage(c, argc, argv);
5149 return -1;
5153 * 'net rpc share' entrypoint.
5154 * @param argc Standard main() style argc.
5155 * @param argv Standard main() style argv. Initial components are already
5156 * stripped.
5159 int net_rpc_share(struct net_context *c, int argc, const char **argv)
5161 NET_API_STATUS status;
5163 struct functable func[] = {
5165 "add",
5166 rpc_share_add,
5167 NET_TRANSPORT_RPC,
5168 N_("Add share"),
5169 N_("net rpc share add\n"
5170 " Add share")
5173 "delete",
5174 rpc_share_delete,
5175 NET_TRANSPORT_RPC,
5176 N_("Remove share"),
5177 N_("net rpc share delete\n"
5178 " Remove share")
5181 "allowedusers",
5182 rpc_share_allowedusers,
5183 NET_TRANSPORT_RPC,
5184 N_("Modify allowed users"),
5185 N_("net rpc share allowedusers\n"
5186 " Modify allowed users")
5189 "migrate",
5190 rpc_share_migrate,
5191 NET_TRANSPORT_RPC,
5192 N_("Migrate share to local server"),
5193 N_("net rpc share migrate\n"
5194 " Migrate share to local server")
5197 "list",
5198 rpc_share_list,
5199 NET_TRANSPORT_RPC,
5200 N_("List shares"),
5201 N_("net rpc share list\n"
5202 " List shares")
5204 {NULL, NULL, 0, NULL, NULL}
5207 status = libnetapi_net_init(&c->netapi_ctx);
5208 if (status != 0) {
5209 return -1;
5211 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5212 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5213 if (c->opt_kerberos) {
5214 libnetapi_set_use_kerberos(c->netapi_ctx);
5217 if (argc == 0) {
5218 if (c->display_usage) {
5219 d_printf("%s\n%s",
5220 _("Usage:"),
5221 _("net rpc share\n"
5222 " List shares\n"
5223 " Alias for net rpc share list\n"));
5224 net_display_usage_from_functable(func);
5225 return 0;
5228 return rpc_share_list(c, argc, argv);
5231 return net_run_function(c, argc, argv, "net rpc share", func);
5234 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5235 TALLOC_CTX *mem_ctx,
5236 struct rpc_sh_ctx *ctx,
5237 struct rpc_pipe_client *pipe_hnd,
5238 int argc, const char **argv)
5241 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5244 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5245 TALLOC_CTX *mem_ctx,
5246 struct rpc_sh_ctx *ctx,
5247 struct rpc_pipe_client *pipe_hnd,
5248 int argc, const char **argv)
5250 NET_API_STATUS status;
5251 uint32_t parm_err = 0;
5252 struct SHARE_INFO_2 i2;
5254 if ((argc < 2) || (argc > 3)) {
5255 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5256 ctx->whoami);
5257 return NT_STATUS_INVALID_PARAMETER;
5260 i2.shi2_netname = argv[0];
5261 i2.shi2_type = STYPE_DISKTREE;
5262 i2.shi2_remark = (argc == 3) ? argv[2] : "";
5263 i2.shi2_permissions = 0;
5264 i2.shi2_max_uses = 0;
5265 i2.shi2_current_uses = 0;
5266 i2.shi2_path = argv[1];
5267 i2.shi2_passwd = NULL;
5269 status = NetShareAdd(pipe_hnd->desthost,
5271 (uint8_t *)&i2,
5272 &parm_err);
5274 return werror_to_ntstatus(W_ERROR(status));
5277 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5278 TALLOC_CTX *mem_ctx,
5279 struct rpc_sh_ctx *ctx,
5280 struct rpc_pipe_client *pipe_hnd,
5281 int argc, const char **argv)
5283 if (argc != 1) {
5284 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5285 return NT_STATUS_INVALID_PARAMETER;
5288 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5291 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5292 TALLOC_CTX *mem_ctx,
5293 struct rpc_sh_ctx *ctx,
5294 struct rpc_pipe_client *pipe_hnd,
5295 int argc, const char **argv)
5297 union srvsvc_NetShareInfo info;
5298 WERROR result;
5299 NTSTATUS status;
5300 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5302 if (argc != 1) {
5303 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5304 return NT_STATUS_INVALID_PARAMETER;
5307 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5308 pipe_hnd->desthost,
5309 argv[0],
5311 &info,
5312 &result);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 result = ntstatus_to_werror(status);
5315 goto done;
5317 if (!W_ERROR_IS_OK(result)) {
5318 goto done;
5321 d_printf(_("Name: %s\n"), info.info2->name);
5322 d_printf(_("Comment: %s\n"), info.info2->comment);
5323 d_printf(_("Path: %s\n"), info.info2->path);
5324 d_printf(_("Password: %s\n"), info.info2->password);
5326 done:
5327 return werror_to_ntstatus(result);
5330 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5331 struct rpc_sh_ctx *ctx)
5333 static struct rpc_sh_cmd cmds[] = {
5335 { "list", NULL, &ndr_table_srvsvc, rpc_sh_share_list,
5336 N_("List available shares") },
5338 { "add", NULL, &ndr_table_srvsvc, rpc_sh_share_add,
5339 N_("Add a share") },
5341 { "delete", NULL, &ndr_table_srvsvc, rpc_sh_share_delete,
5342 N_("Delete a share") },
5344 { "info", NULL, &ndr_table_srvsvc, rpc_sh_share_info,
5345 N_("Get information about a share") },
5347 { NULL, NULL, 0, NULL, NULL }
5350 return cmds;
5353 /****************************************************************************/
5355 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5357 return net_file_usage(c, argc, argv);
5361 * Close a file on a remote RPC server.
5363 * @param argc Standard main() style argc.
5364 * @param argv Standard main() style argv. Initial components are already
5365 * stripped.
5367 * @return A shell status integer (0 for success).
5369 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5371 if (argc < 1 || c->display_usage) {
5372 return rpc_file_usage(c, argc, argv);
5375 return NetFileClose(c->opt_host, atoi(argv[0]));
5379 * Formatted print of open file info
5381 * @param r struct FILE_INFO_3 contents
5384 static void display_file_info_3(struct FILE_INFO_3 *r)
5386 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5387 r->fi3_id, r->fi3_username, r->fi3_permissions,
5388 r->fi3_num_locks, r->fi3_pathname);
5392 * List files for a user on a remote RPC server.
5394 * @param argc Standard main() style argc.
5395 * @param argv Standard main() style argv. Initial components are already
5396 * stripped.
5398 * @return A shell status integer (0 for success)..
5401 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5403 NET_API_STATUS status;
5404 uint32 preferred_len = 0xffffffff, i;
5405 char *username=NULL;
5406 uint32_t total_entries = 0;
5407 uint32_t entries_read = 0;
5408 uint32_t resume_handle = 0;
5409 struct FILE_INFO_3 *i3 = NULL;
5411 if (c->display_usage) {
5412 return rpc_file_usage(c, argc, argv);
5415 /* if argc > 0, must be user command */
5416 if (argc > 0) {
5417 username = smb_xstrdup(argv[0]);
5420 status = NetFileEnum(c->opt_host,
5421 NULL,
5422 username,
5424 (uint8_t **)(void *)&i3,
5425 preferred_len,
5426 &entries_read,
5427 &total_entries,
5428 &resume_handle);
5430 if (status != 0) {
5431 goto done;
5434 /* Display results */
5436 d_printf(_(
5437 "\nEnumerating open files on remote server:\n\n"
5438 "\nFileId Opened by Perms Locks Path"
5439 "\n------ --------- ----- ----- ---- \n"));
5440 for (i = 0; i < entries_read; i++) {
5441 display_file_info_3(&i3[i]);
5443 done:
5444 SAFE_FREE(username);
5445 return status;
5449 * 'net rpc file' entrypoint.
5450 * @param argc Standard main() style argc.
5451 * @param argv Standard main() style argv. Initial components are already
5452 * stripped.
5455 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5457 NET_API_STATUS status;
5459 struct functable func[] = {
5461 "close",
5462 rpc_file_close,
5463 NET_TRANSPORT_RPC,
5464 N_("Close opened file"),
5465 N_("net rpc file close\n"
5466 " Close opened file")
5469 "user",
5470 rpc_file_user,
5471 NET_TRANSPORT_RPC,
5472 N_("List files opened by user"),
5473 N_("net rpc file user\n"
5474 " List files opened by user")
5476 #if 0
5478 "info",
5479 rpc_file_info,
5480 NET_TRANSPORT_RPC,
5481 N_("Display information about opened file"),
5482 N_("net rpc file info\n"
5483 " Display information about opened file")
5485 #endif
5486 {NULL, NULL, 0, NULL, NULL}
5489 status = libnetapi_net_init(&c->netapi_ctx);
5490 if (status != 0) {
5491 return -1;
5493 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5494 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5495 if (c->opt_kerberos) {
5496 libnetapi_set_use_kerberos(c->netapi_ctx);
5499 if (argc == 0) {
5500 if (c->display_usage) {
5501 d_printf(_("Usage:\n"));
5502 d_printf(_("net rpc file\n"
5503 " List opened files\n"));
5504 net_display_usage_from_functable(func);
5505 return 0;
5508 return rpc_file_user(c, argc, argv);
5511 return net_run_function(c, argc, argv, "net rpc file", func);
5515 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5517 * All parameters are provided by the run_rpc_command function, except for
5518 * argc, argv which are passed through.
5520 * @param c A net_context structure.
5521 * @param domain_sid The domain sid acquired from the remote server.
5522 * @param cli A cli_state connected to the server.
5523 * @param mem_ctx Talloc context, destroyed on completion of the function.
5524 * @param argc Standard main() style argc.
5525 * @param argv Standard main() style argv. Initial components are already
5526 * stripped.
5528 * @return Normal NTSTATUS return.
5531 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5532 const struct dom_sid *domain_sid,
5533 const char *domain_name,
5534 struct cli_state *cli,
5535 struct rpc_pipe_client *pipe_hnd,
5536 TALLOC_CTX *mem_ctx,
5537 int argc,
5538 const char **argv)
5540 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5541 WERROR result;
5542 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5544 status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5545 if (!NT_STATUS_IS_OK(status)) {
5546 return status;
5548 if (W_ERROR_IS_OK(result)) {
5549 d_printf(_("\nShutdown successfully aborted\n"));
5550 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5551 } else
5552 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5554 return werror_to_ntstatus(result);
5558 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5560 * All parameters are provided by the run_rpc_command function, except for
5561 * argc, argv which are passed through.
5563 * @param c A net_context structure.
5564 * @param domain_sid The domain sid acquired from the remote server.
5565 * @param cli A cli_state connected to the server.
5566 * @param mem_ctx Talloc context, destroyed on completion of the function.
5567 * @param argc Standard main() style argc.
5568 * @param argv Standard main() style argv. Initial components are already
5569 * stripped.
5571 * @return Normal NTSTATUS return.
5574 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5575 const struct dom_sid *domain_sid,
5576 const char *domain_name,
5577 struct cli_state *cli,
5578 struct rpc_pipe_client *pipe_hnd,
5579 TALLOC_CTX *mem_ctx,
5580 int argc,
5581 const char **argv)
5583 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5584 WERROR werr;
5585 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5587 result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5589 if (!NT_STATUS_IS_OK(result)) {
5590 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5591 return result;
5593 if (W_ERROR_IS_OK(werr)) {
5594 d_printf(_("\nShutdown successfully aborted\n"));
5595 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5596 } else
5597 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5599 return werror_to_ntstatus(werr);
5603 * ABORT the shutdown of a remote RPC server.
5605 * @param argc Standard main() style argc.
5606 * @param argv Standard main() style argv. Initial components are already
5607 * stripped.
5609 * @return A shell status integer (0 for success).
5612 static int rpc_shutdown_abort(struct net_context *c, int argc,
5613 const char **argv)
5615 int rc = -1;
5617 if (c->display_usage) {
5618 d_printf( "%s\n"
5619 "net rpc abortshutdown\n"
5620 " %s\n",
5621 _("Usage:"),
5622 _("Abort a scheduled shutdown"));
5623 return 0;
5626 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5627 rpc_shutdown_abort_internals, argc, argv);
5629 if (rc == 0)
5630 return rc;
5632 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5634 return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5635 rpc_reg_shutdown_abort_internals,
5636 argc, argv);
5640 * Shut down a remote RPC Server via initshutdown pipe.
5642 * All parameters are provided by the run_rpc_command function, except for
5643 * argc, argv which are passed through.
5645 * @param c A net_context structure.
5646 * @param domain_sid The domain sid acquired from the remote server.
5647 * @param cli A cli_state connected to the server.
5648 * @param mem_ctx Talloc context, destroyed on completion of the function.
5649 * @param argc Standard main() style argc.
5650 * @param argv Standard main() style argv. Initial components are already
5651 * stripped.
5653 * @return Normal NTSTATUS return.
5656 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5657 const struct dom_sid *domain_sid,
5658 const char *domain_name,
5659 struct cli_state *cli,
5660 struct rpc_pipe_client *pipe_hnd,
5661 TALLOC_CTX *mem_ctx,
5662 int argc,
5663 const char **argv)
5665 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5666 WERROR result;
5667 const char *msg = N_("This machine will be shutdown shortly");
5668 uint32 timeout = 20;
5669 struct lsa_StringLarge msg_string;
5670 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5672 if (c->opt_comment) {
5673 msg = c->opt_comment;
5675 if (c->opt_timeout) {
5676 timeout = c->opt_timeout;
5679 msg_string.string = msg;
5681 /* create an entry */
5682 status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5683 &msg_string, timeout, c->opt_force, c->opt_reboot,
5684 &result);
5685 if (!NT_STATUS_IS_OK(status)) {
5686 return status;
5688 if (W_ERROR_IS_OK(result)) {
5689 d_printf(_("\nShutdown of remote machine succeeded\n"));
5690 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5691 } else {
5692 DEBUG(1,("Shutdown of remote machine failed!\n"));
5694 return werror_to_ntstatus(result);
5698 * Shut down a remote RPC Server via winreg pipe.
5700 * All parameters are provided by the run_rpc_command function, except for
5701 * argc, argv which are passed through.
5703 * @param c A net_context structure.
5704 * @param domain_sid The domain sid acquired from the remote server.
5705 * @param cli A cli_state connected to the server.
5706 * @param mem_ctx Talloc context, destroyed on completion of the function.
5707 * @param argc Standard main() style argc.
5708 * @param argv Standard main() style argv. Initial components are already
5709 * stripped.
5711 * @return Normal NTSTATUS return.
5714 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5715 const struct dom_sid *domain_sid,
5716 const char *domain_name,
5717 struct cli_state *cli,
5718 struct rpc_pipe_client *pipe_hnd,
5719 TALLOC_CTX *mem_ctx,
5720 int argc,
5721 const char **argv)
5723 const char *msg = N_("This machine will be shutdown shortly");
5724 uint32 timeout = 20;
5725 struct lsa_StringLarge msg_string;
5726 NTSTATUS result;
5727 WERROR werr;
5728 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5730 if (c->opt_comment) {
5731 msg = c->opt_comment;
5733 msg_string.string = msg;
5735 if (c->opt_timeout) {
5736 timeout = c->opt_timeout;
5739 /* create an entry */
5740 result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
5741 &msg_string, timeout, c->opt_force, c->opt_reboot,
5742 &werr);
5743 if (!NT_STATUS_IS_OK(result)) {
5744 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5745 return result;
5748 if (W_ERROR_IS_OK(werr)) {
5749 d_printf(_("\nShutdown of remote machine succeeded\n"));
5750 } else {
5751 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5752 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5753 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5754 else
5755 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5758 return werror_to_ntstatus(werr);
5762 * Shut down a remote RPC server.
5764 * @param argc Standard main() style argc.
5765 * @param argv Standard main() style argv. Initial components are already
5766 * stripped.
5768 * @return A shell status integer (0 for success).
5771 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5773 int rc = -1;
5775 if (c->display_usage) {
5776 d_printf( "%s\n"
5777 "net rpc shutdown\n"
5778 " %s\n",
5779 _("Usage:"),
5780 _("Shut down a remote RPC server"));
5781 return 0;
5784 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5785 rpc_init_shutdown_internals, argc, argv);
5787 if (rc) {
5788 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5789 rc = run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5790 rpc_reg_shutdown_internals, argc, argv);
5793 return rc;
5796 /***************************************************************************
5797 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5798 ***************************************************************************/
5801 * Add interdomain trust account to the RPC server.
5802 * All parameters (except for argc and argv) are passed by run_rpc_command
5803 * function.
5805 * @param c A net_context structure.
5806 * @param domain_sid The domain sid acquired from the server.
5807 * @param cli A cli_state connected to the server.
5808 * @param mem_ctx Talloc context, destroyed on completion of the function.
5809 * @param argc Standard main() style argc.
5810 * @param argv Standard main() style argv. Initial components are already
5811 * stripped.
5813 * @return normal NTSTATUS return code.
5816 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5817 const struct dom_sid *domain_sid,
5818 const char *domain_name,
5819 struct cli_state *cli,
5820 struct rpc_pipe_client *pipe_hnd,
5821 TALLOC_CTX *mem_ctx,
5822 int argc,
5823 const char **argv)
5825 struct policy_handle connect_pol, domain_pol, user_pol;
5826 NTSTATUS status, result;
5827 char *acct_name;
5828 struct lsa_String lsa_acct_name;
5829 uint32 acb_info;
5830 uint32 acct_flags=0;
5831 uint32 user_rid;
5832 uint32_t access_granted = 0;
5833 union samr_UserInfo info;
5834 unsigned int orig_timeout;
5835 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5836 DATA_BLOB session_key = data_blob_null;
5838 if (argc != 2) {
5839 d_printf("%s\n%s",
5840 _("Usage:"),
5841 _(" net rpc trustdom add <domain_name> "
5842 "<trust password>\n"));
5843 return NT_STATUS_INVALID_PARAMETER;
5847 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5850 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5851 return NT_STATUS_NO_MEMORY;
5854 if (!strupper_m(acct_name)) {
5855 SAFE_FREE(acct_name);
5856 return NT_STATUS_INVALID_PARAMETER;
5859 init_lsa_String(&lsa_acct_name, acct_name);
5861 status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
5862 if (!NT_STATUS_IS_OK(status)) {
5863 DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
5864 nt_errstr(status)));
5865 goto done;
5868 /* Get samr policy handle */
5869 status = dcerpc_samr_Connect2(b, mem_ctx,
5870 pipe_hnd->desthost,
5871 MAXIMUM_ALLOWED_ACCESS,
5872 &connect_pol,
5873 &result);
5874 if (!NT_STATUS_IS_OK(status)) {
5875 goto done;
5877 if (!NT_STATUS_IS_OK(result)) {
5878 status = result;
5879 goto done;
5882 /* Get domain policy handle */
5883 status = dcerpc_samr_OpenDomain(b, mem_ctx,
5884 &connect_pol,
5885 MAXIMUM_ALLOWED_ACCESS,
5886 discard_const_p(struct dom_sid2, domain_sid),
5887 &domain_pol,
5888 &result);
5889 if (!NT_STATUS_IS_OK(status)) {
5890 goto done;
5892 if (!NT_STATUS_IS_OK(result)) {
5893 status = result;
5894 goto done;
5897 /* This call can take a long time - allow the server to time out.
5898 * 35 seconds should do it. */
5900 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5902 /* Create trusting domain's account */
5903 acb_info = ACB_NORMAL;
5904 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5905 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5906 SAMR_USER_ACCESS_SET_PASSWORD |
5907 SAMR_USER_ACCESS_GET_ATTRIBUTES |
5908 SAMR_USER_ACCESS_SET_ATTRIBUTES;
5910 status = dcerpc_samr_CreateUser2(b, mem_ctx,
5911 &domain_pol,
5912 &lsa_acct_name,
5913 acb_info,
5914 acct_flags,
5915 &user_pol,
5916 &access_granted,
5917 &user_rid,
5918 &result);
5919 if (!NT_STATUS_IS_OK(status)) {
5920 goto done;
5922 /* And restore our original timeout. */
5923 rpccli_set_timeout(pipe_hnd, orig_timeout);
5925 if (!NT_STATUS_IS_OK(result)) {
5926 status = result;
5927 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5928 acct_name, nt_errstr(result));
5929 goto done;
5933 struct samr_CryptPassword crypt_pwd;
5935 ZERO_STRUCT(info.info23);
5937 init_samr_CryptPassword(argv[1],
5938 &session_key,
5939 &crypt_pwd);
5941 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5942 SAMR_FIELD_NT_PASSWORD_PRESENT;
5943 info.info23.info.acct_flags = ACB_DOMTRUST;
5944 info.info23.password = crypt_pwd;
5946 status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
5947 &user_pol,
5949 &info,
5950 &result);
5951 if (!NT_STATUS_IS_OK(status)) {
5952 goto done;
5955 if (!NT_STATUS_IS_OK(result)) {
5956 status = result;
5957 DEBUG(0,("Could not set trust account password: %s\n",
5958 nt_errstr(result)));
5959 goto done;
5963 done:
5964 SAFE_FREE(acct_name);
5965 data_blob_clear_free(&session_key);
5966 return status;
5970 * Create interdomain trust account for a remote domain.
5972 * @param argc Standard argc.
5973 * @param argv Standard argv without initial components.
5975 * @return Integer status (0 means success).
5978 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5980 if (argc > 0 && !c->display_usage) {
5981 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
5982 rpc_trustdom_add_internals, argc, argv);
5983 } else {
5984 d_printf("%s\n%s",
5985 _("Usage:"),
5986 _("net rpc trustdom add <domain_name> <trust "
5987 "password>\n"));
5988 return -1;
5994 * Remove interdomain trust account from the RPC server.
5995 * All parameters (except for argc and argv) are passed by run_rpc_command
5996 * function.
5998 * @param c A net_context structure.
5999 * @param domain_sid The domain sid acquired from the server.
6000 * @param cli A cli_state connected to the server.
6001 * @param mem_ctx Talloc context, destroyed on completion of the function.
6002 * @param argc Standard main() style argc.
6003 * @param argv Standard main() style argv. Initial components are already
6004 * stripped.
6006 * @return normal NTSTATUS return code.
6009 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
6010 const struct dom_sid *domain_sid,
6011 const char *domain_name,
6012 struct cli_state *cli,
6013 struct rpc_pipe_client *pipe_hnd,
6014 TALLOC_CTX *mem_ctx,
6015 int argc,
6016 const char **argv)
6018 struct policy_handle connect_pol, domain_pol, user_pol;
6019 NTSTATUS status, result;
6020 char *acct_name;
6021 struct dom_sid trust_acct_sid;
6022 struct samr_Ids user_rids, name_types;
6023 struct lsa_String lsa_acct_name;
6024 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6026 if (argc != 1) {
6027 d_printf("%s\n%s",
6028 _("Usage:"),
6029 _(" net rpc trustdom del <domain_name>\n"));
6030 return NT_STATUS_INVALID_PARAMETER;
6034 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6036 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
6038 if (acct_name == NULL)
6039 return NT_STATUS_NO_MEMORY;
6041 if (!strupper_m(acct_name)) {
6042 TALLOC_FREE(acct_name);
6043 return NT_STATUS_INVALID_PARAMETER;
6046 /* Get samr policy handle */
6047 status = dcerpc_samr_Connect2(b, mem_ctx,
6048 pipe_hnd->desthost,
6049 MAXIMUM_ALLOWED_ACCESS,
6050 &connect_pol,
6051 &result);
6052 if (!NT_STATUS_IS_OK(status)) {
6053 goto done;
6055 if (!NT_STATUS_IS_OK(result)) {
6056 status = result;
6057 goto done;
6060 /* Get domain policy handle */
6061 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6062 &connect_pol,
6063 MAXIMUM_ALLOWED_ACCESS,
6064 discard_const_p(struct dom_sid2, domain_sid),
6065 &domain_pol,
6066 &result);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 goto done;
6070 if (!NT_STATUS_IS_OK(result)) {
6071 status = result;
6072 goto done;
6075 init_lsa_String(&lsa_acct_name, acct_name);
6077 status = dcerpc_samr_LookupNames(b, mem_ctx,
6078 &domain_pol,
6080 &lsa_acct_name,
6081 &user_rids,
6082 &name_types,
6083 &result);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6086 "failed %s\n"),
6087 acct_name, nt_errstr(status));
6088 goto done;
6090 if (!NT_STATUS_IS_OK(result)) {
6091 status = result;
6092 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6093 "failed %s\n"),
6094 acct_name, nt_errstr(result) );
6095 goto done;
6097 if (user_rids.count != 1) {
6098 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6099 goto done;
6101 if (name_types.count != 1) {
6102 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6103 goto done;
6106 status = dcerpc_samr_OpenUser(b, mem_ctx,
6107 &domain_pol,
6108 MAXIMUM_ALLOWED_ACCESS,
6109 user_rids.ids[0],
6110 &user_pol,
6111 &result);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6114 "%s\n"),
6115 acct_name, nt_errstr(status) );
6116 goto done;
6119 if (!NT_STATUS_IS_OK(result)) {
6120 status = result;
6121 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6122 "%s\n"),
6123 acct_name, nt_errstr(result) );
6124 goto done;
6127 /* append the rid to the domain sid */
6128 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6129 goto done;
6132 /* remove the sid */
6134 status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6135 &user_pol,
6136 &trust_acct_sid,
6137 &result);
6138 if (!NT_STATUS_IS_OK(status)) {
6139 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6140 " on user %s failed %s\n"),
6141 acct_name, nt_errstr(status));
6142 goto done;
6144 if (!NT_STATUS_IS_OK(result)) {
6145 status = result;
6146 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6147 " on user %s failed %s\n"),
6148 acct_name, nt_errstr(result) );
6149 goto done;
6153 /* Delete user */
6155 status = dcerpc_samr_DeleteUser(b, mem_ctx,
6156 &user_pol,
6157 &result);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6160 "%s\n"),
6161 acct_name, nt_errstr(status));
6162 goto done;
6165 if (!NT_STATUS_IS_OK(result)) {
6166 result = status;
6167 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6168 "%s\n"),
6169 acct_name, nt_errstr(result) );
6170 goto done;
6173 if (!NT_STATUS_IS_OK(result)) {
6174 d_printf(_("Could not set trust account password: %s\n"),
6175 nt_errstr(result));
6176 goto done;
6179 done:
6180 return status;
6184 * Delete interdomain trust account for a remote domain.
6186 * @param argc Standard argc.
6187 * @param argv Standard argv without initial components.
6189 * @return Integer status (0 means success).
6192 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6194 if (argc > 0 && !c->display_usage) {
6195 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6196 rpc_trustdom_del_internals, argc, argv);
6197 } else {
6198 d_printf("%s\n%s",
6199 _("Usage:"),
6200 _("net rpc trustdom del <domain>\n"));
6201 return -1;
6205 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6206 struct cli_state *cli,
6207 TALLOC_CTX *mem_ctx,
6208 const char *domain_name)
6210 char *dc_name = NULL;
6211 const char *buffer = NULL;
6212 struct rpc_pipe_client *netr;
6213 NTSTATUS status;
6214 WERROR result;
6215 struct dcerpc_binding_handle *b;
6217 /* Use NetServerEnum2 */
6219 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6220 SAFE_FREE(dc_name);
6221 return NT_STATUS_OK;
6224 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6225 for domain %s\n", domain_name));
6227 /* Try netr_GetDcName */
6229 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
6230 &netr);
6231 if (!NT_STATUS_IS_OK(status)) {
6232 return status;
6235 b = netr->binding_handle;
6237 status = dcerpc_netr_GetDcName(b, mem_ctx,
6238 netr->desthost,
6239 domain_name,
6240 &buffer,
6241 &result);
6242 TALLOC_FREE(netr);
6244 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6245 return status;
6248 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6249 for domain %s\n", domain_name));
6251 if (!NT_STATUS_IS_OK(status)) {
6252 return status;
6255 return werror_to_ntstatus(result);
6259 * Establish trust relationship to a trusting domain.
6260 * Interdomain account must already be created on remote PDC.
6262 * @param c A net_context structure.
6263 * @param argc Standard argc.
6264 * @param argv Standard argv without initial components.
6266 * @return Integer status (0 means success).
6269 static int rpc_trustdom_establish(struct net_context *c, int argc,
6270 const char **argv)
6272 struct cli_state *cli = NULL;
6273 struct sockaddr_storage server_ss;
6274 struct rpc_pipe_client *pipe_hnd = NULL;
6275 struct policy_handle connect_hnd;
6276 TALLOC_CTX *mem_ctx;
6277 NTSTATUS nt_status, result;
6278 struct dom_sid *domain_sid;
6280 char* domain_name;
6281 char* acct_name;
6282 fstring pdc_name;
6283 union lsa_PolicyInformation *info = NULL;
6284 struct dcerpc_binding_handle *b;
6287 * Connect to \\server\ipc$ as 'our domain' account with password
6290 if (argc != 1 || c->display_usage) {
6291 d_printf("%s\n%s",
6292 _("Usage:"),
6293 _("net rpc trustdom establish <domain_name>\n"));
6294 return -1;
6297 domain_name = smb_xstrdup(argv[0]);
6298 if (!strupper_m(domain_name)) {
6299 SAFE_FREE(domain_name);
6300 return -1;
6303 /* account name used at first is our domain's name with '$' */
6304 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6305 return -1;
6307 if (!strupper_m(acct_name)) {
6308 SAFE_FREE(domain_name);
6309 SAFE_FREE(acct_name);
6310 return -1;
6314 * opt_workgroup will be used by connection functions further,
6315 * hence it should be set to remote domain name instead of ours
6317 if (c->opt_workgroup) {
6318 c->opt_workgroup = smb_xstrdup(domain_name);
6321 c->opt_user_name = acct_name;
6323 /* find the domain controller */
6324 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6325 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6326 return -1;
6329 /* connect to ipc$ as username/password */
6330 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6331 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6333 /* Is it trusting domain account for sure ? */
6334 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6335 nt_errstr(nt_status)));
6336 return -1;
6339 /* store who we connected to */
6341 saf_store( domain_name, pdc_name );
6344 * Connect to \\server\ipc$ again (this time anonymously)
6347 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6348 (char*)pdc_name);
6350 if (NT_STATUS_IS_ERR(nt_status)) {
6351 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6352 domain_name, nt_errstr(nt_status)));
6353 return -1;
6356 if (!(mem_ctx = talloc_init("establishing trust relationship to "
6357 "domain %s", domain_name))) {
6358 DEBUG(0, ("talloc_init() failed\n"));
6359 cli_shutdown(cli);
6360 return -1;
6363 /* Make sure we're talking to a proper server */
6365 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6366 if (!NT_STATUS_IS_OK(nt_status)) {
6367 cli_shutdown(cli);
6368 talloc_destroy(mem_ctx);
6369 return -1;
6373 * Call LsaOpenPolicy and LsaQueryInfo
6376 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6377 &pipe_hnd);
6378 if (!NT_STATUS_IS_OK(nt_status)) {
6379 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6380 cli_shutdown(cli);
6381 talloc_destroy(mem_ctx);
6382 return -1;
6385 b = pipe_hnd->binding_handle;
6387 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6388 &connect_hnd);
6389 if (NT_STATUS_IS_ERR(nt_status)) {
6390 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6391 nt_errstr(nt_status)));
6392 cli_shutdown(cli);
6393 talloc_destroy(mem_ctx);
6394 return -1;
6397 /* Querying info level 5 */
6399 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6400 &connect_hnd,
6401 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6402 &info,
6403 &result);
6404 if (NT_STATUS_IS_ERR(nt_status)) {
6405 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6406 nt_errstr(nt_status)));
6407 cli_shutdown(cli);
6408 talloc_destroy(mem_ctx);
6409 return -1;
6411 if (NT_STATUS_IS_ERR(result)) {
6412 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6413 nt_errstr(result)));
6414 cli_shutdown(cli);
6415 talloc_destroy(mem_ctx);
6416 return -1;
6419 domain_sid = info->account_domain.sid;
6421 /* There should be actually query info level 3 (following nt serv behaviour),
6422 but I still don't know if it's _really_ necessary */
6425 * Store the password in secrets db
6428 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6429 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6430 cli_shutdown(cli);
6431 talloc_destroy(mem_ctx);
6432 return -1;
6436 * Close the pipes and clean up
6439 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6440 if (NT_STATUS_IS_ERR(nt_status)) {
6441 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6442 nt_errstr(nt_status)));
6443 cli_shutdown(cli);
6444 talloc_destroy(mem_ctx);
6445 return -1;
6448 cli_shutdown(cli);
6450 talloc_destroy(mem_ctx);
6452 d_printf(_("Trust to domain %s established\n"), domain_name);
6453 return 0;
6457 * Revoke trust relationship to the remote domain.
6459 * @param c A net_context structure.
6460 * @param argc Standard argc.
6461 * @param argv Standard argv without initial components.
6463 * @return Integer status (0 means success).
6466 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6467 const char **argv)
6469 char* domain_name;
6470 int rc = -1;
6472 if (argc < 1 || c->display_usage) {
6473 d_printf("%s\n%s",
6474 _("Usage:"),
6475 _("net rpc trustdom revoke <domain_name>\n"
6476 " Revoke trust relationship\n"
6477 " domain_name\tName of domain to revoke trust\n"));
6478 return -1;
6481 /* generate upper cased domain name */
6482 domain_name = smb_xstrdup(argv[0]);
6483 if (!strupper_m(domain_name)) {
6484 SAFE_FREE(domain_name);
6485 return -1;
6488 /* delete password of the trust */
6489 if (!pdb_del_trusteddom_pw(domain_name)) {
6490 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6491 domain_name));
6492 goto done;
6495 rc = 0;
6496 done:
6497 SAFE_FREE(domain_name);
6498 return rc;
6501 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6502 const struct dom_sid *domain_sid,
6503 const char *domain_name,
6504 struct cli_state *cli,
6505 struct rpc_pipe_client *pipe_hnd,
6506 TALLOC_CTX *mem_ctx,
6507 int argc,
6508 const char **argv)
6510 fstring str_sid;
6511 if (!sid_to_fstring(str_sid, domain_sid)) {
6512 return NT_STATUS_UNSUCCESSFUL;
6514 d_printf("%s\n", str_sid);
6515 return NT_STATUS_OK;
6518 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6520 fstring ascii_sid;
6522 /* convert sid into ascii string */
6523 sid_to_fstring(ascii_sid, dom_sid);
6525 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6528 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6529 TALLOC_CTX *mem_ctx,
6530 struct policy_handle *pol,
6531 struct dom_sid dom_sid,
6532 const char *trusted_dom_name)
6534 NTSTATUS nt_status, result;
6535 union lsa_TrustedDomainInfo *info = NULL;
6536 char *cleartextpwd = NULL;
6537 DATA_BLOB session_key;
6538 DATA_BLOB data = data_blob_null;
6539 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6541 nt_status = dcerpc_lsa_QueryTrustedDomainInfoBySid(b, mem_ctx,
6542 pol,
6543 &dom_sid,
6544 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6545 &info,
6546 &result);
6547 if (NT_STATUS_IS_ERR(nt_status)) {
6548 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6549 nt_errstr(nt_status)));
6550 goto done;
6552 if (NT_STATUS_IS_ERR(result)) {
6553 nt_status = result;
6554 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6555 nt_errstr(result)));
6556 goto done;
6559 data = data_blob(info->password.password->data,
6560 info->password.password->length);
6562 nt_status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6563 if (!NT_STATUS_IS_OK(nt_status)) {
6564 DEBUG(0, ("Could not retrieve session key: %s\n", nt_errstr(nt_status)));
6565 goto done;
6568 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key);
6569 data_blob_free(&session_key);
6571 if (cleartextpwd == NULL) {
6572 DEBUG(0,("retrieved NULL password\n"));
6573 nt_status = NT_STATUS_UNSUCCESSFUL;
6574 goto done;
6577 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6578 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6579 nt_status = NT_STATUS_UNSUCCESSFUL;
6580 goto done;
6583 #ifdef DEBUG_PASSWORD
6584 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6585 "password: [%s]\n", trusted_dom_name,
6586 sid_string_dbg(&dom_sid), cleartextpwd));
6587 #endif
6589 done:
6590 SAFE_FREE(cleartextpwd);
6591 data_blob_free(&data);
6593 return nt_status;
6596 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6597 const char **argv)
6599 /* common variables */
6600 TALLOC_CTX* mem_ctx;
6601 struct cli_state *cli = NULL;
6602 struct rpc_pipe_client *pipe_hnd = NULL;
6603 NTSTATUS nt_status, result;
6604 const char *domain_name = NULL;
6605 struct policy_handle connect_hnd;
6606 union lsa_PolicyInformation *info = NULL;
6608 /* trusted domains listing variables */
6609 unsigned int enum_ctx = 0;
6610 int i;
6611 struct lsa_DomainList dom_list;
6612 fstring pdc_name;
6613 struct dcerpc_binding_handle *b;
6615 if (c->display_usage) {
6616 d_printf( "%s\n"
6617 "net rpc trustdom vampire\n"
6618 " %s\n",
6619 _("Usage:"),
6620 _("Vampire trust relationship from remote server"));
6621 return 0;
6625 * Listing trusted domains (stored in secrets.tdb, if local)
6628 mem_ctx = talloc_init("trust relationships vampire");
6631 * set domain and pdc name to local samba server (default)
6632 * or to remote one given in command line
6635 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6636 domain_name = c->opt_workgroup;
6637 c->opt_target_workgroup = c->opt_workgroup;
6638 } else {
6639 fstrcpy(pdc_name, lp_netbios_name());
6640 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6641 c->opt_target_workgroup = domain_name;
6644 /* open \PIPE\lsarpc and open policy handle */
6645 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6646 if (!NT_STATUS_IS_OK(nt_status)) {
6647 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6648 nt_errstr(nt_status)));
6649 talloc_destroy(mem_ctx);
6650 return -1;
6653 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6654 &pipe_hnd);
6655 if (!NT_STATUS_IS_OK(nt_status)) {
6656 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6657 nt_errstr(nt_status) ));
6658 cli_shutdown(cli);
6659 talloc_destroy(mem_ctx);
6660 return -1;
6663 b = pipe_hnd->binding_handle;
6665 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6666 &connect_hnd);
6667 if (NT_STATUS_IS_ERR(nt_status)) {
6668 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6669 nt_errstr(nt_status)));
6670 cli_shutdown(cli);
6671 talloc_destroy(mem_ctx);
6672 return -1;
6675 /* query info level 5 to obtain sid of a domain being queried */
6676 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6677 &connect_hnd,
6678 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6679 &info,
6680 &result);
6682 if (NT_STATUS_IS_ERR(nt_status)) {
6683 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6684 nt_errstr(nt_status)));
6685 cli_shutdown(cli);
6686 talloc_destroy(mem_ctx);
6687 return -1;
6689 if (NT_STATUS_IS_ERR(result)) {
6690 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6691 nt_errstr(result)));
6692 cli_shutdown(cli);
6693 talloc_destroy(mem_ctx);
6694 return -1;
6698 * Keep calling LsaEnumTrustdom over opened pipe until
6699 * the end of enumeration is reached
6702 d_printf(_("Vampire trusted domains:\n\n"));
6704 do {
6705 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6706 &connect_hnd,
6707 &enum_ctx,
6708 &dom_list,
6709 (uint32_t)-1,
6710 &result);
6711 if (NT_STATUS_IS_ERR(nt_status)) {
6712 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6713 nt_errstr(nt_status)));
6714 cli_shutdown(cli);
6715 talloc_destroy(mem_ctx);
6716 return -1;
6718 if (NT_STATUS_IS_ERR(result)) {
6719 nt_status = result;
6720 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6721 nt_errstr(result)));
6722 cli_shutdown(cli);
6723 talloc_destroy(mem_ctx);
6724 return -1;
6728 for (i = 0; i < dom_list.count; i++) {
6730 print_trusted_domain(dom_list.domains[i].sid,
6731 dom_list.domains[i].name.string);
6733 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6734 *dom_list.domains[i].sid,
6735 dom_list.domains[i].name.string);
6736 if (!NT_STATUS_IS_OK(nt_status)) {
6737 cli_shutdown(cli);
6738 talloc_destroy(mem_ctx);
6739 return -1;
6744 * in case of no trusted domains say something rather
6745 * than just display blank line
6747 if (!dom_list.count) d_printf(_("none\n"));
6749 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6751 /* close this connection before doing next one */
6752 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6753 if (NT_STATUS_IS_ERR(nt_status)) {
6754 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6755 nt_errstr(nt_status)));
6756 cli_shutdown(cli);
6757 talloc_destroy(mem_ctx);
6758 return -1;
6761 /* close lsarpc pipe and connection to IPC$ */
6762 cli_shutdown(cli);
6764 talloc_destroy(mem_ctx);
6765 return 0;
6768 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6770 /* common variables */
6771 TALLOC_CTX* mem_ctx;
6772 struct cli_state *cli = NULL, *remote_cli = NULL;
6773 struct rpc_pipe_client *pipe_hnd = NULL;
6774 NTSTATUS nt_status, result;
6775 const char *domain_name = NULL;
6776 struct dom_sid *queried_dom_sid;
6777 int ascii_dom_name_len;
6778 struct policy_handle connect_hnd;
6779 union lsa_PolicyInformation *info = NULL;
6780 struct dcerpc_binding_handle *b = NULL;
6782 /* trusted domains listing variables */
6783 unsigned int num_domains, enum_ctx = 0;
6784 int i;
6785 struct lsa_DomainList dom_list;
6786 fstring pdc_name;
6787 bool found_domain;
6789 /* trusting domains listing variables */
6790 struct policy_handle domain_hnd;
6791 struct samr_SamArray *trusts = NULL;
6793 if (c->display_usage) {
6794 d_printf( "%s\n"
6795 "net rpc trustdom list\n"
6796 " %s\n",
6797 _("Usage:"),
6798 _("List incoming and outgoing trust relationships"));
6799 return 0;
6803 * Listing trusted domains (stored in secrets.tdb, if local)
6806 mem_ctx = talloc_init("trust relationships listing");
6809 * set domain and pdc name to local samba server (default)
6810 * or to remote one given in command line
6813 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6814 domain_name = c->opt_workgroup;
6815 c->opt_target_workgroup = c->opt_workgroup;
6816 } else {
6817 fstrcpy(pdc_name, lp_netbios_name());
6818 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6819 c->opt_target_workgroup = domain_name;
6822 /* open \PIPE\lsarpc and open policy handle */
6823 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6824 if (!NT_STATUS_IS_OK(nt_status)) {
6825 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6826 nt_errstr(nt_status)));
6827 talloc_destroy(mem_ctx);
6828 return -1;
6831 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6832 &pipe_hnd);
6833 if (!NT_STATUS_IS_OK(nt_status)) {
6834 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6835 nt_errstr(nt_status) ));
6836 cli_shutdown(cli);
6837 talloc_destroy(mem_ctx);
6838 return -1;
6841 b = pipe_hnd->binding_handle;
6843 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6844 &connect_hnd);
6845 if (NT_STATUS_IS_ERR(nt_status)) {
6846 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6847 nt_errstr(nt_status)));
6848 cli_shutdown(cli);
6849 talloc_destroy(mem_ctx);
6850 return -1;
6853 /* query info level 5 to obtain sid of a domain being queried */
6854 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6855 &connect_hnd,
6856 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6857 &info,
6858 &result);
6860 if (NT_STATUS_IS_ERR(nt_status)) {
6861 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6862 nt_errstr(nt_status)));
6863 cli_shutdown(cli);
6864 talloc_destroy(mem_ctx);
6865 return -1;
6867 if (NT_STATUS_IS_ERR(result)) {
6868 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6869 nt_errstr(result)));
6870 cli_shutdown(cli);
6871 talloc_destroy(mem_ctx);
6872 return -1;
6875 queried_dom_sid = info->account_domain.sid;
6878 * Keep calling LsaEnumTrustdom over opened pipe until
6879 * the end of enumeration is reached
6882 d_printf(_("Trusted domains list:\n\n"));
6884 found_domain = false;
6886 do {
6887 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6888 &connect_hnd,
6889 &enum_ctx,
6890 &dom_list,
6891 (uint32_t)-1,
6892 &result);
6893 if (NT_STATUS_IS_ERR(nt_status)) {
6894 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6895 nt_errstr(nt_status)));
6896 cli_shutdown(cli);
6897 talloc_destroy(mem_ctx);
6898 return -1;
6900 if (NT_STATUS_IS_ERR(result)) {
6901 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6902 nt_errstr(result)));
6903 cli_shutdown(cli);
6904 talloc_destroy(mem_ctx);
6905 return -1;
6909 for (i = 0; i < dom_list.count; i++) {
6910 print_trusted_domain(dom_list.domains[i].sid,
6911 dom_list.domains[i].name.string);
6912 found_domain = true;
6916 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6919 * in case of no trusted domains say something rather
6920 * than just display blank line
6922 if (!found_domain) {
6923 d_printf(_("none\n"));
6926 /* close this connection before doing next one */
6927 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6928 if (NT_STATUS_IS_ERR(nt_status)) {
6929 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6930 nt_errstr(nt_status)));
6931 cli_shutdown(cli);
6932 talloc_destroy(mem_ctx);
6933 return -1;
6936 TALLOC_FREE(pipe_hnd);
6939 * Listing trusting domains (stored in passdb backend, if local)
6942 d_printf(_("\nTrusting domains list:\n\n"));
6945 * Open \PIPE\samr and get needed policy handles
6947 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6948 &pipe_hnd);
6949 if (!NT_STATUS_IS_OK(nt_status)) {
6950 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6951 cli_shutdown(cli);
6952 talloc_destroy(mem_ctx);
6953 return -1;
6956 b = pipe_hnd->binding_handle;
6958 /* SamrConnect2 */
6959 nt_status = dcerpc_samr_Connect2(b, mem_ctx,
6960 pipe_hnd->desthost,
6961 SAMR_ACCESS_LOOKUP_DOMAIN,
6962 &connect_hnd,
6963 &result);
6964 if (!NT_STATUS_IS_OK(nt_status)) {
6965 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6966 nt_errstr(nt_status)));
6967 cli_shutdown(cli);
6968 talloc_destroy(mem_ctx);
6969 return -1;
6971 if (!NT_STATUS_IS_OK(result)) {
6972 nt_status = result;
6973 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6974 nt_errstr(result)));
6975 cli_shutdown(cli);
6976 talloc_destroy(mem_ctx);
6977 return -1;
6980 /* SamrOpenDomain - we have to open domain policy handle in order to be
6981 able to enumerate accounts*/
6982 nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
6983 &connect_hnd,
6984 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6985 queried_dom_sid,
6986 &domain_hnd,
6987 &result);
6988 if (!NT_STATUS_IS_OK(nt_status)) {
6989 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6990 nt_errstr(nt_status)));
6991 cli_shutdown(cli);
6992 talloc_destroy(mem_ctx);
6993 return -1;
6995 if (!NT_STATUS_IS_OK(result)) {
6996 nt_status = result;
6997 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6998 nt_errstr(result)));
6999 cli_shutdown(cli);
7000 talloc_destroy(mem_ctx);
7001 return -1;
7005 * perform actual enumeration
7008 found_domain = false;
7010 enum_ctx = 0; /* reset enumeration context from last enumeration */
7011 do {
7013 nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
7014 &domain_hnd,
7015 &enum_ctx,
7016 ACB_DOMTRUST,
7017 &trusts,
7018 0xffff,
7019 &num_domains,
7020 &result);
7021 if (NT_STATUS_IS_ERR(nt_status)) {
7022 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7023 nt_errstr(nt_status)));
7024 cli_shutdown(cli);
7025 talloc_destroy(mem_ctx);
7026 return -1;
7028 if (NT_STATUS_IS_ERR(result)) {
7029 nt_status = result;
7030 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7031 nt_errstr(result)));
7032 cli_shutdown(cli);
7033 talloc_destroy(mem_ctx);
7034 return -1;
7037 for (i = 0; i < num_domains; i++) {
7039 char *str = discard_const_p(char, trusts->entries[i].name.string);
7041 found_domain = true;
7044 * get each single domain's sid (do we _really_ need this ?):
7045 * 1) connect to domain's pdc
7046 * 2) query the pdc for domain's sid
7049 /* get rid of '$' tail */
7050 ascii_dom_name_len = strlen(str);
7051 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
7052 str[ascii_dom_name_len - 1] = '\0';
7054 /* set opt_* variables to remote domain */
7055 if (!strupper_m(str)) {
7056 cli_shutdown(cli);
7057 talloc_destroy(mem_ctx);
7058 return -1;
7060 c->opt_workgroup = talloc_strdup(mem_ctx, str);
7061 c->opt_target_workgroup = c->opt_workgroup;
7063 d_printf("%-20s", str);
7065 /* connect to remote domain controller */
7066 nt_status = net_make_ipc_connection(c,
7067 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
7068 &remote_cli);
7069 if (NT_STATUS_IS_OK(nt_status)) {
7070 /* query for domain's sid */
7071 if (run_rpc_command(
7072 c, remote_cli,
7073 &ndr_table_lsarpc, 0,
7074 rpc_query_domain_sid, argc,
7075 argv))
7076 d_printf(_("strange - couldn't get domain's sid\n"));
7078 cli_shutdown(remote_cli);
7080 } else {
7081 d_fprintf(stderr, _("domain controller is not "
7082 "responding: %s\n"),
7083 nt_errstr(nt_status));
7084 d_printf(_("couldn't get domain's sid\n"));
7088 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
7090 if (!found_domain) {
7091 d_printf("none\n");
7094 /* close opened samr and domain policy handles */
7095 nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
7096 if (!NT_STATUS_IS_OK(nt_status)) {
7097 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
7100 nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
7101 if (!NT_STATUS_IS_OK(nt_status)) {
7102 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
7105 /* close samr pipe and connection to IPC$ */
7106 cli_shutdown(cli);
7108 talloc_destroy(mem_ctx);
7109 return 0;
7113 * Entrypoint for 'net rpc trustdom' code.
7115 * @param argc Standard argc.
7116 * @param argv Standard argv without initial components.
7118 * @return Integer status (0 means success).
7121 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
7123 struct functable func[] = {
7125 "add",
7126 rpc_trustdom_add,
7127 NET_TRANSPORT_RPC,
7128 N_("Add trusting domain's account"),
7129 N_("net rpc trustdom add\n"
7130 " Add trusting domain's account")
7133 "del",
7134 rpc_trustdom_del,
7135 NET_TRANSPORT_RPC,
7136 N_("Remove trusting domain's account"),
7137 N_("net rpc trustdom del\n"
7138 " Remove trusting domain's account")
7141 "establish",
7142 rpc_trustdom_establish,
7143 NET_TRANSPORT_RPC,
7144 N_("Establish outgoing trust relationship"),
7145 N_("net rpc trustdom establish\n"
7146 " Establish outgoing trust relationship")
7149 "revoke",
7150 rpc_trustdom_revoke,
7151 NET_TRANSPORT_RPC,
7152 N_("Revoke outgoing trust relationship"),
7153 N_("net rpc trustdom revoke\n"
7154 " Revoke outgoing trust relationship")
7157 "list",
7158 rpc_trustdom_list,
7159 NET_TRANSPORT_RPC,
7160 N_("List in- and outgoing domain trusts"),
7161 N_("net rpc trustdom list\n"
7162 " List in- and outgoing domain trusts")
7165 "vampire",
7166 rpc_trustdom_vampire,
7167 NET_TRANSPORT_RPC,
7168 N_("Vampire trusts from remote server"),
7169 N_("net rpc trustdom vampire\n"
7170 " Vampire trusts from remote server")
7172 {NULL, NULL, 0, NULL, NULL}
7175 return net_run_function(c, argc, argv, "net rpc trustdom", func);
7179 * Check if a server will take rpc commands
7180 * @param flags Type of server to connect to (PDC, DMB, localhost)
7181 * if the host is not explicitly specified
7182 * @return bool (true means rpc supported)
7184 bool net_rpc_check(struct net_context *c, unsigned flags)
7186 struct cli_state *cli;
7187 bool ret = false;
7188 struct sockaddr_storage server_ss;
7189 char *server_name = NULL;
7190 NTSTATUS status;
7192 /* flags (i.e. server type) may depend on command */
7193 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7194 return false;
7196 status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
7197 lp_netbios_name(), SMB_SIGNING_DEFAULT,
7198 0, &cli);
7199 if (!NT_STATUS_IS_OK(status)) {
7200 return false;
7202 status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
7203 PROTOCOL_NT1);
7204 if (!NT_STATUS_IS_OK(status))
7205 goto done;
7206 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1)
7207 goto done;
7209 ret = true;
7210 done:
7211 cli_shutdown(cli);
7212 return ret;
7215 /* dump sam database via samsync rpc calls */
7216 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
7217 if (c->display_usage) {
7218 d_printf( "%s\n"
7219 "net rpc samdump\n"
7220 " %s\n",
7221 _("Usage:"),
7222 _("Dump remote SAM database"));
7223 return 0;
7226 return run_rpc_command(c, NULL, &ndr_table_netlogon,
7227 NET_FLAGS_ANONYMOUS,
7228 rpc_samdump_internals, argc, argv);
7231 /* syncronise sam database via samsync rpc calls */
7232 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7234 struct functable func[] = {
7236 "ldif",
7237 rpc_vampire_ldif,
7238 NET_TRANSPORT_RPC,
7239 N_("Dump remote SAM database to ldif"),
7240 N_("net rpc vampire ldif\n"
7241 " Dump remote SAM database to LDIF file or "
7242 "stdout")
7245 "keytab",
7246 rpc_vampire_keytab,
7247 NET_TRANSPORT_RPC,
7248 N_("Dump remote SAM database to Kerberos Keytab"),
7249 N_("net rpc vampire keytab\n"
7250 " Dump remote SAM database to Kerberos keytab "
7251 "file")
7254 "passdb",
7255 rpc_vampire_passdb,
7256 NET_TRANSPORT_RPC,
7257 N_("Dump remote SAM database to passdb"),
7258 N_("net rpc vampire passdb\n"
7259 " Dump remote SAM database to passdb")
7262 {NULL, NULL, 0, NULL, NULL}
7265 if (argc == 0) {
7266 if (c->display_usage) {
7267 d_printf( "%s\n"
7268 "net rpc vampire\n"
7269 " %s\n",
7270 _("Usage:"),
7271 _("Vampire remote SAM database"));
7272 return 0;
7275 return rpc_vampire_passdb(c, argc, argv);
7278 return net_run_function(c, argc, argv, "net rpc vampire", func);
7282 * Migrate everything from a print server.
7284 * @param c A net_context structure.
7285 * @param argc Standard main() style argc.
7286 * @param argv Standard main() style argv. Initial components are already
7287 * stripped.
7289 * @return A shell status integer (0 for success).
7291 * The order is important !
7292 * To successfully add drivers the print queues have to exist !
7293 * Applying ACLs should be the last step, because you're easily locked out.
7296 static int rpc_printer_migrate_all(struct net_context *c, int argc,
7297 const char **argv)
7299 int ret;
7301 if (c->display_usage) {
7302 d_printf( "%s\n"
7303 "net rpc printer migrate all\n"
7304 " %s\n",
7305 _("Usage:"),
7306 _("Migrate everything from a print server"));
7307 return 0;
7310 if (!c->opt_host) {
7311 d_printf(_("no server to migrate\n"));
7312 return -1;
7315 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7316 rpc_printer_migrate_printers_internals, argc,
7317 argv);
7318 if (ret)
7319 return ret;
7321 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7322 rpc_printer_migrate_drivers_internals, argc,
7323 argv);
7324 if (ret)
7325 return ret;
7327 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7328 rpc_printer_migrate_forms_internals, argc, argv);
7329 if (ret)
7330 return ret;
7332 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7333 rpc_printer_migrate_settings_internals, argc,
7334 argv);
7335 if (ret)
7336 return ret;
7338 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7339 rpc_printer_migrate_security_internals, argc,
7340 argv);
7345 * Migrate print drivers from a print server.
7347 * @param c A net_context structure.
7348 * @param argc Standard main() style argc.
7349 * @param argv Standard main() style argv. Initial components are already
7350 * stripped.
7352 * @return A shell status integer (0 for success).
7354 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7355 const char **argv)
7357 if (c->display_usage) {
7358 d_printf( "%s\n"
7359 "net rpc printer migrate drivers\n"
7360 " %s\n",
7361 _("Usage:"),
7362 _("Migrate print-drivers from a print-server"));
7363 return 0;
7366 if (!c->opt_host) {
7367 d_printf(_("no server to migrate\n"));
7368 return -1;
7371 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7372 rpc_printer_migrate_drivers_internals,
7373 argc, argv);
7377 * Migrate print-forms from a print-server.
7379 * @param c A net_context structure.
7380 * @param argc Standard main() style argc.
7381 * @param argv Standard main() style argv. Initial components are already
7382 * stripped.
7384 * @return A shell status integer (0 for success).
7386 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7387 const char **argv)
7389 if (c->display_usage) {
7390 d_printf( "%s\n"
7391 "net rpc printer migrate forms\n"
7392 " %s\n",
7393 _("Usage:"),
7394 _("Migrate print-forms from a print-server"));
7395 return 0;
7398 if (!c->opt_host) {
7399 d_printf(_("no server to migrate\n"));
7400 return -1;
7403 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7404 rpc_printer_migrate_forms_internals,
7405 argc, argv);
7409 * Migrate printers from a print-server.
7411 * @param c A net_context structure.
7412 * @param argc Standard main() style argc.
7413 * @param argv Standard main() style argv. Initial components are already
7414 * stripped.
7416 * @return A shell status integer (0 for success).
7418 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7419 const char **argv)
7421 if (c->display_usage) {
7422 d_printf( "%s\n"
7423 "net rpc printer migrate printers\n"
7424 " %s\n",
7425 _("Usage:"),
7426 _("Migrate printers from a print-server"));
7427 return 0;
7430 if (!c->opt_host) {
7431 d_printf(_("no server to migrate\n"));
7432 return -1;
7435 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7436 rpc_printer_migrate_printers_internals,
7437 argc, argv);
7441 * Migrate printer-ACLs from a print-server
7443 * @param c A net_context structure.
7444 * @param argc Standard main() style argc.
7445 * @param argv Standard main() style argv. Initial components are already
7446 * stripped.
7448 * @return A shell status integer (0 for success).
7450 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7451 const char **argv)
7453 if (c->display_usage) {
7454 d_printf( "%s\n"
7455 "net rpc printer migrate security\n"
7456 " %s\n",
7457 _("Usage:"),
7458 _("Migrate printer-ACLs from a print-server"));
7459 return 0;
7462 if (!c->opt_host) {
7463 d_printf(_("no server to migrate\n"));
7464 return -1;
7467 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7468 rpc_printer_migrate_security_internals,
7469 argc, argv);
7473 * Migrate printer-settings from a print-server.
7475 * @param c A net_context structure.
7476 * @param argc Standard main() style argc.
7477 * @param argv Standard main() style argv. Initial components are already
7478 * stripped.
7480 * @return A shell status integer (0 for success).
7482 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7483 const char **argv)
7485 if (c->display_usage) {
7486 d_printf( "%s\n"
7487 "net rpc printer migrate settings\n"
7488 " %s\n",
7489 _("Usage:"),
7490 _("Migrate printer-settings from a "
7491 "print-server"));
7492 return 0;
7495 if (!c->opt_host) {
7496 d_printf(_("no server to migrate\n"));
7497 return -1;
7500 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7501 rpc_printer_migrate_settings_internals,
7502 argc, argv);
7506 * 'net rpc printer' entrypoint.
7508 * @param c A net_context structure.
7509 * @param argc Standard main() style argc.
7510 * @param argv Standard main() style argv. Initial components are already
7511 * stripped.
7514 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7517 /* ouch: when addriver and setdriver are called from within
7518 rpc_printer_migrate_drivers_internals, the printer-queue already
7519 *has* to exist */
7521 struct functable func[] = {
7523 "all",
7524 rpc_printer_migrate_all,
7525 NET_TRANSPORT_RPC,
7526 N_("Migrate all from remote to local print server"),
7527 N_("net rpc printer migrate all\n"
7528 " Migrate all from remote to local print server")
7531 "drivers",
7532 rpc_printer_migrate_drivers,
7533 NET_TRANSPORT_RPC,
7534 N_("Migrate drivers to local server"),
7535 N_("net rpc printer migrate drivers\n"
7536 " Migrate drivers to local server")
7539 "forms",
7540 rpc_printer_migrate_forms,
7541 NET_TRANSPORT_RPC,
7542 N_("Migrate froms to local server"),
7543 N_("net rpc printer migrate forms\n"
7544 " Migrate froms to local server")
7547 "printers",
7548 rpc_printer_migrate_printers,
7549 NET_TRANSPORT_RPC,
7550 N_("Migrate printers to local server"),
7551 N_("net rpc printer migrate printers\n"
7552 " Migrate printers to local server")
7555 "security",
7556 rpc_printer_migrate_security,
7557 NET_TRANSPORT_RPC,
7558 N_("Mirgate printer ACLs to local server"),
7559 N_("net rpc printer migrate security\n"
7560 " Mirgate printer ACLs to local server")
7563 "settings",
7564 rpc_printer_migrate_settings,
7565 NET_TRANSPORT_RPC,
7566 N_("Migrate printer settings to local server"),
7567 N_("net rpc printer migrate settings\n"
7568 " Migrate printer settings to local server")
7570 {NULL, NULL, 0, NULL, NULL}
7573 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7578 * List printers on a remote RPC server.
7580 * @param c A net_context structure.
7581 * @param argc Standard main() style argc.
7582 * @param argv Standard main() style argv. Initial components are already
7583 * stripped.
7585 * @return A shell status integer (0 for success).
7587 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7589 if (c->display_usage) {
7590 d_printf( "%s\n"
7591 "net rpc printer list\n"
7592 " %s\n",
7593 _("Usage:"),
7594 _("List printers on a remote RPC server"));
7595 return 0;
7598 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7599 rpc_printer_list_internals,
7600 argc, argv);
7604 * List printer-drivers on a remote RPC server.
7606 * @param c A net_context structure.
7607 * @param argc Standard main() style argc.
7608 * @param argv Standard main() style argv. Initial components are already
7609 * stripped.
7611 * @return A shell status integer (0 for success).
7613 static int rpc_printer_driver_list(struct net_context *c, int argc,
7614 const char **argv)
7616 if (c->display_usage) {
7617 d_printf( "%s\n"
7618 "net rpc printer driver\n"
7619 " %s\n",
7620 _("Usage:"),
7621 _("List printer-drivers on a remote RPC server"));
7622 return 0;
7625 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7626 rpc_printer_driver_list_internals,
7627 argc, argv);
7631 * Publish printer in ADS via MSRPC.
7633 * @param c A net_context structure.
7634 * @param argc Standard main() style argc.
7635 * @param argv Standard main() style argv. Initial components are already
7636 * stripped.
7638 * @return A shell status integer (0 for success).
7640 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7641 const char **argv)
7643 if (c->display_usage) {
7644 d_printf( "%s\n"
7645 "net rpc printer publish publish\n"
7646 " %s\n",
7647 _("Usage:"),
7648 _("Publish printer in ADS via MSRPC"));
7649 return 0;
7652 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7653 rpc_printer_publish_publish_internals,
7654 argc, argv);
7658 * Update printer in ADS via MSRPC.
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_publish_update(struct net_context *c, int argc, const char **argv)
7669 if (c->display_usage) {
7670 d_printf( "%s\n"
7671 "net rpc printer publish update\n"
7672 " %s\n",
7673 _("Usage:"),
7674 _("Update printer in ADS via MSRPC"));
7675 return 0;
7678 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7679 rpc_printer_publish_update_internals,
7680 argc, argv);
7684 * UnPublish printer in ADS via MSRPC.
7686 * @param c A net_context structure.
7687 * @param argc Standard main() style argc.
7688 * @param argv Standard main() style argv. Initial components are already
7689 * stripped.
7691 * @return A shell status integer (0 for success).
7693 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7694 const char **argv)
7696 if (c->display_usage) {
7697 d_printf( "%s\n"
7698 "net rpc printer publish unpublish\n"
7699 " %s\n",
7700 _("Usage:\n"),
7701 _("UnPublish printer in ADS via MSRPC"));
7702 return 0;
7705 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7706 rpc_printer_publish_unpublish_internals,
7707 argc, argv);
7711 * List published printers via MSRPC.
7713 * @param c A net_context structure.
7714 * @param argc Standard main() style argc.
7715 * @param argv Standard main() style argv. Initial components are already
7716 * stripped.
7718 * @return A shell status integer (0 for success).
7720 static int rpc_printer_publish_list(struct net_context *c, int argc,
7721 const char **argv)
7723 if (c->display_usage) {
7724 d_printf( "%s\n"
7725 "net rpc printer publish list\n"
7726 " %s\n",
7727 _("Usage:"),
7728 _("List published printers via MSRPC"));
7729 return 0;
7732 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7733 rpc_printer_publish_list_internals,
7734 argc, argv);
7739 * Publish printer in ADS.
7741 * @param c A net_context structure.
7742 * @param argc Standard main() style argc.
7743 * @param argv Standard main() style argv. Initial components are already
7744 * stripped.
7746 * @return A shell status integer (0 for success).
7748 static int rpc_printer_publish(struct net_context *c, int argc,
7749 const char **argv)
7752 struct functable func[] = {
7754 "publish",
7755 rpc_printer_publish_publish,
7756 NET_TRANSPORT_RPC,
7757 N_("Publish printer in AD"),
7758 N_("net rpc printer publish publish\n"
7759 " Publish printer in AD")
7762 "update",
7763 rpc_printer_publish_update,
7764 NET_TRANSPORT_RPC,
7765 N_("Update printer in AD"),
7766 N_("net rpc printer publish update\n"
7767 " Update printer in AD")
7770 "unpublish",
7771 rpc_printer_publish_unpublish,
7772 NET_TRANSPORT_RPC,
7773 N_("Unpublish printer"),
7774 N_("net rpc printer publish unpublish\n"
7775 " Unpublish printer")
7778 "list",
7779 rpc_printer_publish_list,
7780 NET_TRANSPORT_RPC,
7781 N_("List published printers"),
7782 N_("net rpc printer publish list\n"
7783 " List published printers")
7785 {NULL, NULL, 0, NULL, NULL}
7788 if (argc == 0) {
7789 if (c->display_usage) {
7790 d_printf(_("Usage:\n"));
7791 d_printf(_("net rpc printer publish\n"
7792 " List published printers\n"
7793 " Alias of net rpc printer publish "
7794 "list\n"));
7795 net_display_usage_from_functable(func);
7796 return 0;
7798 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7799 rpc_printer_publish_list_internals,
7800 argc, argv);
7803 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7809 * Display rpc printer help page.
7811 * @param c A net_context structure.
7812 * @param argc Standard main() style argc.
7813 * @param argv Standard main() style argv. Initial components are already
7814 * stripped.
7816 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7818 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
7819 "\tlists all printers on print-server\n\n"));
7820 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7821 "\tlists all printer-drivers on print-server\n\n"));
7822 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7823 "\tpublishes printer settings in Active Directory\n"
7824 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
7825 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7826 "\n\tmigrates printers from remote to local server\n\n"));
7827 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7828 "\n\tmigrates printer-settings from remote to local server\n\n"));
7829 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7830 "\n\tmigrates printer-drivers from remote to local server\n\n"));
7831 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7832 "\n\tmigrates printer-forms from remote to local server\n\n"));
7833 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7834 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7835 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7836 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7837 "\tremote to local print-server\n\n"));
7838 net_common_methods_usage(c, argc, argv);
7839 net_common_flags_usage(c, argc, argv);
7840 d_printf(_(
7841 "\t-v or --verbose\t\t\tgive verbose output\n"
7842 "\t --destination\t\tmigration target server (default: localhost)\n"));
7844 return -1;
7848 * 'net rpc printer' entrypoint.
7850 * @param c A net_context structure.
7851 * @param argc Standard main() style argc.
7852 * @param argv Standard main() style argv. Initial components are already
7853 * stripped.
7855 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7857 struct functable func[] = {
7859 "list",
7860 rpc_printer_list,
7861 NET_TRANSPORT_RPC,
7862 N_("List all printers on print server"),
7863 N_("net rpc printer list\n"
7864 " List all printers on print server")
7867 "migrate",
7868 rpc_printer_migrate,
7869 NET_TRANSPORT_RPC,
7870 N_("Migrate printer to local server"),
7871 N_("net rpc printer migrate\n"
7872 " Migrate printer to local server")
7875 "driver",
7876 rpc_printer_driver_list,
7877 NET_TRANSPORT_RPC,
7878 N_("List printer drivers"),
7879 N_("net rpc printer driver\n"
7880 " List printer drivers")
7883 "publish",
7884 rpc_printer_publish,
7885 NET_TRANSPORT_RPC,
7886 N_("Publish printer in AD"),
7887 N_("net rpc printer publish\n"
7888 " Publish printer in AD")
7890 {NULL, NULL, 0, NULL, NULL}
7893 if (argc == 0) {
7894 if (c->display_usage) {
7895 d_printf(_("Usage:\n"));
7896 d_printf(_("net rpc printer\n"
7897 " List printers\n"));
7898 net_display_usage_from_functable(func);
7899 return 0;
7901 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7902 rpc_printer_list_internals,
7903 argc, argv);
7906 return net_run_function(c, argc, argv, "net rpc printer", func);
7910 * 'net rpc' entrypoint.
7912 * @param c A net_context structure.
7913 * @param argc Standard main() style argc.
7914 * @param argv Standard main() style argv. Initial components are already
7915 * stripped.
7918 int net_rpc(struct net_context *c, int argc, const char **argv)
7920 NET_API_STATUS status;
7922 struct functable func[] = {
7924 "audit",
7925 net_rpc_audit,
7926 NET_TRANSPORT_RPC,
7927 N_("Modify global audit settings"),
7928 N_("net rpc audit\n"
7929 " Modify global audit settings")
7932 "info",
7933 net_rpc_info,
7934 NET_TRANSPORT_RPC,
7935 N_("Show basic info about a domain"),
7936 N_("net rpc info\n"
7937 " Show basic info about a domain")
7940 "join",
7941 net_rpc_join,
7942 NET_TRANSPORT_RPC,
7943 N_("Join a domain"),
7944 N_("net rpc join\n"
7945 " Join a domain")
7948 "oldjoin",
7949 net_rpc_oldjoin,
7950 NET_TRANSPORT_RPC,
7951 N_("Join a domain created in server manager"),
7952 N_("net rpc oldjoin\n"
7953 " Join a domain created in server manager")
7956 "testjoin",
7957 net_rpc_testjoin,
7958 NET_TRANSPORT_RPC,
7959 N_("Test that a join is valid"),
7960 N_("net rpc testjoin\n"
7961 " Test that a join is valid")
7964 "user",
7965 net_rpc_user,
7966 NET_TRANSPORT_RPC,
7967 N_("List/modify users"),
7968 N_("net rpc user\n"
7969 " List/modify users")
7972 "password",
7973 rpc_user_password,
7974 NET_TRANSPORT_RPC,
7975 N_("Change a user password"),
7976 N_("net rpc password\n"
7977 " Change a user password\n"
7978 " Alias for net rpc user password")
7981 "group",
7982 net_rpc_group,
7983 NET_TRANSPORT_RPC,
7984 N_("List/modify groups"),
7985 N_("net rpc group\n"
7986 " List/modify groups")
7989 "share",
7990 net_rpc_share,
7991 NET_TRANSPORT_RPC,
7992 N_("List/modify shares"),
7993 N_("net rpc share\n"
7994 " List/modify shares")
7997 "file",
7998 net_rpc_file,
7999 NET_TRANSPORT_RPC,
8000 N_("List open files"),
8001 N_("net rpc file\n"
8002 " List open files")
8005 "printer",
8006 net_rpc_printer,
8007 NET_TRANSPORT_RPC,
8008 N_("List/modify printers"),
8009 N_("net rpc printer\n"
8010 " List/modify printers")
8013 "changetrustpw",
8014 net_rpc_changetrustpw,
8015 NET_TRANSPORT_RPC,
8016 N_("Change trust account password"),
8017 N_("net rpc changetrustpw\n"
8018 " Change trust account password")
8021 "trustdom",
8022 rpc_trustdom,
8023 NET_TRANSPORT_RPC,
8024 N_("Modify domain trusts"),
8025 N_("net rpc trustdom\n"
8026 " Modify domain trusts")
8029 "abortshutdown",
8030 rpc_shutdown_abort,
8031 NET_TRANSPORT_RPC,
8032 N_("Abort a remote shutdown"),
8033 N_("net rpc abortshutdown\n"
8034 " Abort a remote shutdown")
8037 "shutdown",
8038 rpc_shutdown,
8039 NET_TRANSPORT_RPC,
8040 N_("Shutdown a remote server"),
8041 N_("net rpc shutdown\n"
8042 " Shutdown a remote server")
8045 "samdump",
8046 rpc_samdump,
8047 NET_TRANSPORT_RPC,
8048 N_("Dump SAM data of remote NT PDC"),
8049 N_("net rpc samdump\n"
8050 " Dump SAM data of remote NT PDC")
8053 "vampire",
8054 rpc_vampire,
8055 NET_TRANSPORT_RPC,
8056 N_("Sync a remote NT PDC's data into local passdb"),
8057 N_("net rpc vampire\n"
8058 " Sync a remote NT PDC's data into local passdb")
8061 "getsid",
8062 net_rpc_getsid,
8063 NET_TRANSPORT_RPC,
8064 N_("Fetch the domain sid into local secrets.tdb"),
8065 N_("net rpc getsid\n"
8066 " Fetch the domain sid into local secrets.tdb")
8069 "rights",
8070 net_rpc_rights,
8071 NET_TRANSPORT_RPC,
8072 N_("Manage privileges assigned to SID"),
8073 N_("net rpc rights\n"
8074 " Manage privileges assigned to SID")
8077 "service",
8078 net_rpc_service,
8079 NET_TRANSPORT_RPC,
8080 N_("Start/stop/query remote services"),
8081 N_("net rpc service\n"
8082 " Start/stop/query remote services")
8085 "registry",
8086 net_rpc_registry,
8087 NET_TRANSPORT_RPC,
8088 N_("Manage registry hives"),
8089 N_("net rpc registry\n"
8090 " Manage registry hives")
8093 "shell",
8094 net_rpc_shell,
8095 NET_TRANSPORT_RPC,
8096 N_("Open interactive shell on remote server"),
8097 N_("net rpc shell\n"
8098 " Open interactive shell on remote server")
8101 "trust",
8102 net_rpc_trust,
8103 NET_TRANSPORT_RPC,
8104 N_("Manage trusts"),
8105 N_("net rpc trust\n"
8106 " Manage trusts")
8109 "conf",
8110 net_rpc_conf,
8111 NET_TRANSPORT_RPC,
8112 N_("Configure a remote samba server"),
8113 N_("net rpc conf\n"
8114 " Configure a remote samba server")
8116 {NULL, NULL, 0, NULL, NULL}
8119 status = libnetapi_net_init(&c->netapi_ctx);
8120 if (status != 0) {
8121 return -1;
8123 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
8124 libnetapi_set_password(c->netapi_ctx, c->opt_password);
8125 if (c->opt_kerberos) {
8126 libnetapi_set_use_kerberos(c->netapi_ctx);
8128 if (c->opt_ccache) {
8129 libnetapi_set_use_ccache(c->netapi_ctx);
8132 return net_run_function(c, argc, argv, "net rpc", func);