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