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