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