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