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