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