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