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