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