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