Fix shutdown callers.
[samba.git] / source3 / 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_to_ascii_talloc(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_to_ascii_talloc(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_to_ascii_talloc(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         WERROR 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
3029         if ((sharename = talloc_strdup(mem_ctx, argv[0])) == NULL) {
3030                 return NT_STATUS_NO_MEMORY;
3031         }
3032
3033         path = strchr(sharename, '=');
3034         if (!path)
3035                 return NT_STATUS_UNSUCCESSFUL;
3036         *path++ = '\0';
3037
3038         result = rpccli_srvsvc_net_share_add(pipe_hnd, mem_ctx, sharename, type,
3039                                           opt_comment, perms, opt_maxusers,
3040                                           num_users, path, password, 
3041                                           level, NULL);
3042         return werror_to_ntstatus(result);
3043 }
3044
3045 static int rpc_share_add(int argc, const char **argv)
3046 {
3047         if ((argc < 1) || !strchr(argv[0], '=')) {
3048                 DEBUG(1,("Sharename or path not specified on add\n"));
3049                 return rpc_share_usage(argc, argv);
3050         }
3051         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3052                                rpc_share_add_internals,
3053                                argc, argv);
3054 }
3055
3056 /** 
3057  * Delete a share on a remote RPC server
3058  *
3059  * All parameters are provided by the run_rpc_command function, except for
3060  * argc, argv which are passes through. 
3061  *
3062  * @param domain_sid The domain sid acquired from the remote server
3063  * @param cli A cli_state connected to the server.
3064  * @param mem_ctx Talloc context, destoyed on completion of the function.
3065  * @param argc  Standard main() style argc
3066  * @param argv  Standard main() style argv.  Initial components are already
3067  *              stripped
3068  *
3069  * @return Normal NTSTATUS return.
3070  **/
3071 static NTSTATUS rpc_share_del_internals(const DOM_SID *domain_sid,
3072                                         const char *domain_name, 
3073                                         struct cli_state *cli,
3074                                         struct rpc_pipe_client *pipe_hnd,
3075                                         TALLOC_CTX *mem_ctx,
3076                                         int argc,
3077                                         const char **argv)
3078 {
3079         WERROR result;
3080
3081         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
3082         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3083 }
3084
3085 /** 
3086  * Delete a share on a remote RPC server
3087  *
3088  * @param domain_sid The domain sid acquired from the remote server
3089  * @param argc  Standard main() style argc
3090  * @param argv  Standard main() style argv.  Initial components are already
3091  *              stripped
3092  *
3093  * @return A shell status integer (0 for success)
3094  **/
3095 static int rpc_share_delete(int argc, const char **argv)
3096 {
3097         if (argc < 1) {
3098                 DEBUG(1,("Sharename not specified on delete\n"));
3099                 return rpc_share_usage(argc, argv);
3100         }
3101         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3102                                rpc_share_del_internals,
3103                                argc, argv);
3104 }
3105
3106 /**
3107  * Formatted print of share info
3108  *
3109  * @param info1  pointer to SRV_SHARE_INFO_1 to format
3110  **/
3111  
3112 static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
3113 {
3114         fstring netname = "", remark = "";
3115
3116         rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
3117         rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
3118
3119         if (opt_long_list_entries) {
3120                 d_printf("%-12s %-8.8s %-50s\n",
3121                          netname, share_type[info1->info_1.type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)], remark);
3122         } else {
3123                 d_printf("%s\n", netname);
3124         }
3125
3126 }
3127
3128 static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd,
3129                                 TALLOC_CTX *mem_ctx, 
3130                                 uint32 level,
3131                                 int argc,
3132                                 const char **argv, 
3133                                 SRV_SHARE_INFO_CTR *ctr)
3134 {
3135         WERROR result;
3136         SRV_SHARE_INFO info;
3137
3138         /* no specific share requested, enumerate all */
3139         if (argc == 0) {
3140
3141                 ENUM_HND hnd;
3142                 uint32 preferred_len = 0xffffffff;
3143
3144                 init_enum_hnd(&hnd, 0);
3145
3146                 return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr, 
3147                                                  preferred_len, &hnd);
3148         }
3149
3150         /* request just one share */
3151         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info);
3152
3153         if (!W_ERROR_IS_OK(result))
3154                 goto done;
3155
3156         /* construct ctr */
3157         ZERO_STRUCTP(ctr);
3158
3159         ctr->info_level = ctr->switch_value = level;
3160         ctr->ptr_share_info = ctr->ptr_entries = 1;
3161         ctr->num_entries = ctr->num_entries2 = 1;
3162
3163         switch (level) {
3164         case 1:
3165         {
3166                 char *s;
3167                 SRV_SHARE_INFO_1 *info1;
3168                 
3169                 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
3170                 if (ctr->share.info1 == NULL) {
3171                         result = WERR_NOMEM;
3172                         goto done;
3173                 }
3174                 info1 = ctr->share.info1;
3175                                 
3176                 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
3177
3178                 /* Copy pointer crap */
3179
3180                 memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
3181
3182                 /* Duplicate strings */
3183
3184                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info1.info_1_str.uni_netname);
3185                 if (s)
3186                         init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
3187
3188                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info1.info_1_str.uni_remark);
3189                 if (s)
3190                         init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
3191         }
3192         case 2:
3193         {
3194                 char *s;
3195                 SRV_SHARE_INFO_2 *info2;
3196                 
3197                 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
3198                 if (ctr->share.info2 == NULL) {
3199                         result = WERR_NOMEM;
3200                         goto done;
3201                 }
3202                 info2 = ctr->share.info2;
3203                                 
3204                 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
3205
3206                 /* Copy pointer crap */
3207
3208                 memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
3209
3210                 /* Duplicate strings */
3211
3212                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_netname);
3213                 if (s)
3214                         init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
3215
3216                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_remark);
3217                 if (s)
3218                         init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
3219
3220                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_path);
3221                 if (s)
3222                         init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
3223
3224                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
3225                 if (s)
3226                         init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
3227         }
3228         case 502:
3229         {
3230                 char *s;
3231                 SRV_SHARE_INFO_502 *info502;
3232
3233                 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
3234                 if (ctr->share.info502 == NULL) {
3235                         result = WERR_NOMEM;
3236                         goto done;
3237                 }
3238                 info502 = ctr->share.info502;
3239
3240                 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
3241
3242                 /* Copy pointer crap */
3243
3244                 memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
3245
3246                 /* Duplicate strings */
3247
3248                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_netname);
3249                 if (s)
3250                         init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
3251
3252                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_remark);
3253                 if (s)
3254                         init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
3255
3256                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_path);
3257                 if (s)
3258                         init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
3259
3260                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
3261                 if (s)
3262                         init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
3263
3264                 info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
3265                                 
3266         }
3267
3268         } /* switch */
3269
3270 done:
3271         return result;
3272 }
3273
3274 /** 
3275  * List shares on a remote RPC server
3276  *
3277  * All parameters are provided by the run_rpc_command function, except for
3278  * argc, argv which are passes through. 
3279  *
3280  * @param domain_sid The domain sid acquired from the remote server
3281  * @param cli A cli_state connected to the server.
3282  * @param mem_ctx Talloc context, destoyed on completion of the function.
3283  * @param argc  Standard main() style argc
3284  * @param argv  Standard main() style argv.  Initial components are already
3285  *              stripped
3286  *
3287  * @return Normal NTSTATUS return.
3288  **/
3289
3290 static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid,
3291                                         const char *domain_name, 
3292                                         struct cli_state *cli,
3293                                         struct rpc_pipe_client *pipe_hnd,
3294                                         TALLOC_CTX *mem_ctx,
3295                                         int argc,
3296                                         const char **argv)
3297 {
3298         SRV_SHARE_INFO_CTR ctr;
3299         WERROR result;
3300         uint32 i, level = 1;
3301
3302         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr);
3303         if (!W_ERROR_IS_OK(result))
3304                 goto done;
3305
3306         /* Display results */
3307
3308         if (opt_long_list_entries) {
3309                 d_printf(
3310         "\nEnumerating shared resources (exports) on remote server:\n\n"\
3311         "\nShare name   Type     Description\n"\
3312         "----------   ----     -----------\n");
3313         }
3314         for (i = 0; i < ctr.num_entries; i++)
3315                 display_share_info_1(&ctr.share.info1[i]);
3316  done:
3317         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3318 }
3319
3320 /*** 
3321  * 'net rpc share list' entrypoint.
3322  * @param argc  Standard main() style argc
3323  * @param argv  Standard main() style argv.  Initial components are already
3324  *              stripped
3325  **/
3326 static int rpc_share_list(int argc, const char **argv)
3327 {
3328         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
3329 }
3330
3331 static bool check_share_availability(struct cli_state *cli, const char *netname)
3332 {
3333         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3334                 d_printf("skipping   [%s]: not a file share.\n", netname);
3335                 return False;
3336         }
3337
3338         if (!cli_tdis(cli)) 
3339                 return False;
3340
3341         return True;
3342 }
3343
3344 static bool check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
3345 {
3346         /* only support disk shares */
3347         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3348                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3349                 return False;
3350         }
3351
3352         /* skip builtin shares */
3353         /* FIXME: should print$ be added too ? */
3354         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") || 
3355             strequal(netname,"global")) 
3356                 return False;
3357
3358         if (opt_exclude && in_list(netname, opt_exclude, False)) {
3359                 printf("excluding  [%s]\n", netname);
3360                 return False;
3361         }
3362
3363         return check_share_availability(cli, netname);
3364 }
3365
3366 /** 
3367  * Migrate shares from a remote RPC server to the local RPC srever
3368  *
3369  * All parameters are provided by the run_rpc_command function, except for
3370  * argc, argv which are passes through. 
3371  *
3372  * @param domain_sid The domain sid acquired from the remote server
3373  * @param cli A cli_state connected to the server.
3374  * @param mem_ctx Talloc context, destoyed on completion of the function.
3375  * @param argc  Standard main() style argc
3376  * @param argv  Standard main() style argv.  Initial components are already
3377  *              stripped
3378  *
3379  * @return Normal NTSTATUS return.
3380  **/
3381
3382 static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid,
3383                                                 const char *domain_name, 
3384                                                 struct cli_state *cli,
3385                                                 struct rpc_pipe_client *pipe_hnd,
3386                                                 TALLOC_CTX *mem_ctx, 
3387                                                 int argc,
3388                                                 const char **argv)
3389 {
3390         WERROR result;
3391         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3392         SRV_SHARE_INFO_CTR ctr_src;
3393         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3394         char *password = NULL; /* don't allow a share password */
3395         uint32 i;
3396         struct rpc_pipe_client *srvsvc_pipe = NULL;
3397         struct cli_state *cli_dst = NULL;
3398         uint32 level = 502; /* includes secdesc */
3399
3400         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3401         if (!W_ERROR_IS_OK(result))
3402                 goto done;
3403
3404         /* connect destination PI_SRVSVC */
3405         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3406         if (!NT_STATUS_IS_OK(nt_status))
3407                 return nt_status;
3408
3409
3410         for (i = 0; i < ctr_src.num_entries; i++) {
3411
3412                 fstring netname = "", remark = "", path = "";
3413                 /* reset error-code */
3414                 nt_status = NT_STATUS_UNSUCCESSFUL;
3415
3416                 rpcstr_pull_unistr2_fstring(
3417                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3418                 rpcstr_pull_unistr2_fstring(
3419                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3420                 rpcstr_pull_unistr2_fstring(
3421                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
3422
3423                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3424                         continue;
3425
3426                 /* finally add the share on the dst server */ 
3427
3428                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
3429                         netname, path, remark);
3430
3431                 result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark,
3432                                                   ctr_src.share.info502[i].info_502.perms,
3433                                                   ctr_src.share.info502[i].info_502.max_uses,
3434                                                   ctr_src.share.info502[i].info_502.num_uses,
3435                                                   path, password, level, 
3436                                                   NULL);
3437         
3438                 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
3439                         printf("           [%s] does already exist\n", netname);
3440                         continue;
3441                 }
3442
3443                 if (!W_ERROR_IS_OK(result)) {
3444                         printf("cannot add share: %s\n", dos_errstr(result));
3445                         goto done;
3446                 }
3447
3448         }
3449
3450         nt_status = NT_STATUS_OK;
3451
3452 done:
3453         if (cli_dst) {
3454                 cli_shutdown(cli_dst);
3455         }
3456
3457         return nt_status;
3458
3459 }
3460
3461 /** 
3462  * Migrate shares from a rpc-server to another
3463  *
3464  * @param argc  Standard main() style argc
3465  * @param argv  Standard main() style argv.  Initial components are already
3466  *              stripped
3467  *
3468  * @return A shell status integer (0 for success)
3469  **/
3470 static int rpc_share_migrate_shares(int argc, const char **argv)
3471 {
3472
3473         if (!opt_host) {
3474                 printf("no server to migrate\n");
3475                 return -1;
3476         }
3477
3478         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3479                                rpc_share_migrate_shares_internals,
3480                                argc, argv);
3481 }
3482
3483 /**
3484  * Copy a file/dir 
3485  *
3486  * @param f     file_info
3487  * @param mask  current search mask
3488  * @param state arg-pointer
3489  *
3490  **/
3491 static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
3492 {
3493         static NTSTATUS nt_status;
3494         static struct copy_clistate *local_state;
3495         static fstring filename, new_mask;
3496         fstring dir;
3497         char *old_dir;
3498
3499         local_state = (struct copy_clistate *)state;
3500         nt_status = NT_STATUS_UNSUCCESSFUL;
3501
3502         if (strequal(f->name, ".") || strequal(f->name, ".."))
3503                 return;
3504
3505         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3506
3507         /* DIRECTORY */
3508         if (f->mode & aDIR) {
3509
3510                 DEBUG(3,("got dir: %s\n", f->name));
3511
3512                 fstrcpy(dir, local_state->cwd);
3513                 fstrcat(dir, "\\");
3514                 fstrcat(dir, f->name);
3515
3516                 switch (net_mode_share)
3517                 {
3518                 case NET_MODE_SHARE_MIGRATE:
3519                         /* create that directory */
3520                         nt_status = net_copy_file(local_state->mem_ctx,
3521                                                   local_state->cli_share_src,
3522                                                   local_state->cli_share_dst,
3523                                                   dir, dir,
3524                                                   opt_acls? True : False,
3525                                                   opt_attrs? True : False,
3526                                                   opt_timestamps? True : False,
3527                                                   False);
3528                         break;
3529                 default:
3530                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3531                         return;
3532                 }
3533
3534                 if (!NT_STATUS_IS_OK(nt_status)) 
3535                         printf("could not handle dir %s: %s\n", 
3536                                 dir, nt_errstr(nt_status));
3537
3538                 /* search below that directory */
3539                 fstrcpy(new_mask, dir);
3540                 fstrcat(new_mask, "\\*");
3541
3542                 old_dir = local_state->cwd;
3543                 local_state->cwd = dir;
3544                 if (!sync_files(local_state, new_mask))
3545                         printf("could not handle files\n");
3546                 local_state->cwd = old_dir;
3547
3548                 return;
3549         }
3550
3551
3552         /* FILE */
3553         fstrcpy(filename, local_state->cwd);
3554         fstrcat(filename, "\\");
3555         fstrcat(filename, f->name);
3556
3557         DEBUG(3,("got file: %s\n", filename));
3558
3559         switch (net_mode_share)
3560         {
3561         case NET_MODE_SHARE_MIGRATE:
3562                 nt_status = net_copy_file(local_state->mem_ctx, 
3563                                           local_state->cli_share_src, 
3564                                           local_state->cli_share_dst, 
3565                                           filename, filename, 
3566                                           opt_acls? True : False, 
3567                                           opt_attrs? True : False,
3568                                           opt_timestamps? True: False,
3569                                           True);
3570                 break;
3571         default:
3572                 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3573                 return;
3574         }
3575
3576         if (!NT_STATUS_IS_OK(nt_status)) 
3577                 printf("could not handle file %s: %s\n", 
3578                         filename, nt_errstr(nt_status));
3579
3580 }
3581
3582 /**
3583  * sync files, can be called recursivly to list files 
3584  * and then call copy_fn for each file 
3585  *
3586  * @param cp_clistate   pointer to the copy_clistate we work with
3587  * @param mask          the current search mask
3588  *
3589  * @return              Boolean result
3590  **/
3591 bool sync_files(struct copy_clistate *cp_clistate, pstring mask)
3592 {
3593         struct cli_state *targetcli;
3594         char *targetpath = NULL;
3595
3596         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3597
3598         if ( !cli_resolve_path(talloc_tos(), "", cp_clistate->cli_share_src,
3599                                 mask, &targetcli, &targetpath ) ) {
3600                 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", 
3601                         mask, cli_errstr(cp_clistate->cli_share_src));
3602                 return False;
3603         }
3604
3605         if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3606                 d_fprintf(stderr, "listing %s failed with error: %s\n", 
3607                         mask, cli_errstr(targetcli));
3608                 return False;
3609         }
3610
3611         return True;
3612 }
3613
3614
3615 /**
3616  * Set the top level directory permissions before we do any further copies.
3617  * Should set up ACL inheritance.
3618  **/
3619
3620 bool copy_top_level_perms(struct copy_clistate *cp_clistate, 
3621                                 const char *sharename)
3622 {
3623         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3624
3625         switch (net_mode_share) {
3626         case NET_MODE_SHARE_MIGRATE:
3627                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3628                 nt_status = net_copy_fileattr(cp_clistate->mem_ctx,
3629                                                 cp_clistate->cli_share_src, 
3630                                                 cp_clistate->cli_share_dst,
3631                                                 "\\", "\\",
3632                                                 opt_acls? True : False, 
3633                                                 opt_attrs? True : False,
3634                                                 opt_timestamps? True: False,
3635                                                 False);
3636                 break;
3637         default:
3638                 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3639                 break;
3640         }
3641
3642         if (!NT_STATUS_IS_OK(nt_status))  {
3643                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
3644                         sharename, nt_errstr(nt_status));
3645                 return False;
3646         }
3647
3648         return True;
3649 }
3650
3651 /** 
3652  * Sync all files inside a remote share to another share (over smb)
3653  *
3654  * All parameters are provided by the run_rpc_command function, except for
3655  * argc, argv which are passes through. 
3656  *
3657  * @param domain_sid The domain sid acquired from the remote server
3658  * @param cli A cli_state connected to the server.
3659  * @param mem_ctx Talloc context, destoyed on completion of the function.
3660  * @param argc  Standard main() style argc
3661  * @param argv  Standard main() style argv.  Initial components are already
3662  *              stripped
3663  *
3664  * @return Normal NTSTATUS return.
3665  **/
3666
3667 static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid,
3668                                                 const char *domain_name, 
3669                                                 struct cli_state *cli,
3670                                                 struct rpc_pipe_client *pipe_hnd,
3671                                                 TALLOC_CTX *mem_ctx,
3672                                                 int argc,
3673                                                 const char **argv)
3674 {
3675         WERROR result;
3676         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3677         SRV_SHARE_INFO_CTR ctr_src;
3678         uint32 i;
3679         uint32 level = 502;
3680         struct copy_clistate cp_clistate;
3681         bool got_src_share = False;
3682         bool got_dst_share = False;
3683         pstring mask = "\\*";
3684         char *dst = NULL;
3685
3686         dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
3687
3688         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3689
3690         if (!W_ERROR_IS_OK(result))
3691                 goto done;
3692
3693         for (i = 0; i < ctr_src.num_entries; i++) {
3694
3695                 fstring netname = "";
3696
3697                 rpcstr_pull_unistr2_fstring(
3698                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3699
3700                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3701                         continue;
3702
3703                 /* one might not want to mirror whole discs :) */
3704                 if (strequal(netname, "print$") || netname[1] == '$') {
3705                         d_printf("skipping   [%s]: builtin/hidden share\n", netname);
3706                         continue;
3707                 }
3708
3709                 switch (net_mode_share)
3710                 {
3711                 case NET_MODE_SHARE_MIGRATE:
3712                         printf("syncing");
3713                         break;
3714                 default:
3715                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3716                         break;
3717                 }
3718                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
3719                         netname, 
3720                         opt_acls ? "including" : "without", 
3721                         opt_attrs ? "including" : "without",
3722                         opt_timestamps ? "(preserving timestamps)" : "");
3723
3724                 cp_clistate.mem_ctx = mem_ctx;
3725                 cp_clistate.cli_share_src = NULL;
3726                 cp_clistate.cli_share_dst = NULL;
3727                 cp_clistate.cwd = NULL;
3728                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3729
3730                 /* open share source */
3731                 nt_status = connect_to_service(&cp_clistate.cli_share_src,
3732                                                &cli->dest_ss, cli->desthost,
3733                                                netname, "A:");
3734                 if (!NT_STATUS_IS_OK(nt_status))
3735                         goto done;
3736
3737                 got_src_share = True;
3738
3739                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3740                         /* open share destination */
3741                         nt_status = connect_to_service(&cp_clistate.cli_share_dst,
3742                                                        NULL, dst, netname, "A:");
3743                         if (!NT_STATUS_IS_OK(nt_status))
3744                                 goto done;
3745
3746                         got_dst_share = True;
3747                 }
3748
3749                 if (!copy_top_level_perms(&cp_clistate, netname)) {
3750                         d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", netname);
3751                         nt_status = NT_STATUS_UNSUCCESSFUL;
3752                         goto done;
3753                 }
3754
3755                 if (!sync_files(&cp_clistate, mask)) {
3756                         d_fprintf(stderr, "could not handle files for share: %s\n", netname);
3757                         nt_status = NT_STATUS_UNSUCCESSFUL;
3758                         goto done;
3759                 }
3760         }
3761
3762         nt_status = NT_STATUS_OK;
3763
3764 done:
3765
3766         if (got_src_share)
3767                 cli_shutdown(cp_clistate.cli_share_src);
3768
3769         if (got_dst_share)
3770                 cli_shutdown(cp_clistate.cli_share_dst);
3771
3772         return nt_status;
3773
3774 }
3775
3776 static int rpc_share_migrate_files(int argc, const char **argv)
3777 {
3778
3779         if (!opt_host) {
3780                 printf("no server to migrate\n");
3781                 return -1;
3782         }
3783
3784         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3785                                rpc_share_migrate_files_internals,
3786                                argc, argv);
3787 }
3788
3789 /** 
3790  * Migrate share-ACLs from a remote RPC server to the local RPC srever
3791  *
3792  * All parameters are provided by the run_rpc_command function, except for
3793  * argc, argv which are passes through. 
3794  *
3795  * @param domain_sid The domain sid acquired from the remote server
3796  * @param cli A cli_state connected to the server.
3797  * @param mem_ctx Talloc context, destoyed on completion of the function.
3798  * @param argc  Standard main() style argc
3799  * @param argv  Standard main() style argv.  Initial components are already
3800  *              stripped
3801  *
3802  * @return Normal NTSTATUS return.
3803  **/
3804
3805 static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid,
3806                                                 const char *domain_name, 
3807                                                 struct cli_state *cli,
3808                                                 struct rpc_pipe_client *pipe_hnd,
3809                                                 TALLOC_CTX *mem_ctx, 
3810                                                 int argc,
3811                                                 const char **argv)
3812 {
3813         WERROR result;
3814         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3815         SRV_SHARE_INFO_CTR ctr_src;
3816         SRV_SHARE_INFO info;
3817         uint32 i;
3818         struct rpc_pipe_client *srvsvc_pipe = NULL;
3819         struct cli_state *cli_dst = NULL;
3820         uint32 level = 502; /* includes secdesc */
3821
3822         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3823
3824         if (!W_ERROR_IS_OK(result))
3825                 goto done;
3826
3827         /* connect destination PI_SRVSVC */
3828         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3829         if (!NT_STATUS_IS_OK(nt_status))
3830                 return nt_status;
3831
3832
3833         for (i = 0; i < ctr_src.num_entries; i++) {
3834
3835                 fstring netname = "", remark = "", path = "";
3836                 /* reset error-code */
3837                 nt_status = NT_STATUS_UNSUCCESSFUL;
3838
3839                 rpcstr_pull_unistr2_fstring(
3840                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3841                 rpcstr_pull_unistr2_fstring(
3842                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3843                 rpcstr_pull_unistr2_fstring(
3844                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
3845
3846                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3847                         continue;
3848
3849                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
3850                         netname, path, remark);
3851
3852                 if (opt_verbose)
3853                         display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
3854
3855                 /* init info */
3856                 ZERO_STRUCT(info);
3857
3858                 info.switch_value = level;
3859                 info.ptr_share_ctr = 1;
3860
3861                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3862                 info.share.info502 = ctr_src.share.info502[i];
3863
3864                 /* finally modify the share on the dst server */
3865                 result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info);
3866         
3867                 if (!W_ERROR_IS_OK(result)) {
3868                         printf("cannot set share-acl: %s\n", dos_errstr(result));
3869                         goto done;
3870                 }
3871
3872         }
3873
3874         nt_status = NT_STATUS_OK;
3875
3876 done:
3877         if (cli_dst) {
3878                 cli_shutdown(cli_dst);
3879         }
3880
3881         return nt_status;
3882
3883 }
3884
3885 /** 
3886  * Migrate share-acls from a rpc-server to another
3887  *
3888  * @param argc  Standard main() style argc
3889  * @param argv  Standard main() style argv.  Initial components are already
3890  *              stripped
3891  *
3892  * @return A shell status integer (0 for success)
3893  **/
3894 static int rpc_share_migrate_security(int argc, const char **argv)
3895 {
3896
3897         if (!opt_host) {
3898                 printf("no server to migrate\n");
3899                 return -1;
3900         }
3901
3902         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3903                                rpc_share_migrate_security_internals,
3904                                argc, argv);
3905 }
3906
3907 /** 
3908  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3909  * from one server to another
3910  *
3911  * @param argc  Standard main() style argc
3912  * @param argv  Standard main() style argv.  Initial components are already
3913  *              stripped
3914  *
3915  * @return A shell status integer (0 for success)
3916  *
3917  **/
3918 static int rpc_share_migrate_all(int argc, const char **argv)
3919 {
3920         int ret;
3921
3922         if (!opt_host) {
3923                 printf("no server to migrate\n");
3924                 return -1;
3925         }
3926
3927         /* order is important. we don't want to be locked out by the share-acl
3928          * before copying files - gd */
3929         
3930         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
3931         if (ret)
3932                 return ret;
3933
3934         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
3935         if (ret)
3936                 return ret;
3937         
3938         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
3939 }
3940
3941
3942 /** 
3943  * 'net rpc share migrate' entrypoint.
3944  * @param argc  Standard main() style argc
3945  * @param argv  Standard main() style argv.  Initial components are already
3946  *              stripped
3947  **/
3948 static int rpc_share_migrate(int argc, const char **argv)
3949 {
3950
3951         struct functable func[] = {
3952                 {"all",         rpc_share_migrate_all},
3953                 {"files",       rpc_share_migrate_files},
3954                 {"help",        rpc_share_usage},
3955                 {"security",    rpc_share_migrate_security},
3956                 {"shares",      rpc_share_migrate_shares},
3957                 {NULL, NULL}
3958         };
3959
3960         net_mode_share = NET_MODE_SHARE_MIGRATE;
3961
3962         return net_run_function(argc, argv, func, rpc_share_usage);
3963 }
3964
3965 struct full_alias {
3966         DOM_SID sid;
3967         uint32 num_members;
3968         DOM_SID *members;
3969 };
3970
3971 static int num_server_aliases;
3972 static struct full_alias *server_aliases;
3973
3974 /*
3975  * Add an alias to the static list.
3976  */
3977 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3978 {
3979         if (server_aliases == NULL)
3980                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3981
3982         server_aliases[num_server_aliases] = *alias;
3983         num_server_aliases += 1;
3984 }
3985
3986 /*
3987  * For a specific domain on the server, fetch all the aliases
3988  * and their members. Add all of them to the server_aliases.
3989  */
3990
3991 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
3992                                         TALLOC_CTX *mem_ctx,
3993                                         POLICY_HND *connect_pol,
3994                                         const DOM_SID *domain_sid)
3995 {
3996         uint32 start_idx, max_entries, num_entries, i;
3997         struct acct_info *groups;
3998         NTSTATUS result;
3999         POLICY_HND domain_pol;
4000
4001         /* Get domain policy handle */
4002         
4003         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, connect_pol,
4004                                       MAXIMUM_ALLOWED_ACCESS,
4005                                       domain_sid, &domain_pol);
4006         if (!NT_STATUS_IS_OK(result))
4007                 return result;
4008
4009         start_idx = 0;
4010         max_entries = 250;
4011
4012         do {
4013                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
4014                                                   &start_idx, max_entries,
4015                                                   &groups, &num_entries);
4016
4017                 for (i = 0; i < num_entries; i++) {
4018
4019                         POLICY_HND alias_pol;
4020                         struct full_alias alias;
4021                         DOM_SID *members;
4022                         int j;
4023
4024                         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
4025                                                      MAXIMUM_ALLOWED_ACCESS,
4026                                                      groups[i].rid,
4027                                                      &alias_pol);
4028                         if (!NT_STATUS_IS_OK(result))
4029                                 goto done;
4030
4031                         result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx,
4032                                                          &alias_pol,
4033                                                          &alias.num_members,
4034                                                          &members);
4035                         if (!NT_STATUS_IS_OK(result))
4036                                 goto done;
4037
4038                         result = rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol);
4039                         if (!NT_STATUS_IS_OK(result))
4040                                 goto done;
4041
4042                         alias.members = NULL;
4043
4044                         if (alias.num_members > 0) {
4045                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
4046
4047                                 for (j = 0; j < alias.num_members; j++)
4048                                         sid_copy(&alias.members[j],
4049                                                  &members[j]);
4050                         }
4051
4052                         sid_copy(&alias.sid, domain_sid);
4053                         sid_append_rid(&alias.sid, groups[i].rid);
4054
4055                         push_alias(mem_ctx, &alias);
4056                 }
4057         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4058
4059         result = NT_STATUS_OK;
4060
4061  done:
4062         rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
4063
4064         return result;
4065 }
4066
4067 /*
4068  * Dump server_aliases as names for debugging purposes.
4069  */
4070
4071 static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid,
4072                                 const char *domain_name,
4073                                 struct cli_state *cli,
4074                                 struct rpc_pipe_client *pipe_hnd,
4075                                 TALLOC_CTX *mem_ctx, 
4076                                 int argc,
4077                                 const char **argv)
4078 {
4079         int i;
4080         NTSTATUS result;
4081         POLICY_HND lsa_pol;
4082
4083         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
4084                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
4085                                      &lsa_pol);
4086         if (!NT_STATUS_IS_OK(result))
4087                 return result;
4088
4089         for (i=0; i<num_server_aliases; i++) {
4090                 char **names;
4091                 char **domains;
4092                 enum lsa_SidType *types;
4093                 int j;
4094
4095                 struct full_alias *alias = &server_aliases[i];
4096
4097                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4098                                              &alias->sid,
4099                                              &domains, &names, &types);
4100                 if (!NT_STATUS_IS_OK(result))
4101                         continue;
4102
4103                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4104
4105                 if (alias->num_members == 0) {
4106                         DEBUG(1, ("\n"));
4107                         continue;
4108                 }
4109
4110                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4111                                              alias->num_members,
4112                                              alias->members,
4113                                              &domains, &names, &types);
4114
4115                 if (!NT_STATUS_IS_OK(result) &&
4116                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4117                         continue;
4118
4119                 for (j=0; j<alias->num_members; j++)
4120                         DEBUG(1, ("%s\\%s (%d); ",
4121                                   domains[j] ? domains[j] : "*unknown*", 
4122                                   names[j] ? names[j] : "*unknown*",types[j]));
4123                 DEBUG(1, ("\n"));
4124         }
4125
4126         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4127
4128         return NT_STATUS_OK;
4129 }
4130
4131 /*
4132  * Fetch a list of all server aliases and their members into
4133  * server_aliases.
4134  */
4135
4136 static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid,
4137                                         const char *domain_name,
4138                                         struct cli_state *cli,
4139                                         struct rpc_pipe_client *pipe_hnd,
4140                                         TALLOC_CTX *mem_ctx, 
4141                                         int argc,
4142                                         const char **argv)
4143 {
4144         NTSTATUS result;
4145         POLICY_HND connect_pol;
4146
4147         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
4148                                   &connect_pol);
4149
4150         if (!NT_STATUS_IS_OK(result))
4151                 goto done;
4152         
4153         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4154                                           &global_sid_Builtin);
4155
4156         if (!NT_STATUS_IS_OK(result))
4157                 goto done;
4158         
4159         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4160                                           domain_sid);
4161
4162         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
4163  done:
4164         return result;
4165 }
4166
4167 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4168 {
4169         token->num_sids = 4;
4170
4171         if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4172                 d_fprintf(stderr, "malloc failed\n");
4173                 token->num_sids = 0;
4174                 return;
4175         }
4176
4177         token->user_sids[0] = *user_sid;
4178         sid_copy(&token->user_sids[1], &global_sid_World);
4179         sid_copy(&token->user_sids[2], &global_sid_Network);
4180         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4181 }
4182
4183 static void free_user_token(NT_USER_TOKEN *token)
4184 {
4185         SAFE_FREE(token->user_sids);
4186 }
4187
4188 static bool is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
4189 {
4190         int i;
4191
4192         for (i=0; i<token->num_sids; i++) {
4193                 if (sid_compare(sid, &token->user_sids[i]) == 0)
4194                         return True;
4195         }
4196         return False;
4197 }
4198
4199 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4200 {
4201         if (is_sid_in_token(token, sid))
4202                 return;
4203
4204         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4205         if (!token->user_sids) {
4206                 return;
4207         }
4208
4209         sid_copy(&token->user_sids[token->num_sids], sid);
4210
4211         token->num_sids += 1;
4212 }
4213
4214 struct user_token {
4215         fstring name;
4216         NT_USER_TOKEN token;
4217 };
4218
4219 static void dump_user_token(struct user_token *token)
4220 {
4221         int i;
4222
4223         d_printf("%s\n", token->name);
4224
4225         for (i=0; i<token->token.num_sids; i++) {
4226                 d_printf(" %s\n", sid_string_static(&token->token.user_sids[i]));
4227         }
4228 }
4229
4230 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4231 {
4232         int i;
4233
4234         for (i=0; i<alias->num_members; i++) {
4235                 if (sid_compare(sid, &alias->members[i]) == 0)
4236                         return True;
4237         }
4238
4239         return False;
4240 }
4241
4242 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4243 {
4244         int i;
4245
4246         for (i=0; i<num_server_aliases; i++) {
4247                 if (is_alias_member(&sid, &server_aliases[i]))
4248                         add_sid_to_token(token, &server_aliases[i].sid);
4249         }
4250 }
4251
4252 /*
4253  * We got a user token with all the SIDs we can know about without asking the
4254  * server directly. These are the user and domain group sids. All of these can
4255  * be members of aliases. So scan the list of aliases for each of the SIDs and
4256  * add them to the token.
4257  */
4258
4259 static void collect_alias_memberships(NT_USER_TOKEN *token)
4260 {
4261         int num_global_sids = token->num_sids;
4262         int i;
4263
4264         for (i=0; i<num_global_sids; i++) {
4265                 collect_sid_memberships(token, token->user_sids[i]);
4266         }
4267 }
4268
4269 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4270 {
4271         struct winbindd_request request;
4272         struct winbindd_response response;
4273         fstring full_name;
4274         NSS_STATUS result;
4275
4276         DOM_SID user_sid;
4277
4278         int i;
4279
4280         fstr_sprintf(full_name, "%s%c%s",
4281                      domain, *lp_winbind_separator(), user);
4282
4283         /* First let's find out the user sid */
4284
4285         ZERO_STRUCT(request);
4286         ZERO_STRUCT(response);
4287
4288         fstrcpy(request.data.name.dom_name, domain);
4289         fstrcpy(request.data.name.name, user);
4290
4291         result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
4292
4293         if (result != NSS_STATUS_SUCCESS) {
4294                 DEBUG(1, ("winbind could not find %s\n", full_name));
4295                 return False;
4296         }
4297
4298         if (response.data.sid.type != SID_NAME_USER) {
4299                 DEBUG(1, ("%s is not a user\n", full_name));
4300                 return False;
4301         }
4302
4303         string_to_sid(&user_sid, response.data.sid.sid);
4304
4305         init_user_token(token, &user_sid);
4306
4307         /* And now the groups winbind knows about */
4308
4309         ZERO_STRUCT(response);
4310
4311         fstrcpy(request.data.username, full_name);
4312
4313         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
4314
4315         if (result != NSS_STATUS_SUCCESS) {
4316                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
4317                 return False;
4318         }
4319
4320         for (i = 0; i < response.data.num_entries; i++) {
4321                 gid_t gid = ((gid_t *)response.extra_data.data)[i];
4322                 DOM_SID sid;
4323
4324                 struct winbindd_request sidrequest;
4325                 struct winbindd_response sidresponse;
4326
4327                 ZERO_STRUCT(sidrequest);
4328                 ZERO_STRUCT(sidresponse);
4329
4330                 sidrequest.data.gid = gid;
4331
4332                 result = winbindd_request_response(WINBINDD_GID_TO_SID,
4333                                           &sidrequest, &sidresponse);
4334
4335                 if (result != NSS_STATUS_SUCCESS) {
4336                         DEBUG(1, ("winbind could not find SID of gid %d\n",
4337                                   gid));
4338                         return False;
4339                 }
4340
4341                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
4342
4343                 string_to_sid(&sid, sidresponse.data.sid.sid);
4344                 add_sid_to_token(token, &sid);
4345         }
4346
4347         SAFE_FREE(response.extra_data.data);
4348
4349         return True;
4350 }
4351         
4352 /**
4353  * Get a list of all user tokens we want to look at
4354  **/
4355
4356 static bool get_user_tokens(int *num_tokens, struct user_token **user_tokens)
4357 {
4358         struct winbindd_request request;
4359         struct winbindd_response response;
4360         const char *extra_data;
4361         fstring name;
4362         int i;
4363         struct user_token *result;
4364
4365         if (lp_winbind_use_default_domain() &&
4366             (opt_target_workgroup == NULL)) {
4367                 d_fprintf(stderr, "winbind use default domain = yes set, "
4368                          "please specify a workgroup\n");
4369                 return False;
4370         }
4371
4372         /* Send request to winbind daemon */
4373
4374         ZERO_STRUCT(request);
4375         ZERO_STRUCT(response);
4376         
4377         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
4378             NSS_STATUS_SUCCESS)
4379                 return False;
4380
4381         /* Look through extra data */
4382
4383         if (!response.extra_data.data)
4384                 return False;
4385
4386         extra_data = (const char *)response.extra_data.data;
4387         *num_tokens = 0;
4388
4389         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
4390                 *num_tokens += 1;
4391         }
4392
4393         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
4394
4395         if (result == NULL) {
4396                 DEBUG(1, ("Could not malloc sid array\n"));
4397                 return False;
4398         }
4399
4400         extra_data = (const char *)response.extra_data.data;
4401         i=0;
4402
4403         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
4404
4405                 fstring domain, user;
4406                 char *p;
4407
4408                 fstrcpy(result[i].name, name);
4409
4410                 p = strchr(name, *lp_winbind_separator());
4411
4412                 DEBUG(3, ("%s\n", name));
4413
4414                 if (p == NULL) {
4415                         fstrcpy(domain, opt_target_workgroup);
4416                         fstrcpy(user, name);
4417                 } else {
4418                         *p++ = '\0';
4419                         fstrcpy(domain, name);
4420                         strupper_m(domain);
4421                         fstrcpy(user, p);
4422                 }
4423
4424                 get_user_sids(domain, user, &(result[i].token));
4425                 i+=1;
4426         }
4427         
4428         SAFE_FREE(response.extra_data.data);
4429
4430         *user_tokens = result;
4431
4432         return True;
4433 }
4434
4435 static bool get_user_tokens_from_file(FILE *f,
4436                                       int *num_tokens,
4437                                       struct user_token **tokens)
4438 {
4439         struct user_token *token = NULL;
4440
4441         while (!feof(f)) {
4442                 fstring line;
4443
4444                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4445                         return True;
4446                 }
4447
4448                 if (line[strlen(line)-1] == '\n')
4449                         line[strlen(line)-1] = '\0';
4450
4451                 if (line[0] == ' ') {
4452                         /* We have a SID */
4453
4454                         DOM_SID sid;
4455                         string_to_sid(&sid, &line[1]);
4456
4457                         if (token == NULL) {
4458                                 DEBUG(0, ("File does not begin with username"));
4459                                 return False;
4460                         }
4461
4462                         add_sid_to_token(&token->token, &sid);
4463                         continue;
4464                 }
4465
4466                 /* And a new user... */
4467
4468                 *num_tokens += 1;
4469                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4470                 if (*tokens == NULL) {
4471                         DEBUG(0, ("Could not realloc tokens\n"));
4472                         return False;
4473                 }
4474
4475                 token = &((*tokens)[*num_tokens-1]);
4476
4477                 fstrcpy(token->name, line);
4478                 token->token.num_sids = 0;
4479                 token->token.user_sids = NULL;
4480                 continue;
4481         }
4482         
4483         return False;
4484 }
4485
4486
4487 /*
4488  * Show the list of all users that have access to a share
4489  */
4490
4491 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4492                         TALLOC_CTX *mem_ctx,
4493                         const char *netname,
4494                         int num_tokens,
4495                         struct user_token *tokens)
4496 {
4497         int fnum;
4498         SEC_DESC *share_sd = NULL;
4499         SEC_DESC *root_sd = NULL;
4500         struct cli_state *cli = pipe_hnd->cli;
4501         int i;
4502         SRV_SHARE_INFO info;
4503         WERROR result;
4504         uint16 cnum;
4505
4506         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname,
4507                                                502, &info);
4508
4509         if (!W_ERROR_IS_OK(result)) {
4510                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4511                           netname));
4512                 return;
4513         }
4514
4515         share_sd = info.share.info502.info_502_str.sd;
4516         if (share_sd == NULL) {
4517                 DEBUG(1, ("Got no secdesc for share %s\n",
4518                           netname));
4519         }
4520
4521         cnum = cli->cnum;
4522
4523         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4524                 return;
4525         }
4526
4527         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4528
4529         if (fnum != -1) {
4530                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4531         }
4532
4533         for (i=0; i<num_tokens; i++) {
4534                 uint32 acc_granted;
4535                 NTSTATUS status;
4536
4537                 if (share_sd != NULL) {
4538                         if (!se_access_check(share_sd, &tokens[i].token,
4539                                              1, &acc_granted, &status)) {
4540                                 DEBUG(1, ("Could not check share_sd for "
4541                                           "user %s\n",
4542                                           tokens[i].name));
4543                                 continue;
4544                         }
4545
4546                         if (!NT_STATUS_IS_OK(status))
4547                                 continue;
4548                 }
4549
4550                 if (root_sd == NULL) {
4551                         d_printf(" %s\n", tokens[i].name);
4552                         continue;
4553                 }
4554
4555                 if (!se_access_check(root_sd, &tokens[i].token,
4556                                      1, &acc_granted, &status)) {
4557                         DEBUG(1, ("Could not check root_sd for user %s\n",
4558                                   tokens[i].name));
4559                         continue;
4560                 }
4561
4562                 if (!NT_STATUS_IS_OK(status))
4563                         continue;
4564
4565                 d_printf(" %s\n", tokens[i].name);
4566         }
4567
4568         if (fnum != -1)
4569                 cli_close(cli, fnum);
4570         cli_tdis(cli);
4571         cli->cnum = cnum;
4572         
4573         return;
4574 }
4575
4576 struct share_list {
4577         int num_shares;
4578         char **shares;
4579 };
4580
4581 static void collect_share(const char *name, uint32 m,
4582                           const char *comment, void *state)
4583 {
4584         struct share_list *share_list = (struct share_list *)state;
4585
4586         if (m != STYPE_DISKTREE)
4587                 return;
4588
4589         share_list->num_shares += 1;
4590         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4591         if (!share_list->shares) {
4592                 share_list->num_shares = 0;
4593                 return;
4594         }
4595         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4596 }
4597
4598 static void rpc_share_userlist_usage(void)
4599 {
4600         return;
4601 }
4602         
4603 /** 
4604  * List shares on a remote RPC server, including the security descriptors
4605  *
4606  * All parameters are provided by the run_rpc_command function, except for
4607  * argc, argv which are passes through. 
4608  *
4609  * @param domain_sid The domain sid acquired from the remote server
4610  * @param cli A cli_state connected to the server.
4611  * @param mem_ctx Talloc context, destoyed on completion of the function.
4612  * @param argc  Standard main() style argc
4613  * @param argv  Standard main() style argv.  Initial components are already
4614  *              stripped
4615  *
4616  * @return Normal NTSTATUS return.
4617  **/
4618
4619 static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
4620                                                 const char *domain_name,
4621                                                 struct cli_state *cli,
4622                                                 struct rpc_pipe_client *pipe_hnd,
4623                                                 TALLOC_CTX *mem_ctx,
4624                                                 int argc,
4625                                                 const char **argv)
4626 {
4627         int ret;
4628         bool r;
4629         ENUM_HND hnd;
4630         uint32 i;
4631         FILE *f;
4632
4633         struct user_token *tokens = NULL;
4634         int num_tokens = 0;
4635
4636         struct share_list share_list;
4637
4638         if (argc > 1) {
4639                 rpc_share_userlist_usage();
4640                 return NT_STATUS_UNSUCCESSFUL;
4641         }
4642
4643         if (argc == 0) {
4644                 f = stdin;
4645         } else {
4646                 f = fopen(argv[0], "r");
4647         }
4648
4649         if (f == NULL) {
4650                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4651                 return NT_STATUS_UNSUCCESSFUL;
4652         }
4653
4654         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4655
4656         if (f != stdin)
4657                 fclose(f);
4658
4659         if (!r) {
4660                 DEBUG(0, ("Could not read users from file\n"));
4661                 return NT_STATUS_UNSUCCESSFUL;
4662         }
4663
4664         for (i=0; i<num_tokens; i++)
4665                 collect_alias_memberships(&tokens[i].token);
4666
4667         init_enum_hnd(&hnd, 0);
4668
4669         share_list.num_shares = 0;
4670         share_list.shares = NULL;
4671
4672         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4673
4674         if (ret == -1) {
4675                 DEBUG(0, ("Error returning browse list: %s\n",
4676                           cli_errstr(cli)));
4677                 goto done;
4678         }
4679
4680         for (i = 0; i < share_list.num_shares; i++) {
4681                 char *netname = share_list.shares[i];
4682
4683                 if (netname[strlen(netname)-1] == '$')
4684                         continue;
4685
4686                 d_printf("%s\n", netname);
4687
4688                 show_userlist(pipe_hnd, mem_ctx, netname,
4689                               num_tokens, tokens);
4690         }
4691  done:
4692         for (i=0; i<num_tokens; i++) {
4693                 free_user_token(&tokens[i].token);
4694         }
4695         SAFE_FREE(tokens);
4696         SAFE_FREE(share_list.shares);
4697
4698         return NT_STATUS_OK;
4699 }
4700
4701 static int rpc_share_allowedusers(int argc, const char **argv)
4702 {
4703         int result;
4704
4705         result = run_rpc_command(NULL, PI_SAMR, 0,
4706                                  rpc_aliaslist_internals,
4707                                  argc, argv);
4708         if (result != 0)
4709                 return result;
4710
4711         result = run_rpc_command(NULL, PI_LSARPC, 0,
4712                                  rpc_aliaslist_dump,
4713                                  argc, argv);
4714         if (result != 0)
4715                 return result;
4716
4717         return run_rpc_command(NULL, PI_SRVSVC, 0,
4718                                rpc_share_allowedusers_internals,
4719                                argc, argv);
4720 }
4721
4722 int net_usersidlist(int argc, const char **argv)
4723 {
4724         int num_tokens = 0;
4725         struct user_token *tokens = NULL;
4726         int i;
4727
4728         if (argc != 0) {
4729                 net_usersidlist_usage(argc, argv);
4730                 return 0;
4731         }
4732
4733         if (!get_user_tokens(&num_tokens, &tokens)) {
4734                 DEBUG(0, ("Could not get the user/sid list\n"));
4735                 return 0;
4736         }
4737
4738         for (i=0; i<num_tokens; i++) {
4739                 dump_user_token(&tokens[i]);
4740                 free_user_token(&tokens[i].token);
4741         }
4742
4743         SAFE_FREE(tokens);
4744         return 1;
4745 }
4746
4747 int net_usersidlist_usage(int argc, const char **argv)
4748 {
4749         d_printf("net usersidlist\n"
4750                  "\tprints out a list of all users the running winbind knows\n"
4751                  "\tabout, together with all their SIDs. This is used as\n"
4752                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
4753
4754         net_common_flags_usage(argc, argv);
4755         return -1;
4756 }
4757
4758 /** 
4759  * 'net rpc share' entrypoint.
4760  * @param argc  Standard main() style argc
4761  * @param argv  Standard main() style argv.  Initial components are already
4762  *              stripped
4763  **/
4764
4765 int net_rpc_share(int argc, const char **argv) 
4766 {
4767         struct functable func[] = {
4768                 {"add", rpc_share_add},
4769                 {"delete", rpc_share_delete},
4770                 {"allowedusers", rpc_share_allowedusers},
4771                 {"migrate", rpc_share_migrate},
4772                 {"list", rpc_share_list},
4773                 {NULL, NULL}
4774         };
4775
4776         if (argc == 0)
4777                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
4778                                        rpc_share_list_internals,
4779                                        argc, argv);
4780
4781         return net_run_function(argc, argv, func, rpc_share_usage);
4782 }
4783
4784 static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
4785                                   struct rpc_sh_ctx *ctx,
4786                                   struct rpc_pipe_client *pipe_hnd,
4787                                   int argc, const char **argv)
4788 {
4789         return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
4790                                         ctx->cli, pipe_hnd, mem_ctx,
4791                                         argc, argv);
4792 }
4793
4794 static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
4795                                  struct rpc_sh_ctx *ctx,
4796                                  struct rpc_pipe_client *pipe_hnd,
4797                                  int argc, const char **argv)
4798 {
4799         WERROR result;
4800
4801         if ((argc < 2) || (argc > 3)) {
4802                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
4803                           ctx->whoami);
4804                 return NT_STATUS_INVALID_PARAMETER;
4805         }
4806
4807         result = rpccli_srvsvc_net_share_add(
4808                 pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
4809                 (argc == 3) ? argv[2] : "",
4810                 0, 0, 0, argv[1], NULL, 2, NULL);
4811                                              
4812         return werror_to_ntstatus(result);
4813 }
4814
4815 static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
4816                                     struct rpc_sh_ctx *ctx,
4817                                     struct rpc_pipe_client *pipe_hnd,
4818                                     int argc, const char **argv)
4819 {
4820         WERROR result;
4821
4822         if (argc != 1) {
4823                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4824                 return NT_STATUS_INVALID_PARAMETER;
4825         }
4826
4827         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
4828         return werror_to_ntstatus(result);
4829 }
4830
4831 static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
4832                                   struct rpc_sh_ctx *ctx,
4833                                   struct rpc_pipe_client *pipe_hnd,
4834                                   int argc, const char **argv)
4835 {
4836         SRV_SHARE_INFO info;
4837         SRV_SHARE_INFO_2 *info2 = &info.share.info2;
4838         WERROR result;
4839
4840         if (argc != 1) {
4841                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4842                 return NT_STATUS_INVALID_PARAMETER;
4843         }
4844
4845         result = rpccli_srvsvc_net_share_get_info(
4846                 pipe_hnd, mem_ctx, argv[0], 2, &info);
4847         if (!W_ERROR_IS_OK(result)) {
4848                 goto done;
4849         }
4850
4851         d_printf("Name:     %s\n",
4852                  rpcstr_pull_unistr2_talloc(mem_ctx,
4853                                             &info2->info_2_str.uni_netname));
4854         d_printf("Comment:  %s\n",
4855                  rpcstr_pull_unistr2_talloc(mem_ctx,
4856                                             &info2->info_2_str.uni_remark));
4857         
4858         d_printf("Path:     %s\n",
4859                  rpcstr_pull_unistr2_talloc(mem_ctx,
4860                                             &info2->info_2_str.uni_path));
4861         d_printf("Password: %s\n",
4862                  rpcstr_pull_unistr2_talloc(mem_ctx,
4863                                             &info2->info_2_str.uni_passwd));
4864
4865  done:
4866         return werror_to_ntstatus(result);
4867 }
4868
4869 struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
4870                                       struct rpc_sh_ctx *ctx)
4871 {
4872         static struct rpc_sh_cmd cmds[] = {
4873
4874         { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
4875           "List available shares" },
4876
4877         { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
4878           "Add a share" },
4879
4880         { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
4881           "Delete a share" },
4882
4883         { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
4884           "Get information about a share" },
4885
4886         { NULL, NULL, 0, NULL, NULL }
4887         };
4888
4889         return cmds;
4890 }
4891
4892 /****************************************************************************/
4893
4894 static int rpc_file_usage(int argc, const char **argv)
4895 {
4896         return net_help_file(argc, argv);
4897 }
4898
4899 /** 
4900  * Close a file on a remote RPC server
4901  *
4902  * All parameters are provided by the run_rpc_command function, except for
4903  * argc, argv which are passes through. 
4904  *
4905  * @param domain_sid The domain sid acquired from the remote server
4906  * @param cli A cli_state connected to the server.
4907  * @param mem_ctx Talloc context, destoyed on completion of the function.
4908  * @param argc  Standard main() style argc
4909  * @param argv  Standard main() style argv.  Initial components are already
4910  *              stripped
4911  *
4912  * @return Normal NTSTATUS return.
4913  **/
4914 static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
4915                                         const char *domain_name, 
4916                                         struct cli_state *cli,
4917                                         struct rpc_pipe_client *pipe_hnd,
4918                                         TALLOC_CTX *mem_ctx,
4919                                         int argc,
4920                                         const char **argv)
4921 {
4922         return rpccli_srvsvc_NetFileClose(pipe_hnd, mem_ctx, 
4923                                             pipe_hnd->cli->desthost, 
4924                                             atoi(argv[0]), NULL);
4925 }
4926
4927 /** 
4928  * Close a file on a remote RPC server
4929  *
4930  * @param argc  Standard main() style argc
4931  * @param argv  Standard main() style argv.  Initial components are already
4932  *              stripped
4933  *
4934  * @return A shell status integer (0 for success)
4935  **/
4936 static int rpc_file_close(int argc, const char **argv)
4937 {
4938         if (argc < 1) {
4939                 DEBUG(1, ("No fileid given on close\n"));
4940                 return(rpc_file_usage(argc, argv));
4941         }
4942
4943         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4944                                rpc_file_close_internals,
4945                                argc, argv);
4946 }
4947
4948 /** 
4949  * Formatted print of open file info 
4950  *
4951  * @param info3  FILE_INFO_3 contents
4952  * @param str3   strings for FILE_INFO_3
4953  **/
4954
4955 static void display_file_info_3( FILE_INFO_3 *info3 )
4956 {
4957         fstring user = "", path = "";
4958
4959         rpcstr_pull_unistr2_fstring(user, info3->user);
4960         rpcstr_pull_unistr2_fstring(path, info3->path);
4961
4962         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4963                  info3->id, user, info3->perms, info3->num_locks, path);
4964 }
4965
4966 /** 
4967  * List open files on a remote RPC server
4968  *
4969  * All parameters are provided by the run_rpc_command function, except for
4970  * argc, argv which are passes through. 
4971  *
4972  * @param domain_sid The domain sid acquired from the remote server
4973  * @param cli A cli_state connected to the server.
4974  * @param mem_ctx Talloc context, destoyed on completion of the function.
4975  * @param argc  Standard main() style argc
4976  * @param argv  Standard main() style argv.  Initial components are already
4977  *              stripped
4978  *
4979  * @return Normal NTSTATUS return.
4980  **/
4981
4982 static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
4983                                         const char *domain_name, 
4984                                         struct cli_state *cli,
4985                                         struct rpc_pipe_client *pipe_hnd,
4986                                         TALLOC_CTX *mem_ctx,
4987                                         int argc,
4988                                         const char **argv)
4989 {
4990         SRV_FILE_INFO_CTR ctr;
4991         WERROR result;
4992         ENUM_HND hnd;
4993         uint32 preferred_len = 0xffffffff, i;
4994         const char *username=NULL;
4995
4996         init_enum_hnd(&hnd, 0);
4997
4998         /* if argc > 0, must be user command */
4999         if (argc > 0)
5000                 username = smb_xstrdup(argv[0]);
5001                 
5002         result = rpccli_srvsvc_net_file_enum(pipe_hnd,
5003                                         mem_ctx, 3, username, &ctr, preferred_len, &hnd);
5004
5005         if (!W_ERROR_IS_OK(result))
5006                 goto done;
5007
5008         /* Display results */
5009
5010         d_printf(
5011                  "\nEnumerating open files on remote server:\n\n"\
5012                  "\nFileId  Opened by            Perms  Locks  Path"\
5013                  "\n------  ---------            -----  -----  ---- \n");
5014         for (i = 0; i < ctr.num_entries; i++)
5015                 display_file_info_3(&ctr.file.info3[i]);
5016  done:
5017         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
5018 }
5019
5020 /** 
5021  * List files for a user on a remote RPC server
5022  *
5023  * @param argc  Standard main() style argc
5024  * @param argv  Standard main() style argv.  Initial components are already
5025  *              stripped
5026  *
5027  * @return A shell status integer (0 for success)
5028  **/
5029
5030 static int rpc_file_user(int argc, const char **argv)
5031 {
5032         if (argc < 1) {
5033                 DEBUG(1, ("No username given\n"));
5034                 return(rpc_file_usage(argc, argv));
5035         }
5036
5037         return run_rpc_command(NULL, PI_SRVSVC, 0, 
5038                                rpc_file_list_internals,
5039                                argc, argv);
5040 }
5041
5042 /** 
5043  * 'net rpc file' entrypoint.
5044  * @param argc  Standard main() style argc
5045  * @param argv  Standard main() style argv.  Initial components are already
5046  *              stripped
5047  **/
5048
5049 int net_rpc_file(int argc, const char **argv) 
5050 {
5051         struct functable func[] = {
5052                 {"close", rpc_file_close},
5053                 {"user", rpc_file_user},
5054 #if 0
5055                 {"info", rpc_file_info},
5056 #endif
5057                 {NULL, NULL}
5058         };
5059
5060         if (argc == 0)
5061                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
5062                                        rpc_file_list_internals,
5063                                        argc, argv);
5064
5065         return net_run_function(argc, argv, func, rpc_file_usage);
5066 }
5067
5068 /** 
5069  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
5070  *
5071  * All parameters are provided by the run_rpc_command function, except for
5072  * argc, argv which are passed through. 
5073  *
5074  * @param domain_sid The domain sid aquired from the remote server
5075  * @param cli A cli_state connected to the server.
5076  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5077  * @param argc  Standard main() style argc
5078  * @param argv  Standard main() style argv.  Initial components are already
5079  *              stripped
5080  *
5081  * @return Normal NTSTATUS return.
5082  **/
5083
5084 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
5085                                         const char *domain_name, 
5086                                         struct cli_state *cli, 
5087                                         struct rpc_pipe_client *pipe_hnd,
5088                                         TALLOC_CTX *mem_ctx, 
5089                                         int argc,
5090                                         const char **argv) 
5091 {
5092         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5093         
5094         result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5095         
5096         if (NT_STATUS_IS_OK(result)) {
5097                 d_printf("\nShutdown successfully aborted\n");
5098                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5099         } else
5100                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5101         
5102         return result;
5103 }
5104
5105 /** 
5106  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
5107  *
5108  * All parameters are provided by the run_rpc_command function, except for
5109  * argc, argv which are passed through. 
5110  *
5111  * @param domain_sid The domain sid aquired from the remote server
5112  * @param cli A cli_state connected to the server.
5113  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5114  * @param argc  Standard main() style argc
5115  * @param argv  Standard main() style argv.  Initial components are already
5116  *              stripped
5117  *
5118  * @return Normal NTSTATUS return.
5119  **/
5120
5121 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
5122                                                 const char *domain_name, 
5123                                                 struct cli_state *cli, 
5124                                                 struct rpc_pipe_client *pipe_hnd,
5125                                                 TALLOC_CTX *mem_ctx, 
5126                                                 int argc,
5127                                                 const char **argv) 
5128 {
5129         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5130         
5131         result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5132         
5133         if (NT_STATUS_IS_OK(result)) {
5134                 d_printf("\nShutdown successfully aborted\n");
5135                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5136         } else
5137                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5138         
5139         return result;
5140 }
5141
5142 /** 
5143  * ABORT the Shut down of a remote RPC server
5144  *
5145  * @param argc  Standard main() style argc
5146  * @param argv  Standard main() style argv.  Initial components are already
5147  *              stripped
5148  *
5149  * @return A shell status integer (0 for success)
5150  **/
5151
5152 static int rpc_shutdown_abort(int argc, const char **argv) 
5153 {
5154         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5155                                  rpc_shutdown_abort_internals,
5156                                  argc, argv);
5157
5158         if (rc == 0)
5159                 return rc;
5160
5161         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5162
5163         return run_rpc_command(NULL, PI_WINREG, 0, 
5164                                rpc_reg_shutdown_abort_internals,
5165                                argc, argv);
5166 }
5167
5168 /** 
5169  * Shut down a remote RPC Server via initshutdown pipe
5170  *
5171  * All parameters are provided by the run_rpc_command function, except for
5172  * argc, argv which are passes through. 
5173  *
5174  * @param domain_sid The domain sid aquired from the remote server
5175  * @param cli A cli_state connected to the server.
5176  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5177  * @param argc  Standard main() style argc
5178  * @param argc  Standard main() style argv.  Initial components are already
5179  *              stripped
5180  *
5181  * @return Normal NTSTATUS return.
5182  **/
5183
5184 NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
5185                                                 const char *domain_name, 
5186                                                 struct cli_state *cli, 
5187                                                 struct rpc_pipe_client *pipe_hnd,
5188                                                 TALLOC_CTX *mem_ctx, 
5189                                                 int argc,
5190                                                 const char **argv) 
5191 {
5192         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5193         const char *msg = "This machine will be shutdown shortly";
5194         uint32 timeout = 20;
5195         struct initshutdown_String msg_string;
5196         struct initshutdown_String_sub s;
5197
5198         if (opt_comment) {
5199                 msg = opt_comment;
5200         }
5201         if (opt_timeout) {
5202                 timeout = opt_timeout;
5203         }
5204
5205         s.name = msg;
5206         msg_string.name = &s;
5207
5208         /* create an entry */
5209         result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5210                         &msg_string, timeout, opt_force, opt_reboot, NULL);
5211
5212         if (NT_STATUS_IS_OK(result)) {
5213                 d_printf("\nShutdown of remote machine succeeded\n");
5214                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5215         } else {
5216                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5217         }
5218         return result;
5219 }
5220
5221 /** 
5222  * Shut down a remote RPC Server via winreg pipe
5223  *
5224  * All parameters are provided by the run_rpc_command function, except for
5225  * argc, argv which are passes through. 
5226  *
5227  * @param domain_sid The domain sid aquired from the remote server
5228  * @param cli A cli_state connected to the server.
5229  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5230  * @param argc  Standard main() style argc
5231  * @param argc  Standard main() style argv.  Initial components are already
5232  *              stripped
5233  *
5234  * @return Normal NTSTATUS return.
5235  **/
5236
5237 NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid,
5238                                                 const char *domain_name, 
5239                                                 struct cli_state *cli, 
5240                                                 struct rpc_pipe_client *pipe_hnd,
5241                                                 TALLOC_CTX *mem_ctx, 
5242                                                 int argc,
5243                                                 const char **argv) 
5244 {
5245         const char *msg = "This machine will be shutdown shortly";
5246         uint32 timeout = 20;
5247         struct initshutdown_String msg_string;
5248         struct initshutdown_String_sub s;
5249         NTSTATUS result;
5250         WERROR werr;
5251
5252         if (opt_comment) {
5253                 msg = opt_comment;
5254         }
5255         s.name = msg;
5256         msg_string.name = &s;
5257
5258         if (opt_timeout) {
5259                 timeout = opt_timeout;
5260         }
5261
5262         /* create an entry */
5263         result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5264                         &msg_string, timeout, opt_force, opt_reboot, &werr);
5265
5266         if (NT_STATUS_IS_OK(result)) {
5267                 d_printf("\nShutdown of remote machine succeeded\n");
5268         } else {
5269                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5270                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5271                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5272                 else
5273                         d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(werr));
5274         }
5275
5276         return result;
5277 }
5278
5279 /** 
5280  * Shut down a remote RPC server
5281  *
5282  * @param argc  Standard main() style argc
5283  * @param argc  Standard main() style argv.  Initial components are already
5284  *              stripped
5285  *
5286  * @return A shell status integer (0 for success)
5287  **/
5288
5289 static int rpc_shutdown(int argc, const char **argv) 
5290 {
5291         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5292                                  rpc_init_shutdown_internals,
5293                                  argc, argv);
5294
5295         if (rc) {
5296                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5297                 rc = run_rpc_command(NULL, PI_WINREG, 0, 
5298                                      rpc_reg_shutdown_internals, argc, argv);
5299         }
5300
5301         return rc;
5302 }
5303
5304 /***************************************************************************
5305   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5306   
5307  ***************************************************************************/
5308
5309 /**
5310  * Add interdomain trust account to the RPC server.
5311  * All parameters (except for argc and argv) are passed by run_rpc_command
5312  * function.
5313  *
5314  * @param domain_sid The domain sid acquired from the server
5315  * @param cli A cli_state connected to the server.
5316  * @param mem_ctx Talloc context, destoyed on completion of the function.
5317  * @param argc  Standard main() style argc
5318  * @param argc  Standard main() style argv.  Initial components are already
5319  *              stripped
5320  *
5321  * @return normal NTSTATUS return code
5322  */
5323
5324 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
5325                                                 const char *domain_name, 
5326                                                 struct cli_state *cli,
5327                                                 struct rpc_pipe_client *pipe_hnd,
5328                                                 TALLOC_CTX *mem_ctx, 
5329                                                 int argc,
5330                                                 const char **argv)
5331 {
5332         POLICY_HND connect_pol, domain_pol, user_pol;
5333         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5334         char *acct_name;
5335         uint32 acb_info;
5336         uint32 unknown, user_rid;
5337
5338         if (argc != 2) {
5339                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
5340                 return NT_STATUS_INVALID_PARAMETER;
5341         }
5342
5343         /* 
5344          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5345          */
5346          
5347         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5348                 return NT_STATUS_NO_MEMORY;
5349         }
5350
5351         strupper_m(acct_name);
5352
5353         /* Get samr policy handle */
5354         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
5355                                   &connect_pol);
5356         if (!NT_STATUS_IS_OK(result)) {
5357                 goto done;
5358         }
5359         
5360         /* Get domain policy handle */
5361         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
5362                                       MAXIMUM_ALLOWED_ACCESS,
5363                                       domain_sid, &domain_pol);
5364         if (!NT_STATUS_IS_OK(result)) {
5365                 goto done;
5366         }
5367
5368         /* Create trusting domain's account */
5369         acb_info = ACB_NORMAL; 
5370         unknown = 0xe00500b0; /* No idea what this is - a permission mask?
5371                                  mimir: yes, most probably it is */
5372
5373         result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
5374                                           acct_name, acb_info, unknown,
5375                                           &user_pol, &user_rid);
5376         if (!NT_STATUS_IS_OK(result)) {
5377                 goto done;
5378         }
5379
5380         {
5381                 SAM_USERINFO_CTR ctr;
5382                 SAM_USER_INFO_23 p23;
5383                 NTTIME notime;
5384                 char nostr[] = "";
5385                 LOGON_HRS hrs;
5386                 uchar pwbuf[516];
5387
5388                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
5389
5390                 ZERO_STRUCT(ctr);
5391                 ZERO_STRUCT(p23);
5392                 ZERO_STRUCT(notime);
5393                 hrs.max_len = 1260;
5394                 hrs.offset = 0;
5395                 hrs.len = 21;
5396                 memset(hrs.hours, 0xFF, sizeof(hrs.hours));
5397                 acb_info = ACB_DOMTRUST;
5398
5399                 init_sam_user_info23A(&p23, &notime, &notime, &notime,
5400                                       &notime, &notime, &notime,
5401                                       nostr, nostr, nostr, nostr, nostr,
5402                                       nostr, nostr, nostr, nostr, nostr,
5403                                       0, 0, acb_info, ACCT_FLAGS, 168, &hrs, 
5404                                       0, 0, (char *)pwbuf);
5405                 ctr.switch_value = 23;
5406                 ctr.info.id23 = &p23;
5407                 p23.passmustchange = 0;
5408
5409                 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 23,
5410                                                &cli->user_session_key, &ctr);
5411
5412                 if (!NT_STATUS_IS_OK(result)) {
5413                         DEBUG(0,("Could not set trust account password: %s\n",
5414                                  nt_errstr(result)));
5415                         goto done;
5416                 }
5417         }
5418
5419  done:
5420         SAFE_FREE(acct_name);
5421         return result;
5422 }
5423
5424 /**
5425  * Create interdomain trust account for a remote domain.
5426  *
5427  * @param argc standard argc
5428  * @param argv standard argv without initial components
5429  *
5430  * @return Integer status (0 means success)
5431  **/
5432
5433 static int rpc_trustdom_add(int argc, const char **argv)
5434 {
5435         if (argc > 0) {
5436                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
5437                                        argc, argv);
5438         } else {
5439                 d_printf("Usage: net rpc trustdom add <domain>\n");
5440                 return -1;
5441         }
5442 }
5443
5444
5445 /**
5446  * Remove interdomain trust account from the RPC server.
5447  * All parameters (except for argc and argv) are passed by run_rpc_command
5448  * function.
5449  *
5450  * @param domain_sid The domain sid acquired from the server
5451  * @param cli A cli_state connected to the server.
5452  * @param mem_ctx Talloc context, destoyed on completion of the function.
5453  * @param argc  Standard main() style argc
5454  * @param argc  Standard main() style argv.  Initial components are already
5455  *              stripped
5456  *
5457  * @return normal NTSTATUS return code
5458  */
5459
5460 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
5461                                         const char *domain_name, 
5462                                         struct cli_state *cli,
5463                                         struct rpc_pipe_client *pipe_hnd,
5464                                         TALLOC_CTX *mem_ctx, 
5465                                         int argc,
5466                                         const char **argv)
5467 {
5468         POLICY_HND connect_pol, domain_pol, user_pol;
5469         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5470         char *acct_name;
5471         const char **names;
5472         DOM_SID trust_acct_sid;
5473         uint32 *user_rids, num_rids, *name_types;
5474         uint32 flags = 0x000003e8; /* Unknown */
5475
5476         if (argc != 1) {
5477                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5478                 return NT_STATUS_INVALID_PARAMETER;
5479         }
5480
5481         /* 
5482          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5483          */
5484         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5485
5486         if (acct_name == NULL)
5487                 return NT_STATUS_NO_MEMORY;
5488
5489         strupper_m(acct_name);
5490
5491         if ((names = TALLOC_ARRAY(mem_ctx, const char *, 1)) == NULL) {
5492                 return NT_STATUS_NO_MEMORY;
5493         }
5494         names[0] = acct_name;
5495
5496
5497         /* Get samr policy handle */
5498         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
5499                                   &connect_pol);
5500         if (!NT_STATUS_IS_OK(result)) {
5501                 goto done;
5502         }
5503         
5504         /* Get domain policy handle */
5505         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
5506                                       MAXIMUM_ALLOWED_ACCESS,
5507                                       domain_sid, &domain_pol);
5508         if (!NT_STATUS_IS_OK(result)) {
5509                 goto done;
5510         }
5511
5512         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1,
5513                                        names, &num_rids,
5514                                        &user_rids, &name_types);
5515         
5516         if (!NT_STATUS_IS_OK(result)) {
5517                 goto done;
5518         }
5519
5520         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
5521                                     MAXIMUM_ALLOWED_ACCESS,
5522                                     user_rids[0], &user_pol);
5523
5524         if (!NT_STATUS_IS_OK(result)) {
5525                 goto done;
5526         }
5527
5528         /* append the rid to the domain sid */
5529         sid_copy(&trust_acct_sid, domain_sid);
5530         if (!sid_append_rid(&trust_acct_sid, user_rids[0])) {
5531                 goto done;
5532         }
5533
5534         /* remove the sid */
5535
5536         result = rpccli_samr_remove_sid_foreign_domain(pipe_hnd, mem_ctx, &user_pol,
5537                                                     &trust_acct_sid);
5538
5539         if (!NT_STATUS_IS_OK(result)) {
5540                 goto done;
5541         }
5542
5543         /* Delete user */
5544
5545         result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
5546
5547         if (!NT_STATUS_IS_OK(result)) {
5548                 goto done;
5549         }
5550
5551         if (!NT_STATUS_IS_OK(result)) {
5552           DEBUG(0,("Could not set trust account password: %s\n",
5553                    nt_errstr(result)));
5554           goto done;
5555         }
5556
5557  done:
5558         return result;
5559 }
5560
5561 /**
5562  * Delete interdomain trust account for a remote domain.
5563  *
5564  * @param argc standard argc
5565  * @param argv standard argv without initial components
5566  *
5567  * @return Integer status (0 means success)
5568  **/
5569
5570 static int rpc_trustdom_del(int argc, const char **argv)
5571 {
5572         if (argc > 0) {
5573                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
5574                                        argc, argv);
5575         } else {
5576                 d_printf("Usage: net rpc trustdom del <domain>\n");
5577                 return -1;
5578         }
5579 }
5580  
5581
5582 /**
5583  * Establish trust relationship to a trusting domain.
5584  * Interdomain account must already be created on remote PDC.
5585  *
5586  * @param argc standard argc
5587  * @param argv standard argv without initial components
5588  *
5589  * @return Integer status (0 means success)
5590  **/
5591
5592 static int rpc_trustdom_establish(int argc, const char **argv)
5593 {
5594         struct cli_state *cli = NULL;
5595         struct sockaddr_storage server_ss;
5596         struct rpc_pipe_client *pipe_hnd = NULL;
5597         POLICY_HND connect_hnd;
5598         TALLOC_CTX *mem_ctx;
5599         NTSTATUS nt_status;
5600         DOM_SID *domain_sid;
5601
5602         char* domain_name;
5603         char* domain_name_pol;
5604         char* acct_name;
5605         fstring pdc_name;
5606
5607         /*
5608          * Connect to \\server\ipc$ as 'our domain' account with password
5609          */
5610
5611         if (argc != 1) {
5612                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
5613                 return -1;
5614         }
5615
5616         domain_name = smb_xstrdup(argv[0]);
5617         strupper_m(domain_name);
5618
5619         /* account name used at first is our domain's name with '$' */
5620         asprintf(&acct_name, "%s$", lp_workgroup());
5621         strupper_m(acct_name);
5622
5623         /*
5624          * opt_workgroup will be used by connection functions further,
5625          * hence it should be set to remote domain name instead of ours
5626          */
5627         if (opt_workgroup) {
5628                 opt_workgroup = smb_xstrdup(domain_name);
5629         };
5630
5631         opt_user_name = acct_name;
5632
5633         /* find the domain controller */
5634         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5635                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5636                 return -1;
5637         }
5638
5639         /* connect to ipc$ as username/password */
5640         nt_status = connect_to_ipc(&cli, &server_ss, pdc_name);
5641         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5642
5643                 /* Is it trusting domain account for sure ? */
5644                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5645                         nt_errstr(nt_status)));
5646                 return -1;
5647         }
5648
5649         /* store who we connected to */
5650
5651         saf_store( domain_name, pdc_name );
5652
5653         /*
5654          * Connect to \\server\ipc$ again (this time anonymously)
5655          */
5656
5657         nt_status = connect_to_ipc_anonymous(&cli, &server_ss, (char*)pdc_name);
5658         
5659         if (NT_STATUS_IS_ERR(nt_status)) {
5660                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5661                         domain_name, nt_errstr(nt_status)));
5662                 return -1;
5663         }
5664
5665         /*
5666          * Use NetServerEnum2 to make sure we're talking to a proper server
5667          */
5668          
5669         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
5670                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
5671                          for domain %s\n", domain_name));
5672                 cli_shutdown(cli);
5673                 return -1;
5674         }
5675          
5676         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5677                                     "domain %s", domain_name))) {
5678                 DEBUG(0, ("talloc_init() failed\n"));
5679                 cli_shutdown(cli);
5680                 return -1;
5681         }
5682
5683         /*
5684          * Call LsaOpenPolicy and LsaQueryInfo
5685          */
5686          
5687         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5688         if (!pipe_hnd) {
5689                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5690                 cli_shutdown(cli);
5691                 talloc_destroy(mem_ctx);
5692                 return -1;
5693         }
5694
5695         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
5696                                          &connect_hnd);
5697         if (NT_STATUS_IS_ERR(nt_status)) {
5698                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5699                         nt_errstr(nt_status)));
5700                 cli_shutdown(cli);
5701                 talloc_destroy(mem_ctx);
5702                 return -1;
5703         }
5704
5705         /* Querying info level 5 */
5706         
5707         nt_status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &connect_hnd,
5708                                               5 /* info level */,
5709                                               &domain_name_pol, &domain_sid);
5710         if (NT_STATUS_IS_ERR(nt_status)) {
5711                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5712                         nt_errstr(nt_status)));
5713                 cli_shutdown(cli);
5714                 talloc_destroy(mem_ctx);
5715                 return -1;
5716         }
5717
5718         /* There should be actually query info level 3 (following nt serv behaviour),
5719            but I still don't know if it's _really_ necessary */
5720                         
5721         /*
5722          * Store the password in secrets db
5723          */
5724
5725         if (!pdb_set_trusteddom_pw(domain_name, opt_password, domain_sid)) {
5726                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5727                 cli_shutdown(cli);
5728                 talloc_destroy(mem_ctx);
5729                 return -1;
5730         }
5731         
5732         /*
5733          * Close the pipes and clean up
5734          */
5735          
5736         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5737         if (NT_STATUS_IS_ERR(nt_status)) {
5738                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5739                         nt_errstr(nt_status)));
5740                 cli_shutdown(cli);
5741                 talloc_destroy(mem_ctx);
5742                 return -1;
5743         }
5744
5745         cli_shutdown(cli);
5746          
5747         talloc_destroy(mem_ctx);
5748          
5749         d_printf("Trust to domain %s established\n", domain_name);
5750         return 0;
5751 }
5752
5753 /**
5754  * Revoke trust relationship to the remote domain
5755  *
5756  * @param argc standard argc
5757  * @param argv standard argv without initial components
5758  *
5759  * @return Integer status (0 means success)
5760  **/
5761
5762 static int rpc_trustdom_revoke(int argc, const char **argv)
5763 {
5764         char* domain_name;
5765         int rc = -1;
5766
5767         if (argc < 1) return -1;
5768         
5769         /* generate upper cased domain name */
5770         domain_name = smb_xstrdup(argv[0]);
5771         strupper_m(domain_name);
5772
5773         /* delete password of the trust */
5774         if (!pdb_del_trusteddom_pw(domain_name)) {
5775                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5776                           domain_name));
5777                 goto done;
5778         };
5779         
5780         rc = 0;
5781 done:
5782         SAFE_FREE(domain_name);
5783         return rc;
5784 }
5785
5786 /**
5787  * Usage for 'net rpc trustdom' command
5788  *
5789  * @param argc standard argc
5790  * @param argv standard argv without inital components
5791  *
5792  * @return Integer status returned to shell
5793  **/
5794  
5795 static int rpc_trustdom_usage(int argc, const char **argv)
5796 {
5797         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
5798         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
5799         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
5800         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
5801         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
5802         d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
5803         return -1;
5804 }
5805
5806
5807 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
5808                                         const char *domain_name, 
5809                                         struct cli_state *cli,
5810                                         struct rpc_pipe_client *pipe_hnd,
5811                                         TALLOC_CTX *mem_ctx,
5812                                         int argc,
5813                                         const char **argv)
5814 {
5815         fstring str_sid;
5816         sid_to_string(str_sid, domain_sid);
5817         d_printf("%s\n", str_sid);
5818         return NT_STATUS_OK;
5819 }
5820
5821 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
5822 {
5823         fstring ascii_sid, padding;
5824         int pad_len, col_len = 20;
5825
5826         /* convert sid into ascii string */
5827         sid_to_string(ascii_sid, dom_sid);
5828
5829         /* calculate padding space for d_printf to look nicer */
5830         pad_len = col_len - strlen(trusted_dom_name);
5831         padding[pad_len] = 0;
5832         do padding[--pad_len] = ' '; while (pad_len);
5833                         
5834         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
5835 }
5836
5837 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
5838                                       TALLOC_CTX *mem_ctx, 
5839                                       POLICY_HND *pol, 
5840                                       DOM_SID dom_sid, 
5841                                       const char *trusted_dom_name)
5842 {
5843         NTSTATUS nt_status;
5844         LSA_TRUSTED_DOMAIN_INFO *info;
5845         char *cleartextpwd = NULL;
5846         DATA_BLOB data;
5847
5848         nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info);
5849         
5850         if (NT_STATUS_IS_ERR(nt_status)) {
5851                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5852                 nt_errstr(nt_status)));
5853                 goto done;
5854         }
5855
5856         data = data_blob(NULL, info->password.password.length);
5857
5858         memcpy(data.data, info->password.password.data, info->password.password.length);
5859         data.length     = info->password.password.length;
5860                                 
5861         cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password, &data);
5862
5863         if (cleartextpwd == NULL) {
5864                 DEBUG(0,("retrieved NULL password\n"));
5865                 nt_status = NT_STATUS_UNSUCCESSFUL;
5866                 goto done;
5867         }
5868         
5869         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
5870                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5871                 nt_status = NT_STATUS_UNSUCCESSFUL;
5872                 goto done;
5873         }
5874
5875 #ifdef DEBUG_PASSWORD
5876         DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], password: [%s]\n",  
5877                 trusted_dom_name, sid_string_static(&dom_sid), cleartextpwd));
5878 #endif
5879
5880 done:
5881         SAFE_FREE(cleartextpwd);
5882         data_blob_free(&data);
5883
5884         return nt_status;
5885 }
5886
5887 static int rpc_trustdom_vampire(int argc, const char **argv)
5888 {
5889         /* common variables */
5890         TALLOC_CTX* mem_ctx;
5891         struct cli_state *cli = NULL;
5892         struct rpc_pipe_client *pipe_hnd = NULL;
5893         NTSTATUS nt_status;
5894         const char *domain_name = NULL;
5895         DOM_SID *queried_dom_sid;
5896         POLICY_HND connect_hnd;
5897
5898         /* trusted domains listing variables */
5899         unsigned int num_domains, enum_ctx = 0;
5900         int i;
5901         DOM_SID *domain_sids;
5902         char **trusted_dom_names;
5903         fstring pdc_name;
5904         char *dummy;
5905
5906         /*
5907          * Listing trusted domains (stored in secrets.tdb, if local)
5908          */
5909
5910         mem_ctx = talloc_init("trust relationships vampire");
5911
5912         /*
5913          * set domain and pdc name to local samba server (default)
5914          * or to remote one given in command line
5915          */
5916
5917         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
5918                 domain_name = opt_workgroup;
5919                 opt_target_workgroup = opt_workgroup;
5920         } else {
5921                 fstrcpy(pdc_name, global_myname());
5922                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5923                 opt_target_workgroup = domain_name;
5924         };
5925
5926         /* open \PIPE\lsarpc and open policy handle */
5927         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
5928         if (!NT_STATUS_IS_OK(nt_status)) {
5929                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5930                           nt_errstr(nt_status)));
5931                 talloc_destroy(mem_ctx);
5932                 return -1;
5933         };
5934
5935         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5936         if (!pipe_hnd) {
5937                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5938                         nt_errstr(nt_status) ));
5939                 cli_shutdown(cli);
5940                 talloc_destroy(mem_ctx);
5941                 return -1;
5942         };
5943
5944         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
5945                                         &connect_hnd);
5946         if (NT_STATUS_IS_ERR(nt_status)) {
5947                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5948                         nt_errstr(nt_status)));
5949                 cli_shutdown(cli);
5950                 talloc_destroy(mem_ctx);
5951                 return -1;
5952         };
5953
5954         /* query info level 5 to obtain sid of a domain being queried */
5955         nt_status = rpccli_lsa_query_info_policy(
5956                 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
5957                 &dummy, &queried_dom_sid);
5958
5959         if (NT_STATUS_IS_ERR(nt_status)) {
5960                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5961                         nt_errstr(nt_status)));
5962                 cli_shutdown(cli);
5963                 talloc_destroy(mem_ctx);
5964                 return -1;
5965         }
5966
5967         /*
5968          * Keep calling LsaEnumTrustdom over opened pipe until
5969          * the end of enumeration is reached
5970          */
5971
5972         d_printf("Vampire trusted domains:\n\n");
5973
5974         do {
5975                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
5976                                                    &num_domains,
5977                                                    &trusted_dom_names, &domain_sids);
5978                 
5979                 if (NT_STATUS_IS_ERR(nt_status)) {
5980                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5981                                 nt_errstr(nt_status)));
5982                         cli_shutdown(cli);
5983                         talloc_destroy(mem_ctx);
5984                         return -1;
5985                 };
5986                 
5987                 for (i = 0; i < num_domains; i++) {
5988
5989                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
5990
5991                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
5992                                                            domain_sids[i], trusted_dom_names[i]);
5993                         if (!NT_STATUS_IS_OK(nt_status)) {
5994                                 cli_shutdown(cli);
5995                                 talloc_destroy(mem_ctx);
5996                                 return -1;
5997                         }
5998                 };
5999
6000                 /*
6001                  * in case of no trusted domains say something rather
6002                  * than just display blank line
6003                  */
6004                 if (!num_domains) d_printf("none\n");
6005
6006         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6007
6008         /* close this connection before doing next one */
6009         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6010         if (NT_STATUS_IS_ERR(nt_status)) {
6011                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6012                         nt_errstr(nt_status)));
6013                 cli_shutdown(cli);
6014                 talloc_destroy(mem_ctx);
6015                 return -1;
6016         };
6017
6018         /* close lsarpc pipe and connection to IPC$ */
6019         cli_shutdown(cli);
6020
6021         talloc_destroy(mem_ctx);         
6022         return 0;
6023 }
6024
6025 static int rpc_trustdom_list(int argc, const char **argv)
6026 {
6027         /* common variables */
6028         TALLOC_CTX* mem_ctx;
6029         struct cli_state *cli = NULL, *remote_cli = NULL;
6030         struct rpc_pipe_client *pipe_hnd = NULL;
6031         NTSTATUS nt_status;
6032         const char *domain_name = NULL;
6033         DOM_SID *queried_dom_sid;
6034         fstring padding;
6035         int ascii_dom_name_len;
6036         POLICY_HND connect_hnd;
6037         
6038         /* trusted domains listing variables */
6039         unsigned int num_domains, enum_ctx = 0;
6040         int i, pad_len, col_len = 20;
6041         DOM_SID *domain_sids;
6042         char **trusted_dom_names;
6043         fstring pdc_name;
6044         char *dummy;
6045         
6046         /* trusting domains listing variables */
6047         POLICY_HND domain_hnd;
6048         char **trusting_dom_names;
6049         uint32 *trusting_dom_rids;
6050         
6051         /*
6052          * Listing trusted domains (stored in secrets.tdb, if local)
6053          */
6054
6055         mem_ctx = talloc_init("trust relationships listing");
6056
6057         /*
6058          * set domain and pdc name to local samba server (default)
6059          * or to remote one given in command line
6060          */
6061         
6062         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6063                 domain_name = opt_workgroup;
6064                 opt_target_workgroup = opt_workgroup;
6065         } else {
6066                 fstrcpy(pdc_name, global_myname());
6067                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6068                 opt_target_workgroup = domain_name;
6069         };
6070
6071         /* open \PIPE\lsarpc and open policy handle */
6072         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
6073         if (!NT_STATUS_IS_OK(nt_status)) {
6074                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6075                           nt_errstr(nt_status)));
6076                 talloc_destroy(mem_ctx);
6077                 return -1;
6078         };
6079
6080         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6081         if (!pipe_hnd) {
6082                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6083                         nt_errstr(nt_status) ));
6084                 cli_shutdown(cli);
6085                 talloc_destroy(mem_ctx);
6086                 return -1;
6087         };
6088
6089         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6090                                         &connect_hnd);
6091         if (NT_STATUS_IS_ERR(nt_status)) {
6092                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6093                         nt_errstr(nt_status)));
6094                 cli_shutdown(cli);
6095                 talloc_destroy(mem_ctx);
6096                 return -1;
6097         };
6098         
6099         /* query info level 5 to obtain sid of a domain being queried */
6100         nt_status = rpccli_lsa_query_info_policy(
6101                 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
6102                 &dummy, &queried_dom_sid);
6103
6104         if (NT_STATUS_IS_ERR(nt_status)) {
6105                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6106                         nt_errstr(nt_status)));
6107                 cli_shutdown(cli);
6108                 talloc_destroy(mem_ctx);
6109                 return -1;
6110         }
6111                 
6112         /*
6113          * Keep calling LsaEnumTrustdom over opened pipe until
6114          * the end of enumeration is reached
6115          */
6116          
6117         d_printf("Trusted domains list:\n\n");
6118
6119         do {
6120                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
6121                                                    &num_domains,
6122                                                    &trusted_dom_names, &domain_sids);
6123                 
6124                 if (NT_STATUS_IS_ERR(nt_status)) {
6125                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6126                                 nt_errstr(nt_status)));
6127                         cli_shutdown(cli);
6128                         talloc_destroy(mem_ctx);
6129                         return -1;
6130                 };
6131                 
6132                 for (i = 0; i < num_domains; i++) {
6133                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
6134                 };
6135                 
6136                 /*
6137                  * in case of no trusted domains say something rather
6138                  * than just display blank line
6139                  */
6140                 if (!num_domains) d_printf("none\n");
6141
6142         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6143
6144         /* close this connection before doing next one */
6145         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6146         if (NT_STATUS_IS_ERR(nt_status)) {
6147                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6148                         nt_errstr(nt_status)));
6149                 cli_shutdown(cli);
6150                 talloc_destroy(mem_ctx);
6151                 return -1;
6152         };
6153         
6154         cli_rpc_pipe_close(pipe_hnd);
6155
6156         /*
6157          * Listing trusting domains (stored in passdb backend, if local)
6158          */
6159         
6160         d_printf("\nTrusting domains list:\n\n");
6161
6162         /*
6163          * Open \PIPE\samr and get needed policy handles
6164          */
6165         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
6166         if (!pipe_hnd) {
6167                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6168                 cli_shutdown(cli);
6169                 talloc_destroy(mem_ctx);
6170                 return -1;
6171         };
6172         
6173         /* SamrConnect */
6174         nt_status = rpccli_samr_connect(pipe_hnd, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
6175                                                                  &connect_hnd);
6176         if (!NT_STATUS_IS_OK(nt_status)) {
6177                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6178                         nt_errstr(nt_status)));
6179                 cli_shutdown(cli);
6180                 talloc_destroy(mem_ctx);
6181                 return -1;
6182         };
6183         
6184         /* SamrOpenDomain - we have to open domain policy handle in order to be
6185            able to enumerate accounts*/
6186         nt_status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_hnd,
6187                                          SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6188                                          queried_dom_sid, &domain_hnd);                                                                  
6189         if (!NT_STATUS_IS_OK(nt_status)) {
6190                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6191                         nt_errstr(nt_status)));
6192                 cli_shutdown(cli);
6193                 talloc_destroy(mem_ctx);
6194                 return -1;
6195         };
6196         
6197         /*
6198          * perform actual enumeration
6199          */
6200          
6201         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6202         do {
6203                         
6204                 nt_status = rpccli_samr_enum_dom_users(pipe_hnd, mem_ctx, &domain_hnd,
6205                                                     &enum_ctx, ACB_DOMTRUST, 0xffff,
6206                                                     &trusting_dom_names, &trusting_dom_rids,
6207                                                     &num_domains);
6208                 if (NT_STATUS_IS_ERR(nt_status)) {
6209                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6210                                 nt_errstr(nt_status)));
6211                         cli_shutdown(cli);
6212                         talloc_destroy(mem_ctx);
6213                         return -1;
6214                 };
6215                 
6216                 for (i = 0; i < num_domains; i++) {
6217
6218                         /*
6219                          * get each single domain's sid (do we _really_ need this ?):
6220                          *  1) connect to domain's pdc
6221                          *  2) query the pdc for domain's sid
6222                          */
6223
6224                         /* get rid of '$' tail */
6225                         ascii_dom_name_len = strlen(trusting_dom_names[i]);
6226                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6227                                 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
6228                         
6229                         /* calculate padding space for d_printf to look nicer */
6230                         pad_len = col_len - strlen(trusting_dom_names[i]);
6231                         padding[pad_len] = 0;
6232                         do padding[--pad_len] = ' '; while (pad_len);
6233
6234                         /* set opt_* variables to remote domain */
6235                         strupper_m(trusting_dom_names[i]);
6236                         opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
6237                         opt_target_workgroup = opt_workgroup;
6238                         
6239                         d_printf("%s%s", trusting_dom_names[i], padding);
6240                         
6241                         /* connect to remote domain controller */
6242                         nt_status = net_make_ipc_connection(
6243                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6244                                         &remote_cli);
6245                         if (NT_STATUS_IS_OK(nt_status)) {
6246                                 /* query for domain's sid */
6247                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
6248                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6249
6250                                 cli_shutdown(remote_cli);
6251                         
6252                         } else {
6253                                 d_fprintf(stderr, "domain controller is not "
6254                                           "responding: %s\n",
6255                                           nt_errstr(nt_status));
6256                         };
6257                 };
6258                 
6259                 if (!num_domains) d_printf("none\n");
6260                 
6261         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6262
6263         /* close opened samr and domain policy handles */
6264         nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &domain_hnd);
6265         if (!NT_STATUS_IS_OK(nt_status)) {
6266                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6267         };
6268         
6269         nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &connect_hnd);
6270         if (!NT_STATUS_IS_OK(nt_status)) {
6271                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6272         };
6273         
6274         /* close samr pipe and connection to IPC$ */
6275         cli_shutdown(cli);
6276
6277         talloc_destroy(mem_ctx);         
6278         return 0;
6279 }
6280
6281 /**
6282  * Entrypoint for 'net rpc trustdom' code
6283  *
6284  * @param argc standard argc
6285  * @param argv standard argv without initial components
6286  *
6287  * @return Integer status (0 means success)
6288  */
6289
6290 static int rpc_trustdom(int argc, const char **argv)
6291 {
6292         struct functable func[] = {
6293                 {"add", rpc_trustdom_add},
6294                 {"del", rpc_trustdom_del},
6295                 {"establish", rpc_trustdom_establish},
6296                 {"revoke", rpc_trustdom_revoke},
6297                 {"help", rpc_trustdom_usage},
6298                 {"list", rpc_trustdom_list},
6299                 {"vampire", rpc_trustdom_vampire},
6300                 {NULL, NULL}
6301         };
6302
6303         if (argc == 0) {
6304                 rpc_trustdom_usage(argc, argv);
6305                 return -1;
6306         }
6307
6308         return (net_run_function(argc, argv, func, rpc_user_usage));
6309 }
6310
6311 /**
6312  * Check if a server will take rpc commands
6313  * @param flags Type of server to connect to (PDC, DMB, localhost)
6314  *              if the host is not explicitly specified
6315  * @return  bool (true means rpc supported)
6316  */
6317 bool net_rpc_check(unsigned flags)
6318 {
6319         struct cli_state *cli;
6320         bool ret = False;
6321         struct sockaddr_storage server_ss;
6322         char *server_name = NULL;
6323         NTSTATUS status;
6324
6325         /* flags (i.e. server type) may depend on command */
6326         if (!net_find_server(NULL, flags, &server_ss, &server_name))
6327                 return False;
6328
6329         if ((cli = cli_initialise()) == NULL) {
6330                 return False;
6331         }
6332
6333         status = cli_connect(cli, server_name, &server_ss);
6334         if (!NT_STATUS_IS_OK(status))
6335                 goto done;
6336         if (!attempt_netbios_session_request(&cli, global_myname(),
6337                                              server_name, &server_ss))
6338                 goto done;
6339         if (!cli_negprot(cli))
6340                 goto done;
6341         if (cli->protocol < PROTOCOL_NT1)
6342                 goto done;
6343
6344         ret = True;
6345  done:
6346         cli_shutdown(cli);
6347         return ret;
6348 }
6349
6350 /* dump sam database via samsync rpc calls */
6351 static int rpc_samdump(int argc, const char **argv) {
6352                 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
6353                                argc, argv);
6354 }
6355
6356 /* syncronise sam database via samsync rpc calls */
6357 static int rpc_vampire(int argc, const char **argv) {
6358         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
6359                                argc, argv);
6360 }
6361
6362 /** 
6363  * Migrate everything from a print-server
6364  *
6365  * @param argc  Standard main() style argc
6366  * @param argv  Standard main() style argv.  Initial components are already
6367  *              stripped
6368  *
6369  * @return A shell status integer (0 for success)
6370  *
6371  * The order is important !
6372  * To successfully add drivers the print-queues have to exist !
6373  * Applying ACLs should be the last step, because you're easily locked out
6374  *
6375  **/
6376 static int rpc_printer_migrate_all(int argc, const char **argv)
6377 {
6378         int ret;
6379
6380         if (!opt_host) {
6381                 printf("no server to migrate\n");
6382                 return -1;
6383         }
6384
6385         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
6386         if (ret)
6387                 return ret;
6388
6389         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
6390         if (ret)
6391                 return ret;
6392
6393         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
6394         if (ret)
6395                 return ret;
6396
6397         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
6398         if (ret)
6399                 return ret;
6400
6401         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
6402
6403 }
6404
6405 /** 
6406  * Migrate print-drivers from a print-server
6407  *
6408  * @param argc  Standard main() style argc
6409  * @param argv  Standard main() style argv.  Initial components are already
6410  *              stripped
6411  *
6412  * @return A shell status integer (0 for success)
6413  **/
6414 static int rpc_printer_migrate_drivers(int argc, const char **argv)
6415 {
6416         if (!opt_host) {
6417                 printf("no server to migrate\n");
6418                 return -1;
6419         }
6420
6421         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6422                                rpc_printer_migrate_drivers_internals,
6423                                argc, argv);
6424 }
6425
6426 /** 
6427  * Migrate print-forms from a print-server
6428  *
6429  * @param argc  Standard main() style argc
6430  * @param argv  Standard main() style argv.  Initial components are already
6431  *              stripped
6432  *
6433  * @return A shell status integer (0 for success)
6434  **/
6435 static int rpc_printer_migrate_forms(int argc, const char **argv)
6436 {
6437         if (!opt_host) {
6438                 printf("no server to migrate\n");
6439                 return -1;
6440         }
6441
6442         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6443                                rpc_printer_migrate_forms_internals,
6444                                argc, argv);
6445 }
6446
6447 /** 
6448  * Migrate printers from a print-server
6449  *
6450  * @param argc  Standard main() style argc
6451  * @param argv  Standard main() style argv.  Initial components are already
6452  *              stripped
6453  *
6454  * @return A shell status integer (0 for success)
6455  **/
6456 static int rpc_printer_migrate_printers(int argc, const char **argv)
6457 {
6458         if (!opt_host) {
6459                 printf("no server to migrate\n");
6460                 return -1;
6461         }
6462
6463         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6464                                rpc_printer_migrate_printers_internals,
6465                                argc, argv);
6466 }
6467
6468 /** 
6469  * Migrate printer-ACLs from a print-server
6470  *
6471  * @param argc  Standard main() style argc
6472  * @param argv  Standard main() style argv.  Initial components are already
6473  *              stripped
6474  *
6475  * @return A shell status integer (0 for success)
6476  **/
6477 static int rpc_printer_migrate_security(int argc, const char **argv)
6478 {
6479         if (!opt_host) {
6480                 printf("no server to migrate\n");
6481                 return -1;
6482         }
6483
6484         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6485                                rpc_printer_migrate_security_internals,
6486                                argc, argv);
6487 }
6488
6489 /** 
6490  * Migrate printer-settings from a print-server
6491  *
6492  * @param argc  Standard main() style argc
6493  * @param argv  Standard main() style argv.  Initial components are already
6494  *              stripped
6495  *
6496  * @return A shell status integer (0 for success)
6497  **/
6498 static int rpc_printer_migrate_settings(int argc, const char **argv)
6499 {
6500         if (!opt_host) {
6501                 printf("no server to migrate\n");
6502                 return -1;
6503         }
6504
6505         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6506                                rpc_printer_migrate_settings_internals,
6507                                argc, argv);
6508 }
6509
6510 /** 
6511  * 'net rpc printer' entrypoint.
6512  * @param argc  Standard main() style argc
6513  * @param argv  Standard main() style argv.  Initial components are already
6514  *              stripped
6515  **/
6516
6517 int rpc_printer_migrate(int argc, const char **argv) 
6518 {
6519
6520         /* ouch: when addriver and setdriver are called from within
6521            rpc_printer_migrate_drivers_internals, the printer-queue already
6522            *has* to exist */
6523
6524         struct functable func[] = {
6525                 {"all",         rpc_printer_migrate_all},
6526                 {"drivers",     rpc_printer_migrate_drivers},
6527                 {"forms",       rpc_printer_migrate_forms},
6528                 {"help",        rpc_printer_usage},
6529                 {"printers",    rpc_printer_migrate_printers},
6530                 {"security",    rpc_printer_migrate_security},
6531                 {"settings",    rpc_printer_migrate_settings},
6532                 {NULL, NULL}
6533         };
6534
6535         return net_run_function(argc, argv, func, rpc_printer_usage);
6536 }
6537
6538
6539 /** 
6540  * List printers on a remote RPC server
6541  *
6542  * @param argc  Standard main() style argc
6543  * @param argv  Standard main() style argv.  Initial components are already
6544  *              stripped
6545  *
6546  * @return A shell status integer (0 for success)
6547  **/
6548 static int rpc_printer_list(int argc, const char **argv)
6549 {
6550
6551         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6552                                rpc_printer_list_internals,
6553                                argc, argv);
6554 }
6555
6556 /** 
6557  * List printer-drivers on a remote RPC server
6558  *
6559  * @param argc  Standard main() style argc
6560  * @param argv  Standard main() style argv.  Initial components are already
6561  *              stripped
6562  *
6563  * @return A shell status integer (0 for success)
6564  **/
6565 static int rpc_printer_driver_list(int argc, const char **argv)
6566 {
6567
6568         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6569                                rpc_printer_driver_list_internals,
6570                                argc, argv);
6571 }
6572
6573 /** 
6574  * Publish printer in ADS via MSRPC
6575  *
6576  * @param argc  Standard main() style argc
6577  * @param argv  Standard main() style argv.  Initial components are already
6578  *              stripped
6579  *
6580  * @return A shell status integer (0 for success)
6581  **/
6582 static int rpc_printer_publish_publish(int argc, const char **argv)
6583 {
6584
6585         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6586                                rpc_printer_publish_publish_internals,
6587                                argc, argv);
6588 }
6589
6590 /** 
6591  * Update printer in ADS via MSRPC
6592  *
6593  * @param argc  Standard main() style argc
6594  * @param argv  Standard main() style argv.  Initial components are already
6595  *              stripped
6596  *
6597  * @return A shell status integer (0 for success)
6598  **/
6599 static int rpc_printer_publish_update(int argc, const char **argv)
6600 {
6601
6602         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6603                                rpc_printer_publish_update_internals,
6604                                argc, argv);
6605 }
6606
6607 /** 
6608  * UnPublish printer in ADS via MSRPC
6609  *
6610  * @param argc  Standard main() style argc
6611  * @param argv  Standard main() style argv.  Initial components are already
6612  *              stripped
6613  *
6614  * @return A shell status integer (0 for success)
6615  **/
6616 static int rpc_printer_publish_unpublish(int argc, const char **argv)
6617 {
6618
6619         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6620                                rpc_printer_publish_unpublish_internals,
6621                                argc, argv);
6622 }
6623
6624 /** 
6625  * List published printers via MSRPC
6626  *
6627  * @param argc  Standard main() style argc
6628  * @param argv  Standard main() style argv.  Initial components are already
6629  *              stripped
6630  *
6631  * @return A shell status integer (0 for success)
6632  **/
6633 static int rpc_printer_publish_list(int argc, const char **argv)
6634 {
6635
6636         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6637                                rpc_printer_publish_list_internals,
6638                                argc, argv);
6639 }
6640
6641
6642 /** 
6643  * Publish printer in ADS
6644  *
6645  * @param argc  Standard main() style argc
6646  * @param argv  Standard main() style argv.  Initial components are already
6647  *              stripped
6648  *
6649  * @return A shell status integer (0 for success)
6650  **/
6651 static int rpc_printer_publish(int argc, const char **argv)
6652 {
6653
6654         struct functable func[] = {
6655                 {"publish",     rpc_printer_publish_publish},
6656                 {"update",      rpc_printer_publish_update},
6657                 {"unpublish",   rpc_printer_publish_unpublish},
6658                 {"list",        rpc_printer_publish_list},
6659                 {"help",        rpc_printer_usage},
6660                 {NULL, NULL}
6661         };
6662
6663         if (argc == 0)
6664                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6665                                rpc_printer_publish_list_internals,
6666                                argc, argv);
6667
6668         return net_run_function(argc, argv, func, rpc_printer_usage);
6669
6670 }
6671
6672
6673 /** 
6674  * Display rpc printer help page.
6675  * @param argc  Standard main() style argc
6676  * @param argv  Standard main() style argv.  Initial components are already
6677  *              stripped
6678  **/
6679 int rpc_printer_usage(int argc, const char **argv)
6680 {
6681         return net_help_printer(argc, argv);
6682 }
6683
6684 /** 
6685  * 'net rpc printer' entrypoint.
6686  * @param argc  Standard main() style argc
6687  * @param argv  Standard main() style argv.  Initial components are already
6688  *              stripped
6689  **/
6690 int net_rpc_printer(int argc, const char **argv) 
6691 {
6692         struct functable func[] = {
6693                 {"list", rpc_printer_list},
6694                 {"migrate", rpc_printer_migrate},
6695                 {"driver", rpc_printer_driver_list},
6696                 {"publish", rpc_printer_publish},
6697                 {NULL, NULL}
6698         };
6699
6700         if (argc == 0)
6701                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6702                                rpc_printer_list_internals,
6703                                argc, argv);
6704
6705         return net_run_function(argc, argv, func, rpc_printer_usage);
6706 }
6707
6708 /****************************************************************************/
6709
6710
6711 /** 
6712  * Basic usage function for 'net rpc'
6713  * @param argc  Standard main() style argc
6714  * @param argv  Standard main() style argv.  Initial components are already
6715  *              stripped
6716  **/
6717
6718 int net_rpc_usage(int argc, const char **argv) 
6719 {
6720         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
6721         d_printf("  net rpc join \t\t\tto join a domain \n");
6722         d_printf("  net rpc oldjoin \t\tto join a domain created in server manager\n");
6723         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
6724         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
6725         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
6726         d_printf("  net rpc group \t\tto list groups\n");
6727         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
6728         d_printf("  net rpc printer \t\tto list and migrate printers\n");
6729         d_printf("  net rpc file \t\t\tto list open files\n");
6730         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
6731         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
6732         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
6733         d_printf("  net rpc samdump \t\tdisplay an NT PDC's users, groups and other data\n");
6734         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
6735         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
6736         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
6737         d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
6738         d_printf("  net rpc registry\t\tto manage registry hives\n");
6739         d_printf("  net rpc service\t\tto start, stop and query services\n");
6740         d_printf("  net rpc audit\t\t\tto modify global auditing settings\n");
6741         d_printf("  net rpc shell\t\t\tto open an interactive shell for remote server/account management\n");
6742         d_printf("\n");
6743         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
6744         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
6745         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
6746         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
6747         d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
6748         return -1;
6749 }
6750
6751
6752 /**
6753  * Help function for 'net rpc'.  Calls command specific help if requested
6754  * or displays usage of net rpc
6755  * @param argc  Standard main() style argc
6756  * @param argv  Standard main() style argv.  Initial components are already
6757  *              stripped
6758  **/
6759
6760 int net_rpc_help(int argc, const char **argv)
6761 {
6762         struct functable func[] = {
6763                 {"join", rpc_join_usage},
6764                 {"user", rpc_user_usage},
6765                 {"group", rpc_group_usage},
6766                 {"share", rpc_share_usage},
6767                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
6768                 {"trustdom", rpc_trustdom_usage},
6769                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
6770                 /*{"shutdown", rpc_shutdown_usage}, */
6771                 {"vampire", rpc_vampire_usage},
6772                 {NULL, NULL}
6773         };
6774
6775         if (argc == 0) {
6776                 net_rpc_usage(argc, argv);
6777                 return -1;
6778         }
6779
6780         return (net_run_function(argc, argv, func, rpc_user_usage));
6781 }
6782
6783 /** 
6784  * 'net rpc' entrypoint.
6785  * @param argc  Standard main() style argc
6786  * @param argv  Standard main() style argv.  Initial components are already
6787  *              stripped
6788  **/
6789
6790 int net_rpc(int argc, const char **argv)
6791 {
6792         struct functable func[] = {
6793                 {"audit", net_rpc_audit},
6794                 {"info", net_rpc_info},
6795                 {"join", net_rpc_join},
6796                 {"oldjoin", net_rpc_oldjoin},
6797                 {"testjoin", net_rpc_testjoin},
6798                 {"user", net_rpc_user},
6799                 {"password", rpc_user_password},
6800                 {"group", net_rpc_group},
6801                 {"share", net_rpc_share},
6802                 {"file", net_rpc_file},
6803                 {"printer", net_rpc_printer},
6804                 {"changetrustpw", net_rpc_changetrustpw},
6805                 {"trustdom", rpc_trustdom},
6806                 {"abortshutdown", rpc_shutdown_abort},
6807                 {"shutdown", rpc_shutdown},
6808                 {"samdump", rpc_samdump},
6809                 {"vampire", rpc_vampire},
6810                 {"getsid", net_rpc_getsid},
6811                 {"rights", net_rpc_rights},
6812                 {"service", net_rpc_service},
6813                 {"registry", net_rpc_registry},
6814                 {"shell", net_rpc_shell},
6815                 {"help", net_rpc_help},
6816                 {NULL, NULL}
6817         };
6818         return net_run_function(argc, argv, func, net_rpc_usage);
6819 }