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