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