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