Add my copyright.
[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         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
3318         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3319 }
3320
3321 /** 
3322  * Delete a share on a remote RPC server
3323  *
3324  * @param domain_sid The domain sid acquired from the remote server
3325  * @param argc  Standard main() style argc
3326  * @param argv  Standard main() style argv.  Initial components are already
3327  *              stripped
3328  *
3329  * @return A shell status integer (0 for success)
3330  **/
3331 static int rpc_share_delete(int argc, const char **argv)
3332 {
3333         if (argc < 1) {
3334                 DEBUG(1,("Sharename not specified on delete\n"));
3335                 return rpc_share_usage(argc, argv);
3336         }
3337         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3338                                rpc_share_del_internals,
3339                                argc, argv);
3340 }
3341
3342 /**
3343  * Formatted print of share info
3344  *
3345  * @param info1  pointer to SRV_SHARE_INFO_1 to format
3346  **/
3347  
3348 static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
3349 {
3350         fstring netname = "", remark = "";
3351
3352         rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
3353         rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
3354
3355         if (opt_long_list_entries) {
3356                 d_printf("%-12s %-8.8s %-50s\n",
3357                          netname, share_type[info1->info_1.type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)], remark);
3358         } else {
3359                 d_printf("%s\n", netname);
3360         }
3361
3362 }
3363
3364 static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd,
3365                                 TALLOC_CTX *mem_ctx, 
3366                                 uint32 level,
3367                                 int argc,
3368                                 const char **argv, 
3369                                 SRV_SHARE_INFO_CTR *ctr)
3370 {
3371         WERROR result;
3372         SRV_SHARE_INFO info;
3373
3374         /* no specific share requested, enumerate all */
3375         if (argc == 0) {
3376
3377                 ENUM_HND hnd;
3378                 uint32 preferred_len = 0xffffffff;
3379
3380                 init_enum_hnd(&hnd, 0);
3381
3382                 return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr, 
3383                                                  preferred_len, &hnd);
3384         }
3385
3386         /* request just one share */
3387         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info);
3388
3389         if (!W_ERROR_IS_OK(result))
3390                 goto done;
3391
3392         /* construct ctr */
3393         ZERO_STRUCTP(ctr);
3394
3395         ctr->info_level = ctr->switch_value = level;
3396         ctr->ptr_share_info = ctr->ptr_entries = 1;
3397         ctr->num_entries = ctr->num_entries2 = 1;
3398
3399         switch (level) {
3400         case 1:
3401         {
3402                 char *s;
3403                 SRV_SHARE_INFO_1 *info1;
3404                 
3405                 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
3406                 if (ctr->share.info1 == NULL) {
3407                         result = WERR_NOMEM;
3408                         goto done;
3409                 }
3410                 info1 = ctr->share.info1;
3411                                 
3412                 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
3413
3414                 /* Copy pointer crap */
3415
3416                 memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
3417
3418                 /* Duplicate strings */
3419
3420                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info1.info_1_str.uni_netname);
3421                 if (s)
3422                         init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
3423
3424                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info1.info_1_str.uni_remark);
3425                 if (s)
3426                         init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
3427         }
3428         case 2:
3429         {
3430                 char *s;
3431                 SRV_SHARE_INFO_2 *info2;
3432                 
3433                 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
3434                 if (ctr->share.info2 == NULL) {
3435                         result = WERR_NOMEM;
3436                         goto done;
3437                 }
3438                 info2 = ctr->share.info2;
3439                                 
3440                 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
3441
3442                 /* Copy pointer crap */
3443
3444                 memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
3445
3446                 /* Duplicate strings */
3447
3448                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_netname);
3449                 if (s)
3450                         init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
3451
3452                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_remark);
3453                 if (s)
3454                         init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
3455
3456                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_path);
3457                 if (s)
3458                         init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
3459
3460                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
3461                 if (s)
3462                         init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
3463         }
3464         case 502:
3465         {
3466                 char *s;
3467                 SRV_SHARE_INFO_502 *info502;
3468
3469                 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
3470                 if (ctr->share.info502 == NULL) {
3471                         result = WERR_NOMEM;
3472                         goto done;
3473                 }
3474                 info502 = ctr->share.info502;
3475
3476                 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
3477
3478                 /* Copy pointer crap */
3479
3480                 memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
3481
3482                 /* Duplicate strings */
3483
3484                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_netname);
3485                 if (s)
3486                         init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
3487
3488                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_remark);
3489                 if (s)
3490                         init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
3491
3492                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_path);
3493                 if (s)
3494                         init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
3495
3496                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
3497                 if (s)
3498                         init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
3499
3500                 info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
3501                                 
3502         }
3503
3504         } /* switch */
3505
3506 done:
3507         return result;
3508 }
3509
3510 /** 
3511  * List shares on a remote RPC server
3512  *
3513  * All parameters are provided by the run_rpc_command function, except for
3514  * argc, argv which are passes through. 
3515  *
3516  * @param domain_sid The domain sid acquired from the remote server
3517  * @param cli A cli_state connected to the server.
3518  * @param mem_ctx Talloc context, destoyed on completion of the function.
3519  * @param argc  Standard main() style argc
3520  * @param argv  Standard main() style argv.  Initial components are already
3521  *              stripped
3522  *
3523  * @return Normal NTSTATUS return.
3524  **/
3525
3526 static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid,
3527                                         const char *domain_name, 
3528                                         struct cli_state *cli,
3529                                         struct rpc_pipe_client *pipe_hnd,
3530                                         TALLOC_CTX *mem_ctx,
3531                                         int argc,
3532                                         const char **argv)
3533 {
3534         SRV_SHARE_INFO_CTR ctr;
3535         WERROR result;
3536         uint32 i, level = 1;
3537
3538         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr);
3539         if (!W_ERROR_IS_OK(result))
3540                 goto done;
3541
3542         /* Display results */
3543
3544         if (opt_long_list_entries) {
3545                 d_printf(
3546         "\nEnumerating shared resources (exports) on remote server:\n\n"\
3547         "\nShare name   Type     Description\n"\
3548         "----------   ----     -----------\n");
3549         }
3550         for (i = 0; i < ctr.num_entries; i++)
3551                 display_share_info_1(&ctr.share.info1[i]);
3552  done:
3553         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3554 }
3555
3556 /*** 
3557  * 'net rpc share list' entrypoint.
3558  * @param argc  Standard main() style argc
3559  * @param argv  Standard main() style argv.  Initial components are already
3560  *              stripped
3561  **/
3562 static int rpc_share_list(int argc, const char **argv)
3563 {
3564         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
3565 }
3566
3567 static bool check_share_availability(struct cli_state *cli, const char *netname)
3568 {
3569         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3570                 d_printf("skipping   [%s]: not a file share.\n", netname);
3571                 return False;
3572         }
3573
3574         if (!cli_tdis(cli)) 
3575                 return False;
3576
3577         return True;
3578 }
3579
3580 static bool check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
3581 {
3582         /* only support disk shares */
3583         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3584                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3585                 return False;
3586         }
3587
3588         /* skip builtin shares */
3589         /* FIXME: should print$ be added too ? */
3590         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") || 
3591             strequal(netname,"global")) 
3592                 return False;
3593
3594         if (opt_exclude && in_list(netname, opt_exclude, False)) {
3595                 printf("excluding  [%s]\n", netname);
3596                 return False;
3597         }
3598
3599         return check_share_availability(cli, netname);
3600 }
3601
3602 /** 
3603  * Migrate shares from a remote RPC server to the local RPC server
3604  *
3605  * All parameters are provided by the run_rpc_command function, except for
3606  * argc, argv which are passed through. 
3607  *
3608  * @param domain_sid The domain sid acquired from the remote server
3609  * @param cli A cli_state connected to the server.
3610  * @param mem_ctx Talloc context, destroyed on completion of the function.
3611  * @param argc  Standard main() style argc
3612  * @param argv  Standard main() style argv.  Initial components are already
3613  *              stripped
3614  *
3615  * @return Normal NTSTATUS return.
3616  **/
3617
3618 static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid,
3619                                                 const char *domain_name, 
3620                                                 struct cli_state *cli,
3621                                                 struct rpc_pipe_client *pipe_hnd,
3622                                                 TALLOC_CTX *mem_ctx, 
3623                                                 int argc,
3624                                                 const char **argv)
3625 {
3626         WERROR result;
3627         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3628         SRV_SHARE_INFO_CTR ctr_src;
3629         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3630         char *password = NULL; /* don't allow a share password */
3631         uint32 i;
3632         struct rpc_pipe_client *srvsvc_pipe = NULL;
3633         struct cli_state *cli_dst = NULL;
3634         uint32 level = 502; /* includes secdesc */
3635
3636         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3637         if (!W_ERROR_IS_OK(result))
3638                 goto done;
3639
3640         /* connect destination PI_SRVSVC */
3641         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3642         if (!NT_STATUS_IS_OK(nt_status))
3643                 return nt_status;
3644
3645
3646         for (i = 0; i < ctr_src.num_entries; i++) {
3647
3648                 fstring netname = "", remark = "", path = "";
3649                 /* reset error-code */
3650                 nt_status = NT_STATUS_UNSUCCESSFUL;
3651
3652                 rpcstr_pull_unistr2_fstring(
3653                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3654                 rpcstr_pull_unistr2_fstring(
3655                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3656                 rpcstr_pull_unistr2_fstring(
3657                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
3658
3659                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3660                         continue;
3661
3662                 /* finally add the share on the dst server */ 
3663
3664                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
3665                         netname, path, remark);
3666
3667                 result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark,
3668                                                   ctr_src.share.info502[i].info_502.perms,
3669                                                   ctr_src.share.info502[i].info_502.max_uses,
3670                                                   ctr_src.share.info502[i].info_502.num_uses,
3671                                                   path, password, level, 
3672                                                   NULL);
3673         
3674                 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
3675                         printf("           [%s] does already exist\n", netname);
3676                         continue;
3677                 }
3678
3679                 if (!W_ERROR_IS_OK(result)) {
3680                         printf("cannot add share: %s\n", dos_errstr(result));
3681                         goto done;
3682                 }
3683
3684         }
3685
3686         nt_status = NT_STATUS_OK;
3687
3688 done:
3689         if (cli_dst) {
3690                 cli_shutdown(cli_dst);
3691         }
3692
3693         return nt_status;
3694
3695 }
3696
3697 /** 
3698  * Migrate shares from a rpc-server to another
3699  *
3700  * @param argc  Standard main() style argc
3701  * @param argv  Standard main() style argv.  Initial components are already
3702  *              stripped
3703  *
3704  * @return A shell status integer (0 for success)
3705  **/
3706 static int rpc_share_migrate_shares(int argc, const char **argv)
3707 {
3708
3709         if (!opt_host) {
3710                 printf("no server to migrate\n");
3711                 return -1;
3712         }
3713
3714         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3715                                rpc_share_migrate_shares_internals,
3716                                argc, argv);
3717 }
3718
3719 /**
3720  * Copy a file/dir 
3721  *
3722  * @param f     file_info
3723  * @param mask  current search mask
3724  * @param state arg-pointer
3725  *
3726  **/
3727 static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
3728 {
3729         static NTSTATUS nt_status;
3730         static struct copy_clistate *local_state;
3731         static fstring filename, new_mask;
3732         fstring dir;
3733         char *old_dir;
3734
3735         local_state = (struct copy_clistate *)state;
3736         nt_status = NT_STATUS_UNSUCCESSFUL;
3737
3738         if (strequal(f->name, ".") || strequal(f->name, ".."))
3739                 return;
3740
3741         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3742
3743         /* DIRECTORY */
3744         if (f->mode & aDIR) {
3745
3746                 DEBUG(3,("got dir: %s\n", f->name));
3747
3748                 fstrcpy(dir, local_state->cwd);
3749                 fstrcat(dir, "\\");
3750                 fstrcat(dir, f->name);
3751
3752                 switch (net_mode_share)
3753                 {
3754                 case NET_MODE_SHARE_MIGRATE:
3755                         /* create that directory */
3756                         nt_status = net_copy_file(local_state->mem_ctx,
3757                                                   local_state->cli_share_src,
3758                                                   local_state->cli_share_dst,
3759                                                   dir, dir,
3760                                                   opt_acls? True : False,
3761                                                   opt_attrs? True : False,
3762                                                   opt_timestamps? True : False,
3763                                                   False);
3764                         break;
3765                 default:
3766                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3767                         return;
3768                 }
3769
3770                 if (!NT_STATUS_IS_OK(nt_status)) 
3771                         printf("could not handle dir %s: %s\n", 
3772                                 dir, nt_errstr(nt_status));
3773
3774                 /* search below that directory */
3775                 fstrcpy(new_mask, dir);
3776                 fstrcat(new_mask, "\\*");
3777
3778                 old_dir = local_state->cwd;
3779                 local_state->cwd = dir;
3780                 if (!sync_files(local_state, new_mask))
3781                         printf("could not handle files\n");
3782                 local_state->cwd = old_dir;
3783
3784                 return;
3785         }
3786
3787
3788         /* FILE */
3789         fstrcpy(filename, local_state->cwd);
3790         fstrcat(filename, "\\");
3791         fstrcat(filename, f->name);
3792
3793         DEBUG(3,("got file: %s\n", filename));
3794
3795         switch (net_mode_share)
3796         {
3797         case NET_MODE_SHARE_MIGRATE:
3798                 nt_status = net_copy_file(local_state->mem_ctx, 
3799                                           local_state->cli_share_src, 
3800                                           local_state->cli_share_dst, 
3801                                           filename, filename, 
3802                                           opt_acls? True : False, 
3803                                           opt_attrs? True : False,
3804                                           opt_timestamps? True: False,
3805                                           True);
3806                 break;
3807         default:
3808                 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3809                 return;
3810         }
3811
3812         if (!NT_STATUS_IS_OK(nt_status)) 
3813                 printf("could not handle file %s: %s\n", 
3814                         filename, nt_errstr(nt_status));
3815
3816 }
3817
3818 /**
3819  * sync files, can be called recursivly to list files 
3820  * and then call copy_fn for each file 
3821  *
3822  * @param cp_clistate   pointer to the copy_clistate we work with
3823  * @param mask          the current search mask
3824  *
3825  * @return              Boolean result
3826  **/
3827 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
3828 {
3829         struct cli_state *targetcli;
3830         char *targetpath = NULL;
3831
3832         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3833
3834         if ( !cli_resolve_path(talloc_tos(), "", cp_clistate->cli_share_src,
3835                                 mask, &targetcli, &targetpath ) ) {
3836                 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", 
3837                         mask, cli_errstr(cp_clistate->cli_share_src));
3838                 return False;
3839         }
3840
3841         if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3842                 d_fprintf(stderr, "listing %s failed with error: %s\n", 
3843                         mask, cli_errstr(targetcli));
3844                 return False;
3845         }
3846
3847         return True;
3848 }
3849
3850
3851 /**
3852  * Set the top level directory permissions before we do any further copies.
3853  * Should set up ACL inheritance.
3854  **/
3855
3856 bool copy_top_level_perms(struct copy_clistate *cp_clistate, 
3857                                 const char *sharename)
3858 {
3859         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3860
3861         switch (net_mode_share) {
3862         case NET_MODE_SHARE_MIGRATE:
3863                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3864                 nt_status = net_copy_fileattr(cp_clistate->mem_ctx,
3865                                                 cp_clistate->cli_share_src, 
3866                                                 cp_clistate->cli_share_dst,
3867                                                 "\\", "\\",
3868                                                 opt_acls? True : False, 
3869                                                 opt_attrs? True : False,
3870                                                 opt_timestamps? True: False,
3871                                                 False);
3872                 break;
3873         default:
3874                 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3875                 break;
3876         }
3877
3878         if (!NT_STATUS_IS_OK(nt_status))  {
3879                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
3880                         sharename, nt_errstr(nt_status));
3881                 return False;
3882         }
3883
3884         return True;
3885 }
3886
3887 /** 
3888  * Sync all files inside a remote share to another share (over smb)
3889  *
3890  * All parameters are provided by the run_rpc_command function, except for
3891  * argc, argv which are passes through. 
3892  *
3893  * @param domain_sid The domain sid acquired from the remote server
3894  * @param cli A cli_state connected to the server.
3895  * @param mem_ctx Talloc context, destoyed on completion of the function.
3896  * @param argc  Standard main() style argc
3897  * @param argv  Standard main() style argv.  Initial components are already
3898  *              stripped
3899  *
3900  * @return Normal NTSTATUS return.
3901  **/
3902
3903 static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid,
3904                                                 const char *domain_name, 
3905                                                 struct cli_state *cli,
3906                                                 struct rpc_pipe_client *pipe_hnd,
3907                                                 TALLOC_CTX *mem_ctx,
3908                                                 int argc,
3909                                                 const char **argv)
3910 {
3911         WERROR result;
3912         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3913         SRV_SHARE_INFO_CTR ctr_src;
3914         uint32 i;
3915         uint32 level = 502;
3916         struct copy_clistate cp_clistate;
3917         bool got_src_share = False;
3918         bool got_dst_share = False;
3919         const char *mask = "\\*";
3920         char *dst = NULL;
3921
3922         dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
3923
3924         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3925
3926         if (!W_ERROR_IS_OK(result))
3927                 goto done;
3928
3929         for (i = 0; i < ctr_src.num_entries; i++) {
3930
3931                 fstring netname = "";
3932
3933                 rpcstr_pull_unistr2_fstring(
3934                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3935
3936                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3937                         continue;
3938
3939                 /* one might not want to mirror whole discs :) */
3940                 if (strequal(netname, "print$") || netname[1] == '$') {
3941                         d_printf("skipping   [%s]: builtin/hidden share\n", netname);
3942                         continue;
3943                 }
3944
3945                 switch (net_mode_share)
3946                 {
3947                 case NET_MODE_SHARE_MIGRATE:
3948                         printf("syncing");
3949                         break;
3950                 default:
3951                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3952                         break;
3953                 }
3954                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
3955                         netname, 
3956                         opt_acls ? "including" : "without", 
3957                         opt_attrs ? "including" : "without",
3958                         opt_timestamps ? "(preserving timestamps)" : "");
3959
3960                 cp_clistate.mem_ctx = mem_ctx;
3961                 cp_clistate.cli_share_src = NULL;
3962                 cp_clistate.cli_share_dst = NULL;
3963                 cp_clistate.cwd = NULL;
3964                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3965
3966                 /* open share source */
3967                 nt_status = connect_to_service(&cp_clistate.cli_share_src,
3968                                                &cli->dest_ss, cli->desthost,
3969                                                netname, "A:");
3970                 if (!NT_STATUS_IS_OK(nt_status))
3971                         goto done;
3972
3973                 got_src_share = True;
3974
3975                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3976                         /* open share destination */
3977                         nt_status = connect_to_service(&cp_clistate.cli_share_dst,
3978                                                        NULL, dst, netname, "A:");
3979                         if (!NT_STATUS_IS_OK(nt_status))
3980                                 goto done;
3981
3982                         got_dst_share = True;
3983                 }
3984
3985                 if (!copy_top_level_perms(&cp_clistate, netname)) {
3986                         d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", netname);
3987                         nt_status = NT_STATUS_UNSUCCESSFUL;
3988                         goto done;
3989                 }
3990
3991                 if (!sync_files(&cp_clistate, mask)) {
3992                         d_fprintf(stderr, "could not handle files for share: %s\n", netname);
3993                         nt_status = NT_STATUS_UNSUCCESSFUL;
3994                         goto done;
3995                 }
3996         }
3997
3998         nt_status = NT_STATUS_OK;
3999
4000 done:
4001
4002         if (got_src_share)
4003                 cli_shutdown(cp_clistate.cli_share_src);
4004
4005         if (got_dst_share)
4006                 cli_shutdown(cp_clistate.cli_share_dst);
4007
4008         return nt_status;
4009
4010 }
4011
4012 static int rpc_share_migrate_files(int argc, const char **argv)
4013 {
4014
4015         if (!opt_host) {
4016                 printf("no server to migrate\n");
4017                 return -1;
4018         }
4019
4020         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4021                                rpc_share_migrate_files_internals,
4022                                argc, argv);
4023 }
4024
4025 /** 
4026  * Migrate share-ACLs from a remote RPC server to the local RPC srever
4027  *
4028  * All parameters are provided by the run_rpc_command function, except for
4029  * argc, argv which are passes through. 
4030  *
4031  * @param domain_sid The domain sid acquired from the remote server
4032  * @param cli A cli_state connected to the server.
4033  * @param mem_ctx Talloc context, destoyed on completion of the function.
4034  * @param argc  Standard main() style argc
4035  * @param argv  Standard main() style argv.  Initial components are already
4036  *              stripped
4037  *
4038  * @return Normal NTSTATUS return.
4039  **/
4040
4041 static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid,
4042                                                 const char *domain_name, 
4043                                                 struct cli_state *cli,
4044                                                 struct rpc_pipe_client *pipe_hnd,
4045                                                 TALLOC_CTX *mem_ctx, 
4046                                                 int argc,
4047                                                 const char **argv)
4048 {
4049         WERROR result;
4050         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4051         SRV_SHARE_INFO_CTR ctr_src;
4052         SRV_SHARE_INFO info;
4053         uint32 i;
4054         struct rpc_pipe_client *srvsvc_pipe = NULL;
4055         struct cli_state *cli_dst = NULL;
4056         uint32 level = 502; /* includes secdesc */
4057
4058         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
4059
4060         if (!W_ERROR_IS_OK(result))
4061                 goto done;
4062
4063         /* connect destination PI_SRVSVC */
4064         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
4065         if (!NT_STATUS_IS_OK(nt_status))
4066                 return nt_status;
4067
4068
4069         for (i = 0; i < ctr_src.num_entries; i++) {
4070
4071                 fstring netname = "", remark = "", path = "";
4072                 /* reset error-code */
4073                 nt_status = NT_STATUS_UNSUCCESSFUL;
4074
4075                 rpcstr_pull_unistr2_fstring(
4076                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
4077                 rpcstr_pull_unistr2_fstring(
4078                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
4079                 rpcstr_pull_unistr2_fstring(
4080                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
4081
4082                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
4083                         continue;
4084
4085                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
4086                         netname, path, remark);
4087
4088                 if (opt_verbose)
4089                         display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
4090
4091                 /* init info */
4092                 ZERO_STRUCT(info);
4093
4094                 info.switch_value = level;
4095                 info.ptr_share_ctr = 1;
4096
4097                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4098                 info.share.info502 = ctr_src.share.info502[i];
4099
4100                 /* finally modify the share on the dst server */
4101                 result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info);
4102         
4103                 if (!W_ERROR_IS_OK(result)) {
4104                         printf("cannot set share-acl: %s\n", dos_errstr(result));
4105                         goto done;
4106                 }
4107
4108         }
4109
4110         nt_status = NT_STATUS_OK;
4111
4112 done:
4113         if (cli_dst) {
4114                 cli_shutdown(cli_dst);
4115         }
4116
4117         return nt_status;
4118
4119 }
4120
4121 /** 
4122  * Migrate share-acls from a rpc-server to another
4123  *
4124  * @param argc  Standard main() style argc
4125  * @param argv  Standard main() style argv.  Initial components are already
4126  *              stripped
4127  *
4128  * @return A shell status integer (0 for success)
4129  **/
4130 static int rpc_share_migrate_security(int argc, const char **argv)
4131 {
4132
4133         if (!opt_host) {
4134                 printf("no server to migrate\n");
4135                 return -1;
4136         }
4137
4138         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4139                                rpc_share_migrate_security_internals,
4140                                argc, argv);
4141 }
4142
4143 /** 
4144  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4145  * from one server to another
4146  *
4147  * @param argc  Standard main() style argc
4148  * @param argv  Standard main() style argv.  Initial components are already
4149  *              stripped
4150  *
4151  * @return A shell status integer (0 for success)
4152  *
4153  **/
4154 static int rpc_share_migrate_all(int argc, const char **argv)
4155 {
4156         int ret;
4157
4158         if (!opt_host) {
4159                 printf("no server to migrate\n");
4160                 return -1;
4161         }
4162
4163         /* order is important. we don't want to be locked out by the share-acl
4164          * before copying files - gd */
4165         
4166         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
4167         if (ret)
4168                 return ret;
4169
4170         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
4171         if (ret)
4172                 return ret;
4173         
4174         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
4175 }
4176
4177
4178 /** 
4179  * 'net rpc share migrate' entrypoint.
4180  * @param argc  Standard main() style argc
4181  * @param argv  Standard main() style argv.  Initial components are already
4182  *              stripped
4183  **/
4184 static int rpc_share_migrate(int argc, const char **argv)
4185 {
4186
4187         struct functable func[] = {
4188                 {"all",         rpc_share_migrate_all},
4189                 {"files",       rpc_share_migrate_files},
4190                 {"help",        rpc_share_usage},
4191                 {"security",    rpc_share_migrate_security},
4192                 {"shares",      rpc_share_migrate_shares},
4193                 {NULL, NULL}
4194         };
4195
4196         net_mode_share = NET_MODE_SHARE_MIGRATE;
4197
4198         return net_run_function(argc, argv, func, rpc_share_usage);
4199 }
4200
4201 struct full_alias {
4202         DOM_SID sid;
4203         uint32 num_members;
4204         DOM_SID *members;
4205 };
4206
4207 static int num_server_aliases;
4208 static struct full_alias *server_aliases;
4209
4210 /*
4211  * Add an alias to the static list.
4212  */
4213 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4214 {
4215         if (server_aliases == NULL)
4216                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4217
4218         server_aliases[num_server_aliases] = *alias;
4219         num_server_aliases += 1;
4220 }
4221
4222 /*
4223  * For a specific domain on the server, fetch all the aliases
4224  * and their members. Add all of them to the server_aliases.
4225  */
4226
4227 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4228                                         TALLOC_CTX *mem_ctx,
4229                                         POLICY_HND *connect_pol,
4230                                         const DOM_SID *domain_sid)
4231 {
4232         uint32 start_idx, max_entries, num_entries, i;
4233         struct samr_SamArray *groups = NULL;
4234         NTSTATUS result;
4235         POLICY_HND domain_pol;
4236
4237         /* Get domain policy handle */
4238
4239         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
4240                                         connect_pol,
4241                                         MAXIMUM_ALLOWED_ACCESS,
4242                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
4243                                         &domain_pol);
4244         if (!NT_STATUS_IS_OK(result))
4245                 return result;
4246
4247         start_idx = 0;
4248         max_entries = 250;
4249
4250         do {
4251                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
4252                                                        &domain_pol,
4253                                                        &start_idx,
4254                                                        &groups,
4255                                                        max_entries,
4256                                                        &num_entries);
4257                 for (i = 0; i < num_entries; i++) {
4258
4259                         POLICY_HND alias_pol;
4260                         struct full_alias alias;
4261                         struct lsa_SidArray sid_array;
4262                         int j;
4263
4264                         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
4265                                                        &domain_pol,
4266                                                        MAXIMUM_ALLOWED_ACCESS,
4267                                                        groups->entries[i].idx,
4268                                                        &alias_pol);
4269                         if (!NT_STATUS_IS_OK(result))
4270                                 goto done;
4271
4272                         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
4273                                                                &alias_pol,
4274                                                                &sid_array);
4275                         if (!NT_STATUS_IS_OK(result))
4276                                 goto done;
4277
4278                         alias.num_members = sid_array.num_sids;
4279
4280                         result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
4281                         if (!NT_STATUS_IS_OK(result))
4282                                 goto done;
4283
4284                         alias.members = NULL;
4285
4286                         if (alias.num_members > 0) {
4287                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
4288
4289                                 for (j = 0; j < alias.num_members; j++)
4290                                         sid_copy(&alias.members[j],
4291                                                  sid_array.sids[j].sid);
4292                         }
4293
4294                         sid_copy(&alias.sid, domain_sid);
4295                         sid_append_rid(&alias.sid, groups->entries[i].idx);
4296
4297                         push_alias(mem_ctx, &alias);
4298                 }
4299         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4300
4301         result = NT_STATUS_OK;
4302
4303  done:
4304         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
4305
4306         return result;
4307 }
4308
4309 /*
4310  * Dump server_aliases as names for debugging purposes.
4311  */
4312
4313 static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid,
4314                                 const char *domain_name,
4315                                 struct cli_state *cli,
4316                                 struct rpc_pipe_client *pipe_hnd,
4317                                 TALLOC_CTX *mem_ctx, 
4318                                 int argc,
4319                                 const char **argv)
4320 {
4321         int i;
4322         NTSTATUS result;
4323         POLICY_HND lsa_pol;
4324
4325         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
4326                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
4327                                      &lsa_pol);
4328         if (!NT_STATUS_IS_OK(result))
4329                 return result;
4330
4331         for (i=0; i<num_server_aliases; i++) {
4332                 char **names;
4333                 char **domains;
4334                 enum lsa_SidType *types;
4335                 int j;
4336
4337                 struct full_alias *alias = &server_aliases[i];
4338
4339                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4340                                              &alias->sid,
4341                                              &domains, &names, &types);
4342                 if (!NT_STATUS_IS_OK(result))
4343                         continue;
4344
4345                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4346
4347                 if (alias->num_members == 0) {
4348                         DEBUG(1, ("\n"));
4349                         continue;
4350                 }
4351
4352                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4353                                              alias->num_members,
4354                                              alias->members,
4355                                              &domains, &names, &types);
4356
4357                 if (!NT_STATUS_IS_OK(result) &&
4358                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4359                         continue;
4360
4361                 for (j=0; j<alias->num_members; j++)
4362                         DEBUG(1, ("%s\\%s (%d); ",
4363                                   domains[j] ? domains[j] : "*unknown*", 
4364                                   names[j] ? names[j] : "*unknown*",types[j]));
4365                 DEBUG(1, ("\n"));
4366         }
4367
4368         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4369
4370         return NT_STATUS_OK;
4371 }
4372
4373 /*
4374  * Fetch a list of all server aliases and their members into
4375  * server_aliases.
4376  */
4377
4378 static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid,
4379                                         const char *domain_name,
4380                                         struct cli_state *cli,
4381                                         struct rpc_pipe_client *pipe_hnd,
4382                                         TALLOC_CTX *mem_ctx, 
4383                                         int argc,
4384                                         const char **argv)
4385 {
4386         NTSTATUS result;
4387         POLICY_HND connect_pol;
4388
4389         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4390                                       pipe_hnd->cli->desthost,
4391                                       MAXIMUM_ALLOWED_ACCESS,
4392                                       &connect_pol);
4393
4394         if (!NT_STATUS_IS_OK(result))
4395                 goto done;
4396         
4397         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4398                                           &global_sid_Builtin);
4399
4400         if (!NT_STATUS_IS_OK(result))
4401                 goto done;
4402         
4403         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4404                                           domain_sid);
4405
4406         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4407  done:
4408         return result;
4409 }
4410
4411 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4412 {
4413         token->num_sids = 4;
4414
4415         if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4416                 d_fprintf(stderr, "malloc failed\n");
4417                 token->num_sids = 0;
4418                 return;
4419         }
4420
4421         token->user_sids[0] = *user_sid;
4422         sid_copy(&token->user_sids[1], &global_sid_World);
4423         sid_copy(&token->user_sids[2], &global_sid_Network);
4424         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4425 }
4426
4427 static void free_user_token(NT_USER_TOKEN *token)
4428 {
4429         SAFE_FREE(token->user_sids);
4430 }
4431
4432 static bool is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
4433 {
4434         int i;
4435
4436         for (i=0; i<token->num_sids; i++) {
4437                 if (sid_compare(sid, &token->user_sids[i]) == 0)
4438                         return True;
4439         }
4440         return False;
4441 }
4442
4443 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4444 {
4445         if (is_sid_in_token(token, sid))
4446                 return;
4447
4448         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4449         if (!token->user_sids) {
4450                 return;
4451         }
4452
4453         sid_copy(&token->user_sids[token->num_sids], sid);
4454
4455         token->num_sids += 1;
4456 }
4457
4458 struct user_token {
4459         fstring name;
4460         NT_USER_TOKEN token;
4461 };
4462
4463 static void dump_user_token(struct user_token *token)
4464 {
4465         int i;
4466
4467         d_printf("%s\n", token->name);
4468
4469         for (i=0; i<token->token.num_sids; i++) {
4470                 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
4471         }
4472 }
4473
4474 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4475 {
4476         int i;
4477
4478         for (i=0; i<alias->num_members; i++) {
4479                 if (sid_compare(sid, &alias->members[i]) == 0)
4480                         return True;
4481         }
4482
4483         return False;
4484 }
4485
4486 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4487 {
4488         int i;
4489
4490         for (i=0; i<num_server_aliases; i++) {
4491                 if (is_alias_member(&sid, &server_aliases[i]))
4492                         add_sid_to_token(token, &server_aliases[i].sid);
4493         }
4494 }
4495
4496 /*
4497  * We got a user token with all the SIDs we can know about without asking the
4498  * server directly. These are the user and domain group sids. All of these can
4499  * be members of aliases. So scan the list of aliases for each of the SIDs and
4500  * add them to the token.
4501  */
4502
4503 static void collect_alias_memberships(NT_USER_TOKEN *token)
4504 {
4505         int num_global_sids = token->num_sids;
4506         int i;
4507
4508         for (i=0; i<num_global_sids; i++) {
4509                 collect_sid_memberships(token, token->user_sids[i]);
4510         }
4511 }
4512
4513 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4514 {
4515         struct winbindd_request request;
4516         struct winbindd_response response;
4517         fstring full_name;
4518         NSS_STATUS result;
4519
4520         DOM_SID user_sid;
4521
4522         int i;
4523
4524         fstr_sprintf(full_name, "%s%c%s",
4525                      domain, *lp_winbind_separator(), user);
4526
4527         /* First let's find out the user sid */
4528
4529         ZERO_STRUCT(request);
4530         ZERO_STRUCT(response);
4531
4532         fstrcpy(request.data.name.dom_name, domain);
4533         fstrcpy(request.data.name.name, user);
4534
4535         result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
4536
4537         if (result != NSS_STATUS_SUCCESS) {
4538                 DEBUG(1, ("winbind could not find %s\n", full_name));
4539                 return False;
4540         }
4541
4542         if (response.data.sid.type != SID_NAME_USER) {
4543                 DEBUG(1, ("%s is not a user\n", full_name));
4544                 return False;
4545         }
4546
4547         string_to_sid(&user_sid, response.data.sid.sid);
4548
4549         init_user_token(token, &user_sid);
4550
4551         /* And now the groups winbind knows about */
4552
4553         ZERO_STRUCT(response);
4554
4555         fstrcpy(request.data.username, full_name);
4556
4557         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
4558
4559         if (result != NSS_STATUS_SUCCESS) {
4560                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
4561                 return False;
4562         }
4563
4564         for (i = 0; i < response.data.num_entries; i++) {
4565                 gid_t gid = ((gid_t *)response.extra_data.data)[i];
4566                 DOM_SID sid;
4567
4568                 struct winbindd_request sidrequest;
4569                 struct winbindd_response sidresponse;
4570
4571                 ZERO_STRUCT(sidrequest);
4572                 ZERO_STRUCT(sidresponse);
4573
4574                 sidrequest.data.gid = gid;
4575
4576                 result = winbindd_request_response(WINBINDD_GID_TO_SID,
4577                                           &sidrequest, &sidresponse);
4578
4579                 if (result != NSS_STATUS_SUCCESS) {
4580                         DEBUG(1, ("winbind could not find SID of gid %d\n",
4581                                   gid));
4582                         return False;
4583                 }
4584
4585                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
4586
4587                 string_to_sid(&sid, sidresponse.data.sid.sid);
4588                 add_sid_to_token(token, &sid);
4589         }
4590
4591         SAFE_FREE(response.extra_data.data);
4592
4593         return True;
4594 }
4595         
4596 /**
4597  * Get a list of all user tokens we want to look at
4598  **/
4599
4600 static bool get_user_tokens(int *num_tokens, struct user_token **user_tokens)
4601 {
4602         struct winbindd_request request;
4603         struct winbindd_response response;
4604         const char *extra_data;
4605         char *name;
4606         int i;
4607         struct user_token *result;
4608         TALLOC_CTX *frame = NULL;
4609
4610         if (lp_winbind_use_default_domain() &&
4611             (opt_target_workgroup == NULL)) {
4612                 d_fprintf(stderr, "winbind use default domain = yes set, "
4613                          "please specify a workgroup\n");
4614                 return False;
4615         }
4616
4617         /* Send request to winbind daemon */
4618
4619         ZERO_STRUCT(request);
4620         ZERO_STRUCT(response);
4621
4622         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
4623             NSS_STATUS_SUCCESS)
4624                 return False;
4625
4626         /* Look through extra data */
4627
4628         if (!response.extra_data.data)
4629                 return False;
4630
4631         extra_data = (const char *)response.extra_data.data;
4632         *num_tokens = 0;
4633
4634         frame = talloc_stackframe();
4635         while(next_token_talloc(frame, &extra_data, &name, ",")) {
4636                 *num_tokens += 1;
4637         }
4638
4639         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
4640
4641         if (result == NULL) {
4642                 DEBUG(1, ("Could not malloc sid array\n"));
4643                 TALLOC_FREE(frame);
4644                 return False;
4645         }
4646
4647         extra_data = (const char *)response.extra_data.data;
4648         i=0;
4649
4650         while(next_token_talloc(frame, &extra_data, &name, ",")) {
4651                 fstring domain, user;
4652                 char *p;
4653
4654                 fstrcpy(result[i].name, name);
4655
4656                 p = strchr(name, *lp_winbind_separator());
4657
4658                 DEBUG(3, ("%s\n", name));
4659
4660                 if (p == NULL) {
4661                         fstrcpy(domain, opt_target_workgroup);
4662                         fstrcpy(user, name);
4663                 } else {
4664                         *p++ = '\0';
4665                         fstrcpy(domain, name);
4666                         strupper_m(domain);
4667                         fstrcpy(user, p);
4668                 }
4669
4670                 get_user_sids(domain, user, &(result[i].token));
4671                 i+=1;
4672         }
4673         TALLOC_FREE(frame);
4674         SAFE_FREE(response.extra_data.data);
4675
4676         *user_tokens = result;
4677
4678         return True;
4679 }
4680
4681 static bool get_user_tokens_from_file(FILE *f,
4682                                       int *num_tokens,
4683                                       struct user_token **tokens)
4684 {
4685         struct user_token *token = NULL;
4686
4687         while (!feof(f)) {
4688                 fstring line;
4689
4690                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4691                         return True;
4692                 }
4693
4694                 if (line[strlen(line)-1] == '\n')
4695                         line[strlen(line)-1] = '\0';
4696
4697                 if (line[0] == ' ') {
4698                         /* We have a SID */
4699
4700                         DOM_SID sid;
4701                         string_to_sid(&sid, &line[1]);
4702
4703                         if (token == NULL) {
4704                                 DEBUG(0, ("File does not begin with username"));
4705                                 return False;
4706                         }
4707
4708                         add_sid_to_token(&token->token, &sid);
4709                         continue;
4710                 }
4711
4712                 /* And a new user... */
4713
4714                 *num_tokens += 1;
4715                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4716                 if (*tokens == NULL) {
4717                         DEBUG(0, ("Could not realloc tokens\n"));
4718                         return False;
4719                 }
4720
4721                 token = &((*tokens)[*num_tokens-1]);
4722
4723                 fstrcpy(token->name, line);
4724                 token->token.num_sids = 0;
4725                 token->token.user_sids = NULL;
4726                 continue;
4727         }
4728         
4729         return False;
4730 }
4731
4732
4733 /*
4734  * Show the list of all users that have access to a share
4735  */
4736
4737 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4738                         TALLOC_CTX *mem_ctx,
4739                         const char *netname,
4740                         int num_tokens,
4741                         struct user_token *tokens)
4742 {
4743         int fnum;
4744         SEC_DESC *share_sd = NULL;
4745         SEC_DESC *root_sd = NULL;
4746         struct cli_state *cli = pipe_hnd->cli;
4747         int i;
4748         SRV_SHARE_INFO info;
4749         WERROR result;
4750         uint16 cnum;
4751
4752         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname,
4753                                                502, &info);
4754
4755         if (!W_ERROR_IS_OK(result)) {
4756                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4757                           netname));
4758                 return;
4759         }
4760
4761         share_sd = info.share.info502.info_502_str.sd;
4762         if (share_sd == NULL) {
4763                 DEBUG(1, ("Got no secdesc for share %s\n",
4764                           netname));
4765         }
4766
4767         cnum = cli->cnum;
4768
4769         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4770                 return;
4771         }
4772
4773         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4774
4775         if (fnum != -1) {
4776                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4777         }
4778
4779         for (i=0; i<num_tokens; i++) {
4780                 uint32 acc_granted;
4781                 NTSTATUS status;
4782
4783                 if (share_sd != NULL) {
4784                         if (!se_access_check(share_sd, &tokens[i].token,
4785                                              1, &acc_granted, &status)) {
4786                                 DEBUG(1, ("Could not check share_sd for "
4787                                           "user %s\n",
4788                                           tokens[i].name));
4789                                 continue;
4790                         }
4791
4792                         if (!NT_STATUS_IS_OK(status))
4793                                 continue;
4794                 }
4795
4796                 if (root_sd == NULL) {
4797                         d_printf(" %s\n", tokens[i].name);
4798                         continue;
4799                 }
4800
4801                 if (!se_access_check(root_sd, &tokens[i].token,
4802                                      1, &acc_granted, &status)) {
4803                         DEBUG(1, ("Could not check root_sd for user %s\n",
4804                                   tokens[i].name));
4805                         continue;
4806                 }
4807
4808                 if (!NT_STATUS_IS_OK(status))
4809                         continue;
4810
4811                 d_printf(" %s\n", tokens[i].name);
4812         }
4813
4814         if (fnum != -1)
4815                 cli_close(cli, fnum);
4816         cli_tdis(cli);
4817         cli->cnum = cnum;
4818         
4819         return;
4820 }
4821
4822 struct share_list {
4823         int num_shares;
4824         char **shares;
4825 };
4826
4827 static void collect_share(const char *name, uint32 m,
4828                           const char *comment, void *state)
4829 {
4830         struct share_list *share_list = (struct share_list *)state;
4831
4832         if (m != STYPE_DISKTREE)
4833                 return;
4834
4835         share_list->num_shares += 1;
4836         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4837         if (!share_list->shares) {
4838                 share_list->num_shares = 0;
4839                 return;
4840         }
4841         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4842 }
4843
4844 static void rpc_share_userlist_usage(void)
4845 {
4846         return;
4847 }
4848         
4849 /** 
4850  * List shares on a remote RPC server, including the security descriptors
4851  *
4852  * All parameters are provided by the run_rpc_command function, except for
4853  * argc, argv which are passes through. 
4854  *
4855  * @param domain_sid The domain sid acquired from the remote server
4856  * @param cli A cli_state connected to the server.
4857  * @param mem_ctx Talloc context, destoyed on completion of the function.
4858  * @param argc  Standard main() style argc
4859  * @param argv  Standard main() style argv.  Initial components are already
4860  *              stripped
4861  *
4862  * @return Normal NTSTATUS return.
4863  **/
4864
4865 static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
4866                                                 const char *domain_name,
4867                                                 struct cli_state *cli,
4868                                                 struct rpc_pipe_client *pipe_hnd,
4869                                                 TALLOC_CTX *mem_ctx,
4870                                                 int argc,
4871                                                 const char **argv)
4872 {
4873         int ret;
4874         bool r;
4875         ENUM_HND hnd;
4876         uint32 i;
4877         FILE *f;
4878
4879         struct user_token *tokens = NULL;
4880         int num_tokens = 0;
4881
4882         struct share_list share_list;
4883
4884         if (argc > 1) {
4885                 rpc_share_userlist_usage();
4886                 return NT_STATUS_UNSUCCESSFUL;
4887         }
4888
4889         if (argc == 0) {
4890                 f = stdin;
4891         } else {
4892                 f = fopen(argv[0], "r");
4893         }
4894
4895         if (f == NULL) {
4896                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4897                 return NT_STATUS_UNSUCCESSFUL;
4898         }
4899
4900         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4901
4902         if (f != stdin)
4903                 fclose(f);
4904
4905         if (!r) {
4906                 DEBUG(0, ("Could not read users from file\n"));
4907                 return NT_STATUS_UNSUCCESSFUL;
4908         }
4909
4910         for (i=0; i<num_tokens; i++)
4911                 collect_alias_memberships(&tokens[i].token);
4912
4913         init_enum_hnd(&hnd, 0);
4914
4915         share_list.num_shares = 0;
4916         share_list.shares = NULL;
4917
4918         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4919
4920         if (ret == -1) {
4921                 DEBUG(0, ("Error returning browse list: %s\n",
4922                           cli_errstr(cli)));
4923                 goto done;
4924         }
4925
4926         for (i = 0; i < share_list.num_shares; i++) {
4927                 char *netname = share_list.shares[i];
4928
4929                 if (netname[strlen(netname)-1] == '$')
4930                         continue;
4931
4932                 d_printf("%s\n", netname);
4933
4934                 show_userlist(pipe_hnd, mem_ctx, netname,
4935                               num_tokens, tokens);
4936         }
4937  done:
4938         for (i=0; i<num_tokens; i++) {
4939                 free_user_token(&tokens[i].token);
4940         }
4941         SAFE_FREE(tokens);
4942         SAFE_FREE(share_list.shares);
4943
4944         return NT_STATUS_OK;
4945 }
4946
4947 static int rpc_share_allowedusers(int argc, const char **argv)
4948 {
4949         int result;
4950
4951         result = run_rpc_command(NULL, PI_SAMR, 0,
4952                                  rpc_aliaslist_internals,
4953                                  argc, argv);
4954         if (result != 0)
4955                 return result;
4956
4957         result = run_rpc_command(NULL, PI_LSARPC, 0,
4958                                  rpc_aliaslist_dump,
4959                                  argc, argv);
4960         if (result != 0)
4961                 return result;
4962
4963         return run_rpc_command(NULL, PI_SRVSVC, 0,
4964                                rpc_share_allowedusers_internals,
4965                                argc, argv);
4966 }
4967
4968 int net_usersidlist(int argc, const char **argv)
4969 {
4970         int num_tokens = 0;
4971         struct user_token *tokens = NULL;
4972         int i;
4973
4974         if (argc != 0) {
4975                 net_usersidlist_usage(argc, argv);
4976                 return 0;
4977         }
4978
4979         if (!get_user_tokens(&num_tokens, &tokens)) {
4980                 DEBUG(0, ("Could not get the user/sid list\n"));
4981                 return 0;
4982         }
4983
4984         for (i=0; i<num_tokens; i++) {
4985                 dump_user_token(&tokens[i]);
4986                 free_user_token(&tokens[i].token);
4987         }
4988
4989         SAFE_FREE(tokens);
4990         return 1;
4991 }
4992
4993 int net_usersidlist_usage(int argc, const char **argv)
4994 {
4995         d_printf("net usersidlist\n"
4996                  "\tprints out a list of all users the running winbind knows\n"
4997                  "\tabout, together with all their SIDs. This is used as\n"
4998                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
4999
5000         net_common_flags_usage(argc, argv);
5001         return -1;
5002 }
5003
5004 /** 
5005  * 'net rpc share' entrypoint.
5006  * @param argc  Standard main() style argc
5007  * @param argv  Standard main() style argv.  Initial components are already
5008  *              stripped
5009  **/
5010
5011 int net_rpc_share(int argc, const char **argv) 
5012 {
5013         struct functable func[] = {
5014                 {"add", rpc_share_add},
5015                 {"delete", rpc_share_delete},
5016                 {"allowedusers", rpc_share_allowedusers},
5017                 {"migrate", rpc_share_migrate},
5018                 {"list", rpc_share_list},
5019                 {NULL, NULL}
5020         };
5021
5022         if (argc == 0)
5023                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
5024                                        rpc_share_list_internals,
5025                                        argc, argv);
5026
5027         return net_run_function(argc, argv, func, rpc_share_usage);
5028 }
5029
5030 static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
5031                                   struct rpc_sh_ctx *ctx,
5032                                   struct rpc_pipe_client *pipe_hnd,
5033                                   int argc, const char **argv)
5034 {
5035         return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
5036                                         ctx->cli, pipe_hnd, mem_ctx,
5037                                         argc, argv);
5038 }
5039
5040 static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
5041                                  struct rpc_sh_ctx *ctx,
5042                                  struct rpc_pipe_client *pipe_hnd,
5043                                  int argc, const char **argv)
5044 {
5045         WERROR result;
5046
5047         if ((argc < 2) || (argc > 3)) {
5048                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
5049                           ctx->whoami);
5050                 return NT_STATUS_INVALID_PARAMETER;
5051         }
5052
5053         result = rpccli_srvsvc_net_share_add(
5054                 pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
5055                 (argc == 3) ? argv[2] : "",
5056                 0, 0, 0, argv[1], NULL, 2, NULL);
5057                                              
5058         return werror_to_ntstatus(result);
5059 }
5060
5061 static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
5062                                     struct rpc_sh_ctx *ctx,
5063                                     struct rpc_pipe_client *pipe_hnd,
5064                                     int argc, const char **argv)
5065 {
5066         WERROR result;
5067
5068         if (argc != 1) {
5069                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5070                 return NT_STATUS_INVALID_PARAMETER;
5071         }
5072
5073         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
5074         return werror_to_ntstatus(result);
5075 }
5076
5077 static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
5078                                   struct rpc_sh_ctx *ctx,
5079                                   struct rpc_pipe_client *pipe_hnd,
5080                                   int argc, const char **argv)
5081 {
5082         SRV_SHARE_INFO info;
5083         SRV_SHARE_INFO_2 *info2 = &info.share.info2;
5084         WERROR result;
5085
5086         if (argc != 1) {
5087                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5088                 return NT_STATUS_INVALID_PARAMETER;
5089         }
5090
5091         result = rpccli_srvsvc_net_share_get_info(
5092                 pipe_hnd, mem_ctx, argv[0], 2, &info);
5093         if (!W_ERROR_IS_OK(result)) {
5094                 goto done;
5095         }
5096
5097         d_printf("Name:     %s\n",
5098                  rpcstr_pull_unistr2_talloc(mem_ctx,
5099                                             &info2->info_2_str.uni_netname));
5100         d_printf("Comment:  %s\n",
5101                  rpcstr_pull_unistr2_talloc(mem_ctx,
5102                                             &info2->info_2_str.uni_remark));
5103         
5104         d_printf("Path:     %s\n",
5105                  rpcstr_pull_unistr2_talloc(mem_ctx,
5106                                             &info2->info_2_str.uni_path));
5107         d_printf("Password: %s\n",
5108                  rpcstr_pull_unistr2_talloc(mem_ctx,
5109                                             &info2->info_2_str.uni_passwd));
5110
5111  done:
5112         return werror_to_ntstatus(result);
5113 }
5114
5115 struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
5116                                       struct rpc_sh_ctx *ctx)
5117 {
5118         static struct rpc_sh_cmd cmds[] = {
5119
5120         { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
5121           "List available shares" },
5122
5123         { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
5124           "Add a share" },
5125
5126         { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
5127           "Delete a share" },
5128
5129         { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
5130           "Get information about a share" },
5131
5132         { NULL, NULL, 0, NULL, NULL }
5133         };
5134
5135         return cmds;
5136 }
5137
5138 /****************************************************************************/
5139
5140 static int rpc_file_usage(int argc, const char **argv)
5141 {
5142         return net_help_file(argc, argv);
5143 }
5144
5145 /** 
5146  * Close a file on a remote RPC server
5147  *
5148  * All parameters are provided by the run_rpc_command function, except for
5149  * argc, argv which are passes through. 
5150  *
5151  * @param domain_sid The domain sid acquired from the remote server
5152  * @param cli A cli_state connected to the server.
5153  * @param mem_ctx Talloc context, destoyed on completion of the function.
5154  * @param argc  Standard main() style argc
5155  * @param argv  Standard main() style argv.  Initial components are already
5156  *              stripped
5157  *
5158  * @return Normal NTSTATUS return.
5159  **/
5160 static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
5161                                         const char *domain_name, 
5162                                         struct cli_state *cli,
5163                                         struct rpc_pipe_client *pipe_hnd,
5164                                         TALLOC_CTX *mem_ctx,
5165                                         int argc,
5166                                         const char **argv)
5167 {
5168         return rpccli_srvsvc_NetFileClose(pipe_hnd, mem_ctx, 
5169                                             pipe_hnd->cli->desthost, 
5170                                             atoi(argv[0]), NULL);
5171 }
5172
5173 /** 
5174  * Close a file on a remote RPC server
5175  *
5176  * @param argc  Standard main() style argc
5177  * @param argv  Standard main() style argv.  Initial components are already
5178  *              stripped
5179  *
5180  * @return A shell status integer (0 for success)
5181  **/
5182 static int rpc_file_close(int argc, const char **argv)
5183 {
5184         if (argc < 1) {
5185                 DEBUG(1, ("No fileid given on close\n"));
5186                 return(rpc_file_usage(argc, argv));
5187         }
5188
5189         return run_rpc_command(NULL, PI_SRVSVC, 0, 
5190                                rpc_file_close_internals,
5191                                argc, argv);
5192 }
5193
5194 /** 
5195  * Formatted print of open file info 
5196  *
5197  * @param info3  FILE_INFO_3 contents
5198  * @param str3   strings for FILE_INFO_3
5199  **/
5200
5201 static void display_file_info_3( FILE_INFO_3 *info3 )
5202 {
5203         fstring user = "", path = "";
5204
5205         rpcstr_pull_unistr2_fstring(user, info3->user);
5206         rpcstr_pull_unistr2_fstring(path, info3->path);
5207
5208         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5209                  info3->id, user, info3->perms, info3->num_locks, path);
5210 }
5211
5212 /** 
5213  * List open files on a remote RPC server
5214  *
5215  * All parameters are provided by the run_rpc_command function, except for
5216  * argc, argv which are passes through. 
5217  *
5218  * @param domain_sid The domain sid acquired from the remote server
5219  * @param cli A cli_state connected to the server.
5220  * @param mem_ctx Talloc context, destoyed on completion of the function.
5221  * @param argc  Standard main() style argc
5222  * @param argv  Standard main() style argv.  Initial components are already
5223  *              stripped
5224  *
5225  * @return Normal NTSTATUS return.
5226  **/
5227
5228 static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
5229                                         const char *domain_name, 
5230                                         struct cli_state *cli,
5231                                         struct rpc_pipe_client *pipe_hnd,
5232                                         TALLOC_CTX *mem_ctx,
5233                                         int argc,
5234                                         const char **argv)
5235 {
5236         SRV_FILE_INFO_CTR ctr;
5237         WERROR result;
5238         ENUM_HND hnd;
5239         uint32 preferred_len = 0xffffffff, i;
5240         const char *username=NULL;
5241
5242         init_enum_hnd(&hnd, 0);
5243
5244         /* if argc > 0, must be user command */
5245         if (argc > 0)
5246                 username = smb_xstrdup(argv[0]);
5247                 
5248         result = rpccli_srvsvc_net_file_enum(pipe_hnd,
5249                                         mem_ctx, 3, username, &ctr, preferred_len, &hnd);
5250
5251         if (!W_ERROR_IS_OK(result))
5252                 goto done;
5253
5254         /* Display results */
5255
5256         d_printf(
5257                  "\nEnumerating open files on remote server:\n\n"\
5258                  "\nFileId  Opened by            Perms  Locks  Path"\
5259                  "\n------  ---------            -----  -----  ---- \n");
5260         for (i = 0; i < ctr.num_entries; i++)
5261                 display_file_info_3(&ctr.file.info3[i]);
5262  done:
5263         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
5264 }
5265
5266 /** 
5267  * List files for a user on a remote RPC server
5268  *
5269  * @param argc  Standard main() style argc
5270  * @param argv  Standard main() style argv.  Initial components are already
5271  *              stripped
5272  *
5273  * @return A shell status integer (0 for success)
5274  **/
5275
5276 static int rpc_file_user(int argc, const char **argv)
5277 {
5278         if (argc < 1) {
5279                 DEBUG(1, ("No username given\n"));
5280                 return(rpc_file_usage(argc, argv));
5281         }
5282
5283         return run_rpc_command(NULL, PI_SRVSVC, 0, 
5284                                rpc_file_list_internals,
5285                                argc, argv);
5286 }
5287
5288 /** 
5289  * 'net rpc file' entrypoint.
5290  * @param argc  Standard main() style argc
5291  * @param argv  Standard main() style argv.  Initial components are already
5292  *              stripped
5293  **/
5294
5295 int net_rpc_file(int argc, const char **argv) 
5296 {
5297         struct functable func[] = {
5298                 {"close", rpc_file_close},
5299                 {"user", rpc_file_user},
5300 #if 0
5301                 {"info", rpc_file_info},
5302 #endif
5303                 {NULL, NULL}
5304         };
5305
5306         if (argc == 0)
5307                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
5308                                        rpc_file_list_internals,
5309                                        argc, argv);
5310
5311         return net_run_function(argc, argv, func, rpc_file_usage);
5312 }
5313
5314 /** 
5315  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
5316  *
5317  * All parameters are provided by the run_rpc_command function, except for
5318  * argc, argv which are passed through. 
5319  *
5320  * @param domain_sid The domain sid aquired from the remote server
5321  * @param cli A cli_state connected to the server.
5322  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5323  * @param argc  Standard main() style argc
5324  * @param argv  Standard main() style argv.  Initial components are already
5325  *              stripped
5326  *
5327  * @return Normal NTSTATUS return.
5328  **/
5329
5330 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
5331                                         const char *domain_name, 
5332                                         struct cli_state *cli, 
5333                                         struct rpc_pipe_client *pipe_hnd,
5334                                         TALLOC_CTX *mem_ctx, 
5335                                         int argc,
5336                                         const char **argv) 
5337 {
5338         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5339         
5340         result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5341         
5342         if (NT_STATUS_IS_OK(result)) {
5343                 d_printf("\nShutdown successfully aborted\n");
5344                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5345         } else
5346                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5347         
5348         return result;
5349 }
5350
5351 /** 
5352  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
5353  *
5354  * All parameters are provided by the run_rpc_command function, except for
5355  * argc, argv which are passed through. 
5356  *
5357  * @param domain_sid The domain sid aquired from the remote server
5358  * @param cli A cli_state connected to the server.
5359  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5360  * @param argc  Standard main() style argc
5361  * @param argv  Standard main() style argv.  Initial components are already
5362  *              stripped
5363  *
5364  * @return Normal NTSTATUS return.
5365  **/
5366
5367 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
5368                                                 const char *domain_name, 
5369                                                 struct cli_state *cli, 
5370                                                 struct rpc_pipe_client *pipe_hnd,
5371                                                 TALLOC_CTX *mem_ctx, 
5372                                                 int argc,
5373                                                 const char **argv) 
5374 {
5375         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5376         
5377         result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5378         
5379         if (NT_STATUS_IS_OK(result)) {
5380                 d_printf("\nShutdown successfully aborted\n");
5381                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5382         } else
5383                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5384         
5385         return result;
5386 }
5387
5388 /** 
5389  * ABORT the Shut down of a remote RPC server
5390  *
5391  * @param argc  Standard main() style argc
5392  * @param argv  Standard main() style argv.  Initial components are already
5393  *              stripped
5394  *
5395  * @return A shell status integer (0 for success)
5396  **/
5397
5398 static int rpc_shutdown_abort(int argc, const char **argv) 
5399 {
5400         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5401                                  rpc_shutdown_abort_internals,
5402                                  argc, argv);
5403
5404         if (rc == 0)
5405                 return rc;
5406
5407         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5408
5409         return run_rpc_command(NULL, PI_WINREG, 0, 
5410                                rpc_reg_shutdown_abort_internals,
5411                                argc, argv);
5412 }
5413
5414 /** 
5415  * Shut down a remote RPC Server via initshutdown pipe
5416  *
5417  * All parameters are provided by the run_rpc_command function, except for
5418  * argc, argv which are passes through. 
5419  *
5420  * @param domain_sid The domain sid aquired from the remote server
5421  * @param cli A cli_state connected to the server.
5422  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5423  * @param argc  Standard main() style argc
5424  * @param argc  Standard main() style argv.  Initial components are already
5425  *              stripped
5426  *
5427  * @return Normal NTSTATUS return.
5428  **/
5429
5430 NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
5431                                                 const char *domain_name, 
5432                                                 struct cli_state *cli, 
5433                                                 struct rpc_pipe_client *pipe_hnd,
5434                                                 TALLOC_CTX *mem_ctx, 
5435                                                 int argc,
5436                                                 const char **argv) 
5437 {
5438         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5439         const char *msg = "This machine will be shutdown shortly";
5440         uint32 timeout = 20;
5441         struct initshutdown_String msg_string;
5442         struct initshutdown_String_sub s;
5443
5444         if (opt_comment) {
5445                 msg = opt_comment;
5446         }
5447         if (opt_timeout) {
5448                 timeout = opt_timeout;
5449         }
5450
5451         s.name = msg;
5452         msg_string.name = &s;
5453
5454         /* create an entry */
5455         result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5456                         &msg_string, timeout, opt_force, opt_reboot, NULL);
5457
5458         if (NT_STATUS_IS_OK(result)) {
5459                 d_printf("\nShutdown of remote machine succeeded\n");
5460                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5461         } else {
5462                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5463         }
5464         return result;
5465 }
5466
5467 /** 
5468  * Shut down a remote RPC Server via winreg pipe
5469  *
5470  * All parameters are provided by the run_rpc_command function, except for
5471  * argc, argv which are passes through. 
5472  *
5473  * @param domain_sid The domain sid aquired from the remote server
5474  * @param cli A cli_state connected to the server.
5475  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5476  * @param argc  Standard main() style argc
5477  * @param argc  Standard main() style argv.  Initial components are already
5478  *              stripped
5479  *
5480  * @return Normal NTSTATUS return.
5481  **/
5482
5483 NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid,
5484                                                 const char *domain_name, 
5485                                                 struct cli_state *cli, 
5486                                                 struct rpc_pipe_client *pipe_hnd,
5487                                                 TALLOC_CTX *mem_ctx, 
5488                                                 int argc,
5489                                                 const char **argv) 
5490 {
5491         const char *msg = "This machine will be shutdown shortly";
5492         uint32 timeout = 20;
5493         struct initshutdown_String msg_string;
5494         struct initshutdown_String_sub s;
5495         NTSTATUS result;
5496         WERROR werr;
5497
5498         if (opt_comment) {
5499                 msg = opt_comment;
5500         }
5501         s.name = msg;
5502         msg_string.name = &s;
5503
5504         if (opt_timeout) {
5505                 timeout = opt_timeout;
5506         }
5507
5508         /* create an entry */
5509         result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5510                         &msg_string, timeout, opt_force, opt_reboot, &werr);
5511
5512         if (NT_STATUS_IS_OK(result)) {
5513                 d_printf("\nShutdown of remote machine succeeded\n");
5514         } else {
5515                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5516                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5517                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5518                 else
5519                         d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(werr));
5520         }
5521
5522         return result;
5523 }
5524
5525 /** 
5526  * Shut down a remote RPC server
5527  *
5528  * @param argc  Standard main() style argc
5529  * @param argc  Standard main() style argv.  Initial components are already
5530  *              stripped
5531  *
5532  * @return A shell status integer (0 for success)
5533  **/
5534
5535 static int rpc_shutdown(int argc, const char **argv) 
5536 {
5537         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5538                                  rpc_init_shutdown_internals,
5539                                  argc, argv);
5540
5541         if (rc) {
5542                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5543                 rc = run_rpc_command(NULL, PI_WINREG, 0, 
5544                                      rpc_reg_shutdown_internals, argc, argv);
5545         }
5546
5547         return rc;
5548 }
5549
5550 /***************************************************************************
5551   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5552   
5553  ***************************************************************************/
5554
5555 /**
5556  * Add interdomain trust account to the RPC server.
5557  * All parameters (except for argc and argv) are passed by run_rpc_command
5558  * function.
5559  *
5560  * @param domain_sid The domain sid acquired from the server
5561  * @param cli A cli_state connected to the server.
5562  * @param mem_ctx Talloc context, destoyed on completion of the function.
5563  * @param argc  Standard main() style argc
5564  * @param argc  Standard main() style argv.  Initial components are already
5565  *              stripped
5566  *
5567  * @return normal NTSTATUS return code
5568  */
5569
5570 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
5571                                                 const char *domain_name, 
5572                                                 struct cli_state *cli,
5573                                                 struct rpc_pipe_client *pipe_hnd,
5574                                                 TALLOC_CTX *mem_ctx, 
5575                                                 int argc,
5576                                                 const char **argv)
5577 {
5578         POLICY_HND connect_pol, domain_pol, user_pol;
5579         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5580         char *acct_name;
5581         struct lsa_String lsa_acct_name;
5582         uint32 acb_info;
5583         uint32 acct_flags=0;
5584         uint32 user_rid;
5585         uint32_t access_granted = 0;
5586         union samr_UserInfo info;
5587
5588         if (argc != 2) {
5589                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
5590                 return NT_STATUS_INVALID_PARAMETER;
5591         }
5592
5593         /* 
5594          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5595          */
5596
5597         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5598                 return NT_STATUS_NO_MEMORY;
5599         }
5600
5601         strupper_m(acct_name);
5602
5603         init_lsa_String(&lsa_acct_name, acct_name);
5604
5605         /* Get samr policy handle */
5606         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5607                                       pipe_hnd->cli->desthost,
5608                                       MAXIMUM_ALLOWED_ACCESS,
5609                                       &connect_pol);
5610         if (!NT_STATUS_IS_OK(result)) {
5611                 goto done;
5612         }
5613
5614         /* Get domain policy handle */
5615         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5616                                         &connect_pol,
5617                                         MAXIMUM_ALLOWED_ACCESS,
5618                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5619                                         &domain_pol);
5620         if (!NT_STATUS_IS_OK(result)) {
5621                 goto done;
5622         }
5623
5624         /* Create trusting domain's account */
5625         acb_info = ACB_NORMAL;
5626         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5627                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5628                      SAMR_USER_ACCESS_SET_PASSWORD |
5629                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5630                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5631
5632         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5633                                          &domain_pol,
5634                                          &lsa_acct_name,
5635                                          acb_info,
5636                                          acct_flags,
5637                                          &user_pol,
5638                                          &access_granted,
5639                                          &user_rid);
5640         if (!NT_STATUS_IS_OK(result)) {
5641                 goto done;
5642         }
5643
5644         {
5645                 NTTIME notime;
5646                 struct samr_LogonHours hours;
5647                 const int units_per_week = 168;
5648                 uchar pwbuf[516];
5649
5650                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
5651
5652                 ZERO_STRUCT(notime);
5653
5654                 ZERO_STRUCT(hours);
5655                 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
5656                 if (!hours.bits) {
5657                         result = NT_STATUS_NO_MEMORY;
5658                         goto done;
5659                 }
5660                 hours.units_per_week = units_per_week;
5661                 memset(hours.bits, 0xFF, units_per_week);
5662
5663                 init_samr_user_info23(&info.info23,
5664                                       notime, notime, notime,
5665                                       notime, notime, notime,
5666                                       NULL, NULL, NULL, NULL, NULL,
5667                                       NULL, NULL, NULL, NULL, NULL,
5668                                       0, 0, ACB_DOMTRUST, SAMR_FIELD_ACCT_FLAGS,
5669                                       hours,
5670                                       0, 0, 0, 0, 0, 0, 0,
5671                                       pwbuf, 24);
5672
5673                 SamOEMhashBlob(info.info23.password.data, 516,
5674                                &cli->user_session_key);
5675
5676                 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5677                                                   &user_pol,
5678                                                   23,
5679                                                   &info);
5680
5681                 if (!NT_STATUS_IS_OK(result)) {
5682                         DEBUG(0,("Could not set trust account password: %s\n",
5683                                  nt_errstr(result)));
5684                         goto done;
5685                 }
5686         }
5687
5688  done:
5689         SAFE_FREE(acct_name);
5690         return result;
5691 }
5692
5693 /**
5694  * Create interdomain trust account for a remote domain.
5695  *
5696  * @param argc standard argc
5697  * @param argv standard argv without initial components
5698  *
5699  * @return Integer status (0 means success)
5700  **/
5701
5702 static int rpc_trustdom_add(int argc, const char **argv)
5703 {
5704         if (argc > 0) {
5705                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
5706                                        argc, argv);
5707         } else {
5708                 d_printf("Usage: net rpc trustdom add <domain>\n");
5709                 return -1;
5710         }
5711 }
5712
5713
5714 /**
5715  * Remove interdomain trust account from the RPC server.
5716  * All parameters (except for argc and argv) are passed by run_rpc_command
5717  * function.
5718  *
5719  * @param domain_sid The domain sid acquired from the server
5720  * @param cli A cli_state connected to the server.
5721  * @param mem_ctx Talloc context, destoyed on completion of the function.
5722  * @param argc  Standard main() style argc
5723  * @param argc  Standard main() style argv.  Initial components are already
5724  *              stripped
5725  *
5726  * @return normal NTSTATUS return code
5727  */
5728
5729 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
5730                                         const char *domain_name, 
5731                                         struct cli_state *cli,
5732                                         struct rpc_pipe_client *pipe_hnd,
5733                                         TALLOC_CTX *mem_ctx, 
5734                                         int argc,
5735                                         const char **argv)
5736 {
5737         POLICY_HND connect_pol, domain_pol, user_pol;
5738         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5739         char *acct_name;
5740         DOM_SID trust_acct_sid;
5741         struct samr_Ids user_rids, name_types;
5742         struct lsa_String lsa_acct_name;
5743
5744         if (argc != 1) {
5745                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5746                 return NT_STATUS_INVALID_PARAMETER;
5747         }
5748
5749         /* 
5750          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5751          */
5752         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5753
5754         if (acct_name == NULL)
5755                 return NT_STATUS_NO_MEMORY;
5756
5757         strupper_m(acct_name);
5758
5759         /* Get samr policy handle */
5760         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5761                                       pipe_hnd->cli->desthost,
5762                                       MAXIMUM_ALLOWED_ACCESS,
5763                                       &connect_pol);
5764         if (!NT_STATUS_IS_OK(result)) {
5765                 goto done;
5766         }
5767
5768         /* Get domain policy handle */
5769         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5770                                         &connect_pol,
5771                                         MAXIMUM_ALLOWED_ACCESS,
5772                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5773                                         &domain_pol);
5774         if (!NT_STATUS_IS_OK(result)) {
5775                 goto done;
5776         }
5777
5778         init_lsa_String(&lsa_acct_name, acct_name);
5779
5780         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5781                                          &domain_pol,
5782                                          1,
5783                                          &lsa_acct_name,
5784                                          &user_rids,
5785                                          &name_types);
5786
5787         if (!NT_STATUS_IS_OK(result)) {
5788                 goto done;
5789         }
5790
5791         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5792                                       &domain_pol,
5793                                       MAXIMUM_ALLOWED_ACCESS,
5794                                       user_rids.ids[0],
5795                                       &user_pol);
5796
5797         if (!NT_STATUS_IS_OK(result)) {
5798                 goto done;
5799         }
5800
5801         /* append the rid to the domain sid */
5802         sid_copy(&trust_acct_sid, domain_sid);
5803         if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5804                 goto done;
5805         }
5806
5807         /* remove the sid */
5808
5809         result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5810                                                            &user_pol,
5811                                                            &trust_acct_sid);
5812         if (!NT_STATUS_IS_OK(result)) {
5813                 goto done;
5814         }
5815
5816         /* Delete user */
5817
5818         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5819                                         &user_pol);
5820
5821         if (!NT_STATUS_IS_OK(result)) {
5822                 goto done;
5823         }
5824
5825         if (!NT_STATUS_IS_OK(result)) {
5826           DEBUG(0,("Could not set trust account password: %s\n",
5827                    nt_errstr(result)));
5828           goto done;
5829         }
5830
5831  done:
5832         return result;
5833 }
5834
5835 /**
5836  * Delete interdomain trust account for a remote domain.
5837  *
5838  * @param argc standard argc
5839  * @param argv standard argv without initial components
5840  *
5841  * @return Integer status (0 means success)
5842  **/
5843
5844 static int rpc_trustdom_del(int argc, const char **argv)
5845 {
5846         if (argc > 0) {
5847                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
5848                                        argc, argv);
5849         } else {
5850                 d_printf("Usage: net rpc trustdom del <domain>\n");
5851                 return -1;
5852         }
5853 }
5854  
5855
5856 /**
5857  * Establish trust relationship to a trusting domain.
5858  * Interdomain account must already be created on remote PDC.
5859  *
5860  * @param argc standard argc
5861  * @param argv standard argv without initial components
5862  *
5863  * @return Integer status (0 means success)
5864  **/
5865
5866 static int rpc_trustdom_establish(int argc, const char **argv)
5867 {
5868         struct cli_state *cli = NULL;
5869         struct sockaddr_storage server_ss;
5870         struct rpc_pipe_client *pipe_hnd = NULL;
5871         POLICY_HND connect_hnd;
5872         TALLOC_CTX *mem_ctx;
5873         NTSTATUS nt_status;
5874         DOM_SID *domain_sid;
5875
5876         char* domain_name;
5877         char* acct_name;
5878         fstring pdc_name;
5879         char *dc_name;
5880         union lsa_PolicyInformation *info = NULL;
5881
5882         /*
5883          * Connect to \\server\ipc$ as 'our domain' account with password
5884          */
5885
5886         if (argc != 1) {
5887                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
5888                 return -1;
5889         }
5890
5891         domain_name = smb_xstrdup(argv[0]);
5892         strupper_m(domain_name);
5893
5894         /* account name used at first is our domain's name with '$' */
5895         asprintf(&acct_name, "%s$", lp_workgroup());
5896         strupper_m(acct_name);
5897
5898         /*
5899          * opt_workgroup will be used by connection functions further,
5900          * hence it should be set to remote domain name instead of ours
5901          */
5902         if (opt_workgroup) {
5903                 opt_workgroup = smb_xstrdup(domain_name);
5904         };
5905
5906         opt_user_name = acct_name;
5907
5908         /* find the domain controller */
5909         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5910                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5911                 return -1;
5912         }
5913
5914         /* connect to ipc$ as username/password */
5915         nt_status = connect_to_ipc(&cli, &server_ss, pdc_name);
5916         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5917
5918                 /* Is it trusting domain account for sure ? */
5919                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5920                         nt_errstr(nt_status)));
5921                 return -1;
5922         }
5923
5924         /* store who we connected to */
5925
5926         saf_store( domain_name, pdc_name );
5927
5928         /*
5929          * Connect to \\server\ipc$ again (this time anonymously)
5930          */
5931
5932         nt_status = connect_to_ipc_anonymous(&cli, &server_ss, (char*)pdc_name);
5933
5934         if (NT_STATUS_IS_ERR(nt_status)) {
5935                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5936                         domain_name, nt_errstr(nt_status)));
5937                 return -1;
5938         }
5939
5940         /*
5941          * Use NetServerEnum2 to make sure we're talking to a proper server
5942          */
5943
5944         if (!cli_get_pdc_name(cli, domain_name, &dc_name)) {
5945                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
5946                          for domain %s\n", domain_name));
5947                 cli_shutdown(cli);
5948                 return -1;
5949         }
5950         SAFE_FREE(dc_name);
5951          
5952         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5953                                     "domain %s", domain_name))) {
5954                 DEBUG(0, ("talloc_init() failed\n"));
5955                 cli_shutdown(cli);
5956                 return -1;
5957         }
5958
5959         /*
5960          * Call LsaOpenPolicy and LsaQueryInfo
5961          */
5962          
5963         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5964         if (!pipe_hnd) {
5965                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5966                 cli_shutdown(cli);
5967                 talloc_destroy(mem_ctx);
5968                 return -1;
5969         }
5970
5971         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
5972                                          &connect_hnd);
5973         if (NT_STATUS_IS_ERR(nt_status)) {
5974                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5975                         nt_errstr(nt_status)));
5976                 cli_shutdown(cli);
5977                 talloc_destroy(mem_ctx);
5978                 return -1;
5979         }
5980
5981         /* Querying info level 5 */
5982
5983         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5984                                                &connect_hnd,
5985                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5986                                                &info);
5987         if (NT_STATUS_IS_ERR(nt_status)) {
5988                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5989                         nt_errstr(nt_status)));
5990                 cli_shutdown(cli);
5991                 talloc_destroy(mem_ctx);
5992                 return -1;
5993         }
5994
5995         domain_sid = info->account_domain.sid;
5996
5997         /* There should be actually query info level 3 (following nt serv behaviour),
5998            but I still don't know if it's _really_ necessary */
5999                         
6000         /*
6001          * Store the password in secrets db
6002          */
6003
6004         if (!pdb_set_trusteddom_pw(domain_name, opt_password, domain_sid)) {
6005                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6006                 cli_shutdown(cli);
6007                 talloc_destroy(mem_ctx);
6008                 return -1;
6009         }
6010         
6011         /*
6012          * Close the pipes and clean up
6013          */
6014          
6015         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6016         if (NT_STATUS_IS_ERR(nt_status)) {
6017                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6018                         nt_errstr(nt_status)));
6019                 cli_shutdown(cli);
6020                 talloc_destroy(mem_ctx);
6021                 return -1;
6022         }
6023
6024         cli_shutdown(cli);
6025          
6026         talloc_destroy(mem_ctx);
6027          
6028         d_printf("Trust to domain %s established\n", domain_name);
6029         return 0;
6030 }
6031
6032 /**
6033  * Revoke trust relationship to the remote domain
6034  *
6035  * @param argc standard argc
6036  * @param argv standard argv without initial components
6037  *
6038  * @return Integer status (0 means success)
6039  **/
6040
6041 static int rpc_trustdom_revoke(int argc, const char **argv)
6042 {
6043         char* domain_name;
6044         int rc = -1;
6045
6046         if (argc < 1) return -1;
6047         
6048         /* generate upper cased domain name */
6049         domain_name = smb_xstrdup(argv[0]);
6050         strupper_m(domain_name);
6051
6052         /* delete password of the trust */
6053         if (!pdb_del_trusteddom_pw(domain_name)) {
6054                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6055                           domain_name));
6056                 goto done;
6057         };
6058         
6059         rc = 0;
6060 done:
6061         SAFE_FREE(domain_name);
6062         return rc;
6063 }
6064
6065 /**
6066  * Usage for 'net rpc trustdom' command
6067  *
6068  * @param argc standard argc
6069  * @param argv standard argv without inital components
6070  *
6071  * @return Integer status returned to shell
6072  **/
6073  
6074 static int rpc_trustdom_usage(int argc, const char **argv)
6075 {
6076         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
6077         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
6078         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
6079         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
6080         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
6081         d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
6082         return -1;
6083 }
6084
6085
6086 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
6087                                         const char *domain_name, 
6088                                         struct cli_state *cli,
6089                                         struct rpc_pipe_client *pipe_hnd,
6090                                         TALLOC_CTX *mem_ctx,
6091                                         int argc,
6092                                         const char **argv)
6093 {
6094         fstring str_sid;
6095         sid_to_fstring(str_sid, domain_sid);
6096         d_printf("%s\n", str_sid);
6097         return NT_STATUS_OK;
6098 }
6099
6100 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
6101 {
6102         fstring ascii_sid, padding;
6103         int pad_len, col_len = 20;
6104
6105         /* convert sid into ascii string */
6106         sid_to_fstring(ascii_sid, dom_sid);
6107
6108         /* calculate padding space for d_printf to look nicer */
6109         pad_len = col_len - strlen(trusted_dom_name);
6110         padding[pad_len] = 0;
6111         do padding[--pad_len] = ' '; while (pad_len);
6112                         
6113         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
6114 }
6115
6116 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6117                                       TALLOC_CTX *mem_ctx, 
6118                                       POLICY_HND *pol, 
6119                                       DOM_SID dom_sid, 
6120                                       const char *trusted_dom_name)
6121 {
6122         NTSTATUS nt_status;
6123         union lsa_TrustedDomainInfo info;
6124         char *cleartextpwd = NULL;
6125         DATA_BLOB data;
6126
6127         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6128                                                            pol,
6129                                                            &dom_sid,
6130                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6131                                                            &info);
6132         if (NT_STATUS_IS_ERR(nt_status)) {
6133                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6134                 nt_errstr(nt_status)));
6135                 goto done;
6136         }
6137
6138         data = data_blob(NULL, info.password.password->length);
6139
6140         memcpy(data.data,
6141                info.password.password->data,
6142                info.password.password->length);
6143         data.length = info.password.password->length;
6144
6145         cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password,
6146                                                &data);
6147
6148         if (cleartextpwd == NULL) {
6149                 DEBUG(0,("retrieved NULL password\n"));
6150                 nt_status = NT_STATUS_UNSUCCESSFUL;
6151                 goto done;
6152         }
6153         
6154         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6155                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6156                 nt_status = NT_STATUS_UNSUCCESSFUL;
6157                 goto done;
6158         }
6159
6160 #ifdef DEBUG_PASSWORD
6161         DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], "
6162                    "password: [%s]\n", trusted_dom_name,
6163                    sid_string_dbg(&dom_sid), cleartextpwd));
6164 #endif
6165
6166 done:
6167         SAFE_FREE(cleartextpwd);
6168         data_blob_free(&data);
6169
6170         return nt_status;
6171 }
6172
6173 static int rpc_trustdom_vampire(int argc, const char **argv)
6174 {
6175         /* common variables */
6176         TALLOC_CTX* mem_ctx;
6177         struct cli_state *cli = NULL;
6178         struct rpc_pipe_client *pipe_hnd = NULL;
6179         NTSTATUS nt_status;
6180         const char *domain_name = NULL;
6181         DOM_SID *queried_dom_sid;
6182         POLICY_HND connect_hnd;
6183         union lsa_PolicyInformation *info = NULL;
6184
6185         /* trusted domains listing variables */
6186         unsigned int enum_ctx = 0;
6187         int i;
6188         struct lsa_DomainList dom_list;
6189         fstring pdc_name;
6190
6191         /*
6192          * Listing trusted domains (stored in secrets.tdb, if local)
6193          */
6194
6195         mem_ctx = talloc_init("trust relationships vampire");
6196
6197         /*
6198          * set domain and pdc name to local samba server (default)
6199          * or to remote one given in command line
6200          */
6201
6202         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6203                 domain_name = opt_workgroup;
6204                 opt_target_workgroup = opt_workgroup;
6205         } else {
6206                 fstrcpy(pdc_name, global_myname());
6207                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6208                 opt_target_workgroup = domain_name;
6209         };
6210
6211         /* open \PIPE\lsarpc and open policy handle */
6212         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
6213         if (!NT_STATUS_IS_OK(nt_status)) {
6214                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6215                           nt_errstr(nt_status)));
6216                 talloc_destroy(mem_ctx);
6217                 return -1;
6218         };
6219
6220         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6221         if (!pipe_hnd) {
6222                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6223                         nt_errstr(nt_status) ));
6224                 cli_shutdown(cli);
6225                 talloc_destroy(mem_ctx);
6226                 return -1;
6227         };
6228
6229         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6230                                         &connect_hnd);
6231         if (NT_STATUS_IS_ERR(nt_status)) {
6232                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6233                         nt_errstr(nt_status)));
6234                 cli_shutdown(cli);
6235                 talloc_destroy(mem_ctx);
6236                 return -1;
6237         };
6238
6239         /* query info level 5 to obtain sid of a domain being queried */
6240         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6241                                                &connect_hnd,
6242                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6243                                                &info);
6244
6245         if (NT_STATUS_IS_ERR(nt_status)) {
6246                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6247                         nt_errstr(nt_status)));
6248                 cli_shutdown(cli);
6249                 talloc_destroy(mem_ctx);
6250                 return -1;
6251         }
6252
6253         queried_dom_sid = info->account_domain.sid;
6254
6255         /*
6256          * Keep calling LsaEnumTrustdom over opened pipe until
6257          * the end of enumeration is reached
6258          */
6259
6260         d_printf("Vampire trusted domains:\n\n");
6261
6262         do {
6263                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6264                                                     &connect_hnd,
6265                                                     &enum_ctx,
6266                                                     &dom_list,
6267                                                     (uint32_t)-1);
6268                 if (NT_STATUS_IS_ERR(nt_status)) {
6269                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6270                                 nt_errstr(nt_status)));
6271                         cli_shutdown(cli);
6272                         talloc_destroy(mem_ctx);
6273                         return -1;
6274                 };
6275
6276                 for (i = 0; i < dom_list.count; i++) {
6277
6278                         print_trusted_domain(dom_list.domains[i].sid,
6279                                              dom_list.domains[i].name.string);
6280
6281                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
6282                                                            *dom_list.domains[i].sid,
6283                                                            dom_list.domains[i].name.string);
6284                         if (!NT_STATUS_IS_OK(nt_status)) {
6285                                 cli_shutdown(cli);
6286                                 talloc_destroy(mem_ctx);
6287                                 return -1;
6288                         }
6289                 };
6290
6291                 /*
6292                  * in case of no trusted domains say something rather
6293                  * than just display blank line
6294                  */
6295                 if (!dom_list.count) d_printf("none\n");
6296
6297         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6298
6299         /* close this connection before doing next one */
6300         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6301         if (NT_STATUS_IS_ERR(nt_status)) {
6302                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6303                         nt_errstr(nt_status)));
6304                 cli_shutdown(cli);
6305                 talloc_destroy(mem_ctx);
6306                 return -1;
6307         };
6308
6309         /* close lsarpc pipe and connection to IPC$ */
6310         cli_shutdown(cli);
6311
6312         talloc_destroy(mem_ctx);         
6313         return 0;
6314 }
6315
6316 static int rpc_trustdom_list(int argc, const char **argv)
6317 {
6318         /* common variables */
6319         TALLOC_CTX* mem_ctx;
6320         struct cli_state *cli = NULL, *remote_cli = NULL;
6321         struct rpc_pipe_client *pipe_hnd = NULL;
6322         NTSTATUS nt_status;
6323         const char *domain_name = NULL;
6324         DOM_SID *queried_dom_sid;
6325         fstring padding;
6326         int ascii_dom_name_len;
6327         POLICY_HND connect_hnd;
6328         union lsa_PolicyInformation *info = NULL;
6329
6330         /* trusted domains listing variables */
6331         unsigned int num_domains, enum_ctx = 0;
6332         int i, pad_len, col_len = 20;
6333         struct lsa_DomainList dom_list;
6334         fstring pdc_name;
6335
6336         /* trusting domains listing variables */
6337         POLICY_HND domain_hnd;
6338         struct samr_SamArray *trusts = NULL;
6339
6340         /*
6341          * Listing trusted domains (stored in secrets.tdb, if local)
6342          */
6343
6344         mem_ctx = talloc_init("trust relationships listing");
6345
6346         /*
6347          * set domain and pdc name to local samba server (default)
6348          * or to remote one given in command line
6349          */
6350         
6351         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6352                 domain_name = opt_workgroup;
6353                 opt_target_workgroup = opt_workgroup;
6354         } else {
6355                 fstrcpy(pdc_name, global_myname());
6356                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6357                 opt_target_workgroup = domain_name;
6358         };
6359
6360         /* open \PIPE\lsarpc and open policy handle */
6361         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
6362         if (!NT_STATUS_IS_OK(nt_status)) {
6363                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6364                           nt_errstr(nt_status)));
6365                 talloc_destroy(mem_ctx);
6366                 return -1;
6367         };
6368
6369         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6370         if (!pipe_hnd) {
6371                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6372                         nt_errstr(nt_status) ));
6373                 cli_shutdown(cli);
6374                 talloc_destroy(mem_ctx);
6375                 return -1;
6376         };
6377
6378         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6379                                         &connect_hnd);
6380         if (NT_STATUS_IS_ERR(nt_status)) {
6381                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6382                         nt_errstr(nt_status)));
6383                 cli_shutdown(cli);
6384                 talloc_destroy(mem_ctx);
6385                 return -1;
6386         };
6387         
6388         /* query info level 5 to obtain sid of a domain being queried */
6389         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6390                                                &connect_hnd,
6391                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6392                                                &info);
6393
6394         if (NT_STATUS_IS_ERR(nt_status)) {
6395                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6396                         nt_errstr(nt_status)));
6397                 cli_shutdown(cli);
6398                 talloc_destroy(mem_ctx);
6399                 return -1;
6400         }
6401
6402         queried_dom_sid = info->account_domain.sid;
6403
6404         /*
6405          * Keep calling LsaEnumTrustdom over opened pipe until
6406          * the end of enumeration is reached
6407          */
6408          
6409         d_printf("Trusted domains list:\n\n");
6410
6411         do {
6412                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6413                                                     &connect_hnd,
6414                                                     &enum_ctx,
6415                                                     &dom_list,
6416                                                     (uint32_t)-1);
6417                 if (NT_STATUS_IS_ERR(nt_status)) {
6418                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6419                                 nt_errstr(nt_status)));
6420                         cli_shutdown(cli);
6421                         talloc_destroy(mem_ctx);
6422                         return -1;
6423                 };
6424
6425                 for (i = 0; i < dom_list.count; i++) {
6426                         print_trusted_domain(dom_list.domains[i].sid,
6427                                              dom_list.domains[i].name.string);
6428                 };
6429
6430                 /*
6431                  * in case of no trusted domains say something rather
6432                  * than just display blank line
6433                  */
6434                 if (!dom_list.count) d_printf("none\n");
6435
6436         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6437
6438         /* close this connection before doing next one */
6439         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6440         if (NT_STATUS_IS_ERR(nt_status)) {
6441                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6442                         nt_errstr(nt_status)));
6443                 cli_shutdown(cli);
6444                 talloc_destroy(mem_ctx);
6445                 return -1;
6446         };
6447         
6448         cli_rpc_pipe_close(pipe_hnd);
6449
6450         /*
6451          * Listing trusting domains (stored in passdb backend, if local)
6452          */
6453         
6454         d_printf("\nTrusting domains list:\n\n");
6455
6456         /*
6457          * Open \PIPE\samr and get needed policy handles
6458          */
6459         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
6460         if (!pipe_hnd) {
6461                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6462                 cli_shutdown(cli);
6463                 talloc_destroy(mem_ctx);
6464                 return -1;
6465         };
6466
6467         /* SamrConnect2 */
6468         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6469                                          pipe_hnd->cli->desthost,
6470                                          SA_RIGHT_SAM_OPEN_DOMAIN,
6471                                          &connect_hnd);
6472         if (!NT_STATUS_IS_OK(nt_status)) {
6473                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6474                         nt_errstr(nt_status)));
6475                 cli_shutdown(cli);
6476                 talloc_destroy(mem_ctx);
6477                 return -1;
6478         };
6479
6480         /* SamrOpenDomain - we have to open domain policy handle in order to be
6481            able to enumerate accounts*/
6482         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6483                                            &connect_hnd,
6484                                            SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6485                                            queried_dom_sid,
6486                                            &domain_hnd);
6487         if (!NT_STATUS_IS_OK(nt_status)) {
6488                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6489                         nt_errstr(nt_status)));
6490                 cli_shutdown(cli);
6491                 talloc_destroy(mem_ctx);
6492                 return -1;
6493         };
6494         
6495         /*
6496          * perform actual enumeration
6497          */
6498          
6499         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6500         do {
6501
6502                 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6503                                                         &domain_hnd,
6504                                                         &enum_ctx,
6505                                                         ACB_DOMTRUST,
6506                                                         &trusts,
6507                                                         0xffff,
6508                                                         &num_domains);
6509                 if (NT_STATUS_IS_ERR(nt_status)) {
6510                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6511                                 nt_errstr(nt_status)));
6512                         cli_shutdown(cli);
6513                         talloc_destroy(mem_ctx);
6514                         return -1;
6515                 };
6516
6517                 for (i = 0; i < num_domains; i++) {
6518
6519                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6520
6521                         /*
6522                          * get each single domain's sid (do we _really_ need this ?):
6523                          *  1) connect to domain's pdc
6524                          *  2) query the pdc for domain's sid
6525                          */
6526
6527                         /* get rid of '$' tail */
6528                         ascii_dom_name_len = strlen(str);
6529                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6530                                 str[ascii_dom_name_len - 1] = '\0';
6531
6532                         /* calculate padding space for d_printf to look nicer */
6533                         pad_len = col_len - strlen(str);
6534                         padding[pad_len] = 0;
6535                         do padding[--pad_len] = ' '; while (pad_len);
6536
6537                         /* set opt_* variables to remote domain */
6538                         strupper_m(str);
6539                         opt_workgroup = talloc_strdup(mem_ctx, str);
6540                         opt_target_workgroup = opt_workgroup;
6541
6542                         d_printf("%s%s", str, padding);
6543
6544                         /* connect to remote domain controller */
6545                         nt_status = net_make_ipc_connection(
6546                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6547                                         &remote_cli);
6548                         if (NT_STATUS_IS_OK(nt_status)) {
6549                                 /* query for domain's sid */
6550                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
6551                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6552
6553                                 cli_shutdown(remote_cli);
6554                         
6555                         } else {
6556                                 d_fprintf(stderr, "domain controller is not "
6557                                           "responding: %s\n",
6558                                           nt_errstr(nt_status));
6559                         };
6560                 };
6561                 
6562                 if (!num_domains) d_printf("none\n");
6563                 
6564         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6565
6566         /* close opened samr and domain policy handles */
6567         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6568         if (!NT_STATUS_IS_OK(nt_status)) {
6569                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6570         };
6571         
6572         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6573         if (!NT_STATUS_IS_OK(nt_status)) {
6574                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6575         };
6576         
6577         /* close samr pipe and connection to IPC$ */
6578         cli_shutdown(cli);
6579
6580         talloc_destroy(mem_ctx);         
6581         return 0;
6582 }
6583
6584 /**
6585  * Entrypoint for 'net rpc trustdom' code
6586  *
6587  * @param argc standard argc
6588  * @param argv standard argv without initial components
6589  *
6590  * @return Integer status (0 means success)
6591  */
6592
6593 static int rpc_trustdom(int argc, const char **argv)
6594 {
6595         struct functable func[] = {
6596                 {"add", rpc_trustdom_add},
6597                 {"del", rpc_trustdom_del},
6598                 {"establish", rpc_trustdom_establish},
6599                 {"revoke", rpc_trustdom_revoke},
6600                 {"help", rpc_trustdom_usage},
6601                 {"list", rpc_trustdom_list},
6602                 {"vampire", rpc_trustdom_vampire},
6603                 {NULL, NULL}
6604         };
6605
6606         if (argc == 0) {
6607                 rpc_trustdom_usage(argc, argv);
6608                 return -1;
6609         }
6610
6611         return (net_run_function(argc, argv, func, rpc_user_usage));
6612 }
6613
6614 /**
6615  * Check if a server will take rpc commands
6616  * @param flags Type of server to connect to (PDC, DMB, localhost)
6617  *              if the host is not explicitly specified
6618  * @return  bool (true means rpc supported)
6619  */
6620 bool net_rpc_check(unsigned flags)
6621 {
6622         struct cli_state *cli;
6623         bool ret = False;
6624         struct sockaddr_storage server_ss;
6625         char *server_name = NULL;
6626         NTSTATUS status;
6627
6628         /* flags (i.e. server type) may depend on command */
6629         if (!net_find_server(NULL, flags, &server_ss, &server_name))
6630                 return False;
6631
6632         if ((cli = cli_initialise()) == NULL) {
6633                 return False;
6634         }
6635
6636         status = cli_connect(cli, server_name, &server_ss);
6637         if (!NT_STATUS_IS_OK(status))
6638                 goto done;
6639         if (!attempt_netbios_session_request(&cli, global_myname(),
6640                                              server_name, &server_ss))
6641                 goto done;
6642         if (!cli_negprot(cli))
6643                 goto done;
6644         if (cli->protocol < PROTOCOL_NT1)
6645                 goto done;
6646
6647         ret = True;
6648  done:
6649         cli_shutdown(cli);
6650         return ret;
6651 }
6652
6653 /* dump sam database via samsync rpc calls */
6654 static int rpc_samdump(int argc, const char **argv) {
6655                 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
6656                                argc, argv);
6657 }
6658
6659 /* syncronise sam database via samsync rpc calls */
6660 static int rpc_vampire(int argc, const char **argv) {
6661         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
6662                                argc, argv);
6663 }
6664
6665 /** 
6666  * Migrate everything from a print-server
6667  *
6668  * @param argc  Standard main() style argc
6669  * @param argv  Standard main() style argv.  Initial components are already
6670  *              stripped
6671  *
6672  * @return A shell status integer (0 for success)
6673  *
6674  * The order is important !
6675  * To successfully add drivers the print-queues have to exist !
6676  * Applying ACLs should be the last step, because you're easily locked out
6677  *
6678  **/
6679 static int rpc_printer_migrate_all(int argc, const char **argv)
6680 {
6681         int ret;
6682
6683         if (!opt_host) {
6684                 printf("no server to migrate\n");
6685                 return -1;
6686         }
6687
6688         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
6689         if (ret)
6690                 return ret;
6691
6692         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
6693         if (ret)
6694                 return ret;
6695
6696         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
6697         if (ret)
6698                 return ret;
6699
6700         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
6701         if (ret)
6702                 return ret;
6703
6704         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
6705
6706 }
6707
6708 /** 
6709  * Migrate print-drivers from a print-server
6710  *
6711  * @param argc  Standard main() style argc
6712  * @param argv  Standard main() style argv.  Initial components are already
6713  *              stripped
6714  *
6715  * @return A shell status integer (0 for success)
6716  **/
6717 static int rpc_printer_migrate_drivers(int argc, const char **argv)
6718 {
6719         if (!opt_host) {
6720                 printf("no server to migrate\n");
6721                 return -1;
6722         }
6723
6724         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6725                                rpc_printer_migrate_drivers_internals,
6726                                argc, argv);
6727 }
6728
6729 /** 
6730  * Migrate print-forms from a print-server
6731  *
6732  * @param argc  Standard main() style argc
6733  * @param argv  Standard main() style argv.  Initial components are already
6734  *              stripped
6735  *
6736  * @return A shell status integer (0 for success)
6737  **/
6738 static int rpc_printer_migrate_forms(int argc, const char **argv)
6739 {
6740         if (!opt_host) {
6741                 printf("no server to migrate\n");
6742                 return -1;
6743         }
6744
6745         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6746                                rpc_printer_migrate_forms_internals,
6747                                argc, argv);
6748 }
6749
6750 /** 
6751  * Migrate printers from a print-server
6752  *
6753  * @param argc  Standard main() style argc
6754  * @param argv  Standard main() style argv.  Initial components are already
6755  *              stripped
6756  *
6757  * @return A shell status integer (0 for success)
6758  **/
6759 static int rpc_printer_migrate_printers(int argc, const char **argv)
6760 {
6761         if (!opt_host) {
6762                 printf("no server to migrate\n");
6763                 return -1;
6764         }
6765
6766         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6767                                rpc_printer_migrate_printers_internals,
6768                                argc, argv);
6769 }
6770
6771 /** 
6772  * Migrate printer-ACLs from a print-server
6773  *
6774  * @param argc  Standard main() style argc
6775  * @param argv  Standard main() style argv.  Initial components are already
6776  *              stripped
6777  *
6778  * @return A shell status integer (0 for success)
6779  **/
6780 static int rpc_printer_migrate_security(int argc, const char **argv)
6781 {
6782         if (!opt_host) {
6783                 printf("no server to migrate\n");
6784                 return -1;
6785         }
6786
6787         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6788                                rpc_printer_migrate_security_internals,
6789                                argc, argv);
6790 }
6791
6792 /** 
6793  * Migrate printer-settings from a print-server
6794  *
6795  * @param argc  Standard main() style argc
6796  * @param argv  Standard main() style argv.  Initial components are already
6797  *              stripped
6798  *
6799  * @return A shell status integer (0 for success)
6800  **/
6801 static int rpc_printer_migrate_settings(int argc, const char **argv)
6802 {
6803         if (!opt_host) {
6804                 printf("no server to migrate\n");
6805                 return -1;
6806         }
6807
6808         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6809                                rpc_printer_migrate_settings_internals,
6810                                argc, argv);
6811 }
6812
6813 /** 
6814  * 'net rpc printer' entrypoint.
6815  * @param argc  Standard main() style argc
6816  * @param argv  Standard main() style argv.  Initial components are already
6817  *              stripped
6818  **/
6819
6820 int rpc_printer_migrate(int argc, const char **argv) 
6821 {
6822
6823         /* ouch: when addriver and setdriver are called from within
6824            rpc_printer_migrate_drivers_internals, the printer-queue already
6825            *has* to exist */
6826
6827         struct functable func[] = {
6828                 {"all",         rpc_printer_migrate_all},
6829                 {"drivers",     rpc_printer_migrate_drivers},
6830                 {"forms",       rpc_printer_migrate_forms},
6831                 {"help",        rpc_printer_usage},
6832                 {"printers",    rpc_printer_migrate_printers},
6833                 {"security",    rpc_printer_migrate_security},
6834                 {"settings",    rpc_printer_migrate_settings},
6835                 {NULL, NULL}
6836         };
6837
6838         return net_run_function(argc, argv, func, rpc_printer_usage);
6839 }
6840
6841
6842 /** 
6843  * List printers on a remote RPC server
6844  *
6845  * @param argc  Standard main() style argc
6846  * @param argv  Standard main() style argv.  Initial components are already
6847  *              stripped
6848  *
6849  * @return A shell status integer (0 for success)
6850  **/
6851 static int rpc_printer_list(int argc, const char **argv)
6852 {
6853
6854         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6855                                rpc_printer_list_internals,
6856                                argc, argv);
6857 }
6858
6859 /** 
6860  * List printer-drivers on a remote RPC server
6861  *
6862  * @param argc  Standard main() style argc
6863  * @param argv  Standard main() style argv.  Initial components are already
6864  *              stripped
6865  *
6866  * @return A shell status integer (0 for success)
6867  **/
6868 static int rpc_printer_driver_list(int argc, const char **argv)
6869 {
6870
6871         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6872                                rpc_printer_driver_list_internals,
6873                                argc, argv);
6874 }
6875
6876 /** 
6877  * Publish printer in ADS via MSRPC
6878  *
6879  * @param argc  Standard main() style argc
6880  * @param argv  Standard main() style argv.  Initial components are already
6881  *              stripped
6882  *
6883  * @return A shell status integer (0 for success)
6884  **/
6885 static int rpc_printer_publish_publish(int argc, const char **argv)
6886 {
6887
6888         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6889                                rpc_printer_publish_publish_internals,
6890                                argc, argv);
6891 }
6892
6893 /** 
6894  * Update printer in ADS via MSRPC
6895  *
6896  * @param argc  Standard main() style argc
6897  * @param argv  Standard main() style argv.  Initial components are already
6898  *              stripped
6899  *
6900  * @return A shell status integer (0 for success)
6901  **/
6902 static int rpc_printer_publish_update(int argc, const char **argv)
6903 {
6904
6905         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6906                                rpc_printer_publish_update_internals,
6907                                argc, argv);
6908 }
6909
6910 /** 
6911  * UnPublish printer in ADS via MSRPC
6912  *
6913  * @param argc  Standard main() style argc
6914  * @param argv  Standard main() style argv.  Initial components are already
6915  *              stripped
6916  *
6917  * @return A shell status integer (0 for success)
6918  **/
6919 static int rpc_printer_publish_unpublish(int argc, const char **argv)
6920 {
6921
6922         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6923                                rpc_printer_publish_unpublish_internals,
6924                                argc, argv);
6925 }
6926
6927 /** 
6928  * List published printers via MSRPC
6929  *
6930  * @param argc  Standard main() style argc
6931  * @param argv  Standard main() style argv.  Initial components are already
6932  *              stripped
6933  *
6934  * @return A shell status integer (0 for success)
6935  **/
6936 static int rpc_printer_publish_list(int argc, const char **argv)
6937 {
6938
6939         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6940                                rpc_printer_publish_list_internals,
6941                                argc, argv);
6942 }
6943
6944
6945 /** 
6946  * Publish printer in ADS
6947  *
6948  * @param argc  Standard main() style argc
6949  * @param argv  Standard main() style argv.  Initial components are already
6950  *              stripped
6951  *
6952  * @return A shell status integer (0 for success)
6953  **/
6954 static int rpc_printer_publish(int argc, const char **argv)
6955 {
6956
6957         struct functable func[] = {
6958                 {"publish",     rpc_printer_publish_publish},
6959                 {"update",      rpc_printer_publish_update},
6960                 {"unpublish",   rpc_printer_publish_unpublish},
6961                 {"list",        rpc_printer_publish_list},
6962                 {"help",        rpc_printer_usage},
6963                 {NULL, NULL}
6964         };
6965
6966         if (argc == 0)
6967                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6968                                rpc_printer_publish_list_internals,
6969                                argc, argv);
6970
6971         return net_run_function(argc, argv, func, rpc_printer_usage);
6972
6973 }
6974
6975
6976 /** 
6977  * Display rpc printer help page.
6978  * @param argc  Standard main() style argc
6979  * @param argv  Standard main() style argv.  Initial components are already
6980  *              stripped
6981  **/
6982 int rpc_printer_usage(int argc, const char **argv)
6983 {
6984         return net_help_printer(argc, argv);
6985 }
6986
6987 /** 
6988  * 'net rpc printer' entrypoint.
6989  * @param argc  Standard main() style argc
6990  * @param argv  Standard main() style argv.  Initial components are already
6991  *              stripped
6992  **/
6993 int net_rpc_printer(int argc, const char **argv) 
6994 {
6995         struct functable func[] = {
6996                 {"list", rpc_printer_list},
6997                 {"migrate", rpc_printer_migrate},
6998                 {"driver", rpc_printer_driver_list},
6999                 {"publish", rpc_printer_publish},
7000                 {NULL, NULL}
7001         };
7002
7003         if (argc == 0)
7004                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
7005                                rpc_printer_list_internals,
7006                                argc, argv);
7007
7008         return net_run_function(argc, argv, func, rpc_printer_usage);
7009 }
7010
7011 /****************************************************************************/
7012
7013
7014 /** 
7015  * Basic usage function for 'net rpc'
7016  * @param argc  Standard main() style argc
7017  * @param argv  Standard main() style argv.  Initial components are already
7018  *              stripped
7019  **/
7020
7021 int net_rpc_usage(int argc, const char **argv) 
7022 {
7023         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
7024         d_printf("  net rpc join \t\t\tto join a domain \n");
7025         d_printf("  net rpc oldjoin \t\tto join a domain created in server manager\n");
7026         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
7027         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
7028         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
7029         d_printf("  net rpc group \t\tto list groups\n");
7030         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
7031         d_printf("  net rpc printer \t\tto list and migrate printers\n");
7032         d_printf("  net rpc file \t\t\tto list open files\n");
7033         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
7034         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
7035         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
7036         d_printf("  net rpc samdump \t\tdisplay an NT PDC's users, groups and other data\n");
7037         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
7038         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
7039         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
7040         d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
7041         d_printf("  net rpc registry\t\tto manage registry hives\n");
7042         d_printf("  net rpc service\t\tto start, stop and query services\n");
7043         d_printf("  net rpc audit\t\t\tto modify global auditing settings\n");
7044         d_printf("  net rpc shell\t\t\tto open an interactive shell for remote server/account management\n");
7045         d_printf("\n");
7046         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
7047         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
7048         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
7049         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
7050         d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
7051         return -1;
7052 }
7053
7054
7055 /**
7056  * Help function for 'net rpc'.  Calls command specific help if requested
7057  * or displays usage of net rpc
7058  * @param argc  Standard main() style argc
7059  * @param argv  Standard main() style argv.  Initial components are already
7060  *              stripped
7061  **/
7062
7063 int net_rpc_help(int argc, const char **argv)
7064 {
7065         struct functable func[] = {
7066                 {"join", rpc_join_usage},
7067                 {"user", rpc_user_usage},
7068                 {"group", rpc_group_usage},
7069                 {"share", rpc_share_usage},
7070                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
7071                 {"trustdom", rpc_trustdom_usage},
7072                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
7073                 /*{"shutdown", rpc_shutdown_usage}, */
7074                 {"vampire", rpc_vampire_usage},
7075                 {NULL, NULL}
7076         };
7077
7078         if (argc == 0) {
7079                 net_rpc_usage(argc, argv);
7080                 return -1;
7081         }
7082
7083         return (net_run_function(argc, argv, func, rpc_user_usage));
7084 }
7085
7086 /** 
7087  * 'net rpc' entrypoint.
7088  * @param argc  Standard main() style argc
7089  * @param argv  Standard main() style argv.  Initial components are already
7090  *              stripped
7091  **/
7092
7093 int net_rpc(int argc, const char **argv)
7094 {
7095         struct functable func[] = {
7096                 {"audit", net_rpc_audit},
7097                 {"info", net_rpc_info},
7098                 {"join", net_rpc_join},
7099                 {"oldjoin", net_rpc_oldjoin},
7100                 {"testjoin", net_rpc_testjoin},
7101                 {"user", net_rpc_user},
7102                 {"password", rpc_user_password},
7103                 {"group", net_rpc_group},
7104                 {"share", net_rpc_share},
7105                 {"file", net_rpc_file},
7106                 {"printer", net_rpc_printer},
7107                 {"changetrustpw", net_rpc_changetrustpw},
7108                 {"trustdom", rpc_trustdom},
7109                 {"abortshutdown", rpc_shutdown_abort},
7110                 {"shutdown", rpc_shutdown},
7111                 {"samdump", rpc_samdump},
7112                 {"vampire", rpc_vampire},
7113                 {"getsid", net_rpc_getsid},
7114                 {"rights", net_rpc_rights},
7115                 {"service", net_rpc_service},
7116                 {"registry", net_rpc_registry},
7117                 {"shell", net_rpc_shell},
7118                 {"help", net_rpc_help},
7119                 {NULL, NULL}
7120         };
7121         return net_run_function(argc, argv, func, net_rpc_usage);
7122 }