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