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