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