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