Convert "net" to use rpccli_srvsvc_NetShare* interfaces everywhere.
[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                 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         string_to_sid(&user_sid, response.data.sid.sid);
4505
4506         init_user_token(token, &user_sid);
4507
4508         /* And now the groups winbind knows about */
4509
4510         ZERO_STRUCT(response);
4511
4512         fstrcpy(request.data.username, full_name);
4513
4514         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
4515
4516         if (result != NSS_STATUS_SUCCESS) {
4517                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
4518                 return False;
4519         }
4520
4521         for (i = 0; i < response.data.num_entries; i++) {
4522                 gid_t gid = ((gid_t *)response.extra_data.data)[i];
4523                 DOM_SID sid;
4524
4525                 struct winbindd_request sidrequest;
4526                 struct winbindd_response sidresponse;
4527
4528                 ZERO_STRUCT(sidrequest);
4529                 ZERO_STRUCT(sidresponse);
4530
4531                 sidrequest.data.gid = gid;
4532
4533                 result = winbindd_request_response(WINBINDD_GID_TO_SID,
4534                                           &sidrequest, &sidresponse);
4535
4536                 if (result != NSS_STATUS_SUCCESS) {
4537                         DEBUG(1, ("winbind could not find SID of gid %d\n",
4538                                   gid));
4539                         return False;
4540                 }
4541
4542                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
4543
4544                 string_to_sid(&sid, sidresponse.data.sid.sid);
4545                 add_sid_to_token(token, &sid);
4546         }
4547
4548         SAFE_FREE(response.extra_data.data);
4549
4550         return True;
4551 }
4552         
4553 /**
4554  * Get a list of all user tokens we want to look at
4555  **/
4556
4557 static bool get_user_tokens(int *num_tokens, struct user_token **user_tokens)
4558 {
4559         struct winbindd_request request;
4560         struct winbindd_response response;
4561         const char *extra_data;
4562         char *name;
4563         int i;
4564         struct user_token *result;
4565         TALLOC_CTX *frame = NULL;
4566
4567         if (lp_winbind_use_default_domain() &&
4568             (opt_target_workgroup == NULL)) {
4569                 d_fprintf(stderr, "winbind use default domain = yes set, "
4570                          "please specify a workgroup\n");
4571                 return False;
4572         }
4573
4574         /* Send request to winbind daemon */
4575
4576         ZERO_STRUCT(request);
4577         ZERO_STRUCT(response);
4578
4579         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
4580             NSS_STATUS_SUCCESS)
4581                 return False;
4582
4583         /* Look through extra data */
4584
4585         if (!response.extra_data.data)
4586                 return False;
4587
4588         extra_data = (const char *)response.extra_data.data;
4589         *num_tokens = 0;
4590
4591         frame = talloc_stackframe();
4592         while(next_token_talloc(frame, &extra_data, &name, ",")) {
4593                 *num_tokens += 1;
4594         }
4595
4596         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
4597
4598         if (result == NULL) {
4599                 DEBUG(1, ("Could not malloc sid array\n"));
4600                 TALLOC_FREE(frame);
4601                 return False;
4602         }
4603
4604         extra_data = (const char *)response.extra_data.data;
4605         i=0;
4606
4607         while(next_token_talloc(frame, &extra_data, &name, ",")) {
4608                 fstring domain, user;
4609                 char *p;
4610
4611                 fstrcpy(result[i].name, name);
4612
4613                 p = strchr(name, *lp_winbind_separator());
4614
4615                 DEBUG(3, ("%s\n", name));
4616
4617                 if (p == NULL) {
4618                         fstrcpy(domain, opt_target_workgroup);
4619                         fstrcpy(user, name);
4620                 } else {
4621                         *p++ = '\0';
4622                         fstrcpy(domain, name);
4623                         strupper_m(domain);
4624                         fstrcpy(user, p);
4625                 }
4626
4627                 get_user_sids(domain, user, &(result[i].token));
4628                 i+=1;
4629         }
4630         TALLOC_FREE(frame);
4631         SAFE_FREE(response.extra_data.data);
4632
4633         *user_tokens = result;
4634
4635         return True;
4636 }
4637
4638 static bool get_user_tokens_from_file(FILE *f,
4639                                       int *num_tokens,
4640                                       struct user_token **tokens)
4641 {
4642         struct user_token *token = NULL;
4643
4644         while (!feof(f)) {
4645                 fstring line;
4646
4647                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4648                         return True;
4649                 }
4650
4651                 if (line[strlen(line)-1] == '\n')
4652                         line[strlen(line)-1] = '\0';
4653
4654                 if (line[0] == ' ') {
4655                         /* We have a SID */
4656
4657                         DOM_SID sid;
4658                         string_to_sid(&sid, &line[1]);
4659
4660                         if (token == NULL) {
4661                                 DEBUG(0, ("File does not begin with username"));
4662                                 return False;
4663                         }
4664
4665                         add_sid_to_token(&token->token, &sid);
4666                         continue;
4667                 }
4668
4669                 /* And a new user... */
4670
4671                 *num_tokens += 1;
4672                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4673                 if (*tokens == NULL) {
4674                         DEBUG(0, ("Could not realloc tokens\n"));
4675                         return False;
4676                 }
4677
4678                 token = &((*tokens)[*num_tokens-1]);
4679
4680                 fstrcpy(token->name, line);
4681                 token->token.num_sids = 0;
4682                 token->token.user_sids = NULL;
4683                 continue;
4684         }
4685         
4686         return False;
4687 }
4688
4689
4690 /*
4691  * Show the list of all users that have access to a share
4692  */
4693
4694 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4695                         TALLOC_CTX *mem_ctx,
4696                         const char *netname,
4697                         int num_tokens,
4698                         struct user_token *tokens)
4699 {
4700         int fnum;
4701         SEC_DESC *share_sd = NULL;
4702         SEC_DESC *root_sd = NULL;
4703         struct cli_state *cli = pipe_hnd->cli;
4704         int i;
4705         union srvsvc_NetShareInfo info;
4706         WERROR result;
4707         NTSTATUS status;
4708         uint16 cnum;
4709
4710         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4711                                                pipe_hnd->cli->desthost,
4712                                                netname,
4713                                                502,
4714                                                &info,
4715                                                &result);
4716
4717         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4718                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4719                           netname));
4720                 return;
4721         }
4722
4723         share_sd = info.info502->sd;
4724         if (share_sd == NULL) {
4725                 DEBUG(1, ("Got no secdesc for share %s\n",
4726                           netname));
4727         }
4728
4729         cnum = cli->cnum;
4730
4731         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4732                 return;
4733         }
4734
4735         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4736
4737         if (fnum != -1) {
4738                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4739         }
4740
4741         for (i=0; i<num_tokens; i++) {
4742                 uint32 acc_granted;
4743
4744                 if (share_sd != NULL) {
4745                         if (!se_access_check(share_sd, &tokens[i].token,
4746                                              1, &acc_granted, &status)) {
4747                                 DEBUG(1, ("Could not check share_sd for "
4748                                           "user %s\n",
4749                                           tokens[i].name));
4750                                 continue;
4751                         }
4752
4753                         if (!NT_STATUS_IS_OK(status))
4754                                 continue;
4755                 }
4756
4757                 if (root_sd == NULL) {
4758                         d_printf(" %s\n", tokens[i].name);
4759                         continue;
4760                 }
4761
4762                 if (!se_access_check(root_sd, &tokens[i].token,
4763                                      1, &acc_granted, &status)) {
4764                         DEBUG(1, ("Could not check root_sd for user %s\n",
4765                                   tokens[i].name));
4766                         continue;
4767                 }
4768
4769                 if (!NT_STATUS_IS_OK(status))
4770                         continue;
4771
4772                 d_printf(" %s\n", tokens[i].name);
4773         }
4774
4775         if (fnum != -1)
4776                 cli_close(cli, fnum);
4777         cli_tdis(cli);
4778         cli->cnum = cnum;
4779         
4780         return;
4781 }
4782
4783 struct share_list {
4784         int num_shares;
4785         char **shares;
4786 };
4787
4788 static void collect_share(const char *name, uint32 m,
4789                           const char *comment, void *state)
4790 {
4791         struct share_list *share_list = (struct share_list *)state;
4792
4793         if (m != STYPE_DISKTREE)
4794                 return;
4795
4796         share_list->num_shares += 1;
4797         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4798         if (!share_list->shares) {
4799                 share_list->num_shares = 0;
4800                 return;
4801         }
4802         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4803 }
4804
4805 static void rpc_share_userlist_usage(void)
4806 {
4807         return;
4808 }
4809         
4810 /** 
4811  * List shares on a remote RPC server, including the security descriptors
4812  *
4813  * All parameters are provided by the run_rpc_command function, except for
4814  * argc, argv which are passes through. 
4815  *
4816  * @param domain_sid The domain sid acquired from the remote server
4817  * @param cli A cli_state connected to the server.
4818  * @param mem_ctx Talloc context, destoyed on completion of the function.
4819  * @param argc  Standard main() style argc
4820  * @param argv  Standard main() style argv.  Initial components are already
4821  *              stripped
4822  *
4823  * @return Normal NTSTATUS return.
4824  **/
4825
4826 static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
4827                                                 const char *domain_name,
4828                                                 struct cli_state *cli,
4829                                                 struct rpc_pipe_client *pipe_hnd,
4830                                                 TALLOC_CTX *mem_ctx,
4831                                                 int argc,
4832                                                 const char **argv)
4833 {
4834         int ret;
4835         bool r;
4836         ENUM_HND hnd;
4837         uint32 i;
4838         FILE *f;
4839
4840         struct user_token *tokens = NULL;
4841         int num_tokens = 0;
4842
4843         struct share_list share_list;
4844
4845         if (argc > 1) {
4846                 rpc_share_userlist_usage();
4847                 return NT_STATUS_UNSUCCESSFUL;
4848         }
4849
4850         if (argc == 0) {
4851                 f = stdin;
4852         } else {
4853                 f = fopen(argv[0], "r");
4854         }
4855
4856         if (f == NULL) {
4857                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4858                 return NT_STATUS_UNSUCCESSFUL;
4859         }
4860
4861         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4862
4863         if (f != stdin)
4864                 fclose(f);
4865
4866         if (!r) {
4867                 DEBUG(0, ("Could not read users from file\n"));
4868                 return NT_STATUS_UNSUCCESSFUL;
4869         }
4870
4871         for (i=0; i<num_tokens; i++)
4872                 collect_alias_memberships(&tokens[i].token);
4873
4874         init_enum_hnd(&hnd, 0);
4875
4876         share_list.num_shares = 0;
4877         share_list.shares = NULL;
4878
4879         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4880
4881         if (ret == -1) {
4882                 DEBUG(0, ("Error returning browse list: %s\n",
4883                           cli_errstr(cli)));
4884                 goto done;
4885         }
4886
4887         for (i = 0; i < share_list.num_shares; i++) {
4888                 char *netname = share_list.shares[i];
4889
4890                 if (netname[strlen(netname)-1] == '$')
4891                         continue;
4892
4893                 d_printf("%s\n", netname);
4894
4895                 show_userlist(pipe_hnd, mem_ctx, netname,
4896                               num_tokens, tokens);
4897         }
4898  done:
4899         for (i=0; i<num_tokens; i++) {
4900                 free_user_token(&tokens[i].token);
4901         }
4902         SAFE_FREE(tokens);
4903         SAFE_FREE(share_list.shares);
4904
4905         return NT_STATUS_OK;
4906 }
4907
4908 static int rpc_share_allowedusers(int argc, const char **argv)
4909 {
4910         int result;
4911
4912         result = run_rpc_command(NULL, PI_SAMR, 0,
4913                                  rpc_aliaslist_internals,
4914                                  argc, argv);
4915         if (result != 0)
4916                 return result;
4917
4918         result = run_rpc_command(NULL, PI_LSARPC, 0,
4919                                  rpc_aliaslist_dump,
4920                                  argc, argv);
4921         if (result != 0)
4922                 return result;
4923
4924         return run_rpc_command(NULL, PI_SRVSVC, 0,
4925                                rpc_share_allowedusers_internals,
4926                                argc, argv);
4927 }
4928
4929 int net_usersidlist(int argc, const char **argv)
4930 {
4931         int num_tokens = 0;
4932         struct user_token *tokens = NULL;
4933         int i;
4934
4935         if (argc != 0) {
4936                 net_usersidlist_usage(argc, argv);
4937                 return 0;
4938         }
4939
4940         if (!get_user_tokens(&num_tokens, &tokens)) {
4941                 DEBUG(0, ("Could not get the user/sid list\n"));
4942                 return 0;
4943         }
4944
4945         for (i=0; i<num_tokens; i++) {
4946                 dump_user_token(&tokens[i]);
4947                 free_user_token(&tokens[i].token);
4948         }
4949
4950         SAFE_FREE(tokens);
4951         return 1;
4952 }
4953
4954 int net_usersidlist_usage(int argc, const char **argv)
4955 {
4956         d_printf("net usersidlist\n"
4957                  "\tprints out a list of all users the running winbind knows\n"
4958                  "\tabout, together with all their SIDs. This is used as\n"
4959                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
4960
4961         net_common_flags_usage(argc, argv);
4962         return -1;
4963 }
4964
4965 /** 
4966  * 'net rpc share' entrypoint.
4967  * @param argc  Standard main() style argc
4968  * @param argv  Standard main() style argv.  Initial components are already
4969  *              stripped
4970  **/
4971
4972 int net_rpc_share(int argc, const char **argv) 
4973 {
4974         struct functable func[] = {
4975                 {"add", rpc_share_add},
4976                 {"delete", rpc_share_delete},
4977                 {"allowedusers", rpc_share_allowedusers},
4978                 {"migrate", rpc_share_migrate},
4979                 {"list", rpc_share_list},
4980                 {NULL, NULL}
4981         };
4982
4983         if (argc == 0)
4984                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
4985                                        rpc_share_list_internals,
4986                                        argc, argv);
4987
4988         return net_run_function(argc, argv, func, rpc_share_usage);
4989 }
4990
4991 static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
4992                                   struct rpc_sh_ctx *ctx,
4993                                   struct rpc_pipe_client *pipe_hnd,
4994                                   int argc, const char **argv)
4995 {
4996         return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
4997                                         ctx->cli, pipe_hnd, mem_ctx,
4998                                         argc, argv);
4999 }
5000
5001 static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
5002                                  struct rpc_sh_ctx *ctx,
5003                                  struct rpc_pipe_client *pipe_hnd,
5004                                  int argc, const char **argv)
5005 {
5006         WERROR result;
5007         NTSTATUS status;
5008         uint32_t parm_err = 0;
5009         union srvsvc_NetShareInfo info;
5010         struct srvsvc_NetShareInfo2 info2;
5011
5012         if ((argc < 2) || (argc > 3)) {
5013                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
5014                           ctx->whoami);
5015                 return NT_STATUS_INVALID_PARAMETER;
5016         }
5017
5018         info2.name              = argv[0];
5019         info2.type              = STYPE_DISKTREE;
5020         info2.comment           = (argc == 3) ? argv[2] : "";
5021         info2.permissions       = 0;
5022         info2.max_users         = 0;
5023         info2.current_users     = 0;
5024         info2.path              = argv[1];
5025         info2.password          = NULL;
5026
5027         info.info2 = &info2;
5028
5029         status = rpccli_srvsvc_NetShareAdd(pipe_hnd, mem_ctx,
5030                                            pipe_hnd->cli->desthost,
5031                                            2,
5032                                            &info,
5033                                            &parm_err,
5034                                            &result);
5035
5036         return status;
5037 }
5038
5039 static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
5040                                     struct rpc_sh_ctx *ctx,
5041                                     struct rpc_pipe_client *pipe_hnd,
5042                                     int argc, const char **argv)
5043 {
5044         WERROR result;
5045         NTSTATUS status;
5046
5047         if (argc != 1) {
5048                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5049                 return NT_STATUS_INVALID_PARAMETER;
5050         }
5051
5052         status = rpccli_srvsvc_NetShareDel(pipe_hnd, mem_ctx,
5053                                            pipe_hnd->cli->desthost,
5054                                            argv[0],
5055                                            0,
5056                                            &result);
5057
5058         return status;
5059 }
5060
5061 static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
5062                                   struct rpc_sh_ctx *ctx,
5063                                   struct rpc_pipe_client *pipe_hnd,
5064                                   int argc, const char **argv)
5065 {
5066         union srvsvc_NetShareInfo info;
5067         WERROR result;
5068         NTSTATUS status;
5069
5070         if (argc != 1) {
5071                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5072                 return NT_STATUS_INVALID_PARAMETER;
5073         }
5074
5075         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
5076                                                pipe_hnd->cli->desthost,
5077                                                argv[0],
5078                                                2,
5079                                                &info,
5080                                                &result);
5081         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
5082                 goto done;
5083         }
5084
5085         d_printf("Name:     %s\n", info.info2->name);
5086         d_printf("Comment:  %s\n", info.info2->comment);
5087         d_printf("Path:     %s\n", info.info2->path);
5088         d_printf("Password: %s\n", info.info2->password);
5089
5090  done:
5091         return werror_to_ntstatus(result);
5092 }
5093
5094 struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
5095                                       struct rpc_sh_ctx *ctx)
5096 {
5097         static struct rpc_sh_cmd cmds[] = {
5098
5099         { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
5100           "List available shares" },
5101
5102         { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
5103           "Add a share" },
5104
5105         { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
5106           "Delete a share" },
5107
5108         { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
5109           "Get information about a share" },
5110
5111         { NULL, NULL, 0, NULL, NULL }
5112         };
5113
5114         return cmds;
5115 }
5116
5117 /****************************************************************************/
5118
5119 static int rpc_file_usage(int argc, const char **argv)
5120 {
5121         return net_help_file(argc, argv);
5122 }
5123
5124 /** 
5125  * Close a file on a remote RPC server
5126  *
5127  * All parameters are provided by the run_rpc_command function, except for
5128  * argc, argv which are passes through. 
5129  *
5130  * @param domain_sid The domain sid acquired from the remote server
5131  * @param cli A cli_state connected to the server.
5132  * @param mem_ctx Talloc context, destoyed on completion of the function.
5133  * @param argc  Standard main() style argc
5134  * @param argv  Standard main() style argv.  Initial components are already
5135  *              stripped
5136  *
5137  * @return Normal NTSTATUS return.
5138  **/
5139 static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
5140                                         const char *domain_name, 
5141                                         struct cli_state *cli,
5142                                         struct rpc_pipe_client *pipe_hnd,
5143                                         TALLOC_CTX *mem_ctx,
5144                                         int argc,
5145                                         const char **argv)
5146 {
5147         return rpccli_srvsvc_NetFileClose(pipe_hnd, mem_ctx, 
5148                                             pipe_hnd->cli->desthost, 
5149                                             atoi(argv[0]), NULL);
5150 }
5151
5152 /** 
5153  * Close a file on a remote RPC server
5154  *
5155  * @param argc  Standard main() style argc
5156  * @param argv  Standard main() style argv.  Initial components are already
5157  *              stripped
5158  *
5159  * @return A shell status integer (0 for success)
5160  **/
5161 static int rpc_file_close(int argc, const char **argv)
5162 {
5163         if (argc < 1) {
5164                 DEBUG(1, ("No fileid given on close\n"));
5165                 return(rpc_file_usage(argc, argv));
5166         }
5167
5168         return run_rpc_command(NULL, PI_SRVSVC, 0, 
5169                                rpc_file_close_internals,
5170                                argc, argv);
5171 }
5172
5173 /** 
5174  * Formatted print of open file info 
5175  *
5176  * @param info3  FILE_INFO_3 contents
5177  * @param str3   strings for FILE_INFO_3
5178  **/
5179
5180 static void display_file_info_3( FILE_INFO_3 *info3 )
5181 {
5182         fstring user = "", path = "";
5183
5184         rpcstr_pull_unistr2_fstring(user, info3->user);
5185         rpcstr_pull_unistr2_fstring(path, info3->path);
5186
5187         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5188                  info3->id, user, info3->perms, info3->num_locks, path);
5189 }
5190
5191 /** 
5192  * List open files on a remote RPC server
5193  *
5194  * All parameters are provided by the run_rpc_command function, except for
5195  * argc, argv which are passes through. 
5196  *
5197  * @param domain_sid The domain sid acquired from the remote server
5198  * @param cli A cli_state connected to the server.
5199  * @param mem_ctx Talloc context, destoyed on completion of the function.
5200  * @param argc  Standard main() style argc
5201  * @param argv  Standard main() style argv.  Initial components are already
5202  *              stripped
5203  *
5204  * @return Normal NTSTATUS return.
5205  **/
5206
5207 static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
5208                                         const char *domain_name, 
5209                                         struct cli_state *cli,
5210                                         struct rpc_pipe_client *pipe_hnd,
5211                                         TALLOC_CTX *mem_ctx,
5212                                         int argc,
5213                                         const char **argv)
5214 {
5215         SRV_FILE_INFO_CTR ctr;
5216         WERROR result;
5217         ENUM_HND hnd;
5218         uint32 preferred_len = 0xffffffff, i;
5219         const char *username=NULL;
5220
5221         init_enum_hnd(&hnd, 0);
5222
5223         /* if argc > 0, must be user command */
5224         if (argc > 0)
5225                 username = smb_xstrdup(argv[0]);
5226                 
5227         result = rpccli_srvsvc_net_file_enum(pipe_hnd,
5228                                         mem_ctx, 3, username, &ctr, preferred_len, &hnd);
5229
5230         if (!W_ERROR_IS_OK(result))
5231                 goto done;
5232
5233         /* Display results */
5234
5235         d_printf(
5236                  "\nEnumerating open files on remote server:\n\n"\
5237                  "\nFileId  Opened by            Perms  Locks  Path"\
5238                  "\n------  ---------            -----  -----  ---- \n");
5239         for (i = 0; i < ctr.num_entries; i++)
5240                 display_file_info_3(&ctr.file.info3[i]);
5241  done:
5242         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
5243 }
5244
5245 /** 
5246  * List files for a user on a remote RPC server
5247  *
5248  * @param argc  Standard main() style argc
5249  * @param argv  Standard main() style argv.  Initial components are already
5250  *              stripped
5251  *
5252  * @return A shell status integer (0 for success)
5253  **/
5254
5255 static int rpc_file_user(int argc, const char **argv)
5256 {
5257         if (argc < 1) {
5258                 DEBUG(1, ("No username given\n"));
5259                 return(rpc_file_usage(argc, argv));
5260         }
5261
5262         return run_rpc_command(NULL, PI_SRVSVC, 0, 
5263                                rpc_file_list_internals,
5264                                argc, argv);
5265 }
5266
5267 /** 
5268  * 'net rpc file' entrypoint.
5269  * @param argc  Standard main() style argc
5270  * @param argv  Standard main() style argv.  Initial components are already
5271  *              stripped
5272  **/
5273
5274 int net_rpc_file(int argc, const char **argv) 
5275 {
5276         struct functable func[] = {
5277                 {"close", rpc_file_close},
5278                 {"user", rpc_file_user},
5279 #if 0
5280                 {"info", rpc_file_info},
5281 #endif
5282                 {NULL, NULL}
5283         };
5284
5285         if (argc == 0)
5286                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
5287                                        rpc_file_list_internals,
5288                                        argc, argv);
5289
5290         return net_run_function(argc, argv, func, rpc_file_usage);
5291 }
5292
5293 /** 
5294  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
5295  *
5296  * All parameters are provided by the run_rpc_command function, except for
5297  * argc, argv which are passed through. 
5298  *
5299  * @param domain_sid The domain sid aquired from the remote server
5300  * @param cli A cli_state connected to the server.
5301  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5302  * @param argc  Standard main() style argc
5303  * @param argv  Standard main() style argv.  Initial components are already
5304  *              stripped
5305  *
5306  * @return Normal NTSTATUS return.
5307  **/
5308
5309 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
5310                                         const char *domain_name, 
5311                                         struct cli_state *cli, 
5312                                         struct rpc_pipe_client *pipe_hnd,
5313                                         TALLOC_CTX *mem_ctx, 
5314                                         int argc,
5315                                         const char **argv) 
5316 {
5317         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5318         
5319         result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5320         
5321         if (NT_STATUS_IS_OK(result)) {
5322                 d_printf("\nShutdown successfully aborted\n");
5323                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5324         } else
5325                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5326         
5327         return result;
5328 }
5329
5330 /** 
5331  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
5332  *
5333  * All parameters are provided by the run_rpc_command function, except for
5334  * argc, argv which are passed through. 
5335  *
5336  * @param domain_sid The domain sid aquired from the remote server
5337  * @param cli A cli_state connected to the server.
5338  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5339  * @param argc  Standard main() style argc
5340  * @param argv  Standard main() style argv.  Initial components are already
5341  *              stripped
5342  *
5343  * @return Normal NTSTATUS return.
5344  **/
5345
5346 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
5347                                                 const char *domain_name, 
5348                                                 struct cli_state *cli, 
5349                                                 struct rpc_pipe_client *pipe_hnd,
5350                                                 TALLOC_CTX *mem_ctx, 
5351                                                 int argc,
5352                                                 const char **argv) 
5353 {
5354         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5355         
5356         result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5357         
5358         if (NT_STATUS_IS_OK(result)) {
5359                 d_printf("\nShutdown successfully aborted\n");
5360                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5361         } else
5362                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5363         
5364         return result;
5365 }
5366
5367 /** 
5368  * ABORT the Shut down of a remote RPC server
5369  *
5370  * @param argc  Standard main() style argc
5371  * @param argv  Standard main() style argv.  Initial components are already
5372  *              stripped
5373  *
5374  * @return A shell status integer (0 for success)
5375  **/
5376
5377 static int rpc_shutdown_abort(int argc, const char **argv) 
5378 {
5379         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5380                                  rpc_shutdown_abort_internals,
5381                                  argc, argv);
5382
5383         if (rc == 0)
5384                 return rc;
5385
5386         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5387
5388         return run_rpc_command(NULL, PI_WINREG, 0, 
5389                                rpc_reg_shutdown_abort_internals,
5390                                argc, argv);
5391 }
5392
5393 /** 
5394  * Shut down a remote RPC Server via initshutdown pipe
5395  *
5396  * All parameters are provided by the run_rpc_command function, except for
5397  * argc, argv which are passes through. 
5398  *
5399  * @param domain_sid The domain sid aquired from the remote server
5400  * @param cli A cli_state connected to the server.
5401  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5402  * @param argc  Standard main() style argc
5403  * @param argc  Standard main() style argv.  Initial components are already
5404  *              stripped
5405  *
5406  * @return Normal NTSTATUS return.
5407  **/
5408
5409 NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
5410                                                 const char *domain_name, 
5411                                                 struct cli_state *cli, 
5412                                                 struct rpc_pipe_client *pipe_hnd,
5413                                                 TALLOC_CTX *mem_ctx, 
5414                                                 int argc,
5415                                                 const char **argv) 
5416 {
5417         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5418         const char *msg = "This machine will be shutdown shortly";
5419         uint32 timeout = 20;
5420         struct initshutdown_String msg_string;
5421         struct initshutdown_String_sub s;
5422
5423         if (opt_comment) {
5424                 msg = opt_comment;
5425         }
5426         if (opt_timeout) {
5427                 timeout = opt_timeout;
5428         }
5429
5430         s.name = msg;
5431         msg_string.name = &s;
5432
5433         /* create an entry */
5434         result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5435                         &msg_string, timeout, opt_force, opt_reboot, NULL);
5436
5437         if (NT_STATUS_IS_OK(result)) {
5438                 d_printf("\nShutdown of remote machine succeeded\n");
5439                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5440         } else {
5441                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5442         }
5443         return result;
5444 }
5445
5446 /** 
5447  * Shut down a remote RPC Server via winreg pipe
5448  *
5449  * All parameters are provided by the run_rpc_command function, except for
5450  * argc, argv which are passes through. 
5451  *
5452  * @param domain_sid The domain sid aquired from the remote server
5453  * @param cli A cli_state connected to the server.
5454  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5455  * @param argc  Standard main() style argc
5456  * @param argc  Standard main() style argv.  Initial components are already
5457  *              stripped
5458  *
5459  * @return Normal NTSTATUS return.
5460  **/
5461
5462 NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid,
5463                                                 const char *domain_name, 
5464                                                 struct cli_state *cli, 
5465                                                 struct rpc_pipe_client *pipe_hnd,
5466                                                 TALLOC_CTX *mem_ctx, 
5467                                                 int argc,
5468                                                 const char **argv) 
5469 {
5470         const char *msg = "This machine will be shutdown shortly";
5471         uint32 timeout = 20;
5472         struct initshutdown_String msg_string;
5473         struct initshutdown_String_sub s;
5474         NTSTATUS result;
5475         WERROR werr;
5476
5477         if (opt_comment) {
5478                 msg = opt_comment;
5479         }
5480         s.name = msg;
5481         msg_string.name = &s;
5482
5483         if (opt_timeout) {
5484                 timeout = opt_timeout;
5485         }
5486
5487         /* create an entry */
5488         result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5489                         &msg_string, timeout, opt_force, opt_reboot, &werr);
5490
5491         if (NT_STATUS_IS_OK(result)) {
5492                 d_printf("\nShutdown of remote machine succeeded\n");
5493         } else {
5494                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5495                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5496                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5497                 else
5498                         d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(werr));
5499         }
5500
5501         return result;
5502 }
5503
5504 /** 
5505  * Shut down a remote RPC server
5506  *
5507  * @param argc  Standard main() style argc
5508  * @param argc  Standard main() style argv.  Initial components are already
5509  *              stripped
5510  *
5511  * @return A shell status integer (0 for success)
5512  **/
5513
5514 static int rpc_shutdown(int argc, const char **argv) 
5515 {
5516         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5517                                  rpc_init_shutdown_internals,
5518                                  argc, argv);
5519
5520         if (rc) {
5521                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5522                 rc = run_rpc_command(NULL, PI_WINREG, 0, 
5523                                      rpc_reg_shutdown_internals, argc, argv);
5524         }
5525
5526         return rc;
5527 }
5528
5529 /***************************************************************************
5530   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5531   
5532  ***************************************************************************/
5533
5534 /**
5535  * Add interdomain trust account to the RPC server.
5536  * All parameters (except for argc and argv) are passed by run_rpc_command
5537  * function.
5538  *
5539  * @param domain_sid The domain sid acquired from the server
5540  * @param cli A cli_state connected to the server.
5541  * @param mem_ctx Talloc context, destoyed on completion of the function.
5542  * @param argc  Standard main() style argc
5543  * @param argc  Standard main() style argv.  Initial components are already
5544  *              stripped
5545  *
5546  * @return normal NTSTATUS return code
5547  */
5548
5549 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
5550                                                 const char *domain_name, 
5551                                                 struct cli_state *cli,
5552                                                 struct rpc_pipe_client *pipe_hnd,
5553                                                 TALLOC_CTX *mem_ctx, 
5554                                                 int argc,
5555                                                 const char **argv)
5556 {
5557         POLICY_HND connect_pol, domain_pol, user_pol;
5558         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5559         char *acct_name;
5560         struct lsa_String lsa_acct_name;
5561         uint32 acb_info;
5562         uint32 acct_flags=0;
5563         uint32 user_rid;
5564         uint32_t access_granted = 0;
5565         union samr_UserInfo info;
5566
5567         if (argc != 2) {
5568                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
5569                 return NT_STATUS_INVALID_PARAMETER;
5570         }
5571
5572         /* 
5573          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5574          */
5575
5576         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5577                 return NT_STATUS_NO_MEMORY;
5578         }
5579
5580         strupper_m(acct_name);
5581
5582         init_lsa_String(&lsa_acct_name, acct_name);
5583
5584         /* Get samr policy handle */
5585         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5586                                       pipe_hnd->cli->desthost,
5587                                       MAXIMUM_ALLOWED_ACCESS,
5588                                       &connect_pol);
5589         if (!NT_STATUS_IS_OK(result)) {
5590                 goto done;
5591         }
5592
5593         /* Get domain policy handle */
5594         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5595                                         &connect_pol,
5596                                         MAXIMUM_ALLOWED_ACCESS,
5597                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5598                                         &domain_pol);
5599         if (!NT_STATUS_IS_OK(result)) {
5600                 goto done;
5601         }
5602
5603         /* Create trusting domain's account */
5604         acb_info = ACB_NORMAL;
5605         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5606                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5607                      SAMR_USER_ACCESS_SET_PASSWORD |
5608                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5609                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5610
5611         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5612                                          &domain_pol,
5613                                          &lsa_acct_name,
5614                                          acb_info,
5615                                          acct_flags,
5616                                          &user_pol,
5617                                          &access_granted,
5618                                          &user_rid);
5619         if (!NT_STATUS_IS_OK(result)) {
5620                 goto done;
5621         }
5622
5623         {
5624                 NTTIME notime;
5625                 struct samr_LogonHours hours;
5626                 const int units_per_week = 168;
5627                 uchar pwbuf[516];
5628
5629                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
5630
5631                 ZERO_STRUCT(notime);
5632
5633                 ZERO_STRUCT(hours);
5634                 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
5635                 if (!hours.bits) {
5636                         result = NT_STATUS_NO_MEMORY;
5637                         goto done;
5638                 }
5639                 hours.units_per_week = units_per_week;
5640                 memset(hours.bits, 0xFF, units_per_week);
5641
5642                 init_samr_user_info23(&info.info23,
5643                                       notime, notime, notime,
5644                                       notime, notime, notime,
5645                                       NULL, NULL, NULL, NULL, NULL,
5646                                       NULL, NULL, NULL, NULL, NULL,
5647                                       0, 0, ACB_DOMTRUST, SAMR_FIELD_ACCT_FLAGS,
5648                                       hours,
5649                                       0, 0, 0, 0, 0, 0, 0,
5650                                       pwbuf, 24);
5651
5652                 SamOEMhashBlob(info.info23.password.data, 516,
5653                                &cli->user_session_key);
5654
5655                 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5656                                                   &user_pol,
5657                                                   23,
5658                                                   &info);
5659
5660                 if (!NT_STATUS_IS_OK(result)) {
5661                         DEBUG(0,("Could not set trust account password: %s\n",
5662                                  nt_errstr(result)));
5663                         goto done;
5664                 }
5665         }
5666
5667  done:
5668         SAFE_FREE(acct_name);
5669         return result;
5670 }
5671
5672 /**
5673  * Create interdomain trust account for a remote domain.
5674  *
5675  * @param argc standard argc
5676  * @param argv standard argv without initial components
5677  *
5678  * @return Integer status (0 means success)
5679  **/
5680
5681 static int rpc_trustdom_add(int argc, const char **argv)
5682 {
5683         if (argc > 0) {
5684                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
5685                                        argc, argv);
5686         } else {
5687                 d_printf("Usage: net rpc trustdom add <domain>\n");
5688                 return -1;
5689         }
5690 }
5691
5692
5693 /**
5694  * Remove interdomain trust account from the RPC server.
5695  * All parameters (except for argc and argv) are passed by run_rpc_command
5696  * function.
5697  *
5698  * @param domain_sid The domain sid acquired from the server
5699  * @param cli A cli_state connected to the server.
5700  * @param mem_ctx Talloc context, destoyed on completion of the function.
5701  * @param argc  Standard main() style argc
5702  * @param argc  Standard main() style argv.  Initial components are already
5703  *              stripped
5704  *
5705  * @return normal NTSTATUS return code
5706  */
5707
5708 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
5709                                         const char *domain_name, 
5710                                         struct cli_state *cli,
5711                                         struct rpc_pipe_client *pipe_hnd,
5712                                         TALLOC_CTX *mem_ctx, 
5713                                         int argc,
5714                                         const char **argv)
5715 {
5716         POLICY_HND connect_pol, domain_pol, user_pol;
5717         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5718         char *acct_name;
5719         DOM_SID trust_acct_sid;
5720         struct samr_Ids user_rids, name_types;
5721         struct lsa_String lsa_acct_name;
5722
5723         if (argc != 1) {
5724                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5725                 return NT_STATUS_INVALID_PARAMETER;
5726         }
5727
5728         /* 
5729          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5730          */
5731         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5732
5733         if (acct_name == NULL)
5734                 return NT_STATUS_NO_MEMORY;
5735
5736         strupper_m(acct_name);
5737
5738         /* Get samr policy handle */
5739         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5740                                       pipe_hnd->cli->desthost,
5741                                       MAXIMUM_ALLOWED_ACCESS,
5742                                       &connect_pol);
5743         if (!NT_STATUS_IS_OK(result)) {
5744                 goto done;
5745         }
5746
5747         /* Get domain policy handle */
5748         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5749                                         &connect_pol,
5750                                         MAXIMUM_ALLOWED_ACCESS,
5751                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5752                                         &domain_pol);
5753         if (!NT_STATUS_IS_OK(result)) {
5754                 goto done;
5755         }
5756
5757         init_lsa_String(&lsa_acct_name, acct_name);
5758
5759         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5760                                          &domain_pol,
5761                                          1,
5762                                          &lsa_acct_name,
5763                                          &user_rids,
5764                                          &name_types);
5765
5766         if (!NT_STATUS_IS_OK(result)) {
5767                 goto done;
5768         }
5769
5770         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5771                                       &domain_pol,
5772                                       MAXIMUM_ALLOWED_ACCESS,
5773                                       user_rids.ids[0],
5774                                       &user_pol);
5775
5776         if (!NT_STATUS_IS_OK(result)) {
5777                 goto done;
5778         }
5779
5780         /* append the rid to the domain sid */
5781         sid_copy(&trust_acct_sid, domain_sid);
5782         if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5783                 goto done;
5784         }
5785
5786         /* remove the sid */
5787
5788         result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5789                                                            &user_pol,
5790                                                            &trust_acct_sid);
5791         if (!NT_STATUS_IS_OK(result)) {
5792                 goto done;
5793         }
5794
5795         /* Delete user */
5796
5797         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5798                                         &user_pol);
5799
5800         if (!NT_STATUS_IS_OK(result)) {
5801                 goto done;
5802         }
5803
5804         if (!NT_STATUS_IS_OK(result)) {
5805           DEBUG(0,("Could not set trust account password: %s\n",
5806                    nt_errstr(result)));
5807           goto done;
5808         }
5809
5810  done:
5811         return result;
5812 }
5813
5814 /**
5815  * Delete interdomain trust account for a remote domain.
5816  *
5817  * @param argc standard argc
5818  * @param argv standard argv without initial components
5819  *
5820  * @return Integer status (0 means success)
5821  **/
5822
5823 static int rpc_trustdom_del(int argc, const char **argv)
5824 {
5825         if (argc > 0) {
5826                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
5827                                        argc, argv);
5828         } else {
5829                 d_printf("Usage: net rpc trustdom del <domain>\n");
5830                 return -1;
5831         }
5832 }
5833  
5834
5835 /**
5836  * Establish trust relationship to a trusting domain.
5837  * Interdomain account must already be created on remote PDC.
5838  *
5839  * @param argc standard argc
5840  * @param argv standard argv without initial components
5841  *
5842  * @return Integer status (0 means success)
5843  **/
5844
5845 static int rpc_trustdom_establish(int argc, const char **argv)
5846 {
5847         struct cli_state *cli = NULL;
5848         struct sockaddr_storage server_ss;
5849         struct rpc_pipe_client *pipe_hnd = NULL;
5850         POLICY_HND connect_hnd;
5851         TALLOC_CTX *mem_ctx;
5852         NTSTATUS nt_status;
5853         DOM_SID *domain_sid;
5854
5855         char* domain_name;
5856         char* acct_name;
5857         fstring pdc_name;
5858         char *dc_name;
5859         union lsa_PolicyInformation *info = NULL;
5860
5861         /*
5862          * Connect to \\server\ipc$ as 'our domain' account with password
5863          */
5864
5865         if (argc != 1) {
5866                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
5867                 return -1;
5868         }
5869
5870         domain_name = smb_xstrdup(argv[0]);
5871         strupper_m(domain_name);
5872
5873         /* account name used at first is our domain's name with '$' */
5874         asprintf(&acct_name, "%s$", lp_workgroup());
5875         strupper_m(acct_name);
5876
5877         /*
5878          * opt_workgroup will be used by connection functions further,
5879          * hence it should be set to remote domain name instead of ours
5880          */
5881         if (opt_workgroup) {
5882                 opt_workgroup = smb_xstrdup(domain_name);
5883         };
5884
5885         opt_user_name = acct_name;
5886
5887         /* find the domain controller */
5888         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5889                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5890                 return -1;
5891         }
5892
5893         /* connect to ipc$ as username/password */
5894         nt_status = connect_to_ipc(&cli, &server_ss, pdc_name);
5895         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5896
5897                 /* Is it trusting domain account for sure ? */
5898                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5899                         nt_errstr(nt_status)));
5900                 return -1;
5901         }
5902
5903         /* store who we connected to */
5904
5905         saf_store( domain_name, pdc_name );
5906
5907         /*
5908          * Connect to \\server\ipc$ again (this time anonymously)
5909          */
5910
5911         nt_status = connect_to_ipc_anonymous(&cli, &server_ss, (char*)pdc_name);
5912
5913         if (NT_STATUS_IS_ERR(nt_status)) {
5914                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5915                         domain_name, nt_errstr(nt_status)));
5916                 return -1;
5917         }
5918
5919         /*
5920          * Use NetServerEnum2 to make sure we're talking to a proper server
5921          */
5922
5923         if (!cli_get_pdc_name(cli, domain_name, &dc_name)) {
5924                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
5925                          for domain %s\n", domain_name));
5926                 cli_shutdown(cli);
5927                 return -1;
5928         }
5929         SAFE_FREE(dc_name);
5930          
5931         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5932                                     "domain %s", domain_name))) {
5933                 DEBUG(0, ("talloc_init() failed\n"));
5934                 cli_shutdown(cli);
5935                 return -1;
5936         }
5937
5938         /*
5939          * Call LsaOpenPolicy and LsaQueryInfo
5940          */
5941          
5942         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5943         if (!pipe_hnd) {
5944                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5945                 cli_shutdown(cli);
5946                 talloc_destroy(mem_ctx);
5947                 return -1;
5948         }
5949
5950         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
5951                                          &connect_hnd);
5952         if (NT_STATUS_IS_ERR(nt_status)) {
5953                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5954                         nt_errstr(nt_status)));
5955                 cli_shutdown(cli);
5956                 talloc_destroy(mem_ctx);
5957                 return -1;
5958         }
5959
5960         /* Querying info level 5 */
5961
5962         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5963                                                &connect_hnd,
5964                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5965                                                &info);
5966         if (NT_STATUS_IS_ERR(nt_status)) {
5967                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5968                         nt_errstr(nt_status)));
5969                 cli_shutdown(cli);
5970                 talloc_destroy(mem_ctx);
5971                 return -1;
5972         }
5973
5974         domain_sid = info->account_domain.sid;
5975
5976         /* There should be actually query info level 3 (following nt serv behaviour),
5977            but I still don't know if it's _really_ necessary */
5978                         
5979         /*
5980          * Store the password in secrets db
5981          */
5982
5983         if (!pdb_set_trusteddom_pw(domain_name, opt_password, domain_sid)) {
5984                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5985                 cli_shutdown(cli);
5986                 talloc_destroy(mem_ctx);
5987                 return -1;
5988         }
5989         
5990         /*
5991          * Close the pipes and clean up
5992          */
5993          
5994         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5995         if (NT_STATUS_IS_ERR(nt_status)) {
5996                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5997                         nt_errstr(nt_status)));
5998                 cli_shutdown(cli);
5999                 talloc_destroy(mem_ctx);
6000                 return -1;
6001         }
6002
6003         cli_shutdown(cli);
6004          
6005         talloc_destroy(mem_ctx);
6006          
6007         d_printf("Trust to domain %s established\n", domain_name);
6008         return 0;
6009 }
6010
6011 /**
6012  * Revoke trust relationship to the remote domain
6013  *
6014  * @param argc standard argc
6015  * @param argv standard argv without initial components
6016  *
6017  * @return Integer status (0 means success)
6018  **/
6019
6020 static int rpc_trustdom_revoke(int argc, const char **argv)
6021 {
6022         char* domain_name;
6023         int rc = -1;
6024
6025         if (argc < 1) return -1;
6026         
6027         /* generate upper cased domain name */
6028         domain_name = smb_xstrdup(argv[0]);
6029         strupper_m(domain_name);
6030
6031         /* delete password of the trust */
6032         if (!pdb_del_trusteddom_pw(domain_name)) {
6033                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6034                           domain_name));
6035                 goto done;
6036         };
6037         
6038         rc = 0;
6039 done:
6040         SAFE_FREE(domain_name);
6041         return rc;
6042 }
6043
6044 /**
6045  * Usage for 'net rpc trustdom' command
6046  *
6047  * @param argc standard argc
6048  * @param argv standard argv without inital components
6049  *
6050  * @return Integer status returned to shell
6051  **/
6052  
6053 static int rpc_trustdom_usage(int argc, const char **argv)
6054 {
6055         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
6056         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
6057         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
6058         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
6059         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
6060         d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
6061         return -1;
6062 }
6063
6064
6065 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
6066                                         const char *domain_name, 
6067                                         struct cli_state *cli,
6068                                         struct rpc_pipe_client *pipe_hnd,
6069                                         TALLOC_CTX *mem_ctx,
6070                                         int argc,
6071                                         const char **argv)
6072 {
6073         fstring str_sid;
6074         sid_to_fstring(str_sid, domain_sid);
6075         d_printf("%s\n", str_sid);
6076         return NT_STATUS_OK;
6077 }
6078
6079 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
6080 {
6081         fstring ascii_sid, padding;
6082         int pad_len, col_len = 20;
6083
6084         /* convert sid into ascii string */
6085         sid_to_fstring(ascii_sid, dom_sid);
6086
6087         /* calculate padding space for d_printf to look nicer */
6088         pad_len = col_len - strlen(trusted_dom_name);
6089         padding[pad_len] = 0;
6090         do padding[--pad_len] = ' '; while (pad_len);
6091                         
6092         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
6093 }
6094
6095 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6096                                       TALLOC_CTX *mem_ctx, 
6097                                       POLICY_HND *pol, 
6098                                       DOM_SID dom_sid, 
6099                                       const char *trusted_dom_name)
6100 {
6101         NTSTATUS nt_status;
6102         union lsa_TrustedDomainInfo info;
6103         char *cleartextpwd = NULL;
6104         DATA_BLOB data;
6105
6106         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6107                                                            pol,
6108                                                            &dom_sid,
6109                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6110                                                            &info);
6111         if (NT_STATUS_IS_ERR(nt_status)) {
6112                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6113                 nt_errstr(nt_status)));
6114                 goto done;
6115         }
6116
6117         data = data_blob(NULL, info.password.password->length);
6118
6119         memcpy(data.data,
6120                info.password.password->data,
6121                info.password.password->length);
6122         data.length = info.password.password->length;
6123
6124         cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password,
6125                                                &data);
6126
6127         if (cleartextpwd == NULL) {
6128                 DEBUG(0,("retrieved NULL password\n"));
6129                 nt_status = NT_STATUS_UNSUCCESSFUL;
6130                 goto done;
6131         }
6132         
6133         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6134                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6135                 nt_status = NT_STATUS_UNSUCCESSFUL;
6136                 goto done;
6137         }
6138
6139 #ifdef DEBUG_PASSWORD
6140         DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], "
6141                    "password: [%s]\n", trusted_dom_name,
6142                    sid_string_dbg(&dom_sid), cleartextpwd));
6143 #endif
6144
6145 done:
6146         SAFE_FREE(cleartextpwd);
6147         data_blob_free(&data);
6148
6149         return nt_status;
6150 }
6151
6152 static int rpc_trustdom_vampire(int argc, const char **argv)
6153 {
6154         /* common variables */
6155         TALLOC_CTX* mem_ctx;
6156         struct cli_state *cli = NULL;
6157         struct rpc_pipe_client *pipe_hnd = NULL;
6158         NTSTATUS nt_status;
6159         const char *domain_name = NULL;
6160         DOM_SID *queried_dom_sid;
6161         POLICY_HND connect_hnd;
6162         union lsa_PolicyInformation *info = NULL;
6163
6164         /* trusted domains listing variables */
6165         unsigned int enum_ctx = 0;
6166         int i;
6167         struct lsa_DomainList dom_list;
6168         fstring pdc_name;
6169
6170         /*
6171          * Listing trusted domains (stored in secrets.tdb, if local)
6172          */
6173
6174         mem_ctx = talloc_init("trust relationships vampire");
6175
6176         /*
6177          * set domain and pdc name to local samba server (default)
6178          * or to remote one given in command line
6179          */
6180
6181         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6182                 domain_name = opt_workgroup;
6183                 opt_target_workgroup = opt_workgroup;
6184         } else {
6185                 fstrcpy(pdc_name, global_myname());
6186                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6187                 opt_target_workgroup = domain_name;
6188         };
6189
6190         /* open \PIPE\lsarpc and open policy handle */
6191         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
6192         if (!NT_STATUS_IS_OK(nt_status)) {
6193                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6194                           nt_errstr(nt_status)));
6195                 talloc_destroy(mem_ctx);
6196                 return -1;
6197         };
6198
6199         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6200         if (!pipe_hnd) {
6201                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6202                         nt_errstr(nt_status) ));
6203                 cli_shutdown(cli);
6204                 talloc_destroy(mem_ctx);
6205                 return -1;
6206         };
6207
6208         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6209                                         &connect_hnd);
6210         if (NT_STATUS_IS_ERR(nt_status)) {
6211                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6212                         nt_errstr(nt_status)));
6213                 cli_shutdown(cli);
6214                 talloc_destroy(mem_ctx);
6215                 return -1;
6216         };
6217
6218         /* query info level 5 to obtain sid of a domain being queried */
6219         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6220                                                &connect_hnd,
6221                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6222                                                &info);
6223
6224         if (NT_STATUS_IS_ERR(nt_status)) {
6225                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6226                         nt_errstr(nt_status)));
6227                 cli_shutdown(cli);
6228                 talloc_destroy(mem_ctx);
6229                 return -1;
6230         }
6231
6232         queried_dom_sid = info->account_domain.sid;
6233
6234         /*
6235          * Keep calling LsaEnumTrustdom over opened pipe until
6236          * the end of enumeration is reached
6237          */
6238
6239         d_printf("Vampire trusted domains:\n\n");
6240
6241         do {
6242                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6243                                                     &connect_hnd,
6244                                                     &enum_ctx,
6245                                                     &dom_list,
6246                                                     (uint32_t)-1);
6247                 if (NT_STATUS_IS_ERR(nt_status)) {
6248                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6249                                 nt_errstr(nt_status)));
6250                         cli_shutdown(cli);
6251                         talloc_destroy(mem_ctx);
6252                         return -1;
6253                 };
6254
6255                 for (i = 0; i < dom_list.count; i++) {
6256
6257                         print_trusted_domain(dom_list.domains[i].sid,
6258                                              dom_list.domains[i].name.string);
6259
6260                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
6261                                                            *dom_list.domains[i].sid,
6262                                                            dom_list.domains[i].name.string);
6263                         if (!NT_STATUS_IS_OK(nt_status)) {
6264                                 cli_shutdown(cli);
6265                                 talloc_destroy(mem_ctx);
6266                                 return -1;
6267                         }
6268                 };
6269
6270                 /*
6271                  * in case of no trusted domains say something rather
6272                  * than just display blank line
6273                  */
6274                 if (!dom_list.count) d_printf("none\n");
6275
6276         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6277
6278         /* close this connection before doing next one */
6279         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6280         if (NT_STATUS_IS_ERR(nt_status)) {
6281                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6282                         nt_errstr(nt_status)));
6283                 cli_shutdown(cli);
6284                 talloc_destroy(mem_ctx);
6285                 return -1;
6286         };
6287
6288         /* close lsarpc pipe and connection to IPC$ */
6289         cli_shutdown(cli);
6290
6291         talloc_destroy(mem_ctx);         
6292         return 0;
6293 }
6294
6295 static int rpc_trustdom_list(int argc, const char **argv)
6296 {
6297         /* common variables */
6298         TALLOC_CTX* mem_ctx;
6299         struct cli_state *cli = NULL, *remote_cli = NULL;
6300         struct rpc_pipe_client *pipe_hnd = NULL;
6301         NTSTATUS nt_status;
6302         const char *domain_name = NULL;
6303         DOM_SID *queried_dom_sid;
6304         fstring padding;
6305         int ascii_dom_name_len;
6306         POLICY_HND connect_hnd;
6307         union lsa_PolicyInformation *info = NULL;
6308
6309         /* trusted domains listing variables */
6310         unsigned int num_domains, enum_ctx = 0;
6311         int i, pad_len, col_len = 20;
6312         struct lsa_DomainList dom_list;
6313         fstring pdc_name;
6314
6315         /* trusting domains listing variables */
6316         POLICY_HND domain_hnd;
6317         struct samr_SamArray *trusts = NULL;
6318
6319         /*
6320          * Listing trusted domains (stored in secrets.tdb, if local)
6321          */
6322
6323         mem_ctx = talloc_init("trust relationships listing");
6324
6325         /*
6326          * set domain and pdc name to local samba server (default)
6327          * or to remote one given in command line
6328          */
6329         
6330         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6331                 domain_name = opt_workgroup;
6332                 opt_target_workgroup = opt_workgroup;
6333         } else {
6334                 fstrcpy(pdc_name, global_myname());
6335                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6336                 opt_target_workgroup = domain_name;
6337         };
6338
6339         /* open \PIPE\lsarpc and open policy handle */
6340         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
6341         if (!NT_STATUS_IS_OK(nt_status)) {
6342                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6343                           nt_errstr(nt_status)));
6344                 talloc_destroy(mem_ctx);
6345                 return -1;
6346         };
6347
6348         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6349         if (!pipe_hnd) {
6350                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6351                         nt_errstr(nt_status) ));
6352                 cli_shutdown(cli);
6353                 talloc_destroy(mem_ctx);
6354                 return -1;
6355         };
6356
6357         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6358                                         &connect_hnd);
6359         if (NT_STATUS_IS_ERR(nt_status)) {
6360                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6361                         nt_errstr(nt_status)));
6362                 cli_shutdown(cli);
6363                 talloc_destroy(mem_ctx);
6364                 return -1;
6365         };
6366         
6367         /* query info level 5 to obtain sid of a domain being queried */
6368         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6369                                                &connect_hnd,
6370                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6371                                                &info);
6372
6373         if (NT_STATUS_IS_ERR(nt_status)) {
6374                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6375                         nt_errstr(nt_status)));
6376                 cli_shutdown(cli);
6377                 talloc_destroy(mem_ctx);
6378                 return -1;
6379         }
6380
6381         queried_dom_sid = info->account_domain.sid;
6382
6383         /*
6384          * Keep calling LsaEnumTrustdom over opened pipe until
6385          * the end of enumeration is reached
6386          */
6387          
6388         d_printf("Trusted domains list:\n\n");
6389
6390         do {
6391                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6392                                                     &connect_hnd,
6393                                                     &enum_ctx,
6394                                                     &dom_list,
6395                                                     (uint32_t)-1);
6396                 if (NT_STATUS_IS_ERR(nt_status)) {
6397                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6398                                 nt_errstr(nt_status)));
6399                         cli_shutdown(cli);
6400                         talloc_destroy(mem_ctx);
6401                         return -1;
6402                 };
6403
6404                 for (i = 0; i < dom_list.count; i++) {
6405                         print_trusted_domain(dom_list.domains[i].sid,
6406                                              dom_list.domains[i].name.string);
6407                 };
6408
6409                 /*
6410                  * in case of no trusted domains say something rather
6411                  * than just display blank line
6412                  */
6413                 if (!dom_list.count) d_printf("none\n");
6414
6415         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6416
6417         /* close this connection before doing next one */
6418         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6419         if (NT_STATUS_IS_ERR(nt_status)) {
6420                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6421                         nt_errstr(nt_status)));
6422                 cli_shutdown(cli);
6423                 talloc_destroy(mem_ctx);
6424                 return -1;
6425         };
6426         
6427         cli_rpc_pipe_close(pipe_hnd);
6428
6429         /*
6430          * Listing trusting domains (stored in passdb backend, if local)
6431          */
6432         
6433         d_printf("\nTrusting domains list:\n\n");
6434
6435         /*
6436          * Open \PIPE\samr and get needed policy handles
6437          */
6438         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
6439         if (!pipe_hnd) {
6440                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6441                 cli_shutdown(cli);
6442                 talloc_destroy(mem_ctx);
6443                 return -1;
6444         };
6445
6446         /* SamrConnect2 */
6447         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6448                                          pipe_hnd->cli->desthost,
6449                                          SA_RIGHT_SAM_OPEN_DOMAIN,
6450                                          &connect_hnd);
6451         if (!NT_STATUS_IS_OK(nt_status)) {
6452                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6453                         nt_errstr(nt_status)));
6454                 cli_shutdown(cli);
6455                 talloc_destroy(mem_ctx);
6456                 return -1;
6457         };
6458
6459         /* SamrOpenDomain - we have to open domain policy handle in order to be
6460            able to enumerate accounts*/
6461         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6462                                            &connect_hnd,
6463                                            SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6464                                            queried_dom_sid,
6465                                            &domain_hnd);
6466         if (!NT_STATUS_IS_OK(nt_status)) {
6467                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6468                         nt_errstr(nt_status)));
6469                 cli_shutdown(cli);
6470                 talloc_destroy(mem_ctx);
6471                 return -1;
6472         };
6473         
6474         /*
6475          * perform actual enumeration
6476          */
6477          
6478         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6479         do {
6480
6481                 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6482                                                         &domain_hnd,
6483                                                         &enum_ctx,
6484                                                         ACB_DOMTRUST,
6485                                                         &trusts,
6486                                                         0xffff,
6487                                                         &num_domains);
6488                 if (NT_STATUS_IS_ERR(nt_status)) {
6489                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6490                                 nt_errstr(nt_status)));
6491                         cli_shutdown(cli);
6492                         talloc_destroy(mem_ctx);
6493                         return -1;
6494                 };
6495
6496                 for (i = 0; i < num_domains; i++) {
6497
6498                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6499
6500                         /*
6501                          * get each single domain's sid (do we _really_ need this ?):
6502                          *  1) connect to domain's pdc
6503                          *  2) query the pdc for domain's sid
6504                          */
6505
6506                         /* get rid of '$' tail */
6507                         ascii_dom_name_len = strlen(str);
6508                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6509                                 str[ascii_dom_name_len - 1] = '\0';
6510
6511                         /* calculate padding space for d_printf to look nicer */
6512                         pad_len = col_len - strlen(str);
6513                         padding[pad_len] = 0;
6514                         do padding[--pad_len] = ' '; while (pad_len);
6515
6516                         /* set opt_* variables to remote domain */
6517                         strupper_m(str);
6518                         opt_workgroup = talloc_strdup(mem_ctx, str);
6519                         opt_target_workgroup = opt_workgroup;
6520
6521                         d_printf("%s%s", str, padding);
6522
6523                         /* connect to remote domain controller */
6524                         nt_status = net_make_ipc_connection(
6525                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6526                                         &remote_cli);
6527                         if (NT_STATUS_IS_OK(nt_status)) {
6528                                 /* query for domain's sid */
6529                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
6530                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6531
6532                                 cli_shutdown(remote_cli);
6533                         
6534                         } else {
6535                                 d_fprintf(stderr, "domain controller is not "
6536                                           "responding: %s\n",
6537                                           nt_errstr(nt_status));
6538                         };
6539                 };
6540                 
6541                 if (!num_domains) d_printf("none\n");
6542                 
6543         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6544
6545         /* close opened samr and domain policy handles */
6546         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6547         if (!NT_STATUS_IS_OK(nt_status)) {
6548                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6549         };
6550         
6551         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6552         if (!NT_STATUS_IS_OK(nt_status)) {
6553                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6554         };
6555         
6556         /* close samr pipe and connection to IPC$ */
6557         cli_shutdown(cli);
6558
6559         talloc_destroy(mem_ctx);         
6560         return 0;
6561 }
6562
6563 /**
6564  * Entrypoint for 'net rpc trustdom' code
6565  *
6566  * @param argc standard argc
6567  * @param argv standard argv without initial components
6568  *
6569  * @return Integer status (0 means success)
6570  */
6571
6572 static int rpc_trustdom(int argc, const char **argv)
6573 {
6574         struct functable func[] = {
6575                 {"add", rpc_trustdom_add},
6576                 {"del", rpc_trustdom_del},
6577                 {"establish", rpc_trustdom_establish},
6578                 {"revoke", rpc_trustdom_revoke},
6579                 {"help", rpc_trustdom_usage},
6580                 {"list", rpc_trustdom_list},
6581                 {"vampire", rpc_trustdom_vampire},
6582                 {NULL, NULL}
6583         };
6584
6585         if (argc == 0) {
6586                 rpc_trustdom_usage(argc, argv);
6587                 return -1;
6588         }
6589
6590         return (net_run_function(argc, argv, func, rpc_user_usage));
6591 }
6592
6593 /**
6594  * Check if a server will take rpc commands
6595  * @param flags Type of server to connect to (PDC, DMB, localhost)
6596  *              if the host is not explicitly specified
6597  * @return  bool (true means rpc supported)
6598  */
6599 bool net_rpc_check(unsigned flags)
6600 {
6601         struct cli_state *cli;
6602         bool ret = False;
6603         struct sockaddr_storage server_ss;
6604         char *server_name = NULL;
6605         NTSTATUS status;
6606
6607         /* flags (i.e. server type) may depend on command */
6608         if (!net_find_server(NULL, flags, &server_ss, &server_name))
6609                 return False;
6610
6611         if ((cli = cli_initialise()) == NULL) {
6612                 return False;
6613         }
6614
6615         status = cli_connect(cli, server_name, &server_ss);
6616         if (!NT_STATUS_IS_OK(status))
6617                 goto done;
6618         if (!attempt_netbios_session_request(&cli, global_myname(),
6619                                              server_name, &server_ss))
6620                 goto done;
6621         if (!cli_negprot(cli))
6622                 goto done;
6623         if (cli->protocol < PROTOCOL_NT1)
6624                 goto done;
6625
6626         ret = True;
6627  done:
6628         cli_shutdown(cli);
6629         return ret;
6630 }
6631
6632 /* dump sam database via samsync rpc calls */
6633 static int rpc_samdump(int argc, const char **argv) {
6634                 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
6635                                argc, argv);
6636 }
6637
6638 /* syncronise sam database via samsync rpc calls */
6639 static int rpc_vampire(int argc, const char **argv) {
6640         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
6641                                argc, argv);
6642 }
6643
6644 /** 
6645  * Migrate everything from a print-server
6646  *
6647  * @param argc  Standard main() style argc
6648  * @param argv  Standard main() style argv.  Initial components are already
6649  *              stripped
6650  *
6651  * @return A shell status integer (0 for success)
6652  *
6653  * The order is important !
6654  * To successfully add drivers the print-queues have to exist !
6655  * Applying ACLs should be the last step, because you're easily locked out
6656  *
6657  **/
6658 static int rpc_printer_migrate_all(int argc, const char **argv)
6659 {
6660         int ret;
6661
6662         if (!opt_host) {
6663                 printf("no server to migrate\n");
6664                 return -1;
6665         }
6666
6667         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
6668         if (ret)
6669                 return ret;
6670
6671         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
6672         if (ret)
6673                 return ret;
6674
6675         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
6676         if (ret)
6677                 return ret;
6678
6679         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
6680         if (ret)
6681                 return ret;
6682
6683         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
6684
6685 }
6686
6687 /** 
6688  * Migrate print-drivers from a print-server
6689  *
6690  * @param argc  Standard main() style argc
6691  * @param argv  Standard main() style argv.  Initial components are already
6692  *              stripped
6693  *
6694  * @return A shell status integer (0 for success)
6695  **/
6696 static int rpc_printer_migrate_drivers(int argc, const char **argv)
6697 {
6698         if (!opt_host) {
6699                 printf("no server to migrate\n");
6700                 return -1;
6701         }
6702
6703         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6704                                rpc_printer_migrate_drivers_internals,
6705                                argc, argv);
6706 }
6707
6708 /** 
6709  * Migrate print-forms from a print-server
6710  *
6711  * @param argc  Standard main() style argc
6712  * @param argv  Standard main() style argv.  Initial components are already
6713  *              stripped
6714  *
6715  * @return A shell status integer (0 for success)
6716  **/
6717 static int rpc_printer_migrate_forms(int argc, const char **argv)
6718 {
6719         if (!opt_host) {
6720                 printf("no server to migrate\n");
6721                 return -1;
6722         }
6723
6724         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6725                                rpc_printer_migrate_forms_internals,
6726                                argc, argv);
6727 }
6728
6729 /** 
6730  * Migrate printers from a print-server
6731  *
6732  * @param argc  Standard main() style argc
6733  * @param argv  Standard main() style argv.  Initial components are already
6734  *              stripped
6735  *
6736  * @return A shell status integer (0 for success)
6737  **/
6738 static int rpc_printer_migrate_printers(int argc, const char **argv)
6739 {
6740         if (!opt_host) {
6741                 printf("no server to migrate\n");
6742                 return -1;
6743         }
6744
6745         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6746                                rpc_printer_migrate_printers_internals,
6747                                argc, argv);
6748 }
6749
6750 /** 
6751  * Migrate printer-ACLs from a print-server
6752  *
6753  * @param argc  Standard main() style argc
6754  * @param argv  Standard main() style argv.  Initial components are already
6755  *              stripped
6756  *
6757  * @return A shell status integer (0 for success)
6758  **/
6759 static int rpc_printer_migrate_security(int argc, const char **argv)
6760 {
6761         if (!opt_host) {
6762                 printf("no server to migrate\n");
6763                 return -1;
6764         }
6765
6766         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6767                                rpc_printer_migrate_security_internals,
6768                                argc, argv);
6769 }
6770
6771 /** 
6772  * Migrate printer-settings from a print-server
6773  *
6774  * @param argc  Standard main() style argc
6775  * @param argv  Standard main() style argv.  Initial components are already
6776  *              stripped
6777  *
6778  * @return A shell status integer (0 for success)
6779  **/
6780 static int rpc_printer_migrate_settings(int argc, const char **argv)
6781 {
6782         if (!opt_host) {
6783                 printf("no server to migrate\n");
6784                 return -1;
6785         }
6786
6787         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6788                                rpc_printer_migrate_settings_internals,
6789                                argc, argv);
6790 }
6791
6792 /** 
6793  * 'net rpc printer' entrypoint.
6794  * @param argc  Standard main() style argc
6795  * @param argv  Standard main() style argv.  Initial components are already
6796  *              stripped
6797  **/
6798
6799 int rpc_printer_migrate(int argc, const char **argv) 
6800 {
6801
6802         /* ouch: when addriver and setdriver are called from within
6803            rpc_printer_migrate_drivers_internals, the printer-queue already
6804            *has* to exist */
6805
6806         struct functable func[] = {
6807                 {"all",         rpc_printer_migrate_all},
6808                 {"drivers",     rpc_printer_migrate_drivers},
6809                 {"forms",       rpc_printer_migrate_forms},
6810                 {"help",        rpc_printer_usage},
6811                 {"printers",    rpc_printer_migrate_printers},
6812                 {"security",    rpc_printer_migrate_security},
6813                 {"settings",    rpc_printer_migrate_settings},
6814                 {NULL, NULL}
6815         };
6816
6817         return net_run_function(argc, argv, func, rpc_printer_usage);
6818 }
6819
6820
6821 /** 
6822  * List printers on a remote RPC server
6823  *
6824  * @param argc  Standard main() style argc
6825  * @param argv  Standard main() style argv.  Initial components are already
6826  *              stripped
6827  *
6828  * @return A shell status integer (0 for success)
6829  **/
6830 static int rpc_printer_list(int argc, const char **argv)
6831 {
6832
6833         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6834                                rpc_printer_list_internals,
6835                                argc, argv);
6836 }
6837
6838 /** 
6839  * List printer-drivers on a remote RPC server
6840  *
6841  * @param argc  Standard main() style argc
6842  * @param argv  Standard main() style argv.  Initial components are already
6843  *              stripped
6844  *
6845  * @return A shell status integer (0 for success)
6846  **/
6847 static int rpc_printer_driver_list(int argc, const char **argv)
6848 {
6849
6850         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6851                                rpc_printer_driver_list_internals,
6852                                argc, argv);
6853 }
6854
6855 /** 
6856  * Publish printer in ADS via MSRPC
6857  *
6858  * @param argc  Standard main() style argc
6859  * @param argv  Standard main() style argv.  Initial components are already
6860  *              stripped
6861  *
6862  * @return A shell status integer (0 for success)
6863  **/
6864 static int rpc_printer_publish_publish(int argc, const char **argv)
6865 {
6866
6867         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6868                                rpc_printer_publish_publish_internals,
6869                                argc, argv);
6870 }
6871
6872 /** 
6873  * Update printer in ADS via MSRPC
6874  *
6875  * @param argc  Standard main() style argc
6876  * @param argv  Standard main() style argv.  Initial components are already
6877  *              stripped
6878  *
6879  * @return A shell status integer (0 for success)
6880  **/
6881 static int rpc_printer_publish_update(int argc, const char **argv)
6882 {
6883
6884         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6885                                rpc_printer_publish_update_internals,
6886                                argc, argv);
6887 }
6888
6889 /** 
6890  * UnPublish printer in ADS via MSRPC
6891  *
6892  * @param argc  Standard main() style argc
6893  * @param argv  Standard main() style argv.  Initial components are already
6894  *              stripped
6895  *
6896  * @return A shell status integer (0 for success)
6897  **/
6898 static int rpc_printer_publish_unpublish(int argc, const char **argv)
6899 {
6900
6901         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6902                                rpc_printer_publish_unpublish_internals,
6903                                argc, argv);
6904 }
6905
6906 /** 
6907  * List published printers via MSRPC
6908  *
6909  * @param argc  Standard main() style argc
6910  * @param argv  Standard main() style argv.  Initial components are already
6911  *              stripped
6912  *
6913  * @return A shell status integer (0 for success)
6914  **/
6915 static int rpc_printer_publish_list(int argc, const char **argv)
6916 {
6917
6918         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6919                                rpc_printer_publish_list_internals,
6920                                argc, argv);
6921 }
6922
6923
6924 /** 
6925  * Publish printer in ADS
6926  *
6927  * @param argc  Standard main() style argc
6928  * @param argv  Standard main() style argv.  Initial components are already
6929  *              stripped
6930  *
6931  * @return A shell status integer (0 for success)
6932  **/
6933 static int rpc_printer_publish(int argc, const char **argv)
6934 {
6935
6936         struct functable func[] = {
6937                 {"publish",     rpc_printer_publish_publish},
6938                 {"update",      rpc_printer_publish_update},
6939                 {"unpublish",   rpc_printer_publish_unpublish},
6940                 {"list",        rpc_printer_publish_list},
6941                 {"help",        rpc_printer_usage},
6942                 {NULL, NULL}
6943         };
6944
6945         if (argc == 0)
6946                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6947                                rpc_printer_publish_list_internals,
6948                                argc, argv);
6949
6950         return net_run_function(argc, argv, func, rpc_printer_usage);
6951
6952 }
6953
6954
6955 /** 
6956  * Display rpc printer help page.
6957  * @param argc  Standard main() style argc
6958  * @param argv  Standard main() style argv.  Initial components are already
6959  *              stripped
6960  **/
6961 int rpc_printer_usage(int argc, const char **argv)
6962 {
6963         return net_help_printer(argc, argv);
6964 }
6965
6966 /** 
6967  * 'net rpc printer' entrypoint.
6968  * @param argc  Standard main() style argc
6969  * @param argv  Standard main() style argv.  Initial components are already
6970  *              stripped
6971  **/
6972 int net_rpc_printer(int argc, const char **argv) 
6973 {
6974         struct functable func[] = {
6975                 {"list", rpc_printer_list},
6976                 {"migrate", rpc_printer_migrate},
6977                 {"driver", rpc_printer_driver_list},
6978                 {"publish", rpc_printer_publish},
6979                 {NULL, NULL}
6980         };
6981
6982         if (argc == 0)
6983                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6984                                rpc_printer_list_internals,
6985                                argc, argv);
6986
6987         return net_run_function(argc, argv, func, rpc_printer_usage);
6988 }
6989
6990 /****************************************************************************/
6991
6992
6993 /** 
6994  * Basic usage function for 'net rpc'
6995  * @param argc  Standard main() style argc
6996  * @param argv  Standard main() style argv.  Initial components are already
6997  *              stripped
6998  **/
6999
7000 int net_rpc_usage(int argc, const char **argv) 
7001 {
7002         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
7003         d_printf("  net rpc join \t\t\tto join a domain \n");
7004         d_printf("  net rpc oldjoin \t\tto join a domain created in server manager\n");
7005         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
7006         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
7007         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
7008         d_printf("  net rpc group \t\tto list groups\n");
7009         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
7010         d_printf("  net rpc printer \t\tto list and migrate printers\n");
7011         d_printf("  net rpc file \t\t\tto list open files\n");
7012         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
7013         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
7014         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
7015         d_printf("  net rpc samdump \t\tdisplay an NT PDC's users, groups and other data\n");
7016         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
7017         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
7018         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
7019         d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
7020         d_printf("  net rpc registry\t\tto manage registry hives\n");
7021         d_printf("  net rpc service\t\tto start, stop and query services\n");
7022         d_printf("  net rpc audit\t\t\tto modify global auditing settings\n");
7023         d_printf("  net rpc shell\t\t\tto open an interactive shell for remote server/account management\n");
7024         d_printf("\n");
7025         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
7026         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
7027         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
7028         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
7029         d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
7030         return -1;
7031 }
7032
7033
7034 /**
7035  * Help function for 'net rpc'.  Calls command specific help if requested
7036  * or displays usage of net rpc
7037  * @param argc  Standard main() style argc
7038  * @param argv  Standard main() style argv.  Initial components are already
7039  *              stripped
7040  **/
7041
7042 int net_rpc_help(int argc, const char **argv)
7043 {
7044         struct functable func[] = {
7045                 {"join", rpc_join_usage},
7046                 {"user", rpc_user_usage},
7047                 {"group", rpc_group_usage},
7048                 {"share", rpc_share_usage},
7049                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
7050                 {"trustdom", rpc_trustdom_usage},
7051                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
7052                 /*{"shutdown", rpc_shutdown_usage}, */
7053                 {"vampire", rpc_vampire_usage},
7054                 {NULL, NULL}
7055         };
7056
7057         if (argc == 0) {
7058                 net_rpc_usage(argc, argv);
7059                 return -1;
7060         }
7061
7062         return (net_run_function(argc, argv, func, rpc_user_usage));
7063 }
7064
7065 /** 
7066  * 'net rpc' entrypoint.
7067  * @param argc  Standard main() style argc
7068  * @param argv  Standard main() style argv.  Initial components are already
7069  *              stripped
7070  **/
7071
7072 int net_rpc(int argc, const char **argv)
7073 {
7074         struct functable func[] = {
7075                 {"audit", net_rpc_audit},
7076                 {"info", net_rpc_info},
7077                 {"join", net_rpc_join},
7078                 {"oldjoin", net_rpc_oldjoin},
7079                 {"testjoin", net_rpc_testjoin},
7080                 {"user", net_rpc_user},
7081                 {"password", rpc_user_password},
7082                 {"group", net_rpc_group},
7083                 {"share", net_rpc_share},
7084                 {"file", net_rpc_file},
7085                 {"printer", net_rpc_printer},
7086                 {"changetrustpw", net_rpc_changetrustpw},
7087                 {"trustdom", rpc_trustdom},
7088                 {"abortshutdown", rpc_shutdown_abort},
7089                 {"shutdown", rpc_shutdown},
7090                 {"samdump", rpc_samdump},
7091                 {"vampire", rpc_vampire},
7092                 {"getsid", net_rpc_getsid},
7093                 {"rights", net_rpc_rights},
7094                 {"service", net_rpc_service},
7095                 {"registry", net_rpc_registry},
7096                 {"shell", net_rpc_shell},
7097                 {"help", net_rpc_help},
7098                 {NULL, NULL}
7099         };
7100         return net_run_function(argc, argv, func, net_rpc_usage);
7101 }