5dd3df9a6908c9bd6da4b7fe4146df6fc5b5f47e
[jra/samba/.git] / source3 / utils / net_rpc.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2004,2008 Guenther Deschner (gd@samba.org)
7    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8    Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "../libcli/auth/libcli_auth.h"
26
27 static int net_mode_share;
28 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
29
30 /**
31  * @file net_rpc.c
32  *
33  * @brief RPC based subcommands for the 'net' utility.
34  *
35  * This file should contain much of the functionality that used to
36  * be found in rpcclient, execpt that the commands should change
37  * less often, and the fucntionality should be sane (the user is not
38  * expected to know a rid/sid before they conduct an operation etc.)
39  *
40  * @todo Perhaps eventually these should be split out into a number
41  * of files, as this could get quite big.
42  **/
43
44
45 /**
46  * Many of the RPC functions need the domain sid.  This function gets
47  *  it at the start of every run
48  *
49  * @param cli A cli_state already connected to the remote machine
50  *
51  * @return The Domain SID of the remote machine.
52  **/
53
54 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
55                                    DOM_SID **domain_sid,
56                                    const char **domain_name)
57 {
58         struct rpc_pipe_client *lsa_pipe = NULL;
59         struct policy_handle pol;
60         NTSTATUS result = NT_STATUS_OK;
61         union lsa_PolicyInformation *info = NULL;
62
63         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
64                                           &lsa_pipe);
65         if (!NT_STATUS_IS_OK(result)) {
66                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
67                 return result;
68         }
69
70         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
71                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
72                                      &pol);
73         if (!NT_STATUS_IS_OK(result)) {
74                 d_fprintf(stderr, "open_policy failed: %s\n",
75                           nt_errstr(result));
76                 return result;
77         }
78
79         result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
80                                             &pol,
81                                             LSA_POLICY_INFO_ACCOUNT_DOMAIN,
82                                             &info);
83         if (!NT_STATUS_IS_OK(result)) {
84                 d_fprintf(stderr, "lsaquery failed: %s\n",
85                           nt_errstr(result));
86                 return result;
87         }
88
89         *domain_name = info->account_domain.name.string;
90         *domain_sid = info->account_domain.sid;
91
92         rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
93         TALLOC_FREE(lsa_pipe);
94
95         return NT_STATUS_OK;
96 }
97
98 /**
99  * Run a single RPC command, from start to finish.
100  *
101  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
102  * @param conn_flag a NET_FLAG_ combination.  Passed to
103  *                   net_make_ipc_connection.
104  * @param argc  Standard main() style argc.
105  * @param argv  Standard main() style argv. Initial components are already
106  *              stripped.
107  * @return A shell status integer (0 for success).
108  */
109
110 int run_rpc_command(struct net_context *c,
111                         struct cli_state *cli_arg,
112                         const struct ndr_syntax_id *interface,
113                         int conn_flags,
114                         rpc_command_fn fn,
115                         int argc,
116                         const char **argv)
117 {
118         struct cli_state *cli = NULL;
119         struct rpc_pipe_client *pipe_hnd = NULL;
120         TALLOC_CTX *mem_ctx;
121         NTSTATUS nt_status;
122         DOM_SID *domain_sid;
123         const char *domain_name;
124         int ret = -1;
125
126         /* make use of cli_state handed over as an argument, if possible */
127         if (!cli_arg) {
128                 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
129                 if (!NT_STATUS_IS_OK(nt_status)) {
130                         DEBUG(1, ("failed to make ipc connection: %s\n",
131                                   nt_errstr(nt_status)));
132                         return -1;
133                 }
134         } else {
135                 cli = cli_arg;
136         }
137
138         if (!cli) {
139                 return -1;
140         }
141
142         /* Create mem_ctx */
143
144         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
145                 DEBUG(0, ("talloc_init() failed\n"));
146                 goto fail;
147         }
148
149         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
150                                               &domain_name);
151         if (!NT_STATUS_IS_OK(nt_status)) {
152                 goto fail;
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                                 goto fail;
168                         }
169                 } else {
170                         if (conn_flags & NET_FLAGS_SEAL) {
171                                 nt_status = cli_rpc_pipe_open_ntlmssp(
172                                         cli, interface,
173                                         PIPE_AUTH_LEVEL_PRIVACY,
174                                         lp_workgroup(), c->opt_user_name,
175                                         c->opt_password, &pipe_hnd);
176                         } else {
177                                 nt_status = cli_rpc_pipe_open_noauth(
178                                         cli, interface,
179                                         &pipe_hnd);
180                         }
181                         if (!NT_STATUS_IS_OK(nt_status)) {
182                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
183                                         get_pipe_name_from_iface(interface),
184                                         nt_errstr(nt_status) ));
185                                 goto fail;
186                         }
187                 }
188         }
189
190         nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
191
192         if (!NT_STATUS_IS_OK(nt_status)) {
193                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
194         } else {
195                 ret = 0;
196                 DEBUG(5, ("rpc command function succedded\n"));
197         }
198
199         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
200                 if (pipe_hnd) {
201                         TALLOC_FREE(pipe_hnd);
202                 }
203         }
204
205 fail:
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 ret;
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 session_key[16];
5742         DATA_BLOB session_key_blob;
5743         DATA_BLOB data;
5744
5745         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
5746                                                            pol,
5747                                                            &dom_sid,
5748                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
5749                                                            &info);
5750         if (NT_STATUS_IS_ERR(nt_status)) {
5751                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5752                 nt_errstr(nt_status)));
5753                 goto done;
5754         }
5755
5756         data = data_blob(info->password.password->data,
5757                          info->password.password->length);
5758
5759         if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
5760                 DEBUG(0, ("Could not retrieve password hash\n"));
5761                 goto done;
5762         }
5763
5764         session_key_blob = data_blob_const(session_key, sizeof(session_key));
5765         cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
5766
5767         if (cleartextpwd == NULL) {
5768                 DEBUG(0,("retrieved NULL password\n"));
5769                 nt_status = NT_STATUS_UNSUCCESSFUL;
5770                 goto done;
5771         }
5772
5773         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
5774                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5775                 nt_status = NT_STATUS_UNSUCCESSFUL;
5776                 goto done;
5777         }
5778
5779 #ifdef DEBUG_PASSWORD
5780         DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
5781                    "password: [%s]\n", trusted_dom_name,
5782                    sid_string_dbg(&dom_sid), cleartextpwd));
5783 #endif
5784
5785 done:
5786         SAFE_FREE(cleartextpwd);
5787         data_blob_free(&data);
5788
5789         return nt_status;
5790 }
5791
5792 static int rpc_trustdom_vampire(struct net_context *c, int argc,
5793                                 const char **argv)
5794 {
5795         /* common variables */
5796         TALLOC_CTX* mem_ctx;
5797         struct cli_state *cli = NULL;
5798         struct rpc_pipe_client *pipe_hnd = NULL;
5799         NTSTATUS nt_status;
5800         const char *domain_name = NULL;
5801         DOM_SID *queried_dom_sid;
5802         struct policy_handle connect_hnd;
5803         union lsa_PolicyInformation *info = NULL;
5804
5805         /* trusted domains listing variables */
5806         unsigned int enum_ctx = 0;
5807         int i;
5808         struct lsa_DomainList dom_list;
5809         fstring pdc_name;
5810
5811         if (c->display_usage) {
5812                 d_printf("Usage:\n"
5813                          "net rpc trustdom vampire\n"
5814                          "  Vampire trust relationship from remote server\n");
5815                 return 0;
5816         }
5817
5818         /*
5819          * Listing trusted domains (stored in secrets.tdb, if local)
5820          */
5821
5822         mem_ctx = talloc_init("trust relationships vampire");
5823
5824         /*
5825          * set domain and pdc name to local samba server (default)
5826          * or to remote one given in command line
5827          */
5828
5829         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
5830                 domain_name = c->opt_workgroup;
5831                 c->opt_target_workgroup = c->opt_workgroup;
5832         } else {
5833                 fstrcpy(pdc_name, global_myname());
5834                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5835                 c->opt_target_workgroup = domain_name;
5836         };
5837
5838         /* open \PIPE\lsarpc and open policy handle */
5839         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
5840         if (!NT_STATUS_IS_OK(nt_status)) {
5841                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5842                           nt_errstr(nt_status)));
5843                 talloc_destroy(mem_ctx);
5844                 return -1;
5845         };
5846
5847         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5848                                              &pipe_hnd);
5849         if (!NT_STATUS_IS_OK(nt_status)) {
5850                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5851                         nt_errstr(nt_status) ));
5852                 cli_shutdown(cli);
5853                 talloc_destroy(mem_ctx);
5854                 return -1;
5855         };
5856
5857         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, SEC_RIGHTS_QUERY_VALUE,
5858                                         &connect_hnd);
5859         if (NT_STATUS_IS_ERR(nt_status)) {
5860                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5861                         nt_errstr(nt_status)));
5862                 cli_shutdown(cli);
5863                 talloc_destroy(mem_ctx);
5864                 return -1;
5865         };
5866
5867         /* query info level 5 to obtain sid of a domain being queried */
5868         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5869                                                &connect_hnd,
5870                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5871                                                &info);
5872
5873         if (NT_STATUS_IS_ERR(nt_status)) {
5874                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5875                         nt_errstr(nt_status)));
5876                 cli_shutdown(cli);
5877                 talloc_destroy(mem_ctx);
5878                 return -1;
5879         }
5880
5881         queried_dom_sid = info->account_domain.sid;
5882
5883         /*
5884          * Keep calling LsaEnumTrustdom over opened pipe until
5885          * the end of enumeration is reached
5886          */
5887
5888         d_printf("Vampire trusted domains:\n\n");
5889
5890         do {
5891                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
5892                                                     &connect_hnd,
5893                                                     &enum_ctx,
5894                                                     &dom_list,
5895                                                     (uint32_t)-1);
5896                 if (NT_STATUS_IS_ERR(nt_status)) {
5897                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5898                                 nt_errstr(nt_status)));
5899                         cli_shutdown(cli);
5900                         talloc_destroy(mem_ctx);
5901                         return -1;
5902                 };
5903
5904                 for (i = 0; i < dom_list.count; i++) {
5905
5906                         print_trusted_domain(dom_list.domains[i].sid,
5907                                              dom_list.domains[i].name.string);
5908
5909                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
5910                                                            *dom_list.domains[i].sid,
5911                                                            dom_list.domains[i].name.string);
5912                         if (!NT_STATUS_IS_OK(nt_status)) {
5913                                 cli_shutdown(cli);
5914                                 talloc_destroy(mem_ctx);
5915                                 return -1;
5916                         }
5917                 };
5918
5919                 /*
5920                  * in case of no trusted domains say something rather
5921                  * than just display blank line
5922                  */
5923                 if (!dom_list.count) d_printf("none\n");
5924
5925         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5926
5927         /* close this connection before doing next one */
5928         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5929         if (NT_STATUS_IS_ERR(nt_status)) {
5930                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5931                         nt_errstr(nt_status)));
5932                 cli_shutdown(cli);
5933                 talloc_destroy(mem_ctx);
5934                 return -1;
5935         };
5936
5937         /* close lsarpc pipe and connection to IPC$ */
5938         cli_shutdown(cli);
5939
5940         talloc_destroy(mem_ctx);
5941         return 0;
5942 }
5943
5944 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
5945 {
5946         /* common variables */
5947         TALLOC_CTX* mem_ctx;
5948         struct cli_state *cli = NULL, *remote_cli = NULL;
5949         struct rpc_pipe_client *pipe_hnd = NULL;
5950         NTSTATUS nt_status;
5951         const char *domain_name = NULL;
5952         DOM_SID *queried_dom_sid;
5953         fstring padding;
5954         int ascii_dom_name_len;
5955         struct policy_handle connect_hnd;
5956         union lsa_PolicyInformation *info = NULL;
5957
5958         /* trusted domains listing variables */
5959         unsigned int num_domains, enum_ctx = 0;
5960         int i, pad_len, col_len = 20;
5961         struct lsa_DomainList dom_list;
5962         fstring pdc_name;
5963
5964         /* trusting domains listing variables */
5965         struct policy_handle domain_hnd;
5966         struct samr_SamArray *trusts = NULL;
5967
5968         if (c->display_usage) {
5969                 d_printf("Usage:\n"
5970                          "net rpc trustdom list\n"
5971                          "    List trust relationships\n");
5972                 return 0;
5973         }
5974
5975         /*
5976          * Listing trusted domains (stored in secrets.tdb, if local)
5977          */
5978
5979         mem_ctx = talloc_init("trust relationships listing");
5980
5981         /*
5982          * set domain and pdc name to local samba server (default)
5983          * or to remote one given in command line
5984          */
5985
5986         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
5987                 domain_name = c->opt_workgroup;
5988                 c->opt_target_workgroup = c->opt_workgroup;
5989         } else {
5990                 fstrcpy(pdc_name, global_myname());
5991                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5992                 c->opt_target_workgroup = domain_name;
5993         };
5994
5995         /* open \PIPE\lsarpc and open policy handle */
5996         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
5997         if (!NT_STATUS_IS_OK(nt_status)) {
5998                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5999                           nt_errstr(nt_status)));
6000                 talloc_destroy(mem_ctx);
6001                 return -1;
6002         };
6003
6004         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6005                                              &pipe_hnd);
6006         if (!NT_STATUS_IS_OK(nt_status)) {
6007                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6008                         nt_errstr(nt_status) ));
6009                 cli_shutdown(cli);
6010                 talloc_destroy(mem_ctx);
6011                 return -1;
6012         };
6013
6014         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, SEC_RIGHTS_QUERY_VALUE,
6015                                         &connect_hnd);
6016         if (NT_STATUS_IS_ERR(nt_status)) {
6017                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6018                         nt_errstr(nt_status)));
6019                 cli_shutdown(cli);
6020                 talloc_destroy(mem_ctx);
6021                 return -1;
6022         };
6023         
6024         /* query info level 5 to obtain sid of a domain being queried */
6025         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6026                                                &connect_hnd,
6027                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6028                                                &info);
6029
6030         if (NT_STATUS_IS_ERR(nt_status)) {
6031                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6032                         nt_errstr(nt_status)));
6033                 cli_shutdown(cli);
6034                 talloc_destroy(mem_ctx);
6035                 return -1;
6036         }
6037
6038         queried_dom_sid = info->account_domain.sid;
6039
6040         /*
6041          * Keep calling LsaEnumTrustdom over opened pipe until
6042          * the end of enumeration is reached
6043          */
6044          
6045         d_printf("Trusted domains list:\n\n");
6046
6047         do {
6048                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6049                                                     &connect_hnd,
6050                                                     &enum_ctx,
6051                                                     &dom_list,
6052                                                     (uint32_t)-1);
6053                 if (NT_STATUS_IS_ERR(nt_status)) {
6054                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6055                                 nt_errstr(nt_status)));
6056                         cli_shutdown(cli);
6057                         talloc_destroy(mem_ctx);
6058                         return -1;
6059                 };
6060
6061                 for (i = 0; i < dom_list.count; i++) {
6062                         print_trusted_domain(dom_list.domains[i].sid,
6063                                              dom_list.domains[i].name.string);
6064                 };
6065
6066                 /*
6067                  * in case of no trusted domains say something rather
6068                  * than just display blank line
6069                  */
6070                 if (!dom_list.count) d_printf("none\n");
6071
6072         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6073
6074         /* close this connection before doing next one */
6075         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6076         if (NT_STATUS_IS_ERR(nt_status)) {
6077                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6078                         nt_errstr(nt_status)));
6079                 cli_shutdown(cli);
6080                 talloc_destroy(mem_ctx);
6081                 return -1;
6082         };
6083         
6084         TALLOC_FREE(pipe_hnd);
6085
6086         /*
6087          * Listing trusting domains (stored in passdb backend, if local)
6088          */
6089         
6090         d_printf("\nTrusting domains list:\n\n");
6091
6092         /*
6093          * Open \PIPE\samr and get needed policy handles
6094          */
6095         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6096                                              &pipe_hnd);
6097         if (!NT_STATUS_IS_OK(nt_status)) {
6098                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6099                 cli_shutdown(cli);
6100                 talloc_destroy(mem_ctx);
6101                 return -1;
6102         };
6103
6104         /* SamrConnect2 */
6105         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6106                                          pipe_hnd->desthost,
6107                                          SAMR_ACCESS_LOOKUP_DOMAIN,
6108                                          &connect_hnd);
6109         if (!NT_STATUS_IS_OK(nt_status)) {
6110                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6111                         nt_errstr(nt_status)));
6112                 cli_shutdown(cli);
6113                 talloc_destroy(mem_ctx);
6114                 return -1;
6115         };
6116
6117         /* SamrOpenDomain - we have to open domain policy handle in order to be
6118            able to enumerate accounts*/
6119         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6120                                            &connect_hnd,
6121                                            SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6122                                            queried_dom_sid,
6123                                            &domain_hnd);
6124         if (!NT_STATUS_IS_OK(nt_status)) {
6125                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6126                         nt_errstr(nt_status)));
6127                 cli_shutdown(cli);
6128                 talloc_destroy(mem_ctx);
6129                 return -1;
6130         };
6131
6132         /*
6133          * perform actual enumeration
6134          */
6135
6136         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6137         do {
6138
6139                 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6140                                                         &domain_hnd,
6141                                                         &enum_ctx,
6142                                                         ACB_DOMTRUST,
6143                                                         &trusts,
6144                                                         0xffff,
6145                                                         &num_domains);
6146                 if (NT_STATUS_IS_ERR(nt_status)) {
6147                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6148                                 nt_errstr(nt_status)));
6149                         cli_shutdown(cli);
6150                         talloc_destroy(mem_ctx);
6151                         return -1;
6152                 };
6153
6154                 for (i = 0; i < num_domains; i++) {
6155
6156                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6157
6158                         /*
6159                          * get each single domain's sid (do we _really_ need this ?):
6160                          *  1) connect to domain's pdc
6161                          *  2) query the pdc for domain's sid
6162                          */
6163
6164                         /* get rid of '$' tail */
6165                         ascii_dom_name_len = strlen(str);
6166                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6167                                 str[ascii_dom_name_len - 1] = '\0';
6168
6169                         /* calculate padding space for d_printf to look nicer */
6170                         pad_len = col_len - strlen(str);
6171                         padding[pad_len] = 0;
6172                         do padding[--pad_len] = ' '; while (pad_len);
6173
6174                         /* set opt_* variables to remote domain */
6175                         strupper_m(str);
6176                         c->opt_workgroup = talloc_strdup(mem_ctx, str);
6177                         c->opt_target_workgroup = c->opt_workgroup;
6178
6179                         d_printf("%s%s", str, padding);
6180
6181                         /* connect to remote domain controller */
6182                         nt_status = net_make_ipc_connection(c,
6183                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6184                                         &remote_cli);
6185                         if (NT_STATUS_IS_OK(nt_status)) {
6186                                 /* query for domain's sid */
6187                                 if (run_rpc_command(
6188                                             c, remote_cli,
6189                                             &ndr_table_lsarpc.syntax_id, 0,
6190                                             rpc_query_domain_sid, argc,
6191                                             argv))
6192                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6193
6194                                 cli_shutdown(remote_cli);
6195
6196                         } else {
6197                                 d_fprintf(stderr, "domain controller is not "
6198                                           "responding: %s\n",
6199                                           nt_errstr(nt_status));
6200                         };
6201                 };
6202
6203                 if (!num_domains) d_printf("none\n");
6204
6205         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6206
6207         /* close opened samr and domain policy handles */
6208         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6209         if (!NT_STATUS_IS_OK(nt_status)) {
6210                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6211         };
6212
6213         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6214         if (!NT_STATUS_IS_OK(nt_status)) {
6215                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6216         };
6217
6218         /* close samr pipe and connection to IPC$ */
6219         cli_shutdown(cli);
6220
6221         talloc_destroy(mem_ctx);
6222         return 0;
6223 }
6224
6225 /**
6226  * Entrypoint for 'net rpc trustdom' code.
6227  *
6228  * @param argc Standard argc.
6229  * @param argv Standard argv without initial components.
6230  *
6231  * @return Integer status (0 means success).
6232  */
6233
6234 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6235 {
6236         struct functable func[] = {
6237                 {
6238                         "add",
6239                         rpc_trustdom_add,
6240                         NET_TRANSPORT_RPC,
6241                         "Add trusted domain's account",
6242                         "net rpc trustdom add\n"
6243                         "    Add trusted domain's account"
6244                 },
6245                 {
6246                         "del",
6247                         rpc_trustdom_del,
6248                         NET_TRANSPORT_RPC,
6249                         "Remove trusted domain's account",
6250                         "net rpc trustdom del\n"
6251                         "    Remove trusted domain's account"
6252                 },
6253                 {
6254                         "establish",
6255                         rpc_trustdom_establish,
6256                         NET_TRANSPORT_RPC,
6257                         "Establish trust relationship",
6258                         "net rpc trustdom establish\n"
6259                         "    Establish trust relationship"
6260                 },
6261                 {
6262                         "revoke",
6263                         rpc_trustdom_revoke,
6264                         NET_TRANSPORT_RPC,
6265                         "Revoke trust relationship",
6266                         "net rpc trustdom revoke\n"
6267                         "    Revoke trust relationship"
6268                 },
6269                 {
6270                         "list",
6271                         rpc_trustdom_list,
6272                         NET_TRANSPORT_RPC,
6273                         "List domain trusts",
6274                         "net rpc trustdom list\n"
6275                         "    List domain trusts"
6276                 },
6277                 {
6278                         "vampire",
6279                         rpc_trustdom_vampire,
6280                         NET_TRANSPORT_RPC,
6281                         "Vampire trusts from remote server",
6282                         "net rpc trustdom vampire\n"
6283                         "    Vampire trusts from remote server"
6284                 },
6285                 {NULL, NULL, 0, NULL, NULL}
6286         };
6287
6288         return net_run_function(c, argc, argv, "net rpc trustdom", func);
6289 }
6290
6291 /**
6292  * Check if a server will take rpc commands
6293  * @param flags Type of server to connect to (PDC, DMB, localhost)
6294  *              if the host is not explicitly specified
6295  * @return  bool (true means rpc supported)
6296  */
6297 bool net_rpc_check(struct net_context *c, unsigned flags)
6298 {
6299         struct cli_state *cli;
6300         bool ret = false;
6301         struct sockaddr_storage server_ss;
6302         char *server_name = NULL;
6303         NTSTATUS status;
6304
6305         /* flags (i.e. server type) may depend on command */
6306         if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6307                 return false;
6308
6309         if ((cli = cli_initialise()) == NULL) {
6310                 return false;
6311         }
6312
6313         status = cli_connect(cli, server_name, &server_ss);
6314         if (!NT_STATUS_IS_OK(status))
6315                 goto done;
6316         if (!attempt_netbios_session_request(&cli, global_myname(),
6317                                              server_name, &server_ss))
6318                 goto done;
6319         status = cli_negprot(cli);
6320         if (!NT_STATUS_IS_OK(status))
6321                 goto done;
6322         if (cli->protocol < PROTOCOL_NT1)
6323                 goto done;
6324
6325         ret = true;
6326  done:
6327         cli_shutdown(cli);
6328         return ret;
6329 }
6330
6331 /* dump sam database via samsync rpc calls */
6332 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6333         if (c->display_usage) {
6334                 d_printf("Usage:\n"
6335                          "net rpc samdump\n"
6336                          "    Dump remote SAM database\n");
6337                 return 0;
6338         }
6339
6340         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6341                                NET_FLAGS_ANONYMOUS,
6342                                rpc_samdump_internals, argc, argv);
6343 }
6344
6345 /* syncronise sam database via samsync rpc calls */
6346 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6347 {
6348         struct functable func[] = {
6349                 {
6350                         "ldif",
6351                         rpc_vampire_ldif,
6352                         NET_TRANSPORT_RPC,
6353                         "Dump remote SAM database to ldif",
6354                         "net rpc vampire ldif\n"
6355                         "    Dump remote SAM database to LDIF file or stdout"
6356                 },
6357                 {
6358                         "keytab",
6359                         rpc_vampire_keytab,
6360                         NET_TRANSPORT_RPC,
6361                         "Dump remote SAM database to Kerberos Keytab",
6362                         "net rpc vampire keytab\n"
6363                         "    Dump remote SAM database to Kerberos keytab file"
6364                 },
6365                 {
6366                         "passdb",
6367                         rpc_vampire_passdb,
6368                         NET_TRANSPORT_RPC,
6369                         "Dump remote SAM database to passdb",
6370                         "net rpc vampire passdb\n"
6371                         "    Dump remote SAM database to passdb"
6372                 },
6373
6374                 {NULL, NULL, 0, NULL, NULL}
6375         };
6376
6377         if (argc == 0) {
6378                 if (c->display_usage) {
6379                         d_printf("Usage:\n"
6380                                  "net rpc vampire\n"
6381                                  "    Vampire remote SAM database\n");
6382                         return 0;
6383                 }
6384
6385                 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6386                                        NET_FLAGS_ANONYMOUS,
6387                                        rpc_vampire_internals,
6388                                        argc, argv);
6389         }
6390
6391         return net_run_function(c, argc, argv, "net rpc vampire", func);
6392 }
6393
6394 /**
6395  * Migrate everything from a print server.
6396  *
6397  * @param c     A net_context structure.
6398  * @param argc  Standard main() style argc.
6399  * @param argv  Standard main() style argv. Initial components are already
6400  *              stripped.
6401  *
6402  * @return A shell status integer (0 for success).
6403  *
6404  * The order is important !
6405  * To successfully add drivers the print queues have to exist !
6406  * Applying ACLs should be the last step, because you're easily locked out.
6407  *
6408  **/
6409 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6410                                    const char **argv)
6411 {
6412         int ret;
6413
6414         if (c->display_usage) {
6415                 d_printf("Usage:\n"
6416                          "net rpc printer migrate all\n"
6417                          "    Migrate everything from a print server\n");
6418                 return 0;
6419         }
6420
6421         if (!c->opt_host) {
6422                 d_printf("no server to migrate\n");
6423                 return -1;
6424         }
6425
6426         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6427                               rpc_printer_migrate_printers_internals, argc,
6428                               argv);
6429         if (ret)
6430                 return ret;
6431
6432         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6433                               rpc_printer_migrate_drivers_internals, argc,
6434                               argv);
6435         if (ret)
6436                 return ret;
6437
6438         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6439                               rpc_printer_migrate_forms_internals, argc, argv);
6440         if (ret)
6441                 return ret;
6442
6443         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6444                               rpc_printer_migrate_settings_internals, argc,
6445                               argv);
6446         if (ret)
6447                 return ret;
6448
6449         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6450                                rpc_printer_migrate_security_internals, argc,
6451                                argv);
6452
6453 }
6454
6455 /**
6456  * Migrate print drivers from a print server.
6457  *
6458  * @param c     A net_context structure.
6459  * @param argc  Standard main() style argc.
6460  * @param argv  Standard main() style argv. Initial components are already
6461  *              stripped.
6462  *
6463  * @return A shell status integer (0 for success).
6464  **/
6465 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6466                                        const char **argv)
6467 {
6468         if (c->display_usage) {
6469                 d_printf("Usage:\n"
6470                          "net rpc printer migrate drivers\n"
6471                          "     Migrate print-drivers from a print-server\n");
6472                 return 0;
6473         }
6474
6475         if (!c->opt_host) {
6476                 d_printf("no server to migrate\n");
6477                 return -1;
6478         }
6479
6480         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6481                                rpc_printer_migrate_drivers_internals,
6482                                argc, argv);
6483 }
6484
6485 /**
6486  * Migrate print-forms from a print-server.
6487  *
6488  * @param c     A net_context structure.
6489  * @param argc  Standard main() style argc.
6490  * @param argv  Standard main() style argv. Initial components are already
6491  *              stripped.
6492  *
6493  * @return A shell status integer (0 for success).
6494  **/
6495 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6496                                      const char **argv)
6497 {
6498         if (c->display_usage) {
6499                 d_printf("Usage:\n"
6500                          "net rpc printer migrate forms\n"
6501                          "    Migrate print-forms from a print-server\n");
6502                 return 0;
6503         }
6504
6505         if (!c->opt_host) {
6506                 d_printf("no server to migrate\n");
6507                 return -1;
6508         }
6509
6510         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6511                                rpc_printer_migrate_forms_internals,
6512                                argc, argv);
6513 }
6514
6515 /**
6516  * Migrate printers from a print-server.
6517  *
6518  * @param c     A net_context structure.
6519  * @param argc  Standard main() style argc.
6520  * @param argv  Standard main() style argv. Initial components are already
6521  *              stripped.
6522  *
6523  * @return A shell status integer (0 for success).
6524  **/
6525 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
6526                                         const char **argv)
6527 {
6528         if (c->display_usage) {
6529                 d_printf("Usage:\n"
6530                          "net rpc printer migrate printers\n"
6531                          "    Migrate printers from a print-server\n");
6532                 return 0;
6533         }
6534
6535         if (!c->opt_host) {
6536                 d_printf("no server to migrate\n");
6537                 return -1;
6538         }
6539
6540         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6541                                rpc_printer_migrate_printers_internals,
6542                                argc, argv);
6543 }
6544
6545 /**
6546  * Migrate printer-ACLs from a print-server
6547  *
6548  * @param c     A net_context structure.
6549  * @param argc  Standard main() style argc.
6550  * @param argv  Standard main() style argv. Initial components are already
6551  *              stripped.
6552  *
6553  * @return A shell status integer (0 for success).
6554  **/
6555 static int rpc_printer_migrate_security(struct net_context *c, int argc,
6556                                         const char **argv)
6557 {
6558         if (c->display_usage) {
6559                 d_printf("Usage:\n"
6560                          "net rpc printer migrate security\n"
6561                          "    Migrate printer-ACLs from a print-server\n");
6562                 return 0;
6563         }
6564
6565         if (!c->opt_host) {
6566                 d_printf("no server to migrate\n");
6567                 return -1;
6568         }
6569
6570         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6571                                rpc_printer_migrate_security_internals,
6572                                argc, argv);
6573 }
6574
6575 /**
6576  * Migrate printer-settings from a print-server.
6577  *
6578  * @param c     A net_context structure.
6579  * @param argc  Standard main() style argc.
6580  * @param argv  Standard main() style argv. Initial components are already
6581  *              stripped.
6582  *
6583  * @return A shell status integer (0 for success).
6584  **/
6585 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
6586                                         const char **argv)
6587 {
6588         if (c->display_usage) {
6589                 d_printf("Usage:\n"
6590                          "net rpc printer migrate settings\n"
6591                          "    Migrate printer-settings from a print-server\n");
6592                 return 0;
6593         }
6594
6595         if (!c->opt_host) {
6596                 d_printf("no server to migrate\n");
6597                 return -1;
6598         }
6599
6600         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6601                                rpc_printer_migrate_settings_internals,
6602                                argc, argv);
6603 }
6604
6605 /**
6606  * 'net rpc printer' entrypoint.
6607  *
6608  * @param c     A net_context structure.
6609  * @param argc  Standard main() style argc.
6610  * @param argv  Standard main() style argv. Initial components are already
6611  *              stripped.
6612  **/
6613
6614 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
6615 {
6616
6617         /* ouch: when addriver and setdriver are called from within
6618            rpc_printer_migrate_drivers_internals, the printer-queue already
6619            *has* to exist */
6620
6621         struct functable func[] = {
6622                 {
6623                         "all",
6624                         rpc_printer_migrate_all,
6625                         NET_TRANSPORT_RPC,
6626                         "Migrate all from remote to local print server",
6627                         "net rpc printer migrate all\n"
6628                         "    Migrate all from remote to local print server"
6629                 },
6630                 {
6631                         "drivers",
6632                         rpc_printer_migrate_drivers,
6633                         NET_TRANSPORT_RPC,
6634                         "Migrate drivers to local server",
6635                         "net rpc printer migrate drivers\n"
6636                         "    Migrate drivers to local server"
6637                 },
6638                 {
6639                         "forms",
6640                         rpc_printer_migrate_forms,
6641                         NET_TRANSPORT_RPC,
6642                         "Migrate froms to local server",
6643                         "net rpc printer migrate forms\n"
6644                         "    Migrate froms to local server"
6645                 },
6646                 {
6647                         "printers",
6648                         rpc_printer_migrate_printers,
6649                         NET_TRANSPORT_RPC,
6650                         "Migrate printers to local server",
6651                         "net rpc printer migrate printers\n"
6652                         "    Migrate printers to local server"
6653                 },
6654                 {
6655                         "security",
6656                         rpc_printer_migrate_security,
6657                         NET_TRANSPORT_RPC,
6658                         "Mirgate printer ACLs to local server",
6659                         "net rpc printer migrate security\n"
6660                         "    Mirgate printer ACLs to local server"
6661                 },
6662                 {
6663                         "settings",
6664                         rpc_printer_migrate_settings,
6665                         NET_TRANSPORT_RPC,
6666                         "Migrate printer settings to local server",
6667                         "net rpc printer migrate settings\n"
6668                         "    Migrate printer settings to local server"
6669                 },
6670                 {NULL, NULL, 0, NULL, NULL}
6671         };
6672
6673         return net_run_function(c, argc, argv, "net rpc printer migrate",func);
6674 }
6675
6676
6677 /**
6678  * List printers on a remote RPC server.
6679  *
6680  * @param c     A net_context structure.
6681  * @param argc  Standard main() style argc.
6682  * @param argv  Standard main() style argv. Initial components are already
6683  *              stripped.
6684  *
6685  * @return A shell status integer (0 for success).
6686  **/
6687 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
6688 {
6689         if (c->display_usage) {
6690                 d_printf("Usage:\n"
6691                          "net rpc printer list\n"
6692                          "    List printers on a remote RPC server\n");
6693                 return 0;
6694         }
6695
6696         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6697                                rpc_printer_list_internals,
6698                                argc, argv);
6699 }
6700
6701 /**
6702  * List printer-drivers on a remote RPC server.
6703  *
6704  * @param c     A net_context structure.
6705  * @param argc  Standard main() style argc.
6706  * @param argv  Standard main() style argv. Initial components are already
6707  *              stripped.
6708  *
6709  * @return A shell status integer (0 for success).
6710  **/
6711 static int rpc_printer_driver_list(struct net_context *c, int argc,
6712                                    const char **argv)
6713 {
6714         if (c->display_usage) {
6715                 d_printf("Usage:\n"
6716                          "net rpc printer driver\n"
6717                          "    List printer-drivers on a remote RPC server\n");
6718                 return 0;
6719         }
6720
6721         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6722                                rpc_printer_driver_list_internals,
6723                                argc, argv);
6724 }
6725
6726 /**
6727  * Publish printer in ADS via MSRPC.
6728  *
6729  * @param c     A net_context structure.
6730  * @param argc  Standard main() style argc.
6731  * @param argv  Standard main() style argv. Initial components are already
6732  *              stripped.
6733  *
6734  * @return A shell status integer (0 for success).
6735  **/
6736 static int rpc_printer_publish_publish(struct net_context *c, int argc,
6737                                        const char **argv)
6738 {
6739         if (c->display_usage) {
6740                 d_printf("Usage:\n"
6741                          "net rpc printer publish publish\n"
6742                          "     Publish printer in ADS via MSRPC\n");
6743                 return 0;
6744         }
6745
6746         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6747                                rpc_printer_publish_publish_internals,
6748                                argc, argv);
6749 }
6750
6751 /**
6752  * Update printer in ADS via MSRPC.
6753  *
6754  * @param c     A net_context structure.
6755  * @param argc  Standard main() style argc.
6756  * @param argv  Standard main() style argv. Initial components are already
6757  *              stripped.
6758  *
6759  * @return A shell status integer (0 for success).
6760  **/
6761 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
6762 {
6763         if (c->display_usage) {
6764                 d_printf("Usage:\n"
6765                          "net rpc printer publish update\n"
6766                          "    Update printer in ADS via MSRPC\n");
6767                 return 0;
6768         }
6769
6770         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6771                                rpc_printer_publish_update_internals,
6772                                argc, argv);
6773 }
6774
6775 /**
6776  * UnPublish printer in ADS via MSRPC.
6777  *
6778  * @param c     A net_context structure.
6779  * @param argc  Standard main() style argc.
6780  * @param argv  Standard main() style argv. Initial components are already
6781  *              stripped.
6782  *
6783  * @return A shell status integer (0 for success).
6784  **/
6785 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
6786                                          const char **argv)
6787 {
6788         if (c->display_usage) {
6789                 d_printf("Usage:\n"
6790                          "net rpc printer publish unpublish\n"
6791                          "    UnPublish printer in ADS via MSRPC\n");
6792                 return 0;
6793         }
6794
6795         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6796                                rpc_printer_publish_unpublish_internals,
6797                                argc, argv);
6798 }
6799
6800 /**
6801  * List published printers via MSRPC.
6802  *
6803  * @param c     A net_context structure.
6804  * @param argc  Standard main() style argc.
6805  * @param argv  Standard main() style argv. Initial components are already
6806  *              stripped.
6807  *
6808  * @return A shell status integer (0 for success).
6809  **/
6810 static int rpc_printer_publish_list(struct net_context *c, int argc,
6811                                     const char **argv)
6812 {
6813         if (c->display_usage) {
6814                 d_printf("Usage:\n"
6815                          "net rpc printer publish list\n"
6816                          "    List published printers via MSRPC\n");
6817                 return 0;
6818         }
6819
6820         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6821                                rpc_printer_publish_list_internals,
6822                                argc, argv);
6823 }
6824
6825
6826 /**
6827  * Publish printer in ADS.
6828  *
6829  * @param c     A net_context structure.
6830  * @param argc  Standard main() style argc.
6831  * @param argv  Standard main() style argv. Initial components are already
6832  *              stripped.
6833  *
6834  * @return A shell status integer (0 for success).
6835  **/
6836 static int rpc_printer_publish(struct net_context *c, int argc,
6837                                const char **argv)
6838 {
6839
6840         struct functable func[] = {
6841                 {
6842                         "publish",
6843                         rpc_printer_publish_publish,
6844                         NET_TRANSPORT_RPC,
6845                         "Publish printer in AD",
6846                         "net rpc printer publish publish\n"
6847                         "    Publish printer in AD"
6848                 },
6849                 {
6850                         "update",
6851                         rpc_printer_publish_update,
6852                         NET_TRANSPORT_RPC,
6853                         "Update printer in AD",
6854                         "net rpc printer publish update\n"
6855                         "    Update printer in AD"
6856                 },
6857                 {
6858                         "unpublish",
6859                         rpc_printer_publish_unpublish,
6860                         NET_TRANSPORT_RPC,
6861                         "Unpublish printer",
6862                         "net rpc printer publish unpublish\n"
6863                         "    Unpublish printer"
6864                 },
6865                 {
6866                         "list",
6867                         rpc_printer_publish_list,
6868                         NET_TRANSPORT_RPC,
6869                         "List published printers",
6870                         "net rpc printer publish list\n"
6871                         "    List published printers"
6872                 },
6873                 {NULL, NULL, 0, NULL, NULL}
6874         };
6875
6876         if (argc == 0) {
6877                 if (c->display_usage) {
6878                         d_printf("Usage:\n");
6879                         d_printf("net rpc printer publish\n"
6880                                  "    List published printers\n"
6881                                  "    Alias of net rpc printer publish list\n");
6882                         net_display_usage_from_functable(func);
6883                         return 0;
6884                 }
6885                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6886                                rpc_printer_publish_list_internals,
6887                                argc, argv);
6888         }
6889
6890         return net_run_function(c, argc, argv, "net rpc printer publish",func);
6891
6892 }
6893
6894
6895 /**
6896  * Display rpc printer help page.
6897  *
6898  * @param c     A net_context structure.
6899  * @param argc  Standard main() style argc.
6900  * @param argv  Standard main() style argv. Initial components are already
6901  *              stripped.
6902  **/
6903 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
6904 {
6905         d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"
6906                  "\tlists all printers on print-server\n\n");
6907         d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
6908                  "\tlists all printer-drivers on print-server\n\n");
6909         d_printf("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
6910                  "\tpublishes printer settings in Active Directory\n"
6911                  "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n");
6912         d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
6913                  "\n\tmigrates printers from remote to local server\n\n");
6914         d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
6915                  "\n\tmigrates printer-settings from remote to local server\n\n");
6916         d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
6917                  "\n\tmigrates printer-drivers from remote to local server\n\n");
6918         d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
6919                  "\n\tmigrates printer-forms from remote to local server\n\n");
6920         d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
6921                  "\n\tmigrates printer-ACLs from remote to local server\n\n");
6922         d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
6923                  "\n\tmigrates drivers, forms, queues, settings and acls from\n"
6924                  "\tremote to local print-server\n\n");
6925         net_common_methods_usage(c, argc, argv);
6926         net_common_flags_usage(c, argc, argv);
6927         d_printf(
6928          "\t-v or --verbose\t\t\tgive verbose output\n"
6929          "\t      --destination\t\tmigration target server (default: localhost)\n");
6930
6931         return -1;
6932 }
6933
6934 /**
6935  * 'net rpc printer' entrypoint.
6936  *
6937  * @param c     A net_context structure.
6938  * @param argc  Standard main() style argc.
6939  * @param argv  Standard main() style argv. Initial components are already
6940  *              stripped.
6941  **/
6942 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
6943 {
6944         struct functable func[] = {
6945                 {
6946                         "list",
6947                         rpc_printer_list,
6948                         NET_TRANSPORT_RPC,
6949                         "List all printers on print server",
6950                         "net rpc printer list\n"
6951                         "    List all printers on print server"
6952                 },
6953                 {
6954                         "migrate",
6955                         rpc_printer_migrate,
6956                         NET_TRANSPORT_RPC,
6957                         "Migrate printer to local server",
6958                         "net rpc printer migrate\n"
6959                         "    Migrate printer to local server"
6960                 },
6961                 {
6962                         "driver",
6963                         rpc_printer_driver_list,
6964                         NET_TRANSPORT_RPC,
6965                         "List printer drivers",
6966                         "net rpc printer driver\n"
6967                         "    List printer drivers"
6968                 },
6969                 {
6970                         "publish",
6971                         rpc_printer_publish,
6972                         NET_TRANSPORT_RPC,
6973                         "Publish printer in AD",
6974                         "net rpc printer publish\n"
6975                         "    Publish printer in AD"
6976                 },
6977                 {NULL, NULL, 0, NULL, NULL}
6978         };
6979
6980         if (argc == 0) {
6981                 if (c->display_usage) {
6982                         d_printf("Usage:\n");
6983                         d_printf("net rpc printer\n"
6984                                  "    List printers\n");
6985                         net_display_usage_from_functable(func);
6986                         return 0;
6987                 }
6988                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6989                                rpc_printer_list_internals,
6990                                argc, argv);
6991         }
6992
6993         return net_run_function(c, argc, argv, "net rpc printer", func);
6994 }
6995
6996 /**
6997  * 'net rpc' entrypoint.
6998  *
6999  * @param c     A net_context structure.
7000  * @param argc  Standard main() style argc.
7001  * @param argv  Standard main() style argv. Initial components are already
7002  *              stripped.
7003  **/
7004
7005 int net_rpc(struct net_context *c, int argc, const char **argv)
7006 {
7007         struct functable func[] = {
7008                 {
7009                         "audit",
7010                         net_rpc_audit,
7011                         NET_TRANSPORT_RPC,
7012                         "Modify global audit settings",
7013                         "net rpc audit\n"
7014                         "    Modify global audit settings"
7015                 },
7016                 {
7017                         "info",
7018                         net_rpc_info,
7019                         NET_TRANSPORT_RPC,
7020                         "Show basic info about a domain",
7021                         "net rpc info\n"
7022                         "    Show basic info about a domain"
7023                 },
7024                 {
7025                         "join",
7026                         net_rpc_join,
7027                         NET_TRANSPORT_RPC,
7028                         "Join a domain",
7029                         "net rpc join\n"
7030                         "    Join a domain"
7031                 },
7032                 {
7033                         "oldjoin",
7034                         net_rpc_oldjoin,
7035                         NET_TRANSPORT_RPC,
7036                         "Join a domain created in server manager",
7037                         "net rpc oldjoin\n"
7038                         "    Join a domain created in server manager"
7039                 },
7040                 {
7041                         "testjoin",
7042                         net_rpc_testjoin,
7043                         NET_TRANSPORT_RPC,
7044                         "Test that a join is valid",
7045                         "net rpc testjoin\n"
7046                         "    Test that a join is valid"
7047                 },
7048                 {
7049                         "user",
7050                         net_rpc_user,
7051                         NET_TRANSPORT_RPC,
7052                         "List/modify users",
7053                         "net rpc user\n"
7054                         "    List/modify users"
7055                 },
7056                 {
7057                         "password",
7058                         rpc_user_password,
7059                         NET_TRANSPORT_RPC,
7060                         "Change a user password",
7061                         "net rpc password\n"
7062                         "    Change a user password\n"
7063                         "    Alias for net rpc user password"
7064                 },
7065                 {
7066                         "group",
7067                         net_rpc_group,
7068                         NET_TRANSPORT_RPC,
7069                         "List/modify groups",
7070                         "net rpc group\n"
7071                         "    List/modify groups"
7072                 },
7073                 {
7074                         "share",
7075                         net_rpc_share,
7076                         NET_TRANSPORT_RPC,
7077                         "List/modify shares",
7078                         "net rpc share\n"
7079                         "    List/modify shares"
7080                 },
7081                 {
7082                         "file",
7083                         net_rpc_file,
7084                         NET_TRANSPORT_RPC,
7085                         "List open files",
7086                         "net rpc file\n"
7087                         "    List open files"
7088                 },
7089                 {
7090                         "printer",
7091                         net_rpc_printer,
7092                         NET_TRANSPORT_RPC,
7093                         "List/modify printers",
7094                         "net rpc printer\n"
7095                         "    List/modify printers"
7096                 },
7097                 {
7098                         "changetrustpw",
7099                         net_rpc_changetrustpw,
7100                         NET_TRANSPORT_RPC,
7101                         "Change trust account password",
7102                         "net rpc changetrustpw\n"
7103                         "    Change trust account password"
7104                 },
7105                 {
7106                         "trustdom",
7107                         rpc_trustdom,
7108                         NET_TRANSPORT_RPC,
7109                         "Modify domain trusts",
7110                         "net rpc trustdom\n"
7111                         "    Modify domain trusts"
7112                 },
7113                 {
7114                         "abortshutdown",
7115                         rpc_shutdown_abort,
7116                         NET_TRANSPORT_RPC,
7117                         "Abort a remote shutdown",
7118                         "net rpc abortshutdown\n"
7119                         "    Abort a remote shutdown"
7120                 },
7121                 {
7122                         "shutdown",
7123                         rpc_shutdown,
7124                         NET_TRANSPORT_RPC,
7125                         "Shutdown a remote server",
7126                         "net rpc shutdown\n"
7127                         "    Shutdown a remote server"
7128                 },
7129                 {
7130                         "samdump",
7131                         rpc_samdump,
7132                         NET_TRANSPORT_RPC,
7133                         "Dump SAM data of remote NT PDC",
7134                         "net rpc samdump\n"
7135                         "    Dump SAM data of remote NT PDC"
7136                 },
7137                 {
7138                         "vampire",
7139                         rpc_vampire,
7140                         NET_TRANSPORT_RPC,
7141                         "Sync a remote NT PDC's data into local passdb",
7142                         "net rpc vampire\n"
7143                         "    Sync a remote NT PDC's data into local passdb"
7144                 },
7145                 {
7146                         "getsid",
7147                         net_rpc_getsid,
7148                         NET_TRANSPORT_RPC,
7149                         "Fetch the domain sid into local secrets.tdb",
7150                         "net rpc getsid\n"
7151                         "    Fetch the domain sid into local secrets.tdb"
7152                 },
7153                 {
7154                         "rights",
7155                         net_rpc_rights,
7156                         NET_TRANSPORT_RPC,
7157                         "Manage privileges assigned to SID",
7158                         "net rpc rights\n"
7159                         "    Manage privileges assigned to SID"
7160                 },
7161                 {
7162                         "service",
7163                         net_rpc_service,
7164                         NET_TRANSPORT_RPC,
7165                         "Start/stop/query remote services",
7166                         "net rpc service\n"
7167                         "    Start/stop/query remote services"
7168                 },
7169                 {
7170                         "registry",
7171                         net_rpc_registry,
7172                         NET_TRANSPORT_RPC,
7173                         "Manage registry hives",
7174                         "net rpc registry\n"
7175                         "    Manage registry hives"
7176                 },
7177                 {
7178                         "shell",
7179                         net_rpc_shell,
7180                         NET_TRANSPORT_RPC,
7181                         "Open interactive shell on remote server",
7182                         "net rpc shell\n"
7183                         "    Open interactive shell on remote server"
7184                 },
7185                 {NULL, NULL, 0, NULL, NULL}
7186         };
7187         return net_run_function(c, argc, argv, "net rpc", func);
7188 }