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