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