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