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