source: branches/samba-3.0/source/utils/net_rpc.c

Last change on this file was 165, checked in by Paul Smedley, 16 years ago

Add 'missing' 3.0.34 diffs

File size: 173.2 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 Guenther Deschner (gd@samba.org)
7 Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23#include "includes.h"
24#include "utils/net.h"
25
26static int net_mode_share;
27
28/**
29 * @file net_rpc.c
30 *
31 * @brief RPC based subcommands for the 'net' utility.
32 *
33 * This file should contain much of the functionality that used to
34 * be found in rpcclient, execpt that the commands should change
35 * less often, and the fucntionality should be sane (the user is not
36 * expected to know a rid/sid before they conduct an operation etc.)
37 *
38 * @todo Perhaps eventually these should be split out into a number
39 * of files, as this could get quite big.
40 **/
41
42
43/**
44 * Many of the RPC functions need the domain sid. This function gets
45 * it at the start of every run
46 *
47 * @param cli A cli_state already connected to the remote machine
48 *
49 * @return The Domain SID of the remote machine.
50 **/
51
52NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
53 DOM_SID **domain_sid, char **domain_name)
54{
55 struct rpc_pipe_client *lsa_pipe;
56 POLICY_HND pol;
57 NTSTATUS result = NT_STATUS_OK;
58 uint32 info_class = 5;
59
60 lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
61 if (!lsa_pipe) {
62 d_fprintf(stderr, "Could not initialise lsa pipe\n");
63 return result;
64 }
65
66 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False,
67 SEC_RIGHTS_MAXIMUM_ALLOWED,
68 &pol);
69 if (!NT_STATUS_IS_OK(result)) {
70 d_fprintf(stderr, "open_policy failed: %s\n",
71 nt_errstr(result));
72 return result;
73 }
74
75 result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol,
76 info_class, domain_name,
77 domain_sid);
78 if (!NT_STATUS_IS_OK(result)) {
79 d_fprintf(stderr, "lsaquery failed: %s\n",
80 nt_errstr(result));
81 return result;
82 }
83
84 rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
85 cli_rpc_pipe_close(lsa_pipe);
86
87 return NT_STATUS_OK;
88}
89
90/**
91 * Run a single RPC command, from start to finish.
92 *
93 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
94 * @param conn_flag a NET_FLAG_ combination. Passed to
95 * net_make_ipc_connection.
96 * @param argc Standard main() style argc
97 * @param argc Standard main() style argv. Initial components are already
98 * stripped
99 * @return A shell status integer (0 for success)
100 */
101
102int run_rpc_command(struct cli_state *cli_arg,
103 const int pipe_idx,
104 int conn_flags,
105 rpc_command_fn fn,
106 int argc,
107 const char **argv)
108{
109 struct cli_state *cli = NULL;
110 struct rpc_pipe_client *pipe_hnd = NULL;
111 TALLOC_CTX *mem_ctx;
112 NTSTATUS nt_status;
113 DOM_SID *domain_sid;
114 char *domain_name;
115
116 /* make use of cli_state handed over as an argument, if possible */
117 if (!cli_arg) {
118 cli = net_make_ipc_connection(conn_flags);
119 } else {
120 cli = cli_arg;
121 }
122
123 if (!cli) {
124 return -1;
125 }
126
127 /* Create mem_ctx */
128
129 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
130 DEBUG(0, ("talloc_init() failed\n"));
131 cli_shutdown(cli);
132 return -1;
133 }
134
135 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
136 &domain_name);
137 if (!NT_STATUS_IS_OK(nt_status)) {
138 cli_shutdown(cli);
139 return -1;
140 }
141
142 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
143 if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
144 /* Always try and create an schannel netlogon pipe. */
145 pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx,
146 PIPE_AUTH_LEVEL_PRIVACY,
147 domain_name,
148 &nt_status);
149 if (!pipe_hnd) {
150 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
151 nt_errstr(nt_status) ));
152 cli_shutdown(cli);
153 return -1;
154 }
155 } else {
156 pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status);
157 if (!pipe_hnd) {
158 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
159 cli_get_pipe_name(pipe_idx),
160 nt_errstr(nt_status) ));
161 cli_shutdown(cli);
162 return -1;
163 }
164 }
165 }
166
167 nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
168
169 if (!NT_STATUS_IS_OK(nt_status)) {
170 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
171 } else {
172 DEBUG(5, ("rpc command function succedded\n"));
173 }
174
175 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
176 if (pipe_hnd) {
177 cli_rpc_pipe_close(pipe_hnd);
178 }
179 }
180
181 /* close the connection only if it was opened here */
182 if (!cli_arg) {
183 cli_shutdown(cli);
184 }
185
186 talloc_destroy(mem_ctx);
187 return (!NT_STATUS_IS_OK(nt_status));
188}
189
190/**
191 * Force a change of the trust acccount password.
192 *
193 * All parameters are provided by the run_rpc_command function, except for
194 * argc, argv which are passes through.
195 *
196 * @param domain_sid The domain sid aquired from the remote server
197 * @param cli A cli_state connected to the server.
198 * @param mem_ctx Talloc context, destoyed on compleation of the function.
199 * @param argc Standard main() style argc
200 * @param argc Standard main() style argv. Initial components are already
201 * stripped
202 *
203 * @return Normal NTSTATUS return.
204 **/
205
206static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid,
207 const char *domain_name,
208 struct cli_state *cli,
209 struct rpc_pipe_client *pipe_hnd,
210 TALLOC_CTX *mem_ctx,
211 int argc,
212 const char **argv)
213{
214
215 return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup);
216}
217
218/**
219 * Force a change of the trust acccount password.
220 *
221 * @param argc Standard main() style argc
222 * @param argc Standard main() style argv. Initial components are already
223 * stripped
224 *
225 * @return A shell status integer (0 for success)
226 **/
227
228int net_rpc_changetrustpw(int argc, const char **argv)
229{
230 net_use_machine_account();
231
232 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
233 rpc_changetrustpw_internals,
234 argc, argv);
235}
236
237/**
238 * Join a domain, the old way.
239 *
240 * This uses 'machinename' as the inital password, and changes it.
241 *
242 * The password should be created with 'server manager' or equiv first.
243 *
244 * All parameters are provided by the run_rpc_command function, except for
245 * argc, argv which are passes through.
246 *
247 * @param domain_sid The domain sid aquired from the remote server
248 * @param cli A cli_state connected to the server.
249 * @param mem_ctx Talloc context, destoyed on compleation of the function.
250 * @param argc Standard main() style argc
251 * @param argc Standard main() style argv. Initial components are already
252 * stripped
253 *
254 * @return Normal NTSTATUS return.
255 **/
256
257static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid,
258 const char *domain_name,
259 struct cli_state *cli,
260 struct rpc_pipe_client *pipe_hnd,
261 TALLOC_CTX *mem_ctx,
262 int argc,
263 const char **argv)
264{
265
266 fstring trust_passwd;
267 unsigned char orig_trust_passwd_hash[16];
268 NTSTATUS result;
269 uint32 sec_channel_type;
270
271 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
272 if (!pipe_hnd) {
273 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
274 "error was %s\n",
275 cli->desthost,
276 nt_errstr(result) ));
277 return result;
278 }
279
280 /*
281 check what type of join - if the user want's to join as
282 a BDC, the server must agree that we are a BDC.
283 */
284 if (argc >= 0) {
285 sec_channel_type = get_sec_channel_type(argv[0]);
286 } else {
287 sec_channel_type = get_sec_channel_type(NULL);
288 }
289
290 fstrcpy(trust_passwd, global_myname());
291 strlower_m(trust_passwd);
292
293 /*
294 * Machine names can be 15 characters, but the max length on
295 * a password is 14. --jerry
296 */
297
298 trust_passwd[14] = '\0';
299
300 E_md4hash(trust_passwd, orig_trust_passwd_hash);
301
302 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup,
303 orig_trust_passwd_hash,
304 sec_channel_type);
305
306 if (NT_STATUS_IS_OK(result))
307 printf("Joined domain %s.\n",opt_target_workgroup);
308
309
310 if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
311 DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
312 result = NT_STATUS_UNSUCCESSFUL;
313 }
314
315 return result;
316}
317
318/**
319 * Join a domain, the old way.
320 *
321 * @param argc Standard main() style argc
322 * @param argc Standard main() style argv. Initial components are already
323 * stripped
324 *
325 * @return A shell status integer (0 for success)
326 **/
327
328static int net_rpc_perform_oldjoin(int argc, const char **argv)
329{
330 return run_rpc_command(NULL, PI_NETLOGON,
331 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
332 rpc_oldjoin_internals,
333 argc, argv);
334}
335
336/**
337 * Join a domain, the old way. This function exists to allow
338 * the message to be displayed when oldjoin was explicitly
339 * requested, but not when it was implied by "net rpc join"
340 *
341 * @param argc Standard main() style argc
342 * @param argc Standard main() style argv. Initial components are already
343 * stripped
344 *
345 * @return A shell status integer (0 for success)
346 **/
347
348static int net_rpc_oldjoin(int argc, const char **argv)
349{
350 int rc = net_rpc_perform_oldjoin(argc, argv);
351
352 if (rc) {
353 d_fprintf(stderr, "Failed to join domain\n");
354 }
355
356 return rc;
357}
358
359/**
360 * Basic usage function for 'net rpc join'
361 * @param argc Standard main() style argc
362 * @param argc Standard main() style argv. Initial components are already
363 * stripped
364 **/
365
366static int rpc_join_usage(int argc, const char **argv)
367{
368 d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
369 "\t to join a domain with admin username & password\n"\
370 "\t\t password will be prompted if needed and none is specified\n"\
371 "\t <type> can be (default MEMBER)\n"\
372 "\t\t BDC - Join as a BDC\n"\
373 "\t\t PDC - Join as a PDC\n"\
374 "\t\t MEMBER - Join as a MEMBER server\n");
375
376 net_common_flags_usage(argc, argv);
377 return -1;
378}
379
380/**
381 * 'net rpc join' entrypoint.
382 * @param argc Standard main() style argc
383 * @param argc Standard main() style argv. Initial components are already
384 * stripped
385 *
386 * Main 'net_rpc_join()' (where the admin username/password is used) is
387 * in net_rpc_join.c
388 * Try to just change the password, but if that doesn't work, use/prompt
389 * for a username/password.
390 **/
391
392int net_rpc_join(int argc, const char **argv)
393{
394 if (lp_server_role() == ROLE_STANDALONE) {
395 d_printf("cannot join as standalone machine\n");
396 return -1;
397 }
398
399 if (strlen(global_myname()) > 15) {
400 d_printf("Our netbios name can be at most 15 chars long, "
401 "\"%s\" is %u chars long\n",
402 global_myname(), (unsigned int)strlen(global_myname()));
403 return -1;
404 }
405
406 if ((net_rpc_perform_oldjoin(argc, argv) == 0))
407 return 0;
408
409 return net_rpc_join_newstyle(argc, argv);
410}
411
412/**
413 * display info about a rpc domain
414 *
415 * All parameters are provided by the run_rpc_command function, except for
416 * argc, argv which are passed through.
417 *
418 * @param domain_sid The domain sid acquired from the remote server
419 * @param cli A cli_state connected to the server.
420 * @param mem_ctx Talloc context, destoyed on completion of the function.
421 * @param argc Standard main() style argc
422 * @param argv Standard main() style argv. Initial components are already
423 * stripped
424 *
425 * @return Normal NTSTATUS return.
426 **/
427
428NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
429 const char *domain_name,
430 struct cli_state *cli,
431 struct rpc_pipe_client *pipe_hnd,
432 TALLOC_CTX *mem_ctx,
433 int argc,
434 const char **argv)
435{
436 POLICY_HND connect_pol, domain_pol;
437 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
438 SAM_UNK_CTR ctr;
439 fstring sid_str;
440
441 sid_to_string(sid_str, domain_sid);
442
443 /* Get sam policy handle */
444 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
445 &connect_pol);
446 if (!NT_STATUS_IS_OK(result)) {
447 d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
448 goto done;
449 }
450
451 /* Get domain policy handle */
452 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
453 MAXIMUM_ALLOWED_ACCESS,
454 domain_sid, &domain_pol);
455 if (!NT_STATUS_IS_OK(result)) {
456 d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
457 goto done;
458 }
459
460 ZERO_STRUCT(ctr);
461 result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
462 2, &ctr);
463 if (NT_STATUS_IS_OK(result)) {
464 TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
465 d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain));
466 d_printf("Domain SID: %s\n", sid_str);
467 d_printf("Sequence number: %llu\n", (unsigned long long)ctr.info.inf2.seq_num);
468 d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
469 d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
470 d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps);
471 talloc_destroy(ctx);
472 }
473
474 done:
475 return result;
476}
477
478/**
479 * 'net rpc info' entrypoint.
480 * @param argc Standard main() style argc
481 * @param argc Standard main() style argv. Initial components are already
482 * stripped
483 **/
484
485int net_rpc_info(int argc, const char **argv)
486{
487 return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_PDC,
488 rpc_info_internals,
489 argc, argv);
490}
491
492/**
493 * Fetch domain SID into the local secrets.tdb
494 *
495 * All parameters are provided by the run_rpc_command function, except for
496 * argc, argv which are passes through.
497 *
498 * @param domain_sid The domain sid acquired from the remote server
499 * @param cli A cli_state connected to the server.
500 * @param mem_ctx Talloc context, destoyed on completion of the function.
501 * @param argc Standard main() style argc
502 * @param argv Standard main() style argv. Initial components are already
503 * stripped
504 *
505 * @return Normal NTSTATUS return.
506 **/
507
508static NTSTATUS rpc_getsid_internals(const DOM_SID *domain_sid,
509 const char *domain_name,
510 struct cli_state *cli,
511 struct rpc_pipe_client *pipe_hnd,
512 TALLOC_CTX *mem_ctx,
513 int argc,
514 const char **argv)
515{
516 fstring sid_str;
517
518 sid_to_string(sid_str, domain_sid);
519 d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
520 sid_str, domain_name);
521
522 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
523 DEBUG(0,("Can't store domain SID\n"));
524 return NT_STATUS_UNSUCCESSFUL;
525 }
526
527 return NT_STATUS_OK;
528}
529
530/**
531 * 'net rpc getsid' entrypoint.
532 * @param argc Standard main() style argc
533 * @param argc Standard main() style argv. Initial components are already
534 * stripped
535 **/
536
537int net_rpc_getsid(int argc, const char **argv)
538{
539 return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
540 rpc_getsid_internals,
541 argc, argv);
542}
543
544/****************************************************************************/
545
546/**
547 * Basic usage function for 'net rpc user'
548 * @param argc Standard main() style argc.
549 * @param argv Standard main() style argv. Initial components are already
550 * stripped.
551 **/
552
553static int rpc_user_usage(int argc, const char **argv)
554{
555 return net_help_user(argc, argv);
556}
557
558/**
559 * Add a new user to a remote RPC server
560 *
561 * All parameters are provided by the run_rpc_command function, except for
562 * argc, argv which are passes through.
563 *
564 * @param domain_sid The domain sid acquired from the remote server
565 * @param cli A cli_state connected to the server.
566 * @param mem_ctx Talloc context, destoyed on completion of the function.
567 * @param argc Standard main() style argc
568 * @param argv Standard main() style argv. Initial components are already
569 * stripped
570 *
571 * @return Normal NTSTATUS return.
572 **/
573
574static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
575 const char *domain_name,
576 struct cli_state *cli,
577 struct rpc_pipe_client *pipe_hnd,
578 TALLOC_CTX *mem_ctx,
579 int argc, const char **argv)
580{
581
582 POLICY_HND connect_pol, domain_pol, user_pol;
583 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
584 const char *acct_name;
585 uint32 acb_info;
586 uint32 acct_flags=0;
587 uint32 user_rid;
588
589 if (argc < 1) {
590 d_printf("User must be specified\n");
591 rpc_user_usage(argc, argv);
592 return NT_STATUS_OK;
593 }
594
595 acct_name = argv[0];
596
597 /* Get sam policy handle */
598
599 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
600 &connect_pol);
601 if (!NT_STATUS_IS_OK(result)) {
602 goto done;
603 }
604
605 /* Get domain policy handle */
606
607 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
608 MAXIMUM_ALLOWED_ACCESS,
609 domain_sid, &domain_pol);
610 if (!NT_STATUS_IS_OK(result)) {
611 goto done;
612 }
613
614 /* Create domain user */
615
616 acb_info = ACB_NORMAL;
617 acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
618 SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
619 SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
620 SAMR_USER_SETATTR;
621 DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
622
623 result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
624 acct_name, acb_info, acct_flags,
625 &user_pol, &user_rid);
626 if (!NT_STATUS_IS_OK(result)) {
627 goto done;
628 }
629
630 if (argc == 2) {
631
632 uint32 *user_rids, num_rids, *name_types;
633 uint32 flags = 0x000003e8; /* Unknown */
634 SAM_USERINFO_CTR ctr;
635 SAM_USER_INFO_24 p24;
636 uchar pwbuf[516];
637
638 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
639 flags, 1, &acct_name,
640 &num_rids, &user_rids,
641 &name_types);
642
643 if (!NT_STATUS_IS_OK(result)) {
644 goto done;
645 }
646
647 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
648 MAXIMUM_ALLOWED_ACCESS,
649 user_rids[0], &user_pol);
650
651 if (!NT_STATUS_IS_OK(result)) {
652 goto done;
653 }
654
655 /* Set password on account */
656
657 ZERO_STRUCT(ctr);
658 ZERO_STRUCT(p24);
659
660 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
661
662 init_sam_user_info24(&p24, (char *)pwbuf,24);
663
664 ctr.switch_value = 24;
665 ctr.info.id24 = &p24;
666
667 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24,
668 &cli->user_session_key, &ctr);
669
670 if (!NT_STATUS_IS_OK(result)) {
671 d_fprintf(stderr, "Failed to set password for user %s - %s\n",
672 acct_name, nt_errstr(result));
673
674 result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
675
676 if (!NT_STATUS_IS_OK(result)) {
677 d_fprintf(stderr, "Failed to delete user %s - %s\n",
678 acct_name, nt_errstr(result));
679 return result;
680 }
681 }
682
683 }
684 done:
685 if (!NT_STATUS_IS_OK(result)) {
686 d_fprintf(stderr, "Failed to add user %s - %s\n", acct_name,
687 nt_errstr(result));
688 } else {
689 d_printf("Added user %s\n", acct_name);
690 }
691 return result;
692}
693
694/**
695 * Add a new user to a remote RPC server
696 *
697 * @param argc Standard main() style argc
698 * @param argv Standard main() style argv. Initial components are already
699 * stripped
700 *
701 * @return A shell status integer (0 for success)
702 **/
703
704static int rpc_user_add(int argc, const char **argv)
705{
706 return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_add_internals,
707 argc, argv);
708}
709
710/**
711 * Delete a user from a remote RPC server
712 *
713 * All parameters are provided by the run_rpc_command function, except for
714 * argc, argv which are passes through.
715 *
716 * @param domain_sid The domain sid acquired from the remote server
717 * @param cli A cli_state connected to the server.
718 * @param mem_ctx Talloc context, destoyed on completion of the function.
719 * @param argc Standard main() style argc
720 * @param argv Standard main() style argv. Initial components are already
721 * stripped
722 *
723 * @return Normal NTSTATUS return.
724 **/
725
726static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
727 const char *domain_name,
728 struct cli_state *cli,
729 struct rpc_pipe_client *pipe_hnd,
730 TALLOC_CTX *mem_ctx,
731 int argc,
732 const char **argv)
733{
734 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
735 POLICY_HND connect_pol, domain_pol, user_pol;
736
737 if (argc < 1) {
738 d_printf("User must be specified\n");
739 rpc_user_usage(argc, argv);
740 return NT_STATUS_OK;
741 }
742 /* Get sam policy and domain handles */
743
744 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
745 &connect_pol);
746
747 if (!NT_STATUS_IS_OK(result)) {
748 goto done;
749 }
750
751 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
752 MAXIMUM_ALLOWED_ACCESS,
753 domain_sid, &domain_pol);
754
755 if (!NT_STATUS_IS_OK(result)) {
756 goto done;
757 }
758
759 /* Get handle on user */
760
761 {
762 uint32 *user_rids, num_rids, *name_types;
763 uint32 flags = 0x000003e8; /* Unknown */
764
765 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
766 flags, 1, &argv[0],
767 &num_rids, &user_rids,
768 &name_types);
769
770 if (!NT_STATUS_IS_OK(result)) {
771 goto done;
772 }
773
774 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
775 MAXIMUM_ALLOWED_ACCESS,
776 user_rids[0], &user_pol);
777
778 if (!NT_STATUS_IS_OK(result)) {
779 goto done;
780 }
781 }
782
783 /* Delete user */
784
785 result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
786
787 if (!NT_STATUS_IS_OK(result)) {
788 goto done;
789 }
790
791 /* Display results */
792 if (!NT_STATUS_IS_OK(result)) {
793 d_fprintf(stderr, "Failed to delete user account - %s\n", nt_errstr(result));
794 } else {
795 d_printf("Deleted user account\n");
796 }
797
798 done:
799 return result;
800}
801
802/**
803 * Rename a user on a remote RPC server
804 *
805 * All parameters are provided by the run_rpc_command function, except for
806 * argc, argv which are passes through.
807 *
808 * @param domain_sid The domain sid acquired from the remote server
809 * @param cli A cli_state connected to the server.
810 * @param mem_ctx Talloc context, destoyed on completion of the function.
811 * @param argc Standard main() style argc
812 * @param argv Standard main() style argv. Initial components are already
813 * stripped
814 *
815 * @return Normal NTSTATUS return.
816 **/
817
818static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid,
819 const char *domain_name,
820 struct cli_state *cli,
821 struct rpc_pipe_client *pipe_hnd,
822 TALLOC_CTX *mem_ctx,
823 int argc,
824 const char **argv)
825{
826 POLICY_HND connect_pol, domain_pol, user_pol;
827 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
828 uint32 info_level = 7;
829 const char *old_name, *new_name;
830 uint32 *user_rid;
831 uint32 flags = 0x000003e8; /* Unknown */
832 uint32 num_rids, *name_types;
833 uint32 num_names = 1;
834 const char **names;
835 SAM_USERINFO_CTR *user_ctr;
836 SAM_USERINFO_CTR ctr;
837 SAM_USER_INFO_7 info7;
838
839 if (argc != 2) {
840 d_printf("Old and new username must be specified\n");
841 rpc_user_usage(argc, argv);
842 return NT_STATUS_OK;
843 }
844
845 old_name = argv[0];
846 new_name = argv[1];
847
848 ZERO_STRUCT(ctr);
849 ZERO_STRUCT(user_ctr);
850
851 /* Get sam policy handle */
852
853 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
854 &connect_pol);
855 if (!NT_STATUS_IS_OK(result)) {
856 goto done;
857 }
858
859 /* Get domain policy handle */
860
861 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
862 MAXIMUM_ALLOWED_ACCESS,
863 domain_sid, &domain_pol);
864 if (!NT_STATUS_IS_OK(result)) {
865 goto done;
866 }
867
868 if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
869 result = NT_STATUS_NO_MEMORY;
870 goto done;
871 }
872 names[0] = old_name;
873 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
874 flags, num_names, names,
875 &num_rids, &user_rid, &name_types);
876 if (!NT_STATUS_IS_OK(result)) {
877 goto done;
878 }
879
880 /* Open domain user */
881 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
882 MAXIMUM_ALLOWED_ACCESS, user_rid[0], &user_pol);
883
884 if (!NT_STATUS_IS_OK(result)) {
885 goto done;
886 }
887
888 /* Query user info */
889 result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
890 info_level, &user_ctr);
891
892 if (!NT_STATUS_IS_OK(result)) {
893 goto done;
894 }
895
896 ctr.switch_value = info_level;
897 ctr.info.id7 = &info7;
898
899 init_sam_user_info7(&info7, new_name);
900
901 /* Set new name */
902 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol,
903 info_level, &cli->user_session_key, &ctr);
904
905 if (!NT_STATUS_IS_OK(result)) {
906 goto done;
907 }
908
909 done:
910 if (!NT_STATUS_IS_OK(result)) {
911 d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n", old_name, new_name,
912 nt_errstr(result));
913 } else {
914 d_printf("Renamed user from %s to %s\n", old_name, new_name);
915 }
916 return result;
917}
918
919/**
920 * Rename a user on a remote RPC server
921 *
922 * @param argc Standard main() style argc
923 * @param argv Standard main() style argv. Initial components are already
924 * stripped
925 *
926 * @return A shell status integer (0 for success)
927 **/
928
929static int rpc_user_rename(int argc, const char **argv)
930{
931 return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_rename_internals,
932 argc, argv);
933}
934
935/**
936 * Delete a user from a remote RPC server
937 *
938 * @param argc Standard main() style argc
939 * @param argv Standard main() style argv. Initial components are already
940 * stripped
941 *
942 * @return A shell status integer (0 for success)
943 **/
944
945static int rpc_user_delete(int argc, const char **argv)
946{
947 return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_del_internals,
948 argc, argv);
949}
950
951/**
952 * Set a password for a user on a remote RPC server
953 *
954 * All parameters are provided by the run_rpc_command function, except for
955 * argc, argv which are passes through.
956 *
957 * @param domain_sid The domain sid acquired from the remote server
958 * @param cli A cli_state connected to the server.
959 * @param mem_ctx Talloc context, destoyed on completion of the function.
960 * @param argc Standard main() style argc
961 * @param argv Standard main() style argv. Initial components are already
962 * stripped
963 *
964 * @return Normal NTSTATUS return.
965 **/
966
967static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid,
968 const char *domain_name,
969 struct cli_state *cli,
970 struct rpc_pipe_client *pipe_hnd,
971 TALLOC_CTX *mem_ctx,
972 int argc,
973 const char **argv)
974{
975 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
976 POLICY_HND connect_pol, domain_pol, user_pol;
977 SAM_USERINFO_CTR ctr;
978 SAM_USER_INFO_24 p24;
979 uchar pwbuf[516];
980 const char *user;
981 const char *new_password;
982 char *prompt = NULL;
983
984 if (argc < 1) {
985 d_printf("User must be specified\n");
986 rpc_user_usage(argc, argv);
987 return NT_STATUS_OK;
988 }
989
990 user = argv[0];
991
992 if (argv[1]) {
993 new_password = argv[1];
994 } else {
995 asprintf(&prompt, "Enter new password for %s:", user);
996 new_password = getpass(prompt);
997 SAFE_FREE(prompt);
998 }
999
1000 /* Get sam policy and domain handles */
1001
1002 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1003 &connect_pol);
1004
1005 if (!NT_STATUS_IS_OK(result)) {
1006 goto done;
1007 }
1008
1009 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1010 MAXIMUM_ALLOWED_ACCESS,
1011 domain_sid, &domain_pol);
1012
1013 if (!NT_STATUS_IS_OK(result)) {
1014 goto done;
1015 }
1016
1017 /* Get handle on user */
1018
1019 {
1020 uint32 *user_rids, num_rids, *name_types;
1021 uint32 flags = 0x000003e8; /* Unknown */
1022
1023 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1024 flags, 1, &user,
1025 &num_rids, &user_rids,
1026 &name_types);
1027
1028 if (!NT_STATUS_IS_OK(result)) {
1029 goto done;
1030 }
1031
1032 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
1033 MAXIMUM_ALLOWED_ACCESS,
1034 user_rids[0], &user_pol);
1035
1036 if (!NT_STATUS_IS_OK(result)) {
1037 goto done;
1038 }
1039 }
1040
1041 /* Set password on account */
1042
1043 ZERO_STRUCT(ctr);
1044 ZERO_STRUCT(p24);
1045
1046 encode_pw_buffer(pwbuf, new_password, STR_UNICODE);
1047
1048 init_sam_user_info24(&p24, (char *)pwbuf,24);
1049
1050 ctr.switch_value = 24;
1051 ctr.info.id24 = &p24;
1052
1053 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24,
1054 &cli->user_session_key, &ctr);
1055
1056 if (!NT_STATUS_IS_OK(result)) {
1057 goto done;
1058 }
1059
1060 /* Display results */
1061
1062 done:
1063 return result;
1064
1065}
1066
1067/**
1068 * Set a user's password on a remote RPC server
1069 *
1070 * @param argc Standard main() style argc
1071 * @param argv Standard main() style argv. Initial components are already
1072 * stripped
1073 *
1074 * @return A shell status integer (0 for success)
1075 **/
1076
1077static int rpc_user_password(int argc, const char **argv)
1078{
1079 return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_password_internals,
1080 argc, argv);
1081}
1082
1083/**
1084 * List user's groups on a remote RPC server
1085 *
1086 * All parameters are provided by the run_rpc_command function, except for
1087 * argc, argv which are passes through.
1088 *
1089 * @param domain_sid The domain sid acquired from the remote server
1090 * @param cli A cli_state connected to the server.
1091 * @param mem_ctx Talloc context, destoyed on completion of the function.
1092 * @param argc Standard main() style argc
1093 * @param argv Standard main() style argv. Initial components are already
1094 * stripped
1095 *
1096 * @return Normal NTSTATUS return.
1097 **/
1098
1099static NTSTATUS rpc_user_info_internals(const DOM_SID *domain_sid,
1100 const char *domain_name,
1101 struct cli_state *cli,
1102 struct rpc_pipe_client *pipe_hnd,
1103 TALLOC_CTX *mem_ctx,
1104 int argc,
1105 const char **argv)
1106{
1107 POLICY_HND connect_pol, domain_pol, user_pol;
1108 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1109 uint32 *rids, num_rids, *name_types, num_names;
1110 uint32 flags = 0x000003e8; /* Unknown */
1111 int i;
1112 char **names;
1113 DOM_GID *user_gids;
1114
1115 if (argc < 1) {
1116 d_printf("User must be specified\n");
1117 rpc_user_usage(argc, argv);
1118 return NT_STATUS_OK;
1119 }
1120 /* Get sam policy handle */
1121
1122 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1123 &connect_pol);
1124 if (!NT_STATUS_IS_OK(result)) goto done;
1125
1126 /* Get domain policy handle */
1127
1128 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1129 MAXIMUM_ALLOWED_ACCESS,
1130 domain_sid, &domain_pol);
1131 if (!NT_STATUS_IS_OK(result)) goto done;
1132
1133 /* Get handle on user */
1134
1135 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1136 flags, 1, &argv[0],
1137 &num_rids, &rids, &name_types);
1138
1139 if (!NT_STATUS_IS_OK(result)) goto done;
1140
1141 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
1142 MAXIMUM_ALLOWED_ACCESS,
1143 rids[0], &user_pol);
1144 if (!NT_STATUS_IS_OK(result)) goto done;
1145
1146 result = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, &user_pol,
1147 &num_rids, &user_gids);
1148
1149 if (!NT_STATUS_IS_OK(result)) goto done;
1150
1151 /* Look up rids */
1152
1153 if (num_rids) {
1154 if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1155 result = NT_STATUS_NO_MEMORY;
1156 goto done;
1157 }
1158
1159 for (i = 0; i < num_rids; i++)
1160 rids[i] = user_gids[i].g_rid;
1161
1162 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, &domain_pol,
1163 num_rids, rids,
1164 &num_names, &names, &name_types);
1165
1166 if (!NT_STATUS_IS_OK(result)) {
1167 goto done;
1168 }
1169
1170 /* Display results */
1171
1172 for (i = 0; i < num_names; i++)
1173 printf("%s\n", names[i]);
1174 }
1175 done:
1176 return result;
1177}
1178
1179/**
1180 * List a user's groups from a remote RPC server
1181 *
1182 * @param argc Standard main() style argc
1183 * @param argv Standard main() style argv. Initial components are already
1184 * stripped
1185 *
1186 * @return A shell status integer (0 for success)
1187 **/
1188
1189static int rpc_user_info(int argc, const char **argv)
1190{
1191 return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_info_internals,
1192 argc, argv);
1193}
1194
1195/**
1196 * List users on a remote RPC server
1197 *
1198 * All parameters are provided by the run_rpc_command function, except for
1199 * argc, argv which are passes through.
1200 *
1201 * @param domain_sid The domain sid acquired from the remote server
1202 * @param cli A cli_state connected to the server.
1203 * @param mem_ctx Talloc context, destoyed on completion of the function.
1204 * @param argc Standard main() style argc
1205 * @param argv Standard main() style argv. Initial components are already
1206 * stripped
1207 *
1208 * @return Normal NTSTATUS return.
1209 **/
1210
1211static NTSTATUS rpc_user_list_internals(const DOM_SID *domain_sid,
1212 const char *domain_name,
1213 struct cli_state *cli,
1214 struct rpc_pipe_client *pipe_hnd,
1215 TALLOC_CTX *mem_ctx,
1216 int argc,
1217 const char **argv)
1218{
1219 POLICY_HND connect_pol, domain_pol;
1220 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1221 uint32 start_idx=0, num_entries, i, loop_count = 0;
1222 SAM_DISPINFO_CTR ctr;
1223 SAM_DISPINFO_1 info1;
1224
1225 /* Get sam policy handle */
1226
1227 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1228 &connect_pol);
1229 if (!NT_STATUS_IS_OK(result)) {
1230 goto done;
1231 }
1232
1233 /* Get domain policy handle */
1234
1235 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1236 MAXIMUM_ALLOWED_ACCESS,
1237 domain_sid, &domain_pol);
1238 if (!NT_STATUS_IS_OK(result)) {
1239 goto done;
1240 }
1241
1242 /* Query domain users */
1243 ZERO_STRUCT(ctr);
1244 ZERO_STRUCT(info1);
1245 ctr.sam.info1 = &info1;
1246 if (opt_long_list_entries)
1247 d_printf("\nUser name Comment"\
1248 "\n-----------------------------\n");
1249 do {
1250 fstring user, desc;
1251 uint32 max_entries, max_size;
1252
1253 get_query_dispinfo_params(
1254 loop_count, &max_entries, &max_size);
1255
1256 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
1257 &start_idx, 1, &num_entries,
1258 max_entries, max_size, &ctr);
1259 loop_count++;
1260
1261 for (i = 0; i < num_entries; i++) {
1262 unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
1263 if (opt_long_list_entries)
1264 unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
1265
1266 if (opt_long_list_entries)
1267 printf("%-21.21s %s\n", user, desc);
1268 else
1269 printf("%s\n", user);
1270 }
1271 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1272
1273 done:
1274 return result;
1275}
1276
1277/**
1278 * 'net rpc user' entrypoint.
1279 * @param argc Standard main() style argc
1280 * @param argc Standard main() style argv. Initial components are already
1281 * stripped
1282 **/
1283
1284int net_rpc_user(int argc, const char **argv)
1285{
1286 struct functable func[] = {
1287 {"add", rpc_user_add},
1288 {"info", rpc_user_info},
1289 {"delete", rpc_user_delete},
1290 {"password", rpc_user_password},
1291 {"rename", rpc_user_rename},
1292 {NULL, NULL}
1293 };
1294
1295 if (argc == 0) {
1296 return run_rpc_command(NULL,PI_SAMR, 0,
1297 rpc_user_list_internals,
1298 argc, argv);
1299 }
1300
1301 return net_run_function(argc, argv, func, rpc_user_usage);
1302}
1303
1304static NTSTATUS rpc_sh_user_list(TALLOC_CTX *mem_ctx,
1305 struct rpc_sh_ctx *ctx,
1306 struct rpc_pipe_client *pipe_hnd,
1307 int argc, const char **argv)
1308{
1309 return rpc_user_list_internals(ctx->domain_sid, ctx->domain_name,
1310 ctx->cli, pipe_hnd, mem_ctx,
1311 argc, argv);
1312}
1313
1314static NTSTATUS rpc_sh_user_info(TALLOC_CTX *mem_ctx,
1315 struct rpc_sh_ctx *ctx,
1316 struct rpc_pipe_client *pipe_hnd,
1317 int argc, const char **argv)
1318{
1319 return rpc_user_info_internals(ctx->domain_sid, ctx->domain_name,
1320 ctx->cli, pipe_hnd, mem_ctx,
1321 argc, argv);
1322}
1323
1324static NTSTATUS rpc_sh_handle_user(TALLOC_CTX *mem_ctx,
1325 struct rpc_sh_ctx *ctx,
1326 struct rpc_pipe_client *pipe_hnd,
1327 int argc, const char **argv,
1328 NTSTATUS (*fn)(
1329 TALLOC_CTX *mem_ctx,
1330 struct rpc_sh_ctx *ctx,
1331 struct rpc_pipe_client *pipe_hnd,
1332 const POLICY_HND *user_hnd,
1333 int argc, const char **argv))
1334
1335{
1336 POLICY_HND connect_pol, domain_pol, user_pol;
1337 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1338 DOM_SID sid;
1339 uint32 rid;
1340 enum lsa_SidType type;
1341
1342 if (argc == 0) {
1343 d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
1344 return NT_STATUS_INVALID_PARAMETER;
1345 }
1346
1347 ZERO_STRUCT(connect_pol);
1348 ZERO_STRUCT(domain_pol);
1349 ZERO_STRUCT(user_pol);
1350
1351 result = net_rpc_lookup_name(mem_ctx, pipe_hnd->cli, argv[0],
1352 NULL, NULL, &sid, &type);
1353 if (!NT_STATUS_IS_OK(result)) {
1354 d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
1355 nt_errstr(result));
1356 goto done;
1357 }
1358
1359 if (type != SID_NAME_USER) {
1360 d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
1361 sid_type_lookup(type));
1362 result = NT_STATUS_NO_SUCH_USER;
1363 goto done;
1364 }
1365
1366 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1367 d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
1368 result = NT_STATUS_NO_SUCH_USER;
1369 goto done;
1370 }
1371
1372 result = rpccli_samr_connect(pipe_hnd, mem_ctx,
1373 MAXIMUM_ALLOWED_ACCESS, &connect_pol);
1374 if (!NT_STATUS_IS_OK(result)) {
1375 goto done;
1376 }
1377
1378 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1379 MAXIMUM_ALLOWED_ACCESS,
1380 ctx->domain_sid, &domain_pol);
1381 if (!NT_STATUS_IS_OK(result)) {
1382 goto done;
1383 }
1384
1385 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
1386 MAXIMUM_ALLOWED_ACCESS,
1387 rid, &user_pol);
1388 if (!NT_STATUS_IS_OK(result)) {
1389 goto done;
1390 }
1391
1392 result = fn(mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1393
1394 done:
1395 if (is_valid_policy_hnd(&user_pol)) {
1396 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
1397 }
1398 if (is_valid_policy_hnd(&domain_pol)) {
1399 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
1400 }
1401 if (is_valid_policy_hnd(&connect_pol)) {
1402 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
1403 }
1404 return result;
1405}
1406
1407static NTSTATUS rpc_sh_user_show_internals(TALLOC_CTX *mem_ctx,
1408 struct rpc_sh_ctx *ctx,
1409 struct rpc_pipe_client *pipe_hnd,
1410 const POLICY_HND *user_hnd,
1411 int argc, const char **argv)
1412{
1413 NTSTATUS result;
1414 SAM_USERINFO_CTR *ctr;
1415 SAM_USER_INFO_21 *info;
1416
1417 if (argc != 0) {
1418 d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
1419 return NT_STATUS_INVALID_PARAMETER;
1420 }
1421
1422 result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1423 21, &ctr);
1424 if (!NT_STATUS_IS_OK(result)) {
1425 return result;
1426 }
1427
1428 info = ctr->info.id21;
1429
1430 d_printf("user rid: %d, group rid: %d\n", info->user_rid,
1431 info->group_rid);
1432
1433 return result;
1434}
1435
1436static NTSTATUS rpc_sh_user_show(TALLOC_CTX *mem_ctx,
1437 struct rpc_sh_ctx *ctx,
1438 struct rpc_pipe_client *pipe_hnd,
1439 int argc, const char **argv)
1440{
1441 return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1442 rpc_sh_user_show_internals);
1443}
1444
1445#define FETCHSTR(name, rec) \
1446do { if (strequal(ctx->thiscmd, name)) { \
1447 oldval = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_##rec); } \
1448} while (0);
1449
1450#define SETSTR(name, rec, flag) \
1451do { if (strequal(ctx->thiscmd, name)) { \
1452 init_unistr2(&usr->uni_##rec, argv[0], UNI_STR_TERMINATE); \
1453 init_uni_hdr(&usr->hdr_##rec, &usr->uni_##rec); \
1454 usr->fields_present |= ACCT_##flag; } \
1455} while (0);
1456
1457static NTSTATUS rpc_sh_user_str_edit_internals(TALLOC_CTX *mem_ctx,
1458 struct rpc_sh_ctx *ctx,
1459 struct rpc_pipe_client *pipe_hnd,
1460 const POLICY_HND *user_hnd,
1461 int argc, const char **argv)
1462{
1463 NTSTATUS result;
1464 SAM_USERINFO_CTR *ctr;
1465 SAM_USER_INFO_21 *usr;
1466 const char *username;
1467 const char *oldval = "";
1468
1469 if (argc > 1) {
1470 d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
1471 ctx->whoami);
1472 return NT_STATUS_INVALID_PARAMETER;
1473 }
1474
1475 result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1476 21, &ctr);
1477 if (!NT_STATUS_IS_OK(result)) {
1478 return result;
1479 }
1480
1481 usr = ctr->info.id21;
1482
1483 username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
1484
1485 FETCHSTR("fullname", full_name);
1486 FETCHSTR("homedir", home_dir);
1487 FETCHSTR("homedrive", dir_drive);
1488 FETCHSTR("logonscript", logon_script);
1489 FETCHSTR("profilepath", profile_path);
1490 FETCHSTR("description", acct_desc);
1491
1492 if (argc == 0) {
1493 d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
1494 goto done;
1495 }
1496
1497 ZERO_STRUCTP(usr);
1498
1499 if (strcmp(argv[0], "NULL") == 0) {
1500 argv[0] = "";
1501 }
1502
1503 SETSTR("fullname", full_name, FULL_NAME);
1504 SETSTR("homedir", home_dir, HOME_DIR);
1505 SETSTR("homedrive", dir_drive, HOME_DRIVE);
1506 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1507 SETSTR("profilepath", profile_path, PROFILE);
1508 SETSTR("description", acct_desc, DESCRIPTION);
1509
1510 result = rpccli_samr_set_userinfo2(
1511 pipe_hnd, mem_ctx, user_hnd, 21,
1512 &pipe_hnd->cli->user_session_key, ctr);
1513
1514 d_printf("Set %s's %s from [%s] to [%s]\n", username,
1515 ctx->thiscmd, oldval, argv[0]);
1516
1517 done:
1518
1519 return result;
1520}
1521
1522#define HANDLEFLG(name, rec) \
1523do { if (strequal(ctx->thiscmd, name)) { \
1524 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1525 if (newval) { \
1526 newflags = oldflags | ACB_##rec; \
1527 } else { \
1528 newflags = oldflags & ~ACB_##rec; \
1529 } } } while (0);
1530
1531static NTSTATUS rpc_sh_user_str_edit(TALLOC_CTX *mem_ctx,
1532 struct rpc_sh_ctx *ctx,
1533 struct rpc_pipe_client *pipe_hnd,
1534 int argc, const char **argv)
1535{
1536 return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1537 rpc_sh_user_str_edit_internals);
1538}
1539
1540static NTSTATUS rpc_sh_user_flag_edit_internals(TALLOC_CTX *mem_ctx,
1541 struct rpc_sh_ctx *ctx,
1542 struct rpc_pipe_client *pipe_hnd,
1543 const POLICY_HND *user_hnd,
1544 int argc, const char **argv)
1545{
1546 NTSTATUS result;
1547 SAM_USERINFO_CTR *ctr;
1548 SAM_USER_INFO_21 *usr;
1549 const char *username;
1550 const char *oldval = "unknown";
1551 uint32 oldflags, newflags;
1552 BOOL newval;
1553
1554 if ((argc > 1) ||
1555 ((argc == 1) && !strequal(argv[0], "yes") &&
1556 !strequal(argv[0], "no"))) {
1557 d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
1558 ctx->whoami);
1559 return NT_STATUS_INVALID_PARAMETER;
1560 }
1561
1562 newval = strequal(argv[0], "yes");
1563
1564 result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1565 21, &ctr);
1566 if (!NT_STATUS_IS_OK(result)) {
1567 return result;
1568 }
1569
1570 usr = ctr->info.id21;
1571
1572 username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
1573 oldflags = usr->acb_info;
1574 newflags = usr->acb_info;
1575
1576 HANDLEFLG("disabled", DISABLED);
1577 HANDLEFLG("pwnotreq", PWNOTREQ);
1578 HANDLEFLG("autolock", AUTOLOCK);
1579 HANDLEFLG("pwnoexp", PWNOEXP);
1580
1581 if (argc == 0) {
1582 d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
1583 goto done;
1584 }
1585
1586 ZERO_STRUCTP(usr);
1587
1588 usr->acb_info = newflags;
1589 usr->fields_present = ACCT_FLAGS;
1590
1591 result = rpccli_samr_set_userinfo2(
1592 pipe_hnd, mem_ctx, user_hnd, 21,
1593 &pipe_hnd->cli->user_session_key, ctr);
1594
1595 if (NT_STATUS_IS_OK(result)) {
1596 d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
1597 ctx->thiscmd, oldval, argv[0]);
1598 }
1599
1600 done:
1601
1602 return result;
1603}
1604
1605static NTSTATUS rpc_sh_user_flag_edit(TALLOC_CTX *mem_ctx,
1606 struct rpc_sh_ctx *ctx,
1607 struct rpc_pipe_client *pipe_hnd,
1608 int argc, const char **argv)
1609{
1610 return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1611 rpc_sh_user_flag_edit_internals);
1612}
1613
1614struct rpc_sh_cmd *net_rpc_user_edit_cmds(TALLOC_CTX *mem_ctx,
1615 struct rpc_sh_ctx *ctx)
1616{
1617 static struct rpc_sh_cmd cmds[] = {
1618
1619 { "fullname", NULL, PI_SAMR, rpc_sh_user_str_edit,
1620 "Show/Set a user's full name" },
1621
1622 { "homedir", NULL, PI_SAMR, rpc_sh_user_str_edit,
1623 "Show/Set a user's home directory" },
1624
1625 { "homedrive", NULL, PI_SAMR, rpc_sh_user_str_edit,
1626 "Show/Set a user's home drive" },
1627
1628 { "logonscript", NULL, PI_SAMR, rpc_sh_user_str_edit,
1629 "Show/Set a user's logon script" },
1630
1631 { "profilepath", NULL, PI_SAMR, rpc_sh_user_str_edit,
1632 "Show/Set a user's profile path" },
1633
1634 { "description", NULL, PI_SAMR, rpc_sh_user_str_edit,
1635 "Show/Set a user's description" },
1636
1637 { "disabled", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1638 "Show/Set whether a user is disabled" },
1639
1640 { "autolock", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1641 "Show/Set whether a user locked out" },
1642
1643 { "pwnotreq", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1644 "Show/Set whether a user does not need a password" },
1645
1646 { "pwnoexp", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1647 "Show/Set whether a user's password does not expire" },
1648
1649 { NULL, NULL, 0, NULL, NULL }
1650 };
1651
1652 return cmds;
1653}
1654
1655struct rpc_sh_cmd *net_rpc_user_cmds(TALLOC_CTX *mem_ctx,
1656 struct rpc_sh_ctx *ctx)
1657{
1658 static struct rpc_sh_cmd cmds[] = {
1659
1660 { "list", NULL, PI_SAMR, rpc_sh_user_list,
1661 "List available users" },
1662
1663 { "info", NULL, PI_SAMR, rpc_sh_user_info,
1664 "List the domain groups a user is member of" },
1665
1666 { "show", NULL, PI_SAMR, rpc_sh_user_show,
1667 "Show info about a user" },
1668
1669 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1670 "Show/Modify a user's fields" },
1671
1672 { NULL, NULL, 0, NULL, NULL }
1673 };
1674
1675 return cmds;
1676}
1677
1678/****************************************************************************/
1679
1680/**
1681 * Basic usage function for 'net rpc group'
1682 * @param argc Standard main() style argc.
1683 * @param argv Standard main() style argv. Initial components are already
1684 * stripped.
1685 **/
1686
1687static int rpc_group_usage(int argc, const char **argv)
1688{
1689 return net_help_group(argc, argv);
1690}
1691
1692/**
1693 * Delete group on a remote RPC server
1694 *
1695 * All parameters are provided by the run_rpc_command function, except for
1696 * argc, argv which are passes through.
1697 *
1698 * @param domain_sid The domain sid acquired from the remote server
1699 * @param cli A cli_state connected to the server.
1700 * @param mem_ctx Talloc context, destoyed on completion of the function.
1701 * @param argc Standard main() style argc
1702 * @param argv Standard main() style argv. Initial components are already
1703 * stripped
1704 *
1705 * @return Normal NTSTATUS return.
1706 **/
1707
1708static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
1709 const char *domain_name,
1710 struct cli_state *cli,
1711 struct rpc_pipe_client *pipe_hnd,
1712 TALLOC_CTX *mem_ctx,
1713 int argc,
1714 const char **argv)
1715{
1716 POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
1717 BOOL group_is_primary = False;
1718 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1719
1720 uint32 *group_rids, num_rids, *name_types, num_members,
1721 *group_attrs, group_rid;
1722 uint32 flags = 0x000003e8; /* Unknown */
1723 /* char **names; */
1724 int i;
1725 /* DOM_GID *user_gids; */
1726 SAM_USERINFO_CTR *user_ctr;
1727 fstring temp;
1728
1729 if (argc < 1) {
1730 d_printf("specify group\n");
1731 rpc_group_usage(argc,argv);
1732 return NT_STATUS_OK; /* ok? */
1733 }
1734
1735 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1736 &connect_pol);
1737
1738 if (!NT_STATUS_IS_OK(result)) {
1739 d_fprintf(stderr, "Request samr_connect failed\n");
1740 goto done;
1741 }
1742
1743 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1744 MAXIMUM_ALLOWED_ACCESS,
1745 domain_sid, &domain_pol);
1746
1747 if (!NT_STATUS_IS_OK(result)) {
1748 d_fprintf(stderr, "Request open_domain failed\n");
1749 goto done;
1750 }
1751
1752 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1753 flags, 1, &argv[0],
1754 &num_rids, &group_rids,
1755 &name_types);
1756
1757 if (!NT_STATUS_IS_OK(result)) {
1758 d_fprintf(stderr, "Lookup of '%s' failed\n",argv[0]);
1759 goto done;
1760 }
1761
1762 switch (name_types[0])
1763 {
1764 case SID_NAME_DOM_GRP:
1765 result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
1766 MAXIMUM_ALLOWED_ACCESS,
1767 group_rids[0], &group_pol);
1768 if (!NT_STATUS_IS_OK(result)) {
1769 d_fprintf(stderr, "Request open_group failed");
1770 goto done;
1771 }
1772
1773 group_rid = group_rids[0];
1774
1775 result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
1776 &num_members, &group_rids,
1777 &group_attrs);
1778
1779 if (!NT_STATUS_IS_OK(result)) {
1780 d_fprintf(stderr, "Unable to query group members of %s",argv[0]);
1781 goto done;
1782 }
1783
1784 if (opt_verbose) {
1785 d_printf("Domain Group %s (rid: %d) has %d members\n",
1786 argv[0],group_rid,num_members);
1787 }
1788
1789 /* Check if group is anyone's primary group */
1790 for (i = 0; i < num_members; i++)
1791 {
1792 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
1793 MAXIMUM_ALLOWED_ACCESS,
1794 group_rids[i], &user_pol);
1795
1796 if (!NT_STATUS_IS_OK(result)) {
1797 d_fprintf(stderr, "Unable to open group member %d\n",group_rids[i]);
1798 goto done;
1799 }
1800
1801 ZERO_STRUCT(user_ctr);
1802
1803 result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
1804 21, &user_ctr);
1805
1806 if (!NT_STATUS_IS_OK(result)) {
1807 d_fprintf(stderr, "Unable to lookup userinfo for group member %d\n",group_rids[i]);
1808 goto done;
1809 }
1810
1811 if (user_ctr->info.id21->group_rid == group_rid) {
1812 unistr2_to_ascii(temp, &(user_ctr->info.id21)->uni_user_name,
1813 sizeof(temp)-1);
1814 if (opt_verbose)
1815 d_printf("Group is primary group of %s\n",temp);
1816 group_is_primary = True;
1817 }
1818
1819 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
1820 }
1821
1822 if (group_is_primary) {
1823 d_fprintf(stderr, "Unable to delete group because some "
1824 "of it's members have it as primary group\n");
1825 result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1826 goto done;
1827 }
1828
1829 /* remove all group members */
1830 for (i = 0; i < num_members; i++)
1831 {
1832 if (opt_verbose)
1833 d_printf("Remove group member %d...",group_rids[i]);
1834 result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, group_rids[i]);
1835
1836 if (NT_STATUS_IS_OK(result)) {
1837 if (opt_verbose)
1838 d_printf("ok\n");
1839 } else {
1840 if (opt_verbose)
1841 d_printf("failed\n");
1842 goto done;
1843 }
1844 }
1845
1846 result = rpccli_samr_delete_dom_group(pipe_hnd, mem_ctx, &group_pol);
1847
1848 break;
1849 /* removing a local group is easier... */
1850 case SID_NAME_ALIAS:
1851 result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
1852 MAXIMUM_ALLOWED_ACCESS,
1853 group_rids[0], &group_pol);
1854
1855 if (!NT_STATUS_IS_OK(result)) {
1856 d_fprintf(stderr, "Request open_alias failed\n");
1857 goto done;
1858 }
1859
1860 result = rpccli_samr_delete_dom_alias(pipe_hnd, mem_ctx, &group_pol);
1861 break;
1862 default:
1863 d_fprintf(stderr, "%s is of type %s. This command is only for deleting local or global groups\n",
1864 argv[0],sid_type_lookup(name_types[0]));
1865 result = NT_STATUS_UNSUCCESSFUL;
1866 goto done;
1867 }
1868
1869
1870 if (NT_STATUS_IS_OK(result)) {
1871 if (opt_verbose)
1872 d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types[0]),argv[0]);
1873 } else {
1874 d_fprintf(stderr, "Deleting of %s failed: %s\n",argv[0],
1875 get_friendly_nt_error_msg(result));
1876 }
1877
1878 done:
1879 return result;
1880
1881}
1882
1883static int rpc_group_delete(int argc, const char **argv)
1884{
1885 return run_rpc_command(NULL, PI_SAMR, 0, rpc_group_delete_internals,
1886 argc,argv);
1887}
1888
1889static NTSTATUS rpc_group_add_internals(const DOM_SID *domain_sid,
1890 const char *domain_name,
1891 struct cli_state *cli,
1892 struct rpc_pipe_client *pipe_hnd,
1893 TALLOC_CTX *mem_ctx,
1894 int argc,
1895 const char **argv)
1896{
1897 POLICY_HND connect_pol, domain_pol, group_pol;
1898 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1899 GROUP_INFO_CTR group_info;
1900
1901 if (argc != 1) {
1902 d_printf("Group name must be specified\n");
1903 rpc_group_usage(argc, argv);
1904 return NT_STATUS_OK;
1905 }
1906
1907 /* Get sam policy handle */
1908
1909 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1910 &connect_pol);
1911 if (!NT_STATUS_IS_OK(result)) goto done;
1912
1913 /* Get domain policy handle */
1914
1915 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1916 MAXIMUM_ALLOWED_ACCESS,
1917 domain_sid, &domain_pol);
1918 if (!NT_STATUS_IS_OK(result)) goto done;
1919
1920 /* Create the group */
1921
1922 result = rpccli_samr_create_dom_group(pipe_hnd, mem_ctx, &domain_pol,
1923 argv[0], MAXIMUM_ALLOWED_ACCESS,
1924 &group_pol);
1925 if (!NT_STATUS_IS_OK(result)) goto done;
1926
1927 if (strlen(opt_comment) == 0) goto done;
1928
1929 /* We've got a comment to set */
1930
1931 group_info.switch_value1 = 4;
1932 init_samr_group_info4(&group_info.group.info4, opt_comment);
1933
1934 result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &group_info);
1935 if (!NT_STATUS_IS_OK(result)) goto done;
1936
1937 done:
1938 if (NT_STATUS_IS_OK(result))
1939 DEBUG(5, ("add group succeeded\n"));
1940 else
1941 d_fprintf(stderr, "add group failed: %s\n", nt_errstr(result));
1942
1943 return result;
1944}
1945
1946static NTSTATUS rpc_alias_add_internals(const DOM_SID *domain_sid,
1947 const char *domain_name,
1948 struct cli_state *cli,
1949 struct rpc_pipe_client *pipe_hnd,
1950 TALLOC_CTX *mem_ctx,
1951 int argc,
1952 const char **argv)
1953{
1954 POLICY_HND connect_pol, domain_pol, alias_pol;
1955 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1956 ALIAS_INFO_CTR alias_info;
1957
1958 if (argc != 1) {
1959 d_printf("Alias name must be specified\n");
1960 rpc_group_usage(argc, argv);
1961 return NT_STATUS_OK;
1962 }
1963
1964 /* Get sam policy handle */
1965
1966 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1967 &connect_pol);
1968 if (!NT_STATUS_IS_OK(result)) goto done;
1969
1970 /* Get domain policy handle */
1971
1972 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1973 MAXIMUM_ALLOWED_ACCESS,
1974 domain_sid, &domain_pol);
1975 if (!NT_STATUS_IS_OK(result)) goto done;
1976
1977 /* Create the group */
1978
1979 result = rpccli_samr_create_dom_alias(pipe_hnd, mem_ctx, &domain_pol,
1980 argv[0], &alias_pol);
1981 if (!NT_STATUS_IS_OK(result)) goto done;
1982
1983 if (strlen(opt_comment) == 0) goto done;
1984
1985 /* We've got a comment to set */
1986
1987 alias_info.level = 3;
1988 init_samr_alias_info3(&alias_info.alias.info3, opt_comment);
1989
1990 result = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, &alias_pol, &alias_info);
1991 if (!NT_STATUS_IS_OK(result)) goto done;
1992
1993 done:
1994 if (NT_STATUS_IS_OK(result))
1995 DEBUG(5, ("add alias succeeded\n"));
1996 else
1997 d_fprintf(stderr, "add alias failed: %s\n", nt_errstr(result));
1998
1999 return result;
2000}
2001
2002static int rpc_group_add(int argc, const char **argv)
2003{
2004 if (opt_localgroup)
2005 return run_rpc_command(NULL, PI_SAMR, 0,
2006 rpc_alias_add_internals,
2007 argc, argv);
2008
2009 return run_rpc_command(NULL, PI_SAMR, 0,
2010 rpc_group_add_internals,
2011 argc, argv);
2012}
2013
2014static NTSTATUS get_sid_from_name(struct cli_state *cli,
2015 TALLOC_CTX *mem_ctx,
2016 const char *name,
2017 DOM_SID *sid,
2018 enum lsa_SidType *type)
2019{
2020 DOM_SID *sids = NULL;
2021 enum lsa_SidType *types = NULL;
2022 struct rpc_pipe_client *pipe_hnd;
2023 POLICY_HND lsa_pol;
2024 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2025
2026 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
2027 if (!pipe_hnd) {
2028 goto done;
2029 }
2030
2031 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False,
2032 SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2033
2034 if (!NT_STATUS_IS_OK(result)) {
2035 goto done;
2036 }
2037
2038 result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2039 &name, NULL, &sids, &types);
2040
2041 if (NT_STATUS_IS_OK(result)) {
2042 sid_copy(sid, &sids[0]);
2043 *type = types[0];
2044 }
2045
2046 rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
2047
2048 done:
2049 if (pipe_hnd) {
2050 cli_rpc_pipe_close(pipe_hnd);
2051 }
2052
2053 if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
2054
2055 /* Try as S-1-5-whatever */
2056
2057 DOM_SID tmp_sid;
2058
2059 if (string_to_sid(&tmp_sid, name)) {
2060 sid_copy(sid, &tmp_sid);
2061 *type = SID_NAME_UNKNOWN;
2062 result = NT_STATUS_OK;
2063 }
2064 }
2065
2066 return result;
2067}
2068
2069static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2070 TALLOC_CTX *mem_ctx,
2071 const DOM_SID *group_sid,
2072 const char *member)
2073{
2074 POLICY_HND connect_pol, domain_pol;
2075 NTSTATUS result;
2076 uint32 group_rid;
2077 POLICY_HND group_pol;
2078
2079 uint32 num_rids;
2080 uint32 *rids = NULL;
2081 uint32 *rid_types = NULL;
2082
2083 DOM_SID sid;
2084
2085 sid_copy(&sid, group_sid);
2086
2087 if (!sid_split_rid(&sid, &group_rid)) {
2088 return NT_STATUS_UNSUCCESSFUL;
2089 }
2090
2091 /* Get sam policy handle */
2092 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2093 &connect_pol);
2094 if (!NT_STATUS_IS_OK(result)) {
2095 return result;
2096 }
2097
2098 /* Get domain policy handle */
2099 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2100 MAXIMUM_ALLOWED_ACCESS,
2101 &sid, &domain_pol);
2102 if (!NT_STATUS_IS_OK(result)) {
2103 return result;
2104 }
2105
2106 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2107 1, &member,
2108 &num_rids, &rids, &rid_types);
2109
2110 if (!NT_STATUS_IS_OK(result)) {
2111 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2112 goto done;
2113 }
2114
2115 result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
2116 MAXIMUM_ALLOWED_ACCESS,
2117 group_rid, &group_pol);
2118
2119 if (!NT_STATUS_IS_OK(result)) {
2120 goto done;
2121 }
2122
2123 result = rpccli_samr_add_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
2124
2125 done:
2126 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2127 return result;
2128}
2129
2130static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2131 TALLOC_CTX *mem_ctx,
2132 const DOM_SID *alias_sid,
2133 const char *member)
2134{
2135 POLICY_HND connect_pol, domain_pol;
2136 NTSTATUS result;
2137 uint32 alias_rid;
2138 POLICY_HND alias_pol;
2139
2140 DOM_SID member_sid;
2141 enum lsa_SidType member_type;
2142
2143 DOM_SID sid;
2144
2145 sid_copy(&sid, alias_sid);
2146
2147 if (!sid_split_rid(&sid, &alias_rid)) {
2148 return NT_STATUS_UNSUCCESSFUL;
2149 }
2150
2151 result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
2152 &member_sid, &member_type);
2153
2154 if (!NT_STATUS_IS_OK(result)) {
2155 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2156 return result;
2157 }
2158
2159 /* Get sam policy handle */
2160 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2161 &connect_pol);
2162 if (!NT_STATUS_IS_OK(result)) {
2163 goto done;
2164 }
2165
2166 /* Get domain policy handle */
2167 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2168 MAXIMUM_ALLOWED_ACCESS,
2169 &sid, &domain_pol);
2170 if (!NT_STATUS_IS_OK(result)) {
2171 goto done;
2172 }
2173
2174 result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
2175 MAXIMUM_ALLOWED_ACCESS,
2176 alias_rid, &alias_pol);
2177
2178 if (!NT_STATUS_IS_OK(result)) {
2179 return result;
2180 }
2181
2182 result = rpccli_samr_add_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
2183
2184 if (!NT_STATUS_IS_OK(result)) {
2185 return result;
2186 }
2187
2188 done:
2189 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2190 return result;
2191}
2192
2193static NTSTATUS rpc_group_addmem_internals(const DOM_SID *domain_sid,
2194 const char *domain_name,
2195 struct cli_state *cli,
2196 struct rpc_pipe_client *pipe_hnd,
2197 TALLOC_CTX *mem_ctx,
2198 int argc,
2199 const char **argv)
2200{
2201 DOM_SID group_sid;
2202 enum lsa_SidType group_type;
2203
2204 if (argc != 2) {
2205 d_printf("Usage: 'net rpc group addmem <group> <member>\n");
2206 return NT_STATUS_UNSUCCESSFUL;
2207 }
2208
2209 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2210 &group_sid, &group_type))) {
2211 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2212 return NT_STATUS_UNSUCCESSFUL;
2213 }
2214
2215 if (group_type == SID_NAME_DOM_GRP) {
2216 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2217 &group_sid, argv[1]);
2218
2219 if (!NT_STATUS_IS_OK(result)) {
2220 d_fprintf(stderr, "Could not add %s to %s: %s\n",
2221 argv[1], argv[0], nt_errstr(result));
2222 }
2223 return result;
2224 }
2225
2226 if (group_type == SID_NAME_ALIAS) {
2227 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2228 &group_sid, argv[1]);
2229
2230 if (!NT_STATUS_IS_OK(result)) {
2231 d_fprintf(stderr, "Could not add %s to %s: %s\n",
2232 argv[1], argv[0], nt_errstr(result));
2233 }
2234 return result;
2235 }
2236
2237 d_fprintf(stderr, "Can only add members to global or local groups "
2238 "which %s is not\n", argv[0]);
2239
2240 return NT_STATUS_UNSUCCESSFUL;
2241}
2242
2243static int rpc_group_addmem(int argc, const char **argv)
2244{
2245 return run_rpc_command(NULL, PI_SAMR, 0,
2246 rpc_group_addmem_internals,
2247 argc, argv);
2248}
2249
2250static NTSTATUS rpc_del_groupmem(struct rpc_pipe_client *pipe_hnd,
2251 TALLOC_CTX *mem_ctx,
2252 const DOM_SID *group_sid,
2253 const char *member)
2254{
2255 POLICY_HND connect_pol, domain_pol;
2256 NTSTATUS result;
2257 uint32 group_rid;
2258 POLICY_HND group_pol;
2259
2260 uint32 num_rids;
2261 uint32 *rids = NULL;
2262 uint32 *rid_types = NULL;
2263
2264 DOM_SID sid;
2265
2266 sid_copy(&sid, group_sid);
2267
2268 if (!sid_split_rid(&sid, &group_rid))
2269 return NT_STATUS_UNSUCCESSFUL;
2270
2271 /* Get sam policy handle */
2272 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2273 &connect_pol);
2274 if (!NT_STATUS_IS_OK(result))
2275 return result;
2276
2277 /* Get domain policy handle */
2278 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2279 MAXIMUM_ALLOWED_ACCESS,
2280 &sid, &domain_pol);
2281 if (!NT_STATUS_IS_OK(result))
2282 return result;
2283
2284 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2285 1, &member,
2286 &num_rids, &rids, &rid_types);
2287
2288 if (!NT_STATUS_IS_OK(result)) {
2289 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2290 goto done;
2291 }
2292
2293 result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
2294 MAXIMUM_ALLOWED_ACCESS,
2295 group_rid, &group_pol);
2296
2297 if (!NT_STATUS_IS_OK(result))
2298 goto done;
2299
2300 result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
2301
2302 done:
2303 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2304 return result;
2305}
2306
2307static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2308 TALLOC_CTX *mem_ctx,
2309 const DOM_SID *alias_sid,
2310 const char *member)
2311{
2312 POLICY_HND connect_pol, domain_pol;
2313 NTSTATUS result;
2314 uint32 alias_rid;
2315 POLICY_HND alias_pol;
2316
2317 DOM_SID member_sid;
2318 enum lsa_SidType member_type;
2319
2320 DOM_SID sid;
2321
2322 sid_copy(&sid, alias_sid);
2323
2324 if (!sid_split_rid(&sid, &alias_rid))
2325 return NT_STATUS_UNSUCCESSFUL;
2326
2327 result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
2328 &member_sid, &member_type);
2329
2330 if (!NT_STATUS_IS_OK(result)) {
2331 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2332 return result;
2333 }
2334
2335 /* Get sam policy handle */
2336 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2337 &connect_pol);
2338 if (!NT_STATUS_IS_OK(result)) {
2339 goto done;
2340 }
2341
2342 /* Get domain policy handle */
2343 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2344 MAXIMUM_ALLOWED_ACCESS,
2345 &sid, &domain_pol);
2346 if (!NT_STATUS_IS_OK(result)) {
2347 goto done;
2348 }
2349
2350 result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
2351 MAXIMUM_ALLOWED_ACCESS,
2352 alias_rid, &alias_pol);
2353
2354 if (!NT_STATUS_IS_OK(result))
2355 return result;
2356
2357 result = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
2358
2359 if (!NT_STATUS_IS_OK(result))
2360 return result;
2361
2362 done:
2363 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2364 return result;
2365}
2366
2367static NTSTATUS rpc_group_delmem_internals(const DOM_SID *domain_sid,
2368 const char *domain_name,
2369 struct cli_state *cli,
2370 struct rpc_pipe_client *pipe_hnd,
2371 TALLOC_CTX *mem_ctx,
2372 int argc,
2373 const char **argv)
2374{
2375 DOM_SID group_sid;
2376 enum lsa_SidType group_type;
2377
2378 if (argc != 2) {
2379 d_printf("Usage: 'net rpc group delmem <group> <member>\n");
2380 return NT_STATUS_UNSUCCESSFUL;
2381 }
2382
2383 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2384 &group_sid, &group_type))) {
2385 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2386 return NT_STATUS_UNSUCCESSFUL;
2387 }
2388
2389 if (group_type == SID_NAME_DOM_GRP) {
2390 NTSTATUS result = rpc_del_groupmem(pipe_hnd, mem_ctx,
2391 &group_sid, argv[1]);
2392
2393 if (!NT_STATUS_IS_OK(result)) {
2394 d_fprintf(stderr, "Could not del %s from %s: %s\n",
2395 argv[1], argv[0], nt_errstr(result));
2396 }
2397 return result;
2398 }
2399
2400 if (group_type == SID_NAME_ALIAS) {
2401 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2402 &group_sid, argv[1]);
2403
2404 if (!NT_STATUS_IS_OK(result)) {
2405 d_fprintf(stderr, "Could not del %s from %s: %s\n",
2406 argv[1], argv[0], nt_errstr(result));
2407 }
2408 return result;
2409 }
2410
2411 d_fprintf(stderr, "Can only delete members from global or local groups "
2412 "which %s is not\n", argv[0]);
2413
2414 return NT_STATUS_UNSUCCESSFUL;
2415}
2416
2417static int rpc_group_delmem(int argc, const char **argv)
2418{
2419 return run_rpc_command(NULL, PI_SAMR, 0,
2420 rpc_group_delmem_internals,
2421 argc, argv);
2422}
2423
2424/**
2425 * List groups on a remote RPC server
2426 *
2427 * All parameters are provided by the run_rpc_command function, except for
2428 * argc, argv which are passes through.
2429 *
2430 * @param domain_sid The domain sid acquired from the remote server
2431 * @param cli A cli_state connected to the server.
2432 * @param mem_ctx Talloc context, destoyed on completion of the function.
2433 * @param argc Standard main() style argc
2434 * @param argv Standard main() style argv. Initial components are already
2435 * stripped
2436 *
2437 * @return Normal NTSTATUS return.
2438 **/
2439
2440static NTSTATUS rpc_group_list_internals(const DOM_SID *domain_sid,
2441 const char *domain_name,
2442 struct cli_state *cli,
2443 struct rpc_pipe_client *pipe_hnd,
2444 TALLOC_CTX *mem_ctx,
2445 int argc,
2446 const char **argv)
2447{
2448 POLICY_HND connect_pol, domain_pol;
2449 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2450 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2451 struct acct_info *groups;
2452 BOOL global = False;
2453 BOOL local = False;
2454 BOOL builtin = False;
2455
2456 if (argc == 0) {
2457 global = True;
2458 local = True;
2459 builtin = True;
2460 }
2461
2462 for (i=0; i<argc; i++) {
2463 if (strequal(argv[i], "global"))
2464 global = True;
2465
2466 if (strequal(argv[i], "local"))
2467 local = True;
2468
2469 if (strequal(argv[i], "builtin"))
2470 builtin = True;
2471 }
2472
2473 /* Get sam policy handle */
2474
2475 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2476 &connect_pol);
2477 if (!NT_STATUS_IS_OK(result)) {
2478 goto done;
2479 }
2480
2481 /* Get domain policy handle */
2482
2483 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2484 MAXIMUM_ALLOWED_ACCESS,
2485 domain_sid, &domain_pol);
2486 if (!NT_STATUS_IS_OK(result)) {
2487 goto done;
2488 }
2489
2490 /* Query domain groups */
2491 if (opt_long_list_entries)
2492 d_printf("\nGroup name Comment"\
2493 "\n-----------------------------\n");
2494 do {
2495 SAM_DISPINFO_CTR ctr;
2496 SAM_DISPINFO_3 info3;
2497 uint32 max_size;
2498
2499 ZERO_STRUCT(ctr);
2500 ZERO_STRUCT(info3);
2501 ctr.sam.info3 = &info3;
2502
2503 if (!global) break;
2504
2505 get_query_dispinfo_params(
2506 loop_count, &max_entries, &max_size);
2507
2508 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
2509 &start_idx, 3, &num_entries,
2510 max_entries, max_size, &ctr);
2511
2512 if (!NT_STATUS_IS_OK(result) &&
2513 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2514 break;
2515
2516 for (i = 0; i < num_entries; i++) {
2517
2518 fstring group, desc;
2519
2520 unistr2_to_ascii(group, &(&ctr.sam.info3->str[i])->uni_grp_name, sizeof(group)-1);
2521 unistr2_to_ascii(desc, &(&ctr.sam.info3->str[i])->uni_grp_desc, sizeof(desc)-1);
2522
2523 if (opt_long_list_entries)
2524 printf("%-21.21s %-50.50s\n",
2525 group, desc);
2526 else
2527 printf("%s\n", group);
2528 }
2529 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2530 /* query domain aliases */
2531 start_idx = 0;
2532 do {
2533 if (!local) break;
2534
2535 /* The max_size field in cli_samr_enum_als_groups is more like
2536 * an account_control field with indiviual bits what to
2537 * retrieve. Set this to 0xffff as NT4 usrmgr.exe does to get
2538 * everything. I'm too lazy (sorry) to get this through to
2539 * rpc_parse/ etc. Volker */
2540
2541 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2542 &start_idx, 0xffff,
2543 &groups, &num_entries);
2544
2545 if (!NT_STATUS_IS_OK(result) &&
2546 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2547 break;
2548
2549 for (i = 0; i < num_entries; i++) {
2550
2551 char *description = NULL;
2552
2553 if (opt_long_list_entries) {
2554
2555 POLICY_HND alias_pol;
2556 ALIAS_INFO_CTR ctr;
2557
2558 if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
2559 &domain_pol,
2560 0x8,
2561 groups[i].rid,
2562 &alias_pol))) &&
2563 (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
2564 &alias_pol, 3,
2565 &ctr))) &&
2566 (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
2567 &alias_pol)))) {
2568 description = unistr2_tdup(mem_ctx,
2569 ctr.alias.info3.description.string);
2570 }
2571 }
2572
2573 if (description != NULL) {
2574 printf("%-21.21s %-50.50s\n",
2575 groups[i].acct_name,
2576 description);
2577 } else {
2578 printf("%s\n", groups[i].acct_name);
2579 }
2580 }
2581 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2582 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
2583 /* Get builtin policy handle */
2584
2585 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2586 MAXIMUM_ALLOWED_ACCESS,
2587 &global_sid_Builtin, &domain_pol);
2588 if (!NT_STATUS_IS_OK(result)) {
2589 goto done;
2590 }
2591 /* query builtin aliases */
2592 start_idx = 0;
2593 do {
2594 if (!builtin) break;
2595
2596 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2597 &start_idx, max_entries,
2598 &groups, &num_entries);
2599
2600 if (!NT_STATUS_IS_OK(result) &&
2601 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2602 break;
2603
2604 for (i = 0; i < num_entries; i++) {
2605
2606 char *description = NULL;
2607
2608 if (opt_long_list_entries) {
2609
2610 POLICY_HND alias_pol;
2611 ALIAS_INFO_CTR ctr;
2612
2613 if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
2614 &domain_pol,
2615 0x8,
2616 groups[i].rid,
2617 &alias_pol))) &&
2618 (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
2619 &alias_pol, 3,
2620 &ctr))) &&
2621 (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
2622 &alias_pol)))) {
2623 description = unistr2_tdup(mem_ctx,
2624 ctr.alias.info3.description.string);
2625 }
2626 }
2627
2628 if (description != NULL) {
2629 printf("%-21.21s %-50.50s\n",
2630 groups[i].acct_name,
2631 description);
2632 } else {
2633 printf("%s\n", groups[i].acct_name);
2634 }
2635 }
2636 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2637
2638 done:
2639 return result;
2640}
2641
2642static int rpc_group_list(int argc, const char **argv)
2643{
2644 return run_rpc_command(NULL, PI_SAMR, 0,
2645 rpc_group_list_internals,
2646 argc, argv);
2647}
2648
2649static NTSTATUS rpc_list_group_members(struct rpc_pipe_client *pipe_hnd,
2650 TALLOC_CTX *mem_ctx,
2651 const char *domain_name,
2652 const DOM_SID *domain_sid,
2653 POLICY_HND *domain_pol,
2654 uint32 rid)
2655{
2656 NTSTATUS result;
2657 POLICY_HND group_pol;
2658 uint32 num_members, *group_rids, *group_attrs;
2659 uint32 num_names;
2660 char **names;
2661 uint32 *name_types;
2662 int i;
2663
2664 fstring sid_str;
2665 sid_to_string(sid_str, domain_sid);
2666
2667 result = rpccli_samr_open_group(pipe_hnd, mem_ctx, domain_pol,
2668 MAXIMUM_ALLOWED_ACCESS,
2669 rid, &group_pol);
2670
2671 if (!NT_STATUS_IS_OK(result))
2672 return result;
2673
2674 result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
2675 &num_members, &group_rids,
2676 &group_attrs);
2677
2678 if (!NT_STATUS_IS_OK(result))
2679 return result;
2680
2681 while (num_members > 0) {
2682 int this_time = 512;
2683
2684 if (num_members < this_time)
2685 this_time = num_members;
2686
2687 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, domain_pol,
2688 this_time, group_rids,
2689 &num_names, &names, &name_types);
2690
2691 if (!NT_STATUS_IS_OK(result))
2692 return result;
2693
2694 /* We only have users as members, but make the output
2695 the same as the output of alias members */
2696
2697 for (i = 0; i < this_time; i++) {
2698
2699 if (opt_long_list_entries) {
2700 printf("%s-%d %s\\%s %d\n", sid_str,
2701 group_rids[i], domain_name, names[i],
2702 SID_NAME_USER);
2703 } else {
2704 printf("%s\\%s\n", domain_name, names[i]);
2705 }
2706 }
2707
2708 num_members -= this_time;
2709 group_rids += 512;
2710 }
2711
2712 return NT_STATUS_OK;
2713}
2714
2715static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
2716 TALLOC_CTX *mem_ctx,
2717 POLICY_HND *domain_pol,
2718 uint32 rid)
2719{
2720 NTSTATUS result;
2721 struct rpc_pipe_client *lsa_pipe;
2722 POLICY_HND alias_pol, lsa_pol;
2723 uint32 num_members;
2724 DOM_SID *alias_sids;
2725 char **domains;
2726 char **names;
2727 enum lsa_SidType *types;
2728 int i;
2729
2730 result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, domain_pol,
2731 MAXIMUM_ALLOWED_ACCESS, rid, &alias_pol);
2732
2733 if (!NT_STATUS_IS_OK(result))
2734 return result;
2735
2736 result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, &alias_pol,
2737 &num_members, &alias_sids);
2738
2739 if (!NT_STATUS_IS_OK(result)) {
2740 d_fprintf(stderr, "Couldn't list alias members\n");
2741 return result;
2742 }
2743
2744 if (num_members == 0) {
2745 return NT_STATUS_OK;
2746 }
2747
2748 lsa_pipe = cli_rpc_pipe_open_noauth(pipe_hnd->cli, PI_LSARPC, &result);
2749 if (!lsa_pipe) {
2750 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
2751 nt_errstr(result) );
2752 return result;
2753 }
2754
2755 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
2756 SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2757
2758 if (!NT_STATUS_IS_OK(result)) {
2759 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
2760 cli_rpc_pipe_close(lsa_pipe);
2761 return result;
2762 }
2763
2764 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol, num_members,
2765 alias_sids,
2766 &domains, &names, &types);
2767
2768 if (!NT_STATUS_IS_OK(result) &&
2769 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2770 d_fprintf(stderr, "Couldn't lookup SIDs\n");
2771 cli_rpc_pipe_close(lsa_pipe);
2772 return result;
2773 }
2774
2775 for (i = 0; i < num_members; i++) {
2776 fstring sid_str;
2777 sid_to_string(sid_str, &alias_sids[i]);
2778
2779 if (opt_long_list_entries) {
2780 printf("%s %s\\%s %d\n", sid_str,
2781 domains[i] ? domains[i] : "*unknown*",
2782 names[i] ? names[i] : "*unknown*", types[i]);
2783 } else {
2784 if (domains[i])
2785 printf("%s\\%s\n", domains[i], names[i]);
2786 else
2787 printf("%s\n", sid_str);
2788 }
2789 }
2790
2791 cli_rpc_pipe_close(lsa_pipe);
2792 return NT_STATUS_OK;
2793}
2794
2795static NTSTATUS rpc_group_members_internals(const DOM_SID *domain_sid,
2796 const char *domain_name,
2797 struct cli_state *cli,
2798 struct rpc_pipe_client *pipe_hnd,
2799 TALLOC_CTX *mem_ctx,
2800 int argc,
2801 const char **argv)
2802{
2803 NTSTATUS result;
2804 POLICY_HND connect_pol, domain_pol;
2805 uint32 num_rids, *rids, *rid_types;
2806
2807 /* Get sam policy handle */
2808
2809 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2810 &connect_pol);
2811
2812 if (!NT_STATUS_IS_OK(result))
2813 return result;
2814
2815 /* Get domain policy handle */
2816
2817 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2818 MAXIMUM_ALLOWED_ACCESS,
2819 domain_sid, &domain_pol);
2820
2821 if (!NT_STATUS_IS_OK(result))
2822 return result;
2823
2824 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2825 1, argv, &num_rids, &rids, &rid_types);
2826
2827 if (!NT_STATUS_IS_OK(result)) {
2828
2829 /* Ok, did not find it in the global sam, try with builtin */
2830
2831 DOM_SID sid_Builtin;
2832
2833 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
2834
2835 string_to_sid(&sid_Builtin, "S-1-5-32");
2836
2837 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2838 MAXIMUM_ALLOWED_ACCESS,
2839 &sid_Builtin, &domain_pol);
2840
2841 if (!NT_STATUS_IS_OK(result)) {
2842 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2843 return result;
2844 }
2845
2846 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2847 1, argv, &num_rids,
2848 &rids, &rid_types);
2849
2850 if (!NT_STATUS_IS_OK(result)) {
2851 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2852 return result;
2853 }
2854 }
2855
2856 if (num_rids != 1) {
2857 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2858 return result;
2859 }
2860
2861 if (rid_types[0] == SID_NAME_DOM_GRP) {
2862 return rpc_list_group_members(pipe_hnd, mem_ctx, domain_name,
2863 domain_sid, &domain_pol,
2864 rids[0]);
2865 }
2866
2867 if (rid_types[0] == SID_NAME_ALIAS) {
2868 return rpc_list_alias_members(pipe_hnd, mem_ctx, &domain_pol,
2869 rids[0]);
2870 }
2871
2872 return NT_STATUS_NO_SUCH_GROUP;
2873}
2874
2875static int rpc_group_members(int argc, const char **argv)
2876{
2877 if (argc != 1) {
2878 return rpc_group_usage(argc, argv);
2879 }
2880
2881 return run_rpc_command(NULL, PI_SAMR, 0,
2882 rpc_group_members_internals,
2883 argc, argv);
2884}
2885
2886static NTSTATUS rpc_group_rename_internals(const DOM_SID *domain_sid,
2887 const char *domain_name,
2888 struct cli_state *cli,
2889 struct rpc_pipe_client *pipe_hnd,
2890 TALLOC_CTX *mem_ctx,
2891 int argc,
2892 const char **argv)
2893{
2894 NTSTATUS result;
2895 POLICY_HND connect_pol, domain_pol, group_pol;
2896 uint32 num_rids, *rids, *rid_types;
2897 GROUP_INFO_CTR ctr;
2898
2899 if (argc != 2) {
2900 d_printf("Usage: 'net rpc group rename group newname'\n");
2901 return NT_STATUS_UNSUCCESSFUL;
2902 }
2903
2904 /* Get sam policy handle */
2905
2906 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2907 &connect_pol);
2908
2909 if (!NT_STATUS_IS_OK(result))
2910 return result;
2911
2912 /* Get domain policy handle */
2913
2914 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2915 MAXIMUM_ALLOWED_ACCESS,
2916 domain_sid, &domain_pol);
2917
2918 if (!NT_STATUS_IS_OK(result))
2919 return result;
2920
2921 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2922 1, argv, &num_rids, &rids, &rid_types);
2923
2924 if (num_rids != 1) {
2925 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2926 return result;
2927 }
2928
2929 if (rid_types[0] != SID_NAME_DOM_GRP) {
2930 d_fprintf(stderr, "Can only rename domain groups\n");
2931 return NT_STATUS_UNSUCCESSFUL;
2932 }
2933
2934 result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
2935 MAXIMUM_ALLOWED_ACCESS,
2936 rids[0], &group_pol);
2937
2938 if (!NT_STATUS_IS_OK(result))
2939 return result;
2940
2941 ZERO_STRUCT(ctr);
2942
2943 ctr.switch_value1 = 2;
2944 init_samr_group_info2(&ctr.group.info2, argv[1]);
2945
2946 result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &ctr);
2947
2948 if (!NT_STATUS_IS_OK(result))
2949 return result;
2950
2951 return NT_STATUS_NO_SUCH_GROUP;
2952}
2953
2954static int rpc_group_rename(int argc, const char **argv)
2955{
2956 if (argc != 2) {
2957 return rpc_group_usage(argc, argv);
2958 }
2959
2960 return run_rpc_command(NULL, PI_SAMR, 0,
2961 rpc_group_rename_internals,
2962 argc, argv);
2963}
2964
2965/**
2966 * 'net rpc group' entrypoint.
2967 * @param argc Standard main() style argc
2968 * @param argc Standard main() style argv. Initial components are already
2969 * stripped
2970 **/
2971
2972int net_rpc_group(int argc, const char **argv)
2973{
2974 struct functable func[] = {
2975 {"add", rpc_group_add},
2976 {"delete", rpc_group_delete},
2977 {"addmem", rpc_group_addmem},
2978 {"delmem", rpc_group_delmem},
2979 {"list", rpc_group_list},
2980 {"members", rpc_group_members},
2981 {"rename", rpc_group_rename},
2982 {NULL, NULL}
2983 };
2984
2985 if (argc == 0) {
2986 return run_rpc_command(NULL, PI_SAMR, 0,
2987 rpc_group_list_internals,
2988 argc, argv);
2989 }
2990
2991 return net_run_function(argc, argv, func, rpc_group_usage);
2992}
2993
2994/****************************************************************************/
2995
2996static int rpc_share_usage(int argc, const char **argv)
2997{
2998 return net_help_share(argc, argv);
2999}
3000
3001/**
3002 * Add a share on a remote RPC server
3003 *
3004 * All parameters are provided by the run_rpc_command function, except for
3005 * argc, argv which are passes through.
3006 *
3007 * @param domain_sid The domain sid acquired from the remote server
3008 * @param cli A cli_state connected to the server.
3009 * @param mem_ctx Talloc context, destoyed on completion of the function.
3010 * @param argc Standard main() style argc
3011 * @param argv Standard main() style argv. Initial components are already
3012 * stripped
3013 *
3014 * @return Normal NTSTATUS return.
3015 **/
3016static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid,
3017 const char *domain_name,
3018 struct cli_state *cli,
3019 struct rpc_pipe_client *pipe_hnd,
3020 TALLOC_CTX *mem_ctx,int argc,
3021 const char **argv)
3022{
3023 WERROR result;
3024 char *sharename;
3025 char *path;
3026 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3027 uint32 num_users=0, perms=0;
3028 char *password=NULL; /* don't allow a share password */
3029 uint32 level = 2;
3030
3031 if ((sharename = talloc_strdup(mem_ctx, argv[0])) == NULL) {
3032 return NT_STATUS_NO_MEMORY;
3033 }
3034
3035 path = strchr(sharename, '=');
3036 if (!path)
3037 return NT_STATUS_UNSUCCESSFUL;
3038 *path++ = '\0';
3039
3040 result = rpccli_srvsvc_net_share_add(pipe_hnd, mem_ctx, sharename, type,
3041 opt_comment, perms, opt_maxusers,
3042 num_users, path, password,
3043 level, NULL);
3044 return werror_to_ntstatus(result);
3045}
3046
3047static int rpc_share_add(int argc, const char **argv)
3048{
3049 if ((argc < 1) || !strchr(argv[0], '=')) {
3050 DEBUG(1,("Sharename or path not specified on add\n"));
3051 return rpc_share_usage(argc, argv);
3052 }
3053 return run_rpc_command(NULL, PI_SRVSVC, 0,
3054 rpc_share_add_internals,
3055 argc, argv);
3056}
3057
3058/**
3059 * Delete a share on a remote RPC server
3060 *
3061 * All parameters are provided by the run_rpc_command function, except for
3062 * argc, argv which are passes through.
3063 *
3064 * @param domain_sid The domain sid acquired from the remote server
3065 * @param cli A cli_state connected to the server.
3066 * @param mem_ctx Talloc context, destoyed on completion of the function.
3067 * @param argc Standard main() style argc
3068 * @param argv Standard main() style argv. Initial components are already
3069 * stripped
3070 *
3071 * @return Normal NTSTATUS return.
3072 **/
3073static NTSTATUS rpc_share_del_internals(const DOM_SID *domain_sid,
3074 const char *domain_name,
3075 struct cli_state *cli,
3076 struct rpc_pipe_client *pipe_hnd,
3077 TALLOC_CTX *mem_ctx,
3078 int argc,
3079 const char **argv)
3080{
3081 WERROR result;
3082
3083 result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
3084 return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3085}
3086
3087/**
3088 * Delete a share on a remote RPC server
3089 *
3090 * @param domain_sid The domain sid acquired from the remote server
3091 * @param argc Standard main() style argc
3092 * @param argv Standard main() style argv. Initial components are already
3093 * stripped
3094 *
3095 * @return A shell status integer (0 for success)
3096 **/
3097static int rpc_share_delete(int argc, const char **argv)
3098{
3099 if (argc < 1) {
3100 DEBUG(1,("Sharename not specified on delete\n"));
3101 return rpc_share_usage(argc, argv);
3102 }
3103 return run_rpc_command(NULL, PI_SRVSVC, 0,
3104 rpc_share_del_internals,
3105 argc, argv);
3106}
3107
3108/**
3109 * Formatted print of share info
3110 *
3111 * @param info1 pointer to SRV_SHARE_INFO_1 to format
3112 **/
3113
3114static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
3115{
3116 fstring netname = "", remark = "";
3117
3118 rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
3119 rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
3120
3121 if (opt_long_list_entries) {
3122 d_printf("%-12s %-8.8s %-50s\n",
3123 netname, share_type[info1->info_1.type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)], remark);
3124 } else {
3125 d_printf("%s\n", netname);
3126 }
3127
3128}
3129
3130static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd,
3131 TALLOC_CTX *mem_ctx,
3132 uint32 level,
3133 int argc,
3134 const char **argv,
3135 SRV_SHARE_INFO_CTR *ctr)
3136{
3137 WERROR result;
3138 SRV_SHARE_INFO info;
3139
3140 /* no specific share requested, enumerate all */
3141 if (argc == 0) {
3142
3143 ENUM_HND hnd;
3144 uint32 preferred_len = 0xffffffff;
3145
3146 init_enum_hnd(&hnd, 0);
3147
3148 return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr,
3149 preferred_len, &hnd);
3150 }
3151
3152 /* request just one share */
3153 result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info);
3154
3155 if (!W_ERROR_IS_OK(result))
3156 goto done;
3157
3158 /* construct ctr */
3159 ZERO_STRUCTP(ctr);
3160
3161 ctr->info_level = ctr->switch_value = level;
3162 ctr->ptr_share_info = ctr->ptr_entries = 1;
3163 ctr->num_entries = ctr->num_entries2 = 1;
3164
3165 switch (level) {
3166 case 1:
3167 {
3168 char *s;
3169 SRV_SHARE_INFO_1 *info1;
3170
3171 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
3172 if (ctr->share.info1 == NULL) {
3173 result = WERR_NOMEM;
3174 goto done;
3175 }
3176 info1 = ctr->share.info1;
3177
3178 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
3179
3180 /* Copy pointer crap */
3181
3182 memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
3183
3184 /* Duplicate strings */
3185
3186 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_netname);
3187 if (s)
3188 init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
3189
3190 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_remark);
3191 if (s)
3192 init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
3193 }
3194 case 2:
3195 {
3196 char *s;
3197 SRV_SHARE_INFO_2 *info2;
3198
3199 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
3200 if (ctr->share.info2 == NULL) {
3201 result = WERR_NOMEM;
3202 goto done;
3203 }
3204 info2 = ctr->share.info2;
3205
3206 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
3207
3208 /* Copy pointer crap */
3209
3210 memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
3211
3212 /* Duplicate strings */
3213
3214 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_netname);
3215 if (s)
3216 init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
3217
3218 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_remark);
3219 if (s)
3220 init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
3221
3222 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_path);
3223 if (s)
3224 init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
3225
3226 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
3227 if (s)
3228 init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
3229 }
3230 case 502:
3231 {
3232 char *s;
3233 SRV_SHARE_INFO_502 *info502;
3234
3235 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
3236 if (ctr->share.info502 == NULL) {
3237 result = WERR_NOMEM;
3238 goto done;
3239 }
3240 info502 = ctr->share.info502;
3241
3242 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
3243
3244 /* Copy pointer crap */
3245
3246 memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
3247
3248 /* Duplicate strings */
3249
3250 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_netname);
3251 if (s)
3252 init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
3253
3254 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_remark);
3255 if (s)
3256 init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
3257
3258 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_path);
3259 if (s)
3260 init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
3261
3262 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
3263 if (s)
3264 init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
3265
3266 info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
3267
3268 }
3269
3270 } /* switch */
3271
3272done:
3273 return result;
3274}
3275
3276/**
3277 * List shares on a remote RPC server
3278 *
3279 * All parameters are provided by the run_rpc_command function, except for
3280 * argc, argv which are passes through.
3281 *
3282 * @param domain_sid The domain sid acquired from the remote server
3283 * @param cli A cli_state connected to the server.
3284 * @param mem_ctx Talloc context, destoyed on completion of the function.
3285 * @param argc Standard main() style argc
3286 * @param argv Standard main() style argv. Initial components are already
3287 * stripped
3288 *
3289 * @return Normal NTSTATUS return.
3290 **/
3291
3292static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid,
3293 const char *domain_name,
3294 struct cli_state *cli,
3295 struct rpc_pipe_client *pipe_hnd,
3296 TALLOC_CTX *mem_ctx,
3297 int argc,
3298 const char **argv)
3299{
3300 SRV_SHARE_INFO_CTR ctr;
3301 WERROR result;
3302 uint32 i, level = 1;
3303
3304 result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr);
3305 if (!W_ERROR_IS_OK(result))
3306 goto done;
3307
3308 /* Display results */
3309
3310 if (opt_long_list_entries) {
3311 d_printf(
3312 "\nEnumerating shared resources (exports) on remote server:\n\n"\
3313 "\nShare name Type Description\n"\
3314 "---------- ---- -----------\n");
3315 }
3316 for (i = 0; i < ctr.num_entries; i++)
3317 display_share_info_1(&ctr.share.info1[i]);
3318 done:
3319 return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3320}
3321
3322/***
3323 * 'net rpc share list' entrypoint.
3324 * @param argc Standard main() style argc
3325 * @param argv Standard main() style argv. Initial components are already
3326 * stripped
3327 **/
3328static int rpc_share_list(int argc, const char **argv)
3329{
3330 return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
3331}
3332
3333static BOOL check_share_availability(struct cli_state *cli, const char *netname)
3334{
3335 if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3336 d_printf("skipping [%s]: not a file share.\n", netname);
3337 return False;
3338 }
3339
3340 if (!cli_tdis(cli))
3341 return False;
3342
3343 return True;
3344}
3345
3346static BOOL check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
3347{
3348 /* only support disk shares */
3349 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3350 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3351 return False;
3352 }
3353
3354 /* skip builtin shares */
3355 /* FIXME: should print$ be added too ? */
3356 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3357 strequal(netname,"global"))
3358 return False;
3359
3360 if (opt_exclude && in_list(netname, opt_exclude, False)) {
3361 printf("excluding [%s]\n", netname);
3362 return False;
3363 }
3364
3365 return check_share_availability(cli, netname);
3366}
3367
3368/**
3369 * Migrate shares from a remote RPC server to the local RPC srever
3370 *
3371 * All parameters are provided by the run_rpc_command function, except for
3372 * argc, argv which are passes through.
3373 *
3374 * @param domain_sid The domain sid acquired from the remote server
3375 * @param cli A cli_state connected to the server.
3376 * @param mem_ctx Talloc context, destoyed on completion of the function.
3377 * @param argc Standard main() style argc
3378 * @param argv Standard main() style argv. Initial components are already
3379 * stripped
3380 *
3381 * @return Normal NTSTATUS return.
3382 **/
3383
3384static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid,
3385 const char *domain_name,
3386 struct cli_state *cli,
3387 struct rpc_pipe_client *pipe_hnd,
3388 TALLOC_CTX *mem_ctx,
3389 int argc,
3390 const char **argv)
3391{
3392 WERROR result;
3393 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3394 SRV_SHARE_INFO_CTR ctr_src;
3395 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3396 char *password = NULL; /* don't allow a share password */
3397 uint32 i;
3398 struct rpc_pipe_client *srvsvc_pipe = NULL;
3399 struct cli_state *cli_dst = NULL;
3400 uint32 level = 502; /* includes secdesc */
3401
3402 result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3403 if (!W_ERROR_IS_OK(result))
3404 goto done;
3405
3406 /* connect destination PI_SRVSVC */
3407 nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3408 if (!NT_STATUS_IS_OK(nt_status))
3409 return nt_status;
3410
3411
3412 for (i = 0; i < ctr_src.num_entries; i++) {
3413
3414 fstring netname = "", remark = "", path = "";
3415 /* reset error-code */
3416 nt_status = NT_STATUS_UNSUCCESSFUL;
3417
3418 rpcstr_pull_unistr2_fstring(
3419 netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3420 rpcstr_pull_unistr2_fstring(
3421 remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3422 rpcstr_pull_unistr2_fstring(
3423 path, &ctr_src.share.info502[i].info_502_str.uni_path);
3424
3425 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3426 continue;
3427
3428 /* finally add the share on the dst server */
3429
3430 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n",
3431 netname, path, remark);
3432
3433 result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark,
3434 ctr_src.share.info502[i].info_502.perms,
3435 ctr_src.share.info502[i].info_502.max_uses,
3436 ctr_src.share.info502[i].info_502.num_uses,
3437 path, password, level,
3438 NULL);
3439
3440 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
3441 printf(" [%s] does already exist\n", netname);
3442 continue;
3443 }
3444
3445 if (!W_ERROR_IS_OK(result)) {
3446 printf("cannot add share: %s\n", dos_errstr(result));
3447 goto done;
3448 }
3449
3450 }
3451
3452 nt_status = NT_STATUS_OK;
3453
3454done:
3455 if (cli_dst) {
3456 cli_shutdown(cli_dst);
3457 }
3458
3459 return nt_status;
3460
3461}
3462
3463/**
3464 * Migrate shares from a rpc-server to another
3465 *
3466 * @param argc Standard main() style argc
3467 * @param argv Standard main() style argv. Initial components are already
3468 * stripped
3469 *
3470 * @return A shell status integer (0 for success)
3471 **/
3472static int rpc_share_migrate_shares(int argc, const char **argv)
3473{
3474
3475 if (!opt_host) {
3476 printf("no server to migrate\n");
3477 return -1;
3478 }
3479
3480 return run_rpc_command(NULL, PI_SRVSVC, 0,
3481 rpc_share_migrate_shares_internals,
3482 argc, argv);
3483}
3484
3485/**
3486 * Copy a file/dir
3487 *
3488 * @param f file_info
3489 * @param mask current search mask
3490 * @param state arg-pointer
3491 *
3492 **/
3493static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
3494{
3495 static NTSTATUS nt_status;
3496 static struct copy_clistate *local_state;
3497 static fstring filename, new_mask;
3498 fstring dir;
3499 char *old_dir;
3500
3501 local_state = (struct copy_clistate *)state;
3502 nt_status = NT_STATUS_UNSUCCESSFUL;
3503
3504 if (strequal(f->name, ".") || strequal(f->name, ".."))
3505 return;
3506
3507 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3508
3509 /* DIRECTORY */
3510 if (f->mode & aDIR) {
3511
3512 DEBUG(3,("got dir: %s\n", f->name));
3513
3514 fstrcpy(dir, local_state->cwd);
3515 fstrcat(dir, "\\");
3516 fstrcat(dir, f->name);
3517
3518 switch (net_mode_share)
3519 {
3520 case NET_MODE_SHARE_MIGRATE:
3521 /* create that directory */
3522 nt_status = net_copy_file(local_state->mem_ctx,
3523 local_state->cli_share_src,
3524 local_state->cli_share_dst,
3525 dir, dir,
3526 opt_acls? True : False,
3527 opt_attrs? True : False,
3528 opt_timestamps? True : False,
3529 False);
3530 break;
3531 default:
3532 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3533 return;
3534 }
3535
3536 if (!NT_STATUS_IS_OK(nt_status))
3537 printf("could not handle dir %s: %s\n",
3538 dir, nt_errstr(nt_status));
3539
3540 /* search below that directory */
3541 fstrcpy(new_mask, dir);
3542 fstrcat(new_mask, "\\*");
3543
3544 old_dir = local_state->cwd;
3545 local_state->cwd = dir;
3546 if (!sync_files(local_state, new_mask))
3547 printf("could not handle files\n");
3548 local_state->cwd = old_dir;
3549
3550 return;
3551 }
3552
3553
3554 /* FILE */
3555 fstrcpy(filename, local_state->cwd);
3556 fstrcat(filename, "\\");
3557 fstrcat(filename, f->name);
3558
3559 DEBUG(3,("got file: %s\n", filename));
3560
3561 switch (net_mode_share)
3562 {
3563 case NET_MODE_SHARE_MIGRATE:
3564 nt_status = net_copy_file(local_state->mem_ctx,
3565 local_state->cli_share_src,
3566 local_state->cli_share_dst,
3567 filename, filename,
3568 opt_acls? True : False,
3569 opt_attrs? True : False,
3570 opt_timestamps? True: False,
3571 True);
3572 break;
3573 default:
3574 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3575 return;
3576 }
3577
3578 if (!NT_STATUS_IS_OK(nt_status))
3579 printf("could not handle file %s: %s\n",
3580 filename, nt_errstr(nt_status));
3581
3582}
3583
3584/**
3585 * sync files, can be called recursivly to list files
3586 * and then call copy_fn for each file
3587 *
3588 * @param cp_clistate pointer to the copy_clistate we work with
3589 * @param mask the current search mask
3590 *
3591 * @return Boolean result
3592 **/
3593BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask)
3594{
3595 struct cli_state *targetcli;
3596 pstring targetpath;
3597
3598 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3599
3600 if ( !cli_resolve_path( "", cp_clistate->cli_share_src, mask, &targetcli, targetpath ) ) {
3601 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n",
3602 mask, cli_errstr(cp_clistate->cli_share_src));
3603 return False;
3604 }
3605
3606 if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3607 d_fprintf(stderr, "listing %s failed with error: %s\n",
3608 mask, cli_errstr(targetcli));
3609 return False;
3610 }
3611
3612 return True;
3613}
3614
3615
3616/**
3617 * Set the top level directory permissions before we do any further copies.
3618 * Should set up ACL inheritance.
3619 **/
3620
3621BOOL copy_top_level_perms(struct copy_clistate *cp_clistate,
3622 const char *sharename)
3623{
3624 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3625
3626 switch (net_mode_share) {
3627 case NET_MODE_SHARE_MIGRATE:
3628 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3629 nt_status = net_copy_fileattr(cp_clistate->mem_ctx,
3630 cp_clistate->cli_share_src,
3631 cp_clistate->cli_share_dst,
3632 "\\", "\\",
3633 opt_acls? True : False,
3634 opt_attrs? True : False,
3635 opt_timestamps? True: False,
3636 False);
3637 break;
3638 default:
3639 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3640 break;
3641 }
3642
3643 if (!NT_STATUS_IS_OK(nt_status)) {
3644 printf("Could handle directory attributes for top level directory of share %s. Error %s\n",
3645 sharename, nt_errstr(nt_status));
3646 return False;
3647 }
3648
3649 return True;
3650}
3651
3652/**
3653 * Sync all files inside a remote share to another share (over smb)
3654 *
3655 * All parameters are provided by the run_rpc_command function, except for
3656 * argc, argv which are passes through.
3657 *
3658 * @param domain_sid The domain sid acquired from the remote server
3659 * @param cli A cli_state connected to the server.
3660 * @param mem_ctx Talloc context, destoyed on completion of the function.
3661 * @param argc Standard main() style argc
3662 * @param argv Standard main() style argv. Initial components are already
3663 * stripped
3664 *
3665 * @return Normal NTSTATUS return.
3666 **/
3667
3668static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid,
3669 const char *domain_name,
3670 struct cli_state *cli,
3671 struct rpc_pipe_client *pipe_hnd,
3672 TALLOC_CTX *mem_ctx,
3673 int argc,
3674 const char **argv)
3675{
3676 WERROR result;
3677 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3678 SRV_SHARE_INFO_CTR ctr_src;
3679 uint32 i;
3680 uint32 level = 502;
3681 struct copy_clistate cp_clistate;
3682 BOOL got_src_share = False;
3683 BOOL got_dst_share = False;
3684 pstring mask = "\\*";
3685 char *dst = NULL;
3686
3687 dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
3688
3689 result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3690
3691 if (!W_ERROR_IS_OK(result))
3692 goto done;
3693
3694 for (i = 0; i < ctr_src.num_entries; i++) {
3695
3696 fstring netname = "";
3697
3698 rpcstr_pull_unistr2_fstring(
3699 netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3700
3701 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3702 continue;
3703
3704 /* one might not want to mirror whole discs :) */
3705 if (strequal(netname, "print$") || netname[1] == '$') {
3706 d_printf("skipping [%s]: builtin/hidden share\n", netname);
3707 continue;
3708 }
3709
3710 switch (net_mode_share)
3711 {
3712 case NET_MODE_SHARE_MIGRATE:
3713 printf("syncing");
3714 break;
3715 default:
3716 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3717 break;
3718 }
3719 printf(" [%s] files and directories %s ACLs, %s DOS Attributes %s\n",
3720 netname,
3721 opt_acls ? "including" : "without",
3722 opt_attrs ? "including" : "without",
3723 opt_timestamps ? "(preserving timestamps)" : "");
3724
3725 cp_clistate.mem_ctx = mem_ctx;
3726 cp_clistate.cli_share_src = NULL;
3727 cp_clistate.cli_share_dst = NULL;
3728 cp_clistate.cwd = NULL;
3729 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3730
3731 /* open share source */
3732 nt_status = connect_to_service(&cp_clistate.cli_share_src,
3733 &cli->dest_ip, cli->desthost,
3734 netname, "A:");
3735 if (!NT_STATUS_IS_OK(nt_status))
3736 goto done;
3737
3738 got_src_share = True;
3739
3740 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3741 /* open share destination */
3742 nt_status = connect_to_service(&cp_clistate.cli_share_dst,
3743 NULL, dst, netname, "A:");
3744 if (!NT_STATUS_IS_OK(nt_status))
3745 goto done;
3746
3747 got_dst_share = True;
3748 }
3749
3750 if (!copy_top_level_perms(&cp_clistate, netname)) {
3751 d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", netname);
3752 nt_status = NT_STATUS_UNSUCCESSFUL;
3753 goto done;
3754 }
3755
3756 if (!sync_files(&cp_clistate, mask)) {
3757 d_fprintf(stderr, "could not handle files for share: %s\n", netname);
3758 nt_status = NT_STATUS_UNSUCCESSFUL;
3759 goto done;
3760 }
3761 }
3762
3763 nt_status = NT_STATUS_OK;
3764
3765done:
3766
3767 if (got_src_share)
3768 cli_shutdown(cp_clistate.cli_share_src);
3769
3770 if (got_dst_share)
3771 cli_shutdown(cp_clistate.cli_share_dst);
3772
3773 return nt_status;
3774
3775}
3776
3777static int rpc_share_migrate_files(int argc, const char **argv)
3778{
3779
3780 if (!opt_host) {
3781 printf("no server to migrate\n");
3782 return -1;
3783 }
3784
3785 return run_rpc_command(NULL, PI_SRVSVC, 0,
3786 rpc_share_migrate_files_internals,
3787 argc, argv);
3788}
3789
3790/**
3791 * Migrate share-ACLs from a remote RPC server to the local RPC srever
3792 *
3793 * All parameters are provided by the run_rpc_command function, except for
3794 * argc, argv which are passes through.
3795 *
3796 * @param domain_sid The domain sid acquired from the remote server
3797 * @param cli A cli_state connected to the server.
3798 * @param mem_ctx Talloc context, destoyed on completion of the function.
3799 * @param argc Standard main() style argc
3800 * @param argv Standard main() style argv. Initial components are already
3801 * stripped
3802 *
3803 * @return Normal NTSTATUS return.
3804 **/
3805
3806static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid,
3807 const char *domain_name,
3808 struct cli_state *cli,
3809 struct rpc_pipe_client *pipe_hnd,
3810 TALLOC_CTX *mem_ctx,
3811 int argc,
3812 const char **argv)
3813{
3814 WERROR result;
3815 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3816 SRV_SHARE_INFO_CTR ctr_src;
3817 SRV_SHARE_INFO info;
3818 uint32 i;
3819 struct rpc_pipe_client *srvsvc_pipe = NULL;
3820 struct cli_state *cli_dst = NULL;
3821 uint32 level = 502; /* includes secdesc */
3822
3823 result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3824
3825 if (!W_ERROR_IS_OK(result))
3826 goto done;
3827
3828 /* connect destination PI_SRVSVC */
3829 nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3830 if (!NT_STATUS_IS_OK(nt_status))
3831 return nt_status;
3832
3833
3834 for (i = 0; i < ctr_src.num_entries; i++) {
3835
3836 fstring netname = "", remark = "", path = "";
3837 /* reset error-code */
3838 nt_status = NT_STATUS_UNSUCCESSFUL;
3839
3840 rpcstr_pull_unistr2_fstring(
3841 netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3842 rpcstr_pull_unistr2_fstring(
3843 remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3844 rpcstr_pull_unistr2_fstring(
3845 path, &ctr_src.share.info502[i].info_502_str.uni_path);
3846
3847 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3848 continue;
3849
3850 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n",
3851 netname, path, remark);
3852
3853 if (opt_verbose)
3854 display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
3855
3856 /* init info */
3857 ZERO_STRUCT(info);
3858
3859 info.switch_value = level;
3860 info.ptr_share_ctr = 1;
3861
3862 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3863 info.share.info502 = ctr_src.share.info502[i];
3864
3865 /* finally modify the share on the dst server */
3866 result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info);
3867
3868 if (!W_ERROR_IS_OK(result)) {
3869 printf("cannot set share-acl: %s\n", dos_errstr(result));
3870 goto done;
3871 }
3872
3873 }
3874
3875 nt_status = NT_STATUS_OK;
3876
3877done:
3878 if (cli_dst) {
3879 cli_shutdown(cli_dst);
3880 }
3881
3882 return nt_status;
3883
3884}
3885
3886/**
3887 * Migrate share-acls from a rpc-server to another
3888 *
3889 * @param argc Standard main() style argc
3890 * @param argv Standard main() style argv. Initial components are already
3891 * stripped
3892 *
3893 * @return A shell status integer (0 for success)
3894 **/
3895static int rpc_share_migrate_security(int argc, const char **argv)
3896{
3897
3898 if (!opt_host) {
3899 printf("no server to migrate\n");
3900 return -1;
3901 }
3902
3903 return run_rpc_command(NULL, PI_SRVSVC, 0,
3904 rpc_share_migrate_security_internals,
3905 argc, argv);
3906}
3907
3908/**
3909 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3910 * from one server to another
3911 *
3912 * @param argc Standard main() style argc
3913 * @param argv Standard main() style argv. Initial components are already
3914 * stripped
3915 *
3916 * @return A shell status integer (0 for success)
3917 *
3918 **/
3919static int rpc_share_migrate_all(int argc, const char **argv)
3920{
3921 int ret;
3922
3923 if (!opt_host) {
3924 printf("no server to migrate\n");
3925 return -1;
3926 }
3927
3928 /* order is important. we don't want to be locked out by the share-acl
3929 * before copying files - gd */
3930
3931 ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
3932 if (ret)
3933 return ret;
3934
3935 ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
3936 if (ret)
3937 return ret;
3938
3939 return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
3940}
3941
3942
3943/**
3944 * 'net rpc share migrate' entrypoint.
3945 * @param argc Standard main() style argc
3946 * @param argv Standard main() style argv. Initial components are already
3947 * stripped
3948 **/
3949static int rpc_share_migrate(int argc, const char **argv)
3950{
3951
3952 struct functable func[] = {
3953 {"all", rpc_share_migrate_all},
3954 {"files", rpc_share_migrate_files},
3955 {"help", rpc_share_usage},
3956 {"security", rpc_share_migrate_security},
3957 {"shares", rpc_share_migrate_shares},
3958 {NULL, NULL}
3959 };
3960
3961 net_mode_share = NET_MODE_SHARE_MIGRATE;
3962
3963 return net_run_function(argc, argv, func, rpc_share_usage);
3964}
3965
3966struct full_alias {
3967 DOM_SID sid;
3968 uint32 num_members;
3969 DOM_SID *members;
3970};
3971
3972static int num_server_aliases;
3973static struct full_alias *server_aliases;
3974
3975/*
3976 * Add an alias to the static list.
3977 */
3978static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3979{
3980 if (server_aliases == NULL)
3981 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3982
3983 server_aliases[num_server_aliases] = *alias;
3984 num_server_aliases += 1;
3985}
3986
3987/*
3988 * For a specific domain on the server, fetch all the aliases
3989 * and their members. Add all of them to the server_aliases.
3990 */
3991
3992static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
3993 TALLOC_CTX *mem_ctx,
3994 POLICY_HND *connect_pol,
3995 const DOM_SID *domain_sid)
3996{
3997 uint32 start_idx, max_entries, num_entries, i;
3998 struct acct_info *groups;
3999 NTSTATUS result;
4000 POLICY_HND domain_pol;
4001
4002 /* Get domain policy handle */
4003
4004 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, connect_pol,
4005 MAXIMUM_ALLOWED_ACCESS,
4006 domain_sid, &domain_pol);
4007 if (!NT_STATUS_IS_OK(result))
4008 return result;
4009
4010 start_idx = 0;
4011 max_entries = 250;
4012
4013 do {
4014 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
4015 &start_idx, max_entries,
4016 &groups, &num_entries);
4017
4018 for (i = 0; i < num_entries; i++) {
4019
4020 POLICY_HND alias_pol;
4021 struct full_alias alias;
4022 DOM_SID *members;
4023 int j;
4024
4025 result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
4026 MAXIMUM_ALLOWED_ACCESS,
4027 groups[i].rid,
4028 &alias_pol);
4029 if (!NT_STATUS_IS_OK(result))
4030 goto done;
4031
4032 result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx,
4033 &alias_pol,
4034 &alias.num_members,
4035 &members);
4036 if (!NT_STATUS_IS_OK(result))
4037 goto done;
4038
4039 result = rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol);
4040 if (!NT_STATUS_IS_OK(result))
4041 goto done;
4042
4043 alias.members = NULL;
4044
4045 if (alias.num_members > 0) {
4046 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
4047
4048 for (j = 0; j < alias.num_members; j++)
4049 sid_copy(&alias.members[j],
4050 &members[j]);
4051 }
4052
4053 sid_copy(&alias.sid, domain_sid);
4054 sid_append_rid(&alias.sid, groups[i].rid);
4055
4056 push_alias(mem_ctx, &alias);
4057 }
4058 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4059
4060 result = NT_STATUS_OK;
4061
4062 done:
4063 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
4064
4065 return result;
4066}
4067
4068/*
4069 * Dump server_aliases as names for debugging purposes.
4070 */
4071
4072static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid,
4073 const char *domain_name,
4074 struct cli_state *cli,
4075 struct rpc_pipe_client *pipe_hnd,
4076 TALLOC_CTX *mem_ctx,
4077 int argc,
4078 const char **argv)
4079{
4080 int i;
4081 NTSTATUS result;
4082 POLICY_HND lsa_pol;
4083
4084 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
4085 SEC_RIGHTS_MAXIMUM_ALLOWED,
4086 &lsa_pol);
4087 if (!NT_STATUS_IS_OK(result))
4088 return result;
4089
4090 for (i=0; i<num_server_aliases; i++) {
4091 char **names;
4092 char **domains;
4093 uint32 *types;
4094 int j;
4095
4096 struct full_alias *alias = &server_aliases[i];
4097
4098 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4099 &alias->sid,
4100 &domains, &names, &types);
4101 if (!NT_STATUS_IS_OK(result))
4102 continue;
4103
4104 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4105
4106 if (alias->num_members == 0) {
4107 DEBUG(1, ("\n"));
4108 continue;
4109 }
4110
4111 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4112 alias->num_members,
4113 alias->members,
4114 &domains, &names, &types);
4115
4116 if (!NT_STATUS_IS_OK(result) &&
4117 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4118 continue;
4119
4120 for (j=0; j<alias->num_members; j++)
4121 DEBUG(1, ("%s\\%s (%d); ",
4122 domains[j] ? domains[j] : "*unknown*",
4123 names[j] ? names[j] : "*unknown*",types[j]));
4124 DEBUG(1, ("\n"));
4125 }
4126
4127 rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
4128
4129 return NT_STATUS_OK;
4130}
4131
4132/*
4133 * Fetch a list of all server aliases and their members into
4134 * server_aliases.
4135 */
4136
4137static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid,
4138 const char *domain_name,
4139 struct cli_state *cli,
4140 struct rpc_pipe_client *pipe_hnd,
4141 TALLOC_CTX *mem_ctx,
4142 int argc,
4143 const char **argv)
4144{
4145 NTSTATUS result;
4146 POLICY_HND connect_pol;
4147
4148 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
4149 &connect_pol);
4150
4151 if (!NT_STATUS_IS_OK(result))
4152 goto done;
4153
4154 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4155 &global_sid_Builtin);
4156
4157 if (!NT_STATUS_IS_OK(result))
4158 goto done;
4159
4160 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4161 domain_sid);
4162
4163 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
4164 done:
4165 return result;
4166}
4167
4168static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4169{
4170 token->num_sids = 4;
4171
4172 token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4);
4173
4174 token->user_sids[0] = *user_sid;
4175 sid_copy(&token->user_sids[1], &global_sid_World);
4176 sid_copy(&token->user_sids[2], &global_sid_Network);
4177 sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4178}
4179
4180static void free_user_token(NT_USER_TOKEN *token)
4181{
4182 SAFE_FREE(token->user_sids);
4183}
4184
4185static BOOL is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
4186{
4187 int i;
4188
4189 for (i=0; i<token->num_sids; i++) {
4190 if (sid_compare(sid, &token->user_sids[i]) == 0)
4191 return True;
4192 }
4193 return False;
4194}
4195
4196static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4197{
4198 if (is_sid_in_token(token, sid))
4199 return;
4200
4201 token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4202 if (!token->user_sids) {
4203 return;
4204 }
4205
4206 sid_copy(&token->user_sids[token->num_sids], sid);
4207
4208 token->num_sids += 1;
4209}
4210
4211struct user_token {
4212 fstring name;
4213 NT_USER_TOKEN token;
4214};
4215
4216static void dump_user_token(struct user_token *token)
4217{
4218 int i;
4219
4220 d_printf("%s\n", token->name);
4221
4222 for (i=0; i<token->token.num_sids; i++) {
4223 d_printf(" %s\n", sid_string_static(&token->token.user_sids[i]));
4224 }
4225}
4226
4227static BOOL is_alias_member(DOM_SID *sid, struct full_alias *alias)
4228{
4229 int i;
4230
4231 for (i=0; i<alias->num_members; i++) {
4232 if (sid_compare(sid, &alias->members[i]) == 0)
4233 return True;
4234 }
4235
4236 return False;
4237}
4238
4239static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4240{
4241 int i;
4242
4243 for (i=0; i<num_server_aliases; i++) {
4244 if (is_alias_member(&sid, &server_aliases[i]))
4245 add_sid_to_token(token, &server_aliases[i].sid);
4246 }
4247}
4248
4249/*
4250 * We got a user token with all the SIDs we can know about without asking the
4251 * server directly. These are the user and domain group sids. All of these can
4252 * be members of aliases. So scan the list of aliases for each of the SIDs and
4253 * add them to the token.
4254 */
4255
4256static void collect_alias_memberships(NT_USER_TOKEN *token)
4257{
4258 int num_global_sids = token->num_sids;
4259 int i;
4260
4261 for (i=0; i<num_global_sids; i++) {
4262 collect_sid_memberships(token, token->user_sids[i]);
4263 }
4264}
4265
4266static BOOL get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4267{
4268 struct winbindd_request request;
4269 struct winbindd_response response;
4270 fstring full_name;
4271 NSS_STATUS result;
4272
4273 DOM_SID user_sid;
4274
4275 int i;
4276
4277 fstr_sprintf(full_name, "%s%c%s",
4278 domain, *lp_winbind_separator(), user);
4279
4280 /* First let's find out the user sid */
4281
4282 ZERO_STRUCT(request);
4283 ZERO_STRUCT(response);
4284
4285 fstrcpy(request.data.name.dom_name, domain);
4286 fstrcpy(request.data.name.name, user);
4287
4288 result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
4289
4290 if (result != NSS_STATUS_SUCCESS) {
4291 DEBUG(1, ("winbind could not find %s\n", full_name));
4292 return False;
4293 }
4294
4295 if (response.data.sid.type != SID_NAME_USER) {
4296 DEBUG(1, ("%s is not a user\n", full_name));
4297 return False;
4298 }
4299
4300 string_to_sid(&user_sid, response.data.sid.sid);
4301
4302 init_user_token(token, &user_sid);
4303
4304 /* And now the groups winbind knows about */
4305
4306 ZERO_STRUCT(response);
4307
4308 fstrcpy(request.data.username, full_name);
4309
4310 result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
4311
4312 if (result != NSS_STATUS_SUCCESS) {
4313 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
4314 return False;
4315 }
4316
4317 for (i = 0; i < response.data.num_entries; i++) {
4318 gid_t gid = ((gid_t *)response.extra_data.data)[i];
4319 DOM_SID sid;
4320
4321 struct winbindd_request sidrequest;
4322 struct winbindd_response sidresponse;
4323
4324 ZERO_STRUCT(sidrequest);
4325 ZERO_STRUCT(sidresponse);
4326
4327 sidrequest.data.gid = gid;
4328
4329 result = winbindd_request_response(WINBINDD_GID_TO_SID,
4330 &sidrequest, &sidresponse);
4331
4332 if (result != NSS_STATUS_SUCCESS) {
4333 DEBUG(1, ("winbind could not find SID of gid %d\n",
4334 gid));
4335 return False;
4336 }
4337
4338 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
4339
4340 string_to_sid(&sid, sidresponse.data.sid.sid);
4341 add_sid_to_token(token, &sid);
4342 }
4343
4344 SAFE_FREE(response.extra_data.data);
4345
4346 return True;
4347}
4348
4349/**
4350 * Get a list of all user tokens we want to look at
4351 **/
4352
4353static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
4354{
4355 struct winbindd_request request;
4356 struct winbindd_response response;
4357 const char *extra_data;
4358 fstring name;
4359 int i;
4360 struct user_token *result;
4361
4362 if (lp_winbind_use_default_domain() &&
4363 (opt_target_workgroup == NULL)) {
4364 d_fprintf(stderr, "winbind use default domain = yes set, "
4365 "please specify a workgroup\n");
4366 return False;
4367 }
4368
4369 /* Send request to winbind daemon */
4370
4371 ZERO_STRUCT(request);
4372 ZERO_STRUCT(response);
4373
4374 if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
4375 NSS_STATUS_SUCCESS)
4376 return False;
4377
4378 /* Look through extra data */
4379
4380 if (!response.extra_data.data)
4381 return False;
4382
4383 extra_data = (const char *)response.extra_data.data;
4384 *num_tokens = 0;
4385
4386 while(next_token(&extra_data, name, ",", sizeof(fstring))) {
4387 *num_tokens += 1;
4388 }
4389
4390 result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
4391
4392 if (result == NULL) {
4393 DEBUG(1, ("Could not malloc sid array\n"));
4394 return False;
4395 }
4396
4397 extra_data = (const char *)response.extra_data.data;
4398 i=0;
4399
4400 while(next_token(&extra_data, name, ",", sizeof(fstring))) {
4401
4402 fstring domain, user;
4403 char *p;
4404
4405 fstrcpy(result[i].name, name);
4406
4407 p = strchr(name, *lp_winbind_separator());
4408
4409 DEBUG(3, ("%s\n", name));
4410
4411 if (p == NULL) {
4412 fstrcpy(domain, opt_target_workgroup);
4413 fstrcpy(user, name);
4414 } else {
4415 *p++ = '\0';
4416 fstrcpy(domain, name);
4417 strupper_m(domain);
4418 fstrcpy(user, p);
4419 }
4420
4421 get_user_sids(domain, user, &(result[i].token));
4422 i+=1;
4423 }
4424
4425 SAFE_FREE(response.extra_data.data);
4426
4427 *user_tokens = result;
4428
4429 return True;
4430}
4431
4432static BOOL get_user_tokens_from_file(FILE *f,
4433 int *num_tokens,
4434 struct user_token **tokens)
4435{
4436 struct user_token *token = NULL;
4437
4438 while (!feof(f)) {
4439 fstring line;
4440
4441 if (fgets(line, sizeof(line)-1, f) == NULL) {
4442 return True;
4443 }
4444
4445 if (line[strlen(line)-1] == '\n')
4446 line[strlen(line)-1] = '\0';
4447
4448 if (line[0] == ' ') {
4449 /* We have a SID */
4450
4451 DOM_SID sid;
4452 string_to_sid(&sid, &line[1]);
4453
4454 if (token == NULL) {
4455 DEBUG(0, ("File does not begin with username"));
4456 return False;
4457 }
4458
4459 add_sid_to_token(&token->token, &sid);
4460 continue;
4461 }
4462
4463 /* And a new user... */
4464
4465 *num_tokens += 1;
4466 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4467 if (*tokens == NULL) {
4468 DEBUG(0, ("Could not realloc tokens\n"));
4469 return False;
4470 }
4471
4472 token = &((*tokens)[*num_tokens-1]);
4473
4474 fstrcpy(token->name, line);
4475 token->token.num_sids = 0;
4476 token->token.user_sids = NULL;
4477 continue;
4478 }
4479
4480 return False;
4481}
4482
4483
4484/*
4485 * Show the list of all users that have access to a share
4486 */
4487
4488static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4489 TALLOC_CTX *mem_ctx,
4490 const char *netname,
4491 int num_tokens,
4492 struct user_token *tokens)
4493{
4494 int fnum;
4495 SEC_DESC *share_sd = NULL;
4496 SEC_DESC *root_sd = NULL;
4497 struct cli_state *cli = pipe_hnd->cli;
4498 int i;
4499 SRV_SHARE_INFO info;
4500 WERROR result;
4501 uint16 cnum;
4502
4503 result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname,
4504 502, &info);
4505
4506 if (!W_ERROR_IS_OK(result)) {
4507 DEBUG(1, ("Coult not query secdesc for share %s\n",
4508 netname));
4509 return;
4510 }
4511
4512 share_sd = info.share.info502.info_502_str.sd;
4513 if (share_sd == NULL) {
4514 DEBUG(1, ("Got no secdesc for share %s\n",
4515 netname));
4516 }
4517
4518 cnum = cli->cnum;
4519
4520 if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4521 return;
4522 }
4523
4524 fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4525
4526 if (fnum != -1) {
4527 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4528 }
4529
4530 for (i=0; i<num_tokens; i++) {
4531 uint32 acc_granted;
4532 NTSTATUS status;
4533
4534 if (share_sd != NULL) {
4535 if (!se_access_check(share_sd, &tokens[i].token,
4536 1, &acc_granted, &status)) {
4537 DEBUG(1, ("Could not check share_sd for "
4538 "user %s\n",
4539 tokens[i].name));
4540 continue;
4541 }
4542
4543 if (!NT_STATUS_IS_OK(status))
4544 continue;
4545 }
4546
4547 if (root_sd == NULL) {
4548 d_printf(" %s\n", tokens[i].name);
4549 continue;
4550 }
4551
4552 if (!se_access_check(root_sd, &tokens[i].token,
4553 1, &acc_granted, &status)) {
4554 DEBUG(1, ("Could not check root_sd for user %s\n",
4555 tokens[i].name));
4556 continue;
4557 }
4558
4559 if (!NT_STATUS_IS_OK(status))
4560 continue;
4561
4562 d_printf(" %s\n", tokens[i].name);
4563 }
4564
4565 if (fnum != -1)
4566 cli_close(cli, fnum);
4567 cli_tdis(cli);
4568 cli->cnum = cnum;
4569
4570 return;
4571}
4572
4573struct share_list {
4574 int num_shares;
4575 char **shares;
4576};
4577
4578static void collect_share(const char *name, uint32 m,
4579 const char *comment, void *state)
4580{
4581 struct share_list *share_list = (struct share_list *)state;
4582
4583 if (m != STYPE_DISKTREE)
4584 return;
4585
4586 share_list->num_shares += 1;
4587 share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4588 if (!share_list->shares) {
4589 share_list->num_shares = 0;
4590 return;
4591 }
4592 share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4593}
4594
4595static void rpc_share_userlist_usage(void)
4596{
4597 return;
4598}
4599
4600/**
4601 * List shares on a remote RPC server, including the security descriptors
4602 *
4603 * All parameters are provided by the run_rpc_command function, except for
4604 * argc, argv which are passes through.
4605 *
4606 * @param domain_sid The domain sid acquired from the remote server
4607 * @param cli A cli_state connected to the server.
4608 * @param mem_ctx Talloc context, destoyed on completion of the function.
4609 * @param argc Standard main() style argc
4610 * @param argv Standard main() style argv. Initial components are already
4611 * stripped
4612 *
4613 * @return Normal NTSTATUS return.
4614 **/
4615
4616static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
4617 const char *domain_name,
4618 struct cli_state *cli,
4619 struct rpc_pipe_client *pipe_hnd,
4620 TALLOC_CTX *mem_ctx,
4621 int argc,
4622 const char **argv)
4623{
4624 int ret;
4625 BOOL r;
4626 ENUM_HND hnd;
4627 uint32 i;
4628 FILE *f;
4629
4630 struct user_token *tokens = NULL;
4631 int num_tokens = 0;
4632
4633 struct share_list share_list;
4634
4635 if (argc > 1) {
4636 rpc_share_userlist_usage();
4637 return NT_STATUS_UNSUCCESSFUL;
4638 }
4639
4640 if (argc == 0) {
4641 f = stdin;
4642 } else {
4643 f = fopen(argv[0], "r");
4644 }
4645
4646 if (f == NULL) {
4647 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4648 return NT_STATUS_UNSUCCESSFUL;
4649 }
4650
4651 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4652
4653 if (f != stdin)
4654 fclose(f);
4655
4656 if (!r) {
4657 DEBUG(0, ("Could not read users from file\n"));
4658 return NT_STATUS_UNSUCCESSFUL;
4659 }
4660
4661 for (i=0; i<num_tokens; i++)
4662 collect_alias_memberships(&tokens[i].token);
4663
4664 init_enum_hnd(&hnd, 0);
4665
4666 share_list.num_shares = 0;
4667 share_list.shares = NULL;
4668
4669 ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4670
4671 if (ret == -1) {
4672 DEBUG(0, ("Error returning browse list: %s\n",
4673 cli_errstr(cli)));
4674 goto done;
4675 }
4676
4677 for (i = 0; i < share_list.num_shares; i++) {
4678 char *netname = share_list.shares[i];
4679
4680 if (netname[strlen(netname)-1] == '$')
4681 continue;
4682
4683 d_printf("%s\n", netname);
4684
4685 show_userlist(pipe_hnd, mem_ctx, netname,
4686 num_tokens, tokens);
4687 }
4688 done:
4689 for (i=0; i<num_tokens; i++) {
4690 free_user_token(&tokens[i].token);
4691 }
4692 SAFE_FREE(tokens);
4693 SAFE_FREE(share_list.shares);
4694
4695 return NT_STATUS_OK;
4696}
4697
4698static int rpc_share_allowedusers(int argc, const char **argv)
4699{
4700 int result;
4701
4702 result = run_rpc_command(NULL, PI_SAMR, 0,
4703 rpc_aliaslist_internals,
4704 argc, argv);
4705 if (result != 0)
4706 return result;
4707
4708 result = run_rpc_command(NULL, PI_LSARPC, 0,
4709 rpc_aliaslist_dump,
4710 argc, argv);
4711 if (result != 0)
4712 return result;
4713
4714 return run_rpc_command(NULL, PI_SRVSVC, 0,
4715 rpc_share_allowedusers_internals,
4716 argc, argv);
4717}
4718
4719int net_usersidlist(int argc, const char **argv)
4720{
4721 int num_tokens = 0;
4722 struct user_token *tokens = NULL;
4723 int i;
4724
4725 if (argc != 0) {
4726 net_usersidlist_usage(argc, argv);
4727 return 0;
4728 }
4729
4730 if (!get_user_tokens(&num_tokens, &tokens)) {
4731 DEBUG(0, ("Could not get the user/sid list\n"));
4732 return 0;
4733 }
4734
4735 for (i=0; i<num_tokens; i++) {
4736 dump_user_token(&tokens[i]);
4737 free_user_token(&tokens[i].token);
4738 }
4739
4740 SAFE_FREE(tokens);
4741 return 1;
4742}
4743
4744int net_usersidlist_usage(int argc, const char **argv)
4745{
4746 d_printf("net usersidlist\n"
4747 "\tprints out a list of all users the running winbind knows\n"
4748 "\tabout, together with all their SIDs. This is used as\n"
4749 "\tinput to the 'net rpc share allowedusers' command.\n\n");
4750
4751 net_common_flags_usage(argc, argv);
4752 return -1;
4753}
4754
4755/**
4756 * 'net rpc share' entrypoint.
4757 * @param argc Standard main() style argc
4758 * @param argv Standard main() style argv. Initial components are already
4759 * stripped
4760 **/
4761
4762int net_rpc_share(int argc, const char **argv)
4763{
4764 struct functable func[] = {
4765 {"add", rpc_share_add},
4766 {"delete", rpc_share_delete},
4767 {"allowedusers", rpc_share_allowedusers},
4768 {"migrate", rpc_share_migrate},
4769 {"list", rpc_share_list},
4770 {NULL, NULL}
4771 };
4772
4773 if (argc == 0)
4774 return run_rpc_command(NULL, PI_SRVSVC, 0,
4775 rpc_share_list_internals,
4776 argc, argv);
4777
4778 return net_run_function(argc, argv, func, rpc_share_usage);
4779}
4780
4781static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
4782 struct rpc_sh_ctx *ctx,
4783 struct rpc_pipe_client *pipe_hnd,
4784 int argc, const char **argv)
4785{
4786 return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
4787 ctx->cli, pipe_hnd, mem_ctx,
4788 argc, argv);
4789}
4790
4791static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
4792 struct rpc_sh_ctx *ctx,
4793 struct rpc_pipe_client *pipe_hnd,
4794 int argc, const char **argv)
4795{
4796 WERROR result;
4797
4798 if ((argc < 2) || (argc > 3)) {
4799 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
4800 ctx->whoami);
4801 return NT_STATUS_INVALID_PARAMETER;
4802 }
4803
4804 result = rpccli_srvsvc_net_share_add(
4805 pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
4806 (argc == 3) ? argv[2] : "",
4807 0, 0, 0, argv[1], NULL, 2, NULL);
4808
4809 return werror_to_ntstatus(result);
4810}
4811
4812static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
4813 struct rpc_sh_ctx *ctx,
4814 struct rpc_pipe_client *pipe_hnd,
4815 int argc, const char **argv)
4816{
4817 WERROR result;
4818
4819 if (argc != 1) {
4820 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4821 return NT_STATUS_INVALID_PARAMETER;
4822 }
4823
4824 result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
4825 return werror_to_ntstatus(result);
4826}
4827
4828static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
4829 struct rpc_sh_ctx *ctx,
4830 struct rpc_pipe_client *pipe_hnd,
4831 int argc, const char **argv)
4832{
4833 SRV_SHARE_INFO info;
4834 SRV_SHARE_INFO_2 *info2 = &info.share.info2;
4835 WERROR result;
4836
4837 if (argc != 1) {
4838 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4839 return NT_STATUS_INVALID_PARAMETER;
4840 }
4841
4842 result = rpccli_srvsvc_net_share_get_info(
4843 pipe_hnd, mem_ctx, argv[0], 2, &info);
4844 if (!W_ERROR_IS_OK(result)) {
4845 goto done;
4846 }
4847
4848 d_printf("Name: %s\n",
4849 rpcstr_pull_unistr2_talloc(mem_ctx,
4850 &info2->info_2_str.uni_netname));
4851 d_printf("Comment: %s\n",
4852 rpcstr_pull_unistr2_talloc(mem_ctx,
4853 &info2->info_2_str.uni_remark));
4854
4855 d_printf("Path: %s\n",
4856 rpcstr_pull_unistr2_talloc(mem_ctx,
4857 &info2->info_2_str.uni_path));
4858 d_printf("Password: %s\n",
4859 rpcstr_pull_unistr2_talloc(mem_ctx,
4860 &info2->info_2_str.uni_passwd));
4861
4862 done:
4863 return werror_to_ntstatus(result);
4864}
4865
4866struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
4867 struct rpc_sh_ctx *ctx)
4868{
4869 static struct rpc_sh_cmd cmds[] = {
4870
4871 { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
4872 "List available shares" },
4873
4874 { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
4875 "Add a share" },
4876
4877 { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
4878 "Delete a share" },
4879
4880 { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
4881 "Get information about a share" },
4882
4883 { NULL, NULL, 0, NULL, NULL }
4884 };
4885
4886 return cmds;
4887}
4888
4889/****************************************************************************/
4890
4891static int rpc_file_usage(int argc, const char **argv)
4892{
4893 return net_help_file(argc, argv);
4894}
4895
4896/**
4897 * Close a file on a remote RPC server
4898 *
4899 * All parameters are provided by the run_rpc_command function, except for
4900 * argc, argv which are passes through.
4901 *
4902 * @param domain_sid The domain sid acquired from the remote server
4903 * @param cli A cli_state connected to the server.
4904 * @param mem_ctx Talloc context, destoyed on completion of the function.
4905 * @param argc Standard main() style argc
4906 * @param argv Standard main() style argv. Initial components are already
4907 * stripped
4908 *
4909 * @return Normal NTSTATUS return.
4910 **/
4911static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
4912 const char *domain_name,
4913 struct cli_state *cli,
4914 struct rpc_pipe_client *pipe_hnd,
4915 TALLOC_CTX *mem_ctx,
4916 int argc,
4917 const char **argv)
4918{
4919 WERROR result;
4920 result = rpccli_srvsvc_net_file_close(pipe_hnd, mem_ctx, atoi(argv[0]));
4921 return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
4922}
4923
4924/**
4925 * Close a file on a remote RPC server
4926 *
4927 * @param argc Standard main() style argc
4928 * @param argv Standard main() style argv. Initial components are already
4929 * stripped
4930 *
4931 * @return A shell status integer (0 for success)
4932 **/
4933static int rpc_file_close(int argc, const char **argv)
4934{
4935 if (argc < 1) {
4936 DEBUG(1, ("No fileid given on close\n"));
4937 return(rpc_file_usage(argc, argv));
4938 }
4939
4940 return run_rpc_command(NULL, PI_SRVSVC, 0,
4941 rpc_file_close_internals,
4942 argc, argv);
4943}
4944
4945/**
4946 * Formatted print of open file info
4947 *
4948 * @param info3 FILE_INFO_3 contents
4949 * @param str3 strings for FILE_INFO_3
4950 **/
4951
4952static void display_file_info_3( FILE_INFO_3 *info3 )
4953{
4954 fstring user = "", path = "";
4955
4956 rpcstr_pull_unistr2_fstring(user, info3->user);
4957 rpcstr_pull_unistr2_fstring(path, info3->path);
4958
4959 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4960 info3->id, user, info3->perms, info3->num_locks, path);
4961}
4962
4963/**
4964 * List open files on a remote RPC server
4965 *
4966 * All parameters are provided by the run_rpc_command function, except for
4967 * argc, argv which are passes through.
4968 *
4969 * @param domain_sid The domain sid acquired from the remote server
4970 * @param cli A cli_state connected to the server.
4971 * @param mem_ctx Talloc context, destoyed on completion of the function.
4972 * @param argc Standard main() style argc
4973 * @param argv Standard main() style argv. Initial components are already
4974 * stripped
4975 *
4976 * @return Normal NTSTATUS return.
4977 **/
4978
4979static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
4980 const char *domain_name,
4981 struct cli_state *cli,
4982 struct rpc_pipe_client *pipe_hnd,
4983 TALLOC_CTX *mem_ctx,
4984 int argc,
4985 const char **argv)
4986{
4987 SRV_FILE_INFO_CTR ctr;
4988 WERROR result;
4989 ENUM_HND hnd;
4990 uint32 preferred_len = 0xffffffff, i;
4991 const char *username=NULL;
4992
4993 init_enum_hnd(&hnd, 0);
4994
4995 /* if argc > 0, must be user command */
4996 if (argc > 0)
4997 username = smb_xstrdup(argv[0]);
4998
4999 result = rpccli_srvsvc_net_file_enum(pipe_hnd,
5000 mem_ctx, 3, username, &ctr, preferred_len, &hnd);
5001
5002 if (!W_ERROR_IS_OK(result))
5003 goto done;
5004
5005 /* Display results */
5006
5007 d_printf(
5008 "\nEnumerating open files on remote server:\n\n"\
5009 "\nFileId Opened by Perms Locks Path"\
5010 "\n------ --------- ----- ----- ---- \n");
5011 for (i = 0; i < ctr.num_entries; i++)
5012 display_file_info_3(&ctr.file.info3[i]);
5013 done:
5014 return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
5015}
5016
5017/**
5018 * List files for a user on a remote RPC server
5019 *
5020 * @param argc Standard main() style argc
5021 * @param argv Standard main() style argv. Initial components are already
5022 * stripped
5023 *
5024 * @return A shell status integer (0 for success)
5025 **/
5026
5027static int rpc_file_user(int argc, const char **argv)
5028{
5029 if (argc < 1) {
5030 DEBUG(1, ("No username given\n"));
5031 return(rpc_file_usage(argc, argv));
5032 }
5033
5034 return run_rpc_command(NULL, PI_SRVSVC, 0,
5035 rpc_file_list_internals,
5036 argc, argv);
5037}
5038
5039/**
5040 * 'net rpc file' entrypoint.
5041 * @param argc Standard main() style argc
5042 * @param argv Standard main() style argv. Initial components are already
5043 * stripped
5044 **/
5045
5046int net_rpc_file(int argc, const char **argv)
5047{
5048 struct functable func[] = {
5049 {"close", rpc_file_close},
5050 {"user", rpc_file_user},
5051#if 0
5052 {"info", rpc_file_info},
5053#endif
5054 {NULL, NULL}
5055 };
5056
5057 if (argc == 0)
5058 return run_rpc_command(NULL, PI_SRVSVC, 0,
5059 rpc_file_list_internals,
5060 argc, argv);
5061
5062 return net_run_function(argc, argv, func, rpc_file_usage);
5063}
5064
5065/**
5066 * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
5067 *
5068 * All parameters are provided by the run_rpc_command function, except for
5069 * argc, argv which are passed through.
5070 *
5071 * @param domain_sid The domain sid aquired from the remote server
5072 * @param cli A cli_state connected to the server.
5073 * @param mem_ctx Talloc context, destoyed on compleation of the function.
5074 * @param argc Standard main() style argc
5075 * @param argv Standard main() style argv. Initial components are already
5076 * stripped
5077 *
5078 * @return Normal NTSTATUS return.
5079 **/
5080
5081static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid,
5082 const char *domain_name,
5083 struct cli_state *cli,
5084 struct rpc_pipe_client *pipe_hnd,
5085 TALLOC_CTX *mem_ctx,
5086 int argc,
5087 const char **argv)
5088{
5089 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5090
5091 result = rpccli_shutdown_abort(pipe_hnd, mem_ctx);
5092
5093 if (NT_STATUS_IS_OK(result)) {
5094 d_printf("\nShutdown successfully aborted\n");
5095 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5096 } else
5097 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5098
5099 return result;
5100}
5101
5102/**
5103 * ABORT the shutdown of a remote RPC Server, over winreg pipe
5104 *
5105 * All parameters are provided by the run_rpc_command function, except for
5106 * argc, argv which are passed through.
5107 *
5108 * @param domain_sid The domain sid aquired from the remote server
5109 * @param cli A cli_state connected to the server.
5110 * @param mem_ctx Talloc context, destoyed on compleation of the function.
5111 * @param argc Standard main() style argc
5112 * @param argv Standard main() style argv. Initial components are already
5113 * stripped
5114 *
5115 * @return Normal NTSTATUS return.
5116 **/
5117
5118static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid,
5119 const char *domain_name,
5120 struct cli_state *cli,
5121 struct rpc_pipe_client *pipe_hnd,
5122 TALLOC_CTX *mem_ctx,
5123 int argc,
5124 const char **argv)
5125{
5126 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5127
5128 result = werror_to_ntstatus(rpccli_reg_abort_shutdown(pipe_hnd, mem_ctx));
5129
5130 if (NT_STATUS_IS_OK(result)) {
5131 d_printf("\nShutdown successfully aborted\n");
5132 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5133 } else
5134 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5135
5136 return result;
5137}
5138
5139/**
5140 * ABORT the Shut down of a remote RPC server
5141 *
5142 * @param argc Standard main() style argc
5143 * @param argv Standard main() style argv. Initial components are already
5144 * stripped
5145 *
5146 * @return A shell status integer (0 for success)
5147 **/
5148
5149static int rpc_shutdown_abort(int argc, const char **argv)
5150{
5151 int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0,
5152 rpc_shutdown_abort_internals,
5153 argc, argv);
5154
5155 if (rc == 0)
5156 return rc;
5157
5158 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5159
5160 return run_rpc_command(NULL, PI_WINREG, 0,
5161 rpc_reg_shutdown_abort_internals,
5162 argc, argv);
5163}
5164
5165/**
5166 * Shut down a remote RPC Server via initshutdown pipe
5167 *
5168 * All parameters are provided by the run_rpc_command function, except for
5169 * argc, argv which are passes through.
5170 *
5171 * @param domain_sid The domain sid aquired from the remote server
5172 * @param cli A cli_state connected to the server.
5173 * @param mem_ctx Talloc context, destoyed on compleation of the function.
5174 * @param argc Standard main() style argc
5175 * @param argc Standard main() style argv. Initial components are already
5176 * stripped
5177 *
5178 * @return Normal NTSTATUS return.
5179 **/
5180
5181static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
5182 const char *domain_name,
5183 struct cli_state *cli,
5184 struct rpc_pipe_client *pipe_hnd,
5185 TALLOC_CTX *mem_ctx,
5186 int argc,
5187 const char **argv)
5188{
5189 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5190 const char *msg = "This machine will be shutdown shortly";
5191 uint32 timeout = 20;
5192
5193 if (opt_comment) {
5194 msg = opt_comment;
5195 }
5196 if (opt_timeout) {
5197 timeout = opt_timeout;
5198 }
5199
5200 /* create an entry */
5201 result = rpccli_shutdown_init(pipe_hnd, mem_ctx, msg, timeout, opt_reboot,
5202 opt_force);
5203
5204 if (NT_STATUS_IS_OK(result)) {
5205 d_printf("\nShutdown of remote machine succeeded\n");
5206 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5207 } else {
5208 DEBUG(1,("Shutdown of remote machine failed!\n"));
5209 }
5210 return result;
5211}
5212
5213/**
5214 * Shut down a remote RPC Server via winreg pipe
5215 *
5216 * All parameters are provided by the run_rpc_command function, except for
5217 * argc, argv which are passes through.
5218 *
5219 * @param domain_sid The domain sid aquired from the remote server
5220 * @param cli A cli_state connected to the server.
5221 * @param mem_ctx Talloc context, destoyed on compleation of the function.
5222 * @param argc Standard main() style argc
5223 * @param argc Standard main() style argv. Initial components are already
5224 * stripped
5225 *
5226 * @return Normal NTSTATUS return.
5227 **/
5228
5229static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid,
5230 const char *domain_name,
5231 struct cli_state *cli,
5232 struct rpc_pipe_client *pipe_hnd,
5233 TALLOC_CTX *mem_ctx,
5234 int argc,
5235 const char **argv)
5236{
5237 WERROR result;
5238 const char *msg = "This machine will be shutdown shortly";
5239 uint32 timeout = 20;
5240#if 0
5241 poptContext pc;
5242 int rc;
5243
5244 struct poptOption long_options[] = {
5245 {"message", 'm', POPT_ARG_STRING, &msg},
5246 {"timeout", 't', POPT_ARG_INT, &timeout},
5247 {"reboot", 'r', POPT_ARG_NONE, &reboot},
5248 {"force", 'f', POPT_ARG_NONE, &force},
5249 { 0, 0, 0, 0}
5250 };
5251
5252 pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
5253 POPT_CONTEXT_KEEP_FIRST);
5254
5255 rc = poptGetNextOpt(pc);
5256
5257 if (rc < -1) {
5258 /* an error occurred during option processing */
5259 DEBUG(0, ("%s: %s\n",
5260 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
5261 poptStrerror(rc)));
5262 return NT_STATUS_INVALID_PARAMETER;
5263 }
5264#endif
5265 if (opt_comment) {
5266 msg = opt_comment;
5267 }
5268 if (opt_timeout) {
5269 timeout = opt_timeout;
5270 }
5271
5272 /* create an entry */
5273 result = rpccli_reg_shutdown(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, opt_force);
5274
5275 if (W_ERROR_IS_OK(result)) {
5276 d_printf("\nShutdown of remote machine succeeded\n");
5277 } else {
5278 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5279 if (W_ERROR_EQUAL(result,WERR_MACHINE_LOCKED))
5280 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5281 else
5282 d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(result));
5283 }
5284
5285 return werror_to_ntstatus(result);
5286}
5287
5288/**
5289 * Shut down a remote RPC server
5290 *
5291 * @param argc Standard main() style argc
5292 * @param argc Standard main() style argv. Initial components are already
5293 * stripped
5294 *
5295 * @return A shell status integer (0 for success)
5296 **/
5297
5298static int rpc_shutdown(int argc, const char **argv)
5299{
5300 int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0,
5301 rpc_init_shutdown_internals,
5302 argc, argv);
5303
5304 if (rc) {
5305 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5306 rc = run_rpc_command(NULL, PI_WINREG, 0,
5307 rpc_reg_shutdown_internals, argc, argv);
5308 }
5309
5310 return rc;
5311}
5312
5313/***************************************************************************
5314 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5315
5316 ***************************************************************************/
5317
5318/**
5319 * Add interdomain trust account to the RPC server.
5320 * All parameters (except for argc and argv) are passed by run_rpc_command
5321 * function.
5322 *
5323 * @param domain_sid The domain sid acquired from the server
5324 * @param cli A cli_state connected to the server.
5325 * @param mem_ctx Talloc context, destoyed on completion of the function.
5326 * @param argc Standard main() style argc
5327 * @param argc Standard main() style argv. Initial components are already
5328 * stripped
5329 *
5330 * @return normal NTSTATUS return code
5331 */
5332
5333static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
5334 const char *domain_name,
5335 struct cli_state *cli,
5336 struct rpc_pipe_client *pipe_hnd,
5337 TALLOC_CTX *mem_ctx,
5338 int argc,
5339 const char **argv)
5340{
5341 POLICY_HND connect_pol, domain_pol, user_pol;
5342 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5343 char *acct_name;
5344 uint32 acb_info;
5345 uint32 user_rid;
5346 uint32 acct_flags=0;
5347
5348 if (argc != 2) {
5349 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
5350 return NT_STATUS_INVALID_PARAMETER;
5351 }
5352
5353 /*
5354 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5355 */
5356
5357 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5358 return NT_STATUS_NO_MEMORY;
5359 }
5360
5361 strupper_m(acct_name);
5362
5363 /* Get samr policy handle */
5364 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
5365 &connect_pol);
5366 if (!NT_STATUS_IS_OK(result)) {
5367 goto done;
5368 }
5369
5370 /* Get domain policy handle */
5371 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
5372 MAXIMUM_ALLOWED_ACCESS,
5373 domain_sid, &domain_pol);
5374 if (!NT_STATUS_IS_OK(result)) {
5375 goto done;
5376 }
5377
5378 /* Create trusting domain's account */
5379 acb_info = ACB_NORMAL;
5380 acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
5381 SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
5382 SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
5383 SAMR_USER_SETATTR;
5384
5385 result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
5386 acct_name, acb_info, acct_flags,
5387 &user_pol, &user_rid);
5388 if (!NT_STATUS_IS_OK(result)) {
5389 goto done;
5390 }
5391
5392 {
5393 SAM_USERINFO_CTR ctr;
5394 SAM_USER_INFO_23 p23;
5395 NTTIME notime;
5396 char nostr[] = "";
5397 LOGON_HRS hrs;
5398 uchar pwbuf[516];
5399
5400 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
5401
5402 ZERO_STRUCT(ctr);
5403 ZERO_STRUCT(p23);
5404 ZERO_STRUCT(notime);
5405 hrs.max_len = 1260;
5406 hrs.offset = 0;
5407 hrs.len = 21;
5408 memset(hrs.hours, 0xFF, sizeof(hrs.hours));
5409 acb_info = ACB_DOMTRUST;
5410
5411 init_sam_user_info23A(&p23, &notime, &notime, &notime,
5412 &notime, &notime, &notime,
5413 nostr, nostr, nostr, nostr, nostr,
5414 nostr, nostr, nostr, nostr, nostr,
5415 0, 0, acb_info, ACCT_FLAGS, 168, &hrs,
5416 0, 0, (char *)pwbuf);
5417 ctr.switch_value = 23;
5418 ctr.info.id23 = &p23;
5419 p23.passmustchange = 0;
5420
5421 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 23,
5422 &cli->user_session_key, &ctr);
5423
5424 if (!NT_STATUS_IS_OK(result)) {
5425 DEBUG(0,("Could not set trust account password: %s\n",
5426 nt_errstr(result)));
5427 goto done;
5428 }
5429 }
5430
5431 done:
5432 SAFE_FREE(acct_name);
5433 return result;
5434}
5435
5436/**
5437 * Create interdomain trust account for a remote domain.
5438 *
5439 * @param argc standard argc
5440 * @param argv standard argv without initial components
5441 *
5442 * @return Integer status (0 means success)
5443 **/
5444
5445static int rpc_trustdom_add(int argc, const char **argv)
5446{
5447 if (argc > 0) {
5448 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
5449 argc, argv);
5450 } else {
5451 d_printf("Usage: net rpc trustdom add <domain> <trust password>\n");
5452 return -1;
5453 }
5454}
5455
5456
5457/**
5458 * Remove interdomain trust account from the RPC server.
5459 * All parameters (except for argc and argv) are passed by run_rpc_command
5460 * function.
5461 *
5462 * @param domain_sid The domain sid acquired from the server
5463 * @param cli A cli_state connected to the server.
5464 * @param mem_ctx Talloc context, destoyed on completion of the function.
5465 * @param argc Standard main() style argc
5466 * @param argc Standard main() style argv. Initial components are already
5467 * stripped
5468 *
5469 * @return normal NTSTATUS return code
5470 */
5471
5472static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid,
5473 const char *domain_name,
5474 struct cli_state *cli,
5475 struct rpc_pipe_client *pipe_hnd,
5476 TALLOC_CTX *mem_ctx,
5477 int argc,
5478 const char **argv)
5479{
5480 POLICY_HND connect_pol, domain_pol, user_pol;
5481 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5482 char *acct_name;
5483 const char **names;
5484 DOM_SID trust_acct_sid;
5485 uint32 *user_rids, num_rids, *name_types;
5486 uint32 flags = 0x000003e8; /* Unknown */
5487
5488 if (argc != 1) {
5489 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5490 return NT_STATUS_INVALID_PARAMETER;
5491 }
5492
5493 /*
5494 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5495 */
5496 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5497
5498 if (acct_name == NULL)
5499 return NT_STATUS_NO_MEMORY;
5500
5501 strupper_m(acct_name);
5502
5503 if ((names = TALLOC_ARRAY(mem_ctx, const char *, 1)) == NULL) {
5504 return NT_STATUS_NO_MEMORY;
5505 }
5506 names[0] = acct_name;
5507
5508
5509 /* Get samr policy handle */
5510 result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
5511 &connect_pol);
5512 if (!NT_STATUS_IS_OK(result)) {
5513 goto done;
5514 }
5515
5516 /* Get domain policy handle */
5517 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
5518 MAXIMUM_ALLOWED_ACCESS,
5519 domain_sid, &domain_pol);
5520 if (!NT_STATUS_IS_OK(result)) {
5521 goto done;
5522 }
5523
5524 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1,
5525 names, &num_rids,
5526 &user_rids, &name_types);
5527
5528 if (!NT_STATUS_IS_OK(result)) {
5529 goto done;
5530 }
5531
5532 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
5533 MAXIMUM_ALLOWED_ACCESS,
5534 user_rids[0], &user_pol);
5535
5536 if (!NT_STATUS_IS_OK(result)) {
5537 goto done;
5538 }
5539
5540 /* append the rid to the domain sid */
5541 sid_copy(&trust_acct_sid, domain_sid);
5542 if (!sid_append_rid(&trust_acct_sid, user_rids[0])) {
5543 goto done;
5544 }
5545
5546 /* remove the sid */
5547
5548 result = rpccli_samr_remove_sid_foreign_domain(pipe_hnd, mem_ctx, &user_pol,
5549 &trust_acct_sid);
5550
5551 if (!NT_STATUS_IS_OK(result)) {
5552 goto done;
5553 }
5554
5555 /* Delete user */
5556
5557 result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
5558
5559 if (!NT_STATUS_IS_OK(result)) {
5560 goto done;
5561 }
5562
5563 if (!NT_STATUS_IS_OK(result)) {
5564 DEBUG(0,("Could not set trust account password: %s\n",
5565 nt_errstr(result)));
5566 goto done;
5567 }
5568
5569 done:
5570 return result;
5571}
5572
5573/**
5574 * Delete interdomain trust account for a remote domain.
5575 *
5576 * @param argc standard argc
5577 * @param argv standard argv without initial components
5578 *
5579 * @return Integer status (0 means success)
5580 **/
5581
5582static int rpc_trustdom_del(int argc, const char **argv)
5583{
5584 if (argc > 0) {
5585 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
5586 argc, argv);
5587 } else {
5588 d_printf("Usage: net rpc trustdom del <domain>\n");
5589 return -1;
5590 }
5591}
5592
5593
5594/**
5595 * Establish trust relationship to a trusting domain.
5596 * Interdomain account must already be created on remote PDC.
5597 *
5598 * @param argc standard argc
5599 * @param argv standard argv without initial components
5600 *
5601 * @return Integer status (0 means success)
5602 **/
5603
5604static int rpc_trustdom_establish(int argc, const char **argv)
5605{
5606 struct cli_state *cli = NULL;
5607 struct in_addr server_ip;
5608 struct rpc_pipe_client *pipe_hnd = NULL;
5609 POLICY_HND connect_hnd;
5610 TALLOC_CTX *mem_ctx;
5611 NTSTATUS nt_status;
5612 DOM_SID *domain_sid;
5613
5614 char* domain_name;
5615 char* domain_name_pol;
5616 char* acct_name;
5617 fstring pdc_name;
5618
5619 /*
5620 * Connect to \\server\ipc$ as 'our domain' account with password
5621 */
5622
5623 if (argc != 1) {
5624 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
5625 return -1;
5626 }
5627
5628 domain_name = smb_xstrdup(argv[0]);
5629 strupper_m(domain_name);
5630
5631 /* account name used at first is our domain's name with '$' */
5632 asprintf(&acct_name, "%s$", lp_workgroup());
5633 strupper_m(acct_name);
5634
5635 /*
5636 * opt_workgroup will be used by connection functions further,
5637 * hence it should be set to remote domain name instead of ours
5638 */
5639 if (opt_workgroup) {
5640 opt_workgroup = smb_xstrdup(domain_name);
5641 };
5642
5643 opt_user_name = acct_name;
5644
5645 /* find the domain controller */
5646 if (!net_find_pdc(&server_ip, pdc_name, domain_name)) {
5647 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5648 return -1;
5649 }
5650
5651 /* connect to ipc$ as username/password */
5652 nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
5653 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5654
5655 /* Is it trusting domain account for sure ? */
5656 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5657 nt_errstr(nt_status)));
5658 return -1;
5659 }
5660
5661 /* store who we connected to */
5662
5663 saf_store( domain_name, pdc_name );
5664
5665 /*
5666 * Connect to \\server\ipc$ again (this time anonymously)
5667 */
5668
5669 nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
5670
5671 if (NT_STATUS_IS_ERR(nt_status)) {
5672 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5673 domain_name, nt_errstr(nt_status)));
5674 return -1;
5675 }
5676
5677 /*
5678 * Use NetServerEnum2 to make sure we're talking to a proper server
5679 */
5680
5681 if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
5682 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
5683 for domain %s\n", domain_name));
5684 cli_shutdown(cli);
5685 return -1;
5686 }
5687
5688 if (!(mem_ctx = talloc_init("establishing trust relationship to "
5689 "domain %s", domain_name))) {
5690 DEBUG(0, ("talloc_init() failed\n"));
5691 cli_shutdown(cli);
5692 return -1;
5693 }
5694
5695 /*
5696 * Call LsaOpenPolicy and LsaQueryInfo
5697 */
5698
5699 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5700 if (!pipe_hnd) {
5701 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5702 cli_shutdown(cli);
5703 talloc_destroy(mem_ctx);
5704 return -1;
5705 }
5706
5707 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
5708 &connect_hnd);
5709 if (NT_STATUS_IS_ERR(nt_status)) {
5710 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5711 nt_errstr(nt_status)));
5712 cli_shutdown(cli);
5713 talloc_destroy(mem_ctx);
5714 return -1;
5715 }
5716
5717 /* Querying info level 5 */
5718
5719 nt_status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &connect_hnd,
5720 5 /* info level */,
5721 &domain_name_pol, &domain_sid);
5722 if (NT_STATUS_IS_ERR(nt_status)) {
5723 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5724 nt_errstr(nt_status)));
5725 cli_shutdown(cli);
5726 talloc_destroy(mem_ctx);
5727 return -1;
5728 }
5729
5730 /* There should be actually query info level 3 (following nt serv behaviour),
5731 but I still don't know if it's _really_ necessary */
5732
5733 /*
5734 * Store the password in secrets db
5735 */
5736
5737 if (!secrets_store_trusted_domain_password(domain_name,
5738 opt_password,
5739 domain_sid)) {
5740 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5741 cli_shutdown(cli);
5742 talloc_destroy(mem_ctx);
5743 return -1;
5744 }
5745
5746 /*
5747 * Close the pipes and clean up
5748 */
5749
5750 nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
5751 if (NT_STATUS_IS_ERR(nt_status)) {
5752 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5753 nt_errstr(nt_status)));
5754 cli_shutdown(cli);
5755 talloc_destroy(mem_ctx);
5756 return -1;
5757 }
5758
5759 cli_shutdown(cli);
5760
5761 talloc_destroy(mem_ctx);
5762
5763 d_printf("Trust to domain %s established\n", domain_name);
5764 return 0;
5765}
5766
5767/**
5768 * Revoke trust relationship to the remote domain
5769 *
5770 * @param argc standard argc
5771 * @param argv standard argv without initial components
5772 *
5773 * @return Integer status (0 means success)
5774 **/
5775
5776static int rpc_trustdom_revoke(int argc, const char **argv)
5777{
5778 char* domain_name;
5779
5780 if (argc < 1) return -1;
5781
5782 /* generate upper cased domain name */
5783 domain_name = smb_xstrdup(argv[0]);
5784 strupper_m(domain_name);
5785
5786 /* delete password of the trust */
5787 if (!trusted_domain_password_delete(domain_name)) {
5788 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5789 domain_name));
5790 return -1;
5791 };
5792
5793 return 0;
5794}
5795
5796/**
5797 * Usage for 'net rpc trustdom' command
5798 *
5799 * @param argc standard argc
5800 * @param argv standard argv without inital components
5801 *
5802 * @return Integer status returned to shell
5803 **/
5804
5805static int rpc_trustdom_usage(int argc, const char **argv)
5806{
5807 d_printf(" net rpc trustdom add \t\t add trusting domain's account\n");
5808 d_printf(" net rpc trustdom del \t\t delete trusting domain's account\n");
5809 d_printf(" net rpc trustdom establish \t establish relationship to trusted domain\n");
5810 d_printf(" net rpc trustdom revoke \t abandon relationship to trusted domain\n");
5811 d_printf(" net rpc trustdom list \t show current interdomain trust relationships\n");
5812 d_printf(" net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
5813 return -1;
5814}
5815
5816
5817static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid,
5818 const char *domain_name,
5819 struct cli_state *cli,
5820 struct rpc_pipe_client *pipe_hnd,
5821 TALLOC_CTX *mem_ctx,
5822 int argc,
5823 const char **argv)
5824{
5825 fstring str_sid;
5826 sid_to_string(str_sid, domain_sid);
5827 d_printf("%s\n", str_sid);
5828 return NT_STATUS_OK;
5829}
5830
5831static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
5832{
5833 fstring ascii_sid, padding;
5834 int pad_len, col_len = 20;
5835
5836 /* convert sid into ascii string */
5837 sid_to_string(ascii_sid, dom_sid);
5838
5839 /* calculate padding space for d_printf to look nicer */
5840 pad_len = col_len - strlen(trusted_dom_name);
5841 padding[pad_len] = 0;
5842 do padding[--pad_len] = ' '; while (pad_len);
5843
5844 d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
5845}
5846
5847static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
5848 TALLOC_CTX *mem_ctx,
5849 POLICY_HND *pol,
5850 DOM_SID dom_sid,
5851 const char *trusted_dom_name)
5852{
5853 NTSTATUS nt_status;
5854 LSA_TRUSTED_DOMAIN_INFO *info;
5855 char *cleartextpwd = NULL;
5856 DATA_BLOB data;
5857
5858 nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info);
5859
5860 if (NT_STATUS_IS_ERR(nt_status)) {
5861 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5862 nt_errstr(nt_status)));
5863 goto done;
5864 }
5865
5866 data = data_blob(NULL, info->password.password.length);
5867
5868 memcpy(data.data, info->password.password.data, info->password.password.length);
5869 data.length = info->password.password.length;
5870
5871 cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password, &data);
5872
5873 if (cleartextpwd == NULL) {
5874 DEBUG(0,("retrieved NULL password\n"));
5875 nt_status = NT_STATUS_UNSUCCESSFUL;
5876 goto done;
5877 }
5878
5879 if (!secrets_store_trusted_domain_password(trusted_dom_name,
5880 cleartextpwd,
5881 &dom_sid)) {
5882 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5883 nt_status = NT_STATUS_UNSUCCESSFUL;
5884 goto done;
5885 }
5886
5887#ifdef DEBUG_PASSWORD
5888 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], password: [%s]\n",
5889 trusted_dom_name, sid_string_static(&dom_sid), cleartextpwd));
5890#endif
5891
5892done:
5893 SAFE_FREE(cleartextpwd);
5894 data_blob_free(&data);
5895
5896 return nt_status;
5897}
5898
5899static int rpc_trustdom_vampire(int argc, const char **argv)
5900{
5901 /* common variables */
5902 TALLOC_CTX* mem_ctx;
5903 struct cli_state *cli = NULL;
5904 struct rpc_pipe_client *pipe_hnd = NULL;
5905 NTSTATUS nt_status;
5906 const char *domain_name = NULL;
5907 DOM_SID *queried_dom_sid;
5908 POLICY_HND connect_hnd;
5909
5910 /* trusted domains listing variables */
5911 unsigned int num_domains, enum_ctx = 0;
5912 int i;
5913 DOM_SID *domain_sids;
5914 char **trusted_dom_names;
5915 fstring pdc_name;
5916 char *dummy;
5917
5918 /*
5919 * Listing trusted domains (stored in secrets.tdb, if local)
5920 */
5921
5922 mem_ctx = talloc_init("trust relationships vampire");
5923
5924 /*
5925 * set domain and pdc name to local samba server (default)
5926 * or to remote one given in command line
5927 */
5928
5929 if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
5930 domain_name = opt_workgroup;
5931 opt_target_workgroup = opt_workgroup;
5932 } else {
5933 fstrcpy(pdc_name, global_myname());
5934 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5935 opt_target_workgroup = domain_name;
5936 };
5937
5938 /* open \PIPE\lsarpc and open policy handle */
5939 if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
5940 DEBUG(0, ("Couldn't connect to domain controller\n"));
5941 talloc_destroy(mem_ctx);
5942 return -1;
5943 };
5944
5945 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5946 if (!pipe_hnd) {
5947 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5948 nt_errstr(nt_status) ));
5949 cli_shutdown(cli);
5950 talloc_destroy(mem_ctx);
5951 return -1;
5952 };
5953
5954 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
5955 &connect_hnd);
5956 if (NT_STATUS_IS_ERR(nt_status)) {
5957 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5958 nt_errstr(nt_status)));
5959 cli_shutdown(cli);
5960 talloc_destroy(mem_ctx);
5961 return -1;
5962 };
5963
5964 /* query info level 5 to obtain sid of a domain being queried */
5965 nt_status = rpccli_lsa_query_info_policy(
5966 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */,
5967 &dummy, &queried_dom_sid);
5968
5969 if (NT_STATUS_IS_ERR(nt_status)) {
5970 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5971 nt_errstr(nt_status)));
5972 cli_shutdown(cli);
5973 talloc_destroy(mem_ctx);
5974 return -1;
5975 }
5976
5977 /*
5978 * Keep calling LsaEnumTrustdom over opened pipe until
5979 * the end of enumeration is reached
5980 */
5981
5982 d_printf("Vampire trusted domains:\n\n");
5983
5984 do {
5985 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
5986 &num_domains,
5987 &trusted_dom_names, &domain_sids);
5988
5989 if (NT_STATUS_IS_ERR(nt_status)) {
5990 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5991 nt_errstr(nt_status)));
5992 cli_shutdown(cli);
5993 talloc_destroy(mem_ctx);
5994 return -1;
5995 };
5996
5997 for (i = 0; i < num_domains; i++) {
5998
5999 print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
6000
6001 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6002 domain_sids[i], trusted_dom_names[i]);
6003 if (!NT_STATUS_IS_OK(nt_status)) {
6004 cli_shutdown(cli);
6005 talloc_destroy(mem_ctx);
6006 return -1;
6007 }
6008 };
6009
6010 /*
6011 * in case of no trusted domains say something rather
6012 * than just display blank line
6013 */
6014 if (!num_domains) d_printf("none\n");
6015
6016 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6017
6018 /* close this connection before doing next one */
6019 nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
6020 if (NT_STATUS_IS_ERR(nt_status)) {
6021 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6022 nt_errstr(nt_status)));
6023 cli_shutdown(cli);
6024 talloc_destroy(mem_ctx);
6025 return -1;
6026 };
6027
6028 /* close lsarpc pipe and connection to IPC$ */
6029 cli_shutdown(cli);
6030
6031 talloc_destroy(mem_ctx);
6032 return 0;
6033}
6034
6035static int rpc_trustdom_list(int argc, const char **argv)
6036{
6037 /* common variables */
6038 TALLOC_CTX* mem_ctx;
6039 struct cli_state *cli = NULL, *remote_cli = NULL;
6040 struct rpc_pipe_client *pipe_hnd = NULL;
6041 NTSTATUS nt_status;
6042 const char *domain_name = NULL;
6043 DOM_SID *queried_dom_sid;
6044 fstring padding;
6045 int ascii_dom_name_len;
6046 POLICY_HND connect_hnd;
6047
6048 /* trusted domains listing variables */
6049 unsigned int num_domains, enum_ctx = 0;
6050 int i, pad_len, col_len = 20;
6051 DOM_SID *domain_sids;
6052 char **trusted_dom_names;
6053 fstring pdc_name;
6054 char *dummy;
6055
6056 /* trusting domains listing variables */
6057 POLICY_HND domain_hnd;
6058 char **trusting_dom_names;
6059 uint32 *trusting_dom_rids;
6060
6061 /*
6062 * Listing trusted domains (stored in secrets.tdb, if local)
6063 */
6064
6065 mem_ctx = talloc_init("trust relationships listing");
6066
6067 /*
6068 * set domain and pdc name to local samba server (default)
6069 * or to remote one given in command line
6070 */
6071
6072 if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6073 domain_name = opt_workgroup;
6074 opt_target_workgroup = opt_workgroup;
6075 } else {
6076 fstrcpy(pdc_name, global_myname());
6077 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6078 opt_target_workgroup = domain_name;
6079 };
6080
6081 /* open \PIPE\lsarpc and open policy handle */
6082 if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
6083 DEBUG(0, ("Couldn't connect to domain controller\n"));
6084 talloc_destroy(mem_ctx);
6085 return -1;
6086 };
6087
6088 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6089 if (!pipe_hnd) {
6090 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6091 nt_errstr(nt_status) ));
6092 cli_shutdown(cli);
6093 talloc_destroy(mem_ctx);
6094 return -1;
6095 };
6096
6097 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6098 &connect_hnd);
6099 if (NT_STATUS_IS_ERR(nt_status)) {
6100 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6101 nt_errstr(nt_status)));
6102 cli_shutdown(cli);
6103 talloc_destroy(mem_ctx);
6104 return -1;
6105 };
6106
6107 /* query info level 5 to obtain sid of a domain being queried */
6108 nt_status = rpccli_lsa_query_info_policy(
6109 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */,
6110 &dummy, &queried_dom_sid);
6111
6112 if (NT_STATUS_IS_ERR(nt_status)) {
6113 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6114 nt_errstr(nt_status)));
6115 cli_shutdown(cli);
6116 talloc_destroy(mem_ctx);
6117 return -1;
6118 }
6119
6120 /*
6121 * Keep calling LsaEnumTrustdom over opened pipe until
6122 * the end of enumeration is reached
6123 */
6124
6125 d_printf("Trusted domains list:\n\n");
6126
6127 do {
6128 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
6129 &num_domains,
6130 &trusted_dom_names, &domain_sids);
6131
6132 if (NT_STATUS_IS_ERR(nt_status)) {
6133 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6134 nt_errstr(nt_status)));
6135 cli_shutdown(cli);
6136 talloc_destroy(mem_ctx);
6137 return -1;
6138 };
6139
6140 for (i = 0; i < num_domains; i++) {
6141 print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
6142 };
6143
6144 /*
6145 * in case of no trusted domains say something rather
6146 * than just display blank line
6147 */
6148 if (!num_domains) d_printf("none\n");
6149
6150 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6151
6152 /* close this connection before doing next one */
6153 nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
6154 if (NT_STATUS_IS_ERR(nt_status)) {
6155 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6156 nt_errstr(nt_status)));
6157 cli_shutdown(cli);
6158 talloc_destroy(mem_ctx);
6159 return -1;
6160 };
6161
6162 cli_rpc_pipe_close(pipe_hnd);
6163
6164 /*
6165 * Listing trusting domains (stored in passdb backend, if local)
6166 */
6167
6168 d_printf("\nTrusting domains list:\n\n");
6169
6170 /*
6171 * Open \PIPE\samr and get needed policy handles
6172 */
6173 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
6174 if (!pipe_hnd) {
6175 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6176 cli_shutdown(cli);
6177 talloc_destroy(mem_ctx);
6178 return -1;
6179 };
6180
6181 /* SamrConnect */
6182 nt_status = rpccli_samr_connect(pipe_hnd, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
6183 &connect_hnd);
6184 if (!NT_STATUS_IS_OK(nt_status)) {
6185 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6186 nt_errstr(nt_status)));
6187 cli_shutdown(cli);
6188 talloc_destroy(mem_ctx);
6189 return -1;
6190 };
6191
6192 /* SamrOpenDomain - we have to open domain policy handle in order to be
6193 able to enumerate accounts*/
6194 nt_status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_hnd,
6195 SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6196 queried_dom_sid, &domain_hnd);
6197 if (!NT_STATUS_IS_OK(nt_status)) {
6198 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6199 nt_errstr(nt_status)));
6200 cli_shutdown(cli);
6201 talloc_destroy(mem_ctx);
6202 return -1;
6203 };
6204
6205 /*
6206 * perform actual enumeration
6207 */
6208
6209 enum_ctx = 0; /* reset enumeration context from last enumeration */
6210 do {
6211
6212 nt_status = rpccli_samr_enum_dom_users(pipe_hnd, mem_ctx, &domain_hnd,
6213 &enum_ctx, ACB_DOMTRUST, 0xffff,
6214 &trusting_dom_names, &trusting_dom_rids,
6215 &num_domains);
6216 if (NT_STATUS_IS_ERR(nt_status)) {
6217 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6218 nt_errstr(nt_status)));
6219 cli_shutdown(cli);
6220 talloc_destroy(mem_ctx);
6221 return -1;
6222 };
6223
6224 for (i = 0; i < num_domains; i++) {
6225
6226 /*
6227 * get each single domain's sid (do we _really_ need this ?):
6228 * 1) connect to domain's pdc
6229 * 2) query the pdc for domain's sid
6230 */
6231
6232 /* get rid of '$' tail */
6233 ascii_dom_name_len = strlen(trusting_dom_names[i]);
6234 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6235 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
6236
6237 /* calculate padding space for d_printf to look nicer */
6238 pad_len = col_len - strlen(trusting_dom_names[i]);
6239 padding[pad_len] = 0;
6240 do padding[--pad_len] = ' '; while (pad_len);
6241
6242 /* set opt_* variables to remote domain */
6243 strupper_m(trusting_dom_names[i]);
6244 opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
6245 opt_target_workgroup = opt_workgroup;
6246
6247 d_printf("%s%s", trusting_dom_names[i], padding);
6248
6249 /* connect to remote domain controller */
6250 remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
6251 if (remote_cli) {
6252 /* query for domain's sid */
6253 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
6254 d_fprintf(stderr, "couldn't get domain's sid\n");
6255
6256 cli_shutdown(remote_cli);
6257
6258 } else {
6259 d_fprintf(stderr, "domain controller is not responding\n");
6260 };
6261 };
6262
6263 if (!num_domains) d_printf("none\n");
6264
6265 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6266
6267 /* close opened samr and domain policy handles */
6268 nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &domain_hnd);
6269 if (!NT_STATUS_IS_OK(nt_status)) {
6270 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6271 };
6272
6273 nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &connect_hnd);
6274 if (!NT_STATUS_IS_OK(nt_status)) {
6275 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6276 };
6277
6278 /* close samr pipe and connection to IPC$ */
6279 cli_shutdown(cli);
6280
6281 talloc_destroy(mem_ctx);
6282 return 0;
6283}
6284
6285/**
6286 * Entrypoint for 'net rpc trustdom' code
6287 *
6288 * @param argc standard argc
6289 * @param argv standard argv without initial components
6290 *
6291 * @return Integer status (0 means success)
6292 */
6293
6294static int rpc_trustdom(int argc, const char **argv)
6295{
6296 struct functable func[] = {
6297 {"add", rpc_trustdom_add},
6298 {"del", rpc_trustdom_del},
6299 {"establish", rpc_trustdom_establish},
6300 {"revoke", rpc_trustdom_revoke},
6301 {"help", rpc_trustdom_usage},
6302 {"list", rpc_trustdom_list},
6303 {"vampire", rpc_trustdom_vampire},
6304 {NULL, NULL}
6305 };
6306
6307 if (argc == 0) {
6308 rpc_trustdom_usage(argc, argv);
6309 return -1;
6310 }
6311
6312 return (net_run_function(argc, argv, func, rpc_user_usage));
6313}
6314
6315/**
6316 * Check if a server will take rpc commands
6317 * @param flags Type of server to connect to (PDC, DMB, localhost)
6318 * if the host is not explicitly specified
6319 * @return BOOL (true means rpc supported)
6320 */
6321BOOL net_rpc_check(unsigned flags)
6322{
6323 struct cli_state *cli;
6324 BOOL ret = False;
6325 struct in_addr server_ip;
6326 char *server_name = NULL;
6327 NTSTATUS status;
6328
6329 /* flags (i.e. server type) may depend on command */
6330 if (!net_find_server(NULL, flags, &server_ip, &server_name))
6331 return False;
6332
6333 if ((cli = cli_initialise()) == NULL) {
6334 return False;
6335 }
6336
6337 status = cli_connect(cli, server_name, &server_ip);
6338 if (!NT_STATUS_IS_OK(status))
6339 goto done;
6340 if (!attempt_netbios_session_request(&cli, global_myname(),
6341 server_name, &server_ip))
6342 goto done;
6343 if (!cli_negprot(cli))
6344 goto done;
6345 if (cli->protocol < PROTOCOL_NT1)
6346 goto done;
6347
6348 ret = True;
6349 done:
6350 cli_shutdown(cli);
6351 return ret;
6352}
6353
6354/* dump sam database via samsync rpc calls */
6355static int rpc_samdump(int argc, const char **argv) {
6356 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
6357 argc, argv);
6358}
6359
6360/* syncronise sam database via samsync rpc calls */
6361static int rpc_vampire(int argc, const char **argv) {
6362 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
6363 argc, argv);
6364}
6365
6366/**
6367 * Migrate everything from a print-server
6368 *
6369 * @param argc Standard main() style argc
6370 * @param argv Standard main() style argv. Initial components are already
6371 * stripped
6372 *
6373 * @return A shell status integer (0 for success)
6374 *
6375 * The order is important !
6376 * To successfully add drivers the print-queues have to exist !
6377 * Applying ACLs should be the last step, because you're easily locked out
6378 *
6379 **/
6380static int rpc_printer_migrate_all(int argc, const char **argv)
6381{
6382 int ret;
6383
6384 if (!opt_host) {
6385 printf("no server to migrate\n");
6386 return -1;
6387 }
6388
6389 ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
6390 if (ret)
6391 return ret;
6392
6393 ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
6394 if (ret)
6395 return ret;
6396
6397 ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
6398 if (ret)
6399 return ret;
6400
6401 ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
6402 if (ret)
6403 return ret;
6404
6405 return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
6406
6407}
6408
6409/**
6410 * Migrate print-drivers from a print-server
6411 *
6412 * @param argc Standard main() style argc
6413 * @param argv Standard main() style argv. Initial components are already
6414 * stripped
6415 *
6416 * @return A shell status integer (0 for success)
6417 **/
6418static int rpc_printer_migrate_drivers(int argc, const char **argv)
6419{
6420 if (!opt_host) {
6421 printf("no server to migrate\n");
6422 return -1;
6423 }
6424
6425 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6426 rpc_printer_migrate_drivers_internals,
6427 argc, argv);
6428}
6429
6430/**
6431 * Migrate print-forms from a print-server
6432 *
6433 * @param argc Standard main() style argc
6434 * @param argv Standard main() style argv. Initial components are already
6435 * stripped
6436 *
6437 * @return A shell status integer (0 for success)
6438 **/
6439static int rpc_printer_migrate_forms(int argc, const char **argv)
6440{
6441 if (!opt_host) {
6442 printf("no server to migrate\n");
6443 return -1;
6444 }
6445
6446 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6447 rpc_printer_migrate_forms_internals,
6448 argc, argv);
6449}
6450
6451/**
6452 * Migrate printers from a print-server
6453 *
6454 * @param argc Standard main() style argc
6455 * @param argv Standard main() style argv. Initial components are already
6456 * stripped
6457 *
6458 * @return A shell status integer (0 for success)
6459 **/
6460static int rpc_printer_migrate_printers(int argc, const char **argv)
6461{
6462 if (!opt_host) {
6463 printf("no server to migrate\n");
6464 return -1;
6465 }
6466
6467 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6468 rpc_printer_migrate_printers_internals,
6469 argc, argv);
6470}
6471
6472/**
6473 * Migrate printer-ACLs from a print-server
6474 *
6475 * @param argc Standard main() style argc
6476 * @param argv Standard main() style argv. Initial components are already
6477 * stripped
6478 *
6479 * @return A shell status integer (0 for success)
6480 **/
6481static int rpc_printer_migrate_security(int argc, const char **argv)
6482{
6483 if (!opt_host) {
6484 printf("no server to migrate\n");
6485 return -1;
6486 }
6487
6488 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6489 rpc_printer_migrate_security_internals,
6490 argc, argv);
6491}
6492
6493/**
6494 * Migrate printer-settings from a print-server
6495 *
6496 * @param argc Standard main() style argc
6497 * @param argv Standard main() style argv. Initial components are already
6498 * stripped
6499 *
6500 * @return A shell status integer (0 for success)
6501 **/
6502static int rpc_printer_migrate_settings(int argc, const char **argv)
6503{
6504 if (!opt_host) {
6505 printf("no server to migrate\n");
6506 return -1;
6507 }
6508
6509 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6510 rpc_printer_migrate_settings_internals,
6511 argc, argv);
6512}
6513
6514/**
6515 * 'net rpc printer' entrypoint.
6516 * @param argc Standard main() style argc
6517 * @param argv Standard main() style argv. Initial components are already
6518 * stripped
6519 **/
6520
6521int rpc_printer_migrate(int argc, const char **argv)
6522{
6523
6524 /* ouch: when addriver and setdriver are called from within
6525 rpc_printer_migrate_drivers_internals, the printer-queue already
6526 *has* to exist */
6527
6528 struct functable func[] = {
6529 {"all", rpc_printer_migrate_all},
6530 {"drivers", rpc_printer_migrate_drivers},
6531 {"forms", rpc_printer_migrate_forms},
6532 {"help", rpc_printer_usage},
6533 {"printers", rpc_printer_migrate_printers},
6534 {"security", rpc_printer_migrate_security},
6535 {"settings", rpc_printer_migrate_settings},
6536 {NULL, NULL}
6537 };
6538
6539 return net_run_function(argc, argv, func, rpc_printer_usage);
6540}
6541
6542
6543/**
6544 * List printers on a remote RPC server
6545 *
6546 * @param argc Standard main() style argc
6547 * @param argv Standard main() style argv. Initial components are already
6548 * stripped
6549 *
6550 * @return A shell status integer (0 for success)
6551 **/
6552static int rpc_printer_list(int argc, const char **argv)
6553{
6554
6555 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6556 rpc_printer_list_internals,
6557 argc, argv);
6558}
6559
6560/**
6561 * List printer-drivers on a remote RPC server
6562 *
6563 * @param argc Standard main() style argc
6564 * @param argv Standard main() style argv. Initial components are already
6565 * stripped
6566 *
6567 * @return A shell status integer (0 for success)
6568 **/
6569static int rpc_printer_driver_list(int argc, const char **argv)
6570{
6571
6572 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6573 rpc_printer_driver_list_internals,
6574 argc, argv);
6575}
6576
6577/**
6578 * Publish printer in ADS via MSRPC
6579 *
6580 * @param argc Standard main() style argc
6581 * @param argv Standard main() style argv. Initial components are already
6582 * stripped
6583 *
6584 * @return A shell status integer (0 for success)
6585 **/
6586static int rpc_printer_publish_publish(int argc, const char **argv)
6587{
6588
6589 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6590 rpc_printer_publish_publish_internals,
6591 argc, argv);
6592}
6593
6594/**
6595 * Update printer in ADS via MSRPC
6596 *
6597 * @param argc Standard main() style argc
6598 * @param argv Standard main() style argv. Initial components are already
6599 * stripped
6600 *
6601 * @return A shell status integer (0 for success)
6602 **/
6603static int rpc_printer_publish_update(int argc, const char **argv)
6604{
6605
6606 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6607 rpc_printer_publish_update_internals,
6608 argc, argv);
6609}
6610
6611/**
6612 * UnPublish printer in ADS via MSRPC
6613 *
6614 * @param argc Standard main() style argc
6615 * @param argv Standard main() style argv. Initial components are already
6616 * stripped
6617 *
6618 * @return A shell status integer (0 for success)
6619 **/
6620static int rpc_printer_publish_unpublish(int argc, const char **argv)
6621{
6622
6623 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6624 rpc_printer_publish_unpublish_internals,
6625 argc, argv);
6626}
6627
6628/**
6629 * List published printers via MSRPC
6630 *
6631 * @param argc Standard main() style argc
6632 * @param argv Standard main() style argv. Initial components are already
6633 * stripped
6634 *
6635 * @return A shell status integer (0 for success)
6636 **/
6637static int rpc_printer_publish_list(int argc, const char **argv)
6638{
6639
6640 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6641 rpc_printer_publish_list_internals,
6642 argc, argv);
6643}
6644
6645
6646/**
6647 * Publish printer in ADS
6648 *
6649 * @param argc Standard main() style argc
6650 * @param argv Standard main() style argv. Initial components are already
6651 * stripped
6652 *
6653 * @return A shell status integer (0 for success)
6654 **/
6655static int rpc_printer_publish(int argc, const char **argv)
6656{
6657
6658 struct functable func[] = {
6659 {"publish", rpc_printer_publish_publish},
6660 {"update", rpc_printer_publish_update},
6661 {"unpublish", rpc_printer_publish_unpublish},
6662 {"list", rpc_printer_publish_list},
6663 {"help", rpc_printer_usage},
6664 {NULL, NULL}
6665 };
6666
6667 if (argc == 0)
6668 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6669 rpc_printer_publish_list_internals,
6670 argc, argv);
6671
6672 return net_run_function(argc, argv, func, rpc_printer_usage);
6673
6674}
6675
6676
6677/**
6678 * Display rpc printer help page.
6679 * @param argc Standard main() style argc
6680 * @param argv Standard main() style argv. Initial components are already
6681 * stripped
6682 **/
6683int rpc_printer_usage(int argc, const char **argv)
6684{
6685 return net_help_printer(argc, argv);
6686}
6687
6688/**
6689 * 'net rpc printer' entrypoint.
6690 * @param argc Standard main() style argc
6691 * @param argv Standard main() style argv. Initial components are already
6692 * stripped
6693 **/
6694int net_rpc_printer(int argc, const char **argv)
6695{
6696 struct functable func[] = {
6697 {"list", rpc_printer_list},
6698 {"migrate", rpc_printer_migrate},
6699 {"driver", rpc_printer_driver_list},
6700 {"publish", rpc_printer_publish},
6701 {NULL, NULL}
6702 };
6703
6704 if (argc == 0)
6705 return run_rpc_command(NULL, PI_SPOOLSS, 0,
6706 rpc_printer_list_internals,
6707 argc, argv);
6708
6709 return net_run_function(argc, argv, func, rpc_printer_usage);
6710}
6711
6712/****************************************************************************/
6713
6714
6715/**
6716 * Basic usage function for 'net rpc'
6717 * @param argc Standard main() style argc
6718 * @param argv Standard main() style argv. Initial components are already
6719 * stripped
6720 **/
6721
6722int net_rpc_usage(int argc, const char **argv)
6723{
6724 d_printf(" net rpc info \t\t\tshow basic info about a domain \n");
6725 d_printf(" net rpc join \t\t\tto join a domain \n");
6726 d_printf(" net rpc oldjoin \t\t\tto join a domain created in server manager\n");
6727 d_printf(" net rpc testjoin \t\ttests that a join is valid\n");
6728 d_printf(" net rpc user \t\t\tto add, delete and list users\n");
6729 d_printf(" net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
6730 d_printf(" net rpc group \t\tto list groups\n");
6731 d_printf(" net rpc share \t\tto add, delete, list and migrate shares\n");
6732 d_printf(" net rpc printer \t\tto list and migrate printers\n");
6733 d_printf(" net rpc file \t\t\tto list open files\n");
6734 d_printf(" net rpc changetrustpw \tto change the trust account password\n");
6735 d_printf(" net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
6736 d_printf(" net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
6737 d_printf(" net rpc samdump \t\tdiplay an NT PDC's users, groups and other data\n");
6738 d_printf(" net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
6739 d_printf(" net rpc abortshutdown \tto abort the shutdown of a remote server\n");
6740 d_printf(" net rpc shutdown \t\tto shutdown a remote server\n");
6741 d_printf(" net rpc rights\t\tto manage privileges assigned to SIDs\n");
6742 d_printf(" net rpc registry\t\tto manage registry hives\n");
6743 d_printf(" net rpc service\t\tto start, stop and query services\n");
6744 d_printf(" net rpc audit\t\t\tto modify global auditing settings\n");
6745 d_printf(" net rpc shell\t\t\tto open an interactive shell for remote server/account management\n");
6746 d_printf("\n");
6747 d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
6748 d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
6749 d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
6750 d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
6751 d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
6752 return -1;
6753}
6754
6755
6756/**
6757 * Help function for 'net rpc'. Calls command specific help if requested
6758 * or displays usage of net rpc
6759 * @param argc Standard main() style argc
6760 * @param argv Standard main() style argv. Initial components are already
6761 * stripped
6762 **/
6763
6764int net_rpc_help(int argc, const char **argv)
6765{
6766 struct functable func[] = {
6767 {"join", rpc_join_usage},
6768 {"user", rpc_user_usage},
6769 {"group", rpc_group_usage},
6770 {"share", rpc_share_usage},
6771 /*{"changetrustpw", rpc_changetrustpw_usage}, */
6772 {"trustdom", rpc_trustdom_usage},
6773 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
6774 /*{"shutdown", rpc_shutdown_usage}, */
6775 {"vampire", rpc_vampire_usage},
6776 {NULL, NULL}
6777 };
6778
6779 if (argc == 0) {
6780 net_rpc_usage(argc, argv);
6781 return -1;
6782 }
6783
6784 return (net_run_function(argc, argv, func, rpc_user_usage));
6785}
6786
6787/**
6788 * 'net rpc' entrypoint.
6789 * @param argc Standard main() style argc
6790 * @param argv Standard main() style argv. Initial components are already
6791 * stripped
6792 **/
6793
6794int net_rpc(int argc, const char **argv)
6795{
6796 struct functable func[] = {
6797 {"audit", net_rpc_audit},
6798 {"info", net_rpc_info},
6799 {"join", net_rpc_join},
6800 {"oldjoin", net_rpc_oldjoin},
6801 {"testjoin", net_rpc_testjoin},
6802 {"user", net_rpc_user},
6803 {"password", rpc_user_password},
6804 {"group", net_rpc_group},
6805 {"share", net_rpc_share},
6806 {"file", net_rpc_file},
6807 {"printer", net_rpc_printer},
6808 {"changetrustpw", net_rpc_changetrustpw},
6809 {"trustdom", rpc_trustdom},
6810 {"abortshutdown", rpc_shutdown_abort},
6811 {"shutdown", rpc_shutdown},
6812 {"samdump", rpc_samdump},
6813 {"vampire", rpc_vampire},
6814 {"getsid", net_rpc_getsid},
6815 {"rights", net_rpc_rights},
6816 {"service", net_rpc_service},
6817 {"registry", net_rpc_registry},
6818 {"shell", net_rpc_shell},
6819 {"help", net_rpc_help},
6820 {NULL, NULL}
6821 };
6822 return net_run_function(argc, argv, func, net_rpc_usage);
6823}
Note: See TracBrowser for help on using the repository browser.