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