source: vendor/3.6.23/source3/utils/net_rpc.c

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

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