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