Use rpccli_samr_Connect2() all over the place.
[jra/samba/.git] / source3 / utils / net_rpc.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
7    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8    Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22  
23 #include "includes.h"
24 #include "utils/net.h"
25
26 static void init_lsa_String(struct lsa_String *name, const char *s)
27 {
28         name->string = s;
29 }
30
31 static int net_mode_share;
32 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
33
34 /**
35  * @file net_rpc.c
36  *
37  * @brief RPC based subcommands for the 'net' utility.
38  *
39  * This file should contain much of the functionality that used to
40  * be found in rpcclient, execpt that the commands should change 
41  * less often, and the fucntionality should be sane (the user is not 
42  * expected to know a rid/sid before they conduct an operation etc.)
43  *
44  * @todo Perhaps eventually these should be split out into a number
45  * of files, as this could get quite big.
46  **/
47
48
49 /**
50  * Many of the RPC functions need the domain sid.  This function gets
51  *  it at the start of every run 
52  *
53  * @param cli A cli_state already connected to the remote machine
54  *
55  * @return The Domain SID of the remote machine.
56  **/
57
58 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
59                                    DOM_SID **domain_sid,
60                                    const char **domain_name)
61 {
62         struct rpc_pipe_client *lsa_pipe;
63         POLICY_HND pol;
64         NTSTATUS result = NT_STATUS_OK;
65         uint32 info_class = 5;
66         
67         lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
68         if (!lsa_pipe) {
69                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
70                 return result;
71         }
72         
73         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, 
74                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
75                                      &pol);
76         if (!NT_STATUS_IS_OK(result)) {
77                 d_fprintf(stderr, "open_policy failed: %s\n",
78                           nt_errstr(result));
79                 return result;
80         }
81
82         result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol,
83                                               info_class, domain_name,
84                                               domain_sid);
85         if (!NT_STATUS_IS_OK(result)) {
86                 d_fprintf(stderr, "lsaquery failed: %s\n",
87                           nt_errstr(result));
88                 return result;
89         }
90
91         rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
92         cli_rpc_pipe_close(lsa_pipe);
93
94         return NT_STATUS_OK;
95 }
96
97 /**
98  * Run a single RPC command, from start to finish.
99  *
100  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
101  * @param conn_flag a NET_FLAG_ combination.  Passed to 
102  *                   net_make_ipc_connection.
103  * @param argc  Standard main() style argc
104  * @param argc  Standard main() style argv.  Initial components are already
105  *              stripped
106  * @return A shell status integer (0 for success)
107  */
108
109 int run_rpc_command(struct cli_state *cli_arg,
110                         const int pipe_idx,
111                         int conn_flags,
112                         rpc_command_fn fn,
113                         int argc,
114                         const char **argv) 
115 {
116         struct cli_state *cli = NULL;
117         struct rpc_pipe_client *pipe_hnd = NULL;
118         TALLOC_CTX *mem_ctx;
119         NTSTATUS nt_status;
120         DOM_SID *domain_sid;
121         const char *domain_name;
122
123         /* make use of cli_state handed over as an argument, if possible */
124         if (!cli_arg) {
125                 nt_status = net_make_ipc_connection(conn_flags, &cli);
126                 if (!NT_STATUS_IS_OK(nt_status)) {
127                         DEBUG(1, ("failed to make ipc connection: %s\n",
128                                   nt_errstr(nt_status)));
129                         return -1;
130                 }
131         } else {
132                 cli = cli_arg;
133         }
134
135         if (!cli) {
136                 return -1;
137         }
138
139         /* Create mem_ctx */
140         
141         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
142                 DEBUG(0, ("talloc_init() failed\n"));
143                 cli_shutdown(cli);
144                 return -1;
145         }
146         
147         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
148                                               &domain_name);
149         if (!NT_STATUS_IS_OK(nt_status)) {
150                 cli_shutdown(cli);
151                 return -1;
152         }
153
154         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
155                 if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
156                         /* Always try and create an schannel netlogon pipe. */
157                         pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx,
158                                                         PIPE_AUTH_LEVEL_PRIVACY,
159                                                         domain_name,
160                                                         &nt_status);
161                         if (!pipe_hnd) {
162                                 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
163                                         nt_errstr(nt_status) ));
164                                 cli_shutdown(cli);
165                                 return -1;
166                         }
167                 } else {
168                         pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status);
169                         if (!pipe_hnd) {
170                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
171                                         cli_get_pipe_name(pipe_idx),
172                                         nt_errstr(nt_status) ));
173                                 cli_shutdown(cli);
174                                 return -1;
175                         }
176                 }
177         }
178         
179         nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
180         
181         if (!NT_STATUS_IS_OK(nt_status)) {
182                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
183         } else {
184                 DEBUG(5, ("rpc command function succedded\n"));
185         }
186                 
187         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
188                 if (pipe_hnd) {
189                         cli_rpc_pipe_close(pipe_hnd);
190                 }
191         }
192
193         /* close the connection only if it was opened here */
194         if (!cli_arg) {
195                 cli_shutdown(cli);
196         }
197         
198         talloc_destroy(mem_ctx);
199         return (!NT_STATUS_IS_OK(nt_status));
200 }
201
202 /** 
203  * Force a change of the trust acccount password.
204  *
205  * All parameters are provided by the run_rpc_command function, except for
206  * argc, argv which are passes through. 
207  *
208  * @param domain_sid The domain sid aquired from the remote server
209  * @param cli A cli_state connected to the server.
210  * @param mem_ctx Talloc context, destoyed on compleation of the function.
211  * @param argc  Standard main() style argc
212  * @param argc  Standard main() style argv.  Initial components are already
213  *              stripped
214  *
215  * @return Normal NTSTATUS return.
216  **/
217
218 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid,
219                                         const char *domain_name, 
220                                         struct cli_state *cli,
221                                         struct rpc_pipe_client *pipe_hnd,
222                                         TALLOC_CTX *mem_ctx, 
223                                         int argc,
224                                         const char **argv)
225 {
226         
227         return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup);
228 }
229
230 /** 
231  * Force a change of the trust acccount password.
232  *
233  * @param argc  Standard main() style argc
234  * @param argc  Standard main() style argv.  Initial components are already
235  *              stripped
236  *
237  * @return A shell status integer (0 for success)
238  **/
239
240 int net_rpc_changetrustpw(int argc, const char **argv) 
241 {
242         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
243                                rpc_changetrustpw_internals,
244                                argc, argv);
245 }
246
247 /** 
248  * Join a domain, the old way.
249  *
250  * This uses 'machinename' as the inital password, and changes it. 
251  *
252  * The password should be created with 'server manager' or equiv first.
253  *
254  * All parameters are provided by the run_rpc_command function, except for
255  * argc, argv which are passes through. 
256  *
257  * @param domain_sid The domain sid aquired from the remote server
258  * @param cli A cli_state connected to the server.
259  * @param mem_ctx Talloc context, destoyed on compleation of the function.
260  * @param argc  Standard main() style argc
261  * @param argc  Standard main() style argv.  Initial components are already
262  *              stripped
263  *
264  * @return Normal NTSTATUS return.
265  **/
266
267 static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid,
268                                         const char *domain_name, 
269                                         struct cli_state *cli, 
270                                         struct rpc_pipe_client *pipe_hnd,
271                                         TALLOC_CTX *mem_ctx, 
272                                         int argc,
273                                         const char **argv)
274 {
275         
276         fstring trust_passwd;
277         unsigned char orig_trust_passwd_hash[16];
278         NTSTATUS result;
279         uint32 sec_channel_type;
280
281         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
282         if (!pipe_hnd) {
283                 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
284                         "error was %s\n",
285                         cli->desthost,
286                         nt_errstr(result) ));
287                 return result;
288         }
289
290         /* 
291            check what type of join - if the user want's to join as
292            a BDC, the server must agree that we are a BDC.
293         */
294         if (argc >= 0) {
295                 sec_channel_type = get_sec_channel_type(argv[0]);
296         } else {
297                 sec_channel_type = get_sec_channel_type(NULL);
298         }
299         
300         fstrcpy(trust_passwd, global_myname());
301         strlower_m(trust_passwd);
302
303         /*
304          * Machine names can be 15 characters, but the max length on
305          * a password is 14.  --jerry
306          */
307
308         trust_passwd[14] = '\0';
309
310         E_md4hash(trust_passwd, orig_trust_passwd_hash);
311
312         result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup,
313                                               orig_trust_passwd_hash,
314                                               sec_channel_type);
315
316         if (NT_STATUS_IS_OK(result))
317                 printf("Joined domain %s.\n",opt_target_workgroup);
318
319
320         if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
321                 DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
322                 result = NT_STATUS_UNSUCCESSFUL;
323         }
324
325         return result;
326 }
327
328 /** 
329  * Join a domain, the old way.
330  *
331  * @param argc  Standard main() style argc
332  * @param argc  Standard main() style argv.  Initial components are already
333  *              stripped
334  *
335  * @return A shell status integer (0 for success)
336  **/
337
338 static int net_rpc_perform_oldjoin(int argc, const char **argv)
339 {
340         return run_rpc_command(NULL, PI_NETLOGON, 
341                                NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
342                                rpc_oldjoin_internals,
343                                argc, argv);
344 }
345
346 /** 
347  * Join a domain, the old way.  This function exists to allow
348  * the message to be displayed when oldjoin was explicitly 
349  * requested, but not when it was implied by "net rpc join"
350  *
351  * @param argc  Standard main() style argc
352  * @param argc  Standard main() style argv.  Initial components are already
353  *              stripped
354  *
355  * @return A shell status integer (0 for success)
356  **/
357
358 static int net_rpc_oldjoin(int argc, const char **argv) 
359 {
360         int rc = net_rpc_perform_oldjoin(argc, argv);
361
362         if (rc) {
363                 d_fprintf(stderr, "Failed to join domain\n");
364         }
365
366         return rc;
367 }
368
369 /** 
370  * Basic usage function for 'net rpc join'
371  * @param argc  Standard main() style argc
372  * @param argc  Standard main() style argv.  Initial components are already
373  *              stripped
374  **/
375
376 static int rpc_join_usage(int argc, const char **argv) 
377 {       
378         d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
379                  "\t to join a domain with admin username & password\n"\
380                  "\t\t password will be prompted if needed and none is specified\n"\
381                  "\t <type> can be (default MEMBER)\n"\
382                  "\t\t BDC - Join as a BDC\n"\
383                  "\t\t PDC - Join as a PDC\n"\
384                  "\t\t MEMBER - Join as a MEMBER server\n");
385
386         net_common_flags_usage(argc, argv);
387         return -1;
388 }
389
390 /** 
391  * 'net rpc join' entrypoint.
392  * @param argc  Standard main() style argc
393  * @param argc  Standard main() style argv.  Initial components are already
394  *              stripped
395  *
396  * Main 'net_rpc_join()' (where the admain username/password is used) is 
397  * in net_rpc_join.c
398  * Try to just change the password, but if that doesn't work, use/prompt
399  * for a username/password.
400  **/
401
402 int net_rpc_join(int argc, const char **argv) 
403 {
404         if (lp_server_role() == ROLE_STANDALONE) {
405                 d_printf("cannot join as standalone machine\n");
406                 return -1;
407         }
408
409         if (strlen(global_myname()) > 15) {
410                 d_printf("Our netbios name can be at most 15 chars long, "
411                          "\"%s\" is %u chars long\n",
412                          global_myname(), (unsigned int)strlen(global_myname()));
413                 return -1;
414         }
415
416         if ((net_rpc_perform_oldjoin(argc, argv) == 0))
417                 return 0;
418         
419         return net_rpc_join_newstyle(argc, argv);
420 }
421
422 /** 
423  * display info about a rpc domain
424  *
425  * All parameters are provided by the run_rpc_command function, except for
426  * argc, argv which are passed through. 
427  *
428  * @param domain_sid The domain sid acquired from the remote server
429  * @param cli A cli_state connected to the server.
430  * @param mem_ctx Talloc context, destoyed on completion of the function.
431  * @param argc  Standard main() style argc
432  * @param argv  Standard main() style argv.  Initial components are already
433  *              stripped
434  *
435  * @return Normal NTSTATUS return.
436  **/
437
438 NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
439                         const char *domain_name, 
440                         struct cli_state *cli,
441                         struct rpc_pipe_client *pipe_hnd,
442                         TALLOC_CTX *mem_ctx,
443                         int argc,
444                         const char **argv)
445 {
446         POLICY_HND connect_pol, domain_pol;
447         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
448         SAM_UNK_CTR ctr;
449         fstring sid_str;
450
451         sid_to_fstring(sid_str, domain_sid);
452
453         /* Get sam policy handle */
454         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
455                                       pipe_hnd->cli->desthost,
456                                       MAXIMUM_ALLOWED_ACCESS,
457                                       &connect_pol);
458         if (!NT_STATUS_IS_OK(result)) {
459                 d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
460                 goto done;
461         }
462
463         /* Get domain policy handle */
464         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
465                                         &connect_pol,
466                                         MAXIMUM_ALLOWED_ACCESS,
467                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
468                                         &domain_pol);
469         if (!NT_STATUS_IS_OK(result)) {
470                 d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
471                 goto done;
472         }
473
474         ZERO_STRUCT(ctr);
475         result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
476                                          2, &ctr);
477         if (NT_STATUS_IS_OK(result)) {
478                 TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
479                 d_printf("Domain Name: %s\n", unistr2_to_ascii_talloc(ctx, &ctr.info.inf2.uni_domain));
480                 d_printf("Domain SID: %s\n", sid_str);
481                 d_printf("Sequence number: %llu\n", (unsigned long long)ctr.info.inf2.seq_num);
482                 d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
483                 d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
484                 d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps);
485                 talloc_destroy(ctx);
486         }
487
488  done:
489         return result;
490 }
491
492 /** 
493  * 'net rpc info' entrypoint.
494  * @param argc  Standard main() style argc
495  * @param argc  Standard main() style argv.  Initial components are already
496  *              stripped
497  **/
498
499 int net_rpc_info(int argc, const char **argv) 
500 {
501         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_PDC, 
502                                rpc_info_internals,
503                                argc, argv);
504 }
505
506 /** 
507  * Fetch domain SID into the local secrets.tdb
508  *
509  * All parameters are provided by the run_rpc_command function, except for
510  * argc, argv which are passes through. 
511  *
512  * @param domain_sid The domain sid acquired from the remote server
513  * @param cli A cli_state connected to the server.
514  * @param mem_ctx Talloc context, destoyed on completion of the function.
515  * @param argc  Standard main() style argc
516  * @param argv  Standard main() style argv.  Initial components are already
517  *              stripped
518  *
519  * @return Normal NTSTATUS return.
520  **/
521
522 static NTSTATUS rpc_getsid_internals(const DOM_SID *domain_sid,
523                         const char *domain_name, 
524                         struct cli_state *cli,
525                         struct rpc_pipe_client *pipe_hnd,
526                         TALLOC_CTX *mem_ctx,
527                         int argc,
528                         const char **argv)
529 {
530         fstring sid_str;
531
532         sid_to_fstring(sid_str, domain_sid);
533         d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
534                  sid_str, domain_name);
535
536         if (!secrets_store_domain_sid(domain_name, domain_sid)) {
537                 DEBUG(0,("Can't store domain SID\n"));
538                 return NT_STATUS_UNSUCCESSFUL;
539         }
540
541         return NT_STATUS_OK;
542 }
543
544 /** 
545  * 'net rpc getsid' entrypoint.
546  * @param argc  Standard main() style argc
547  * @param argc  Standard main() style argv.  Initial components are already
548  *              stripped
549  **/
550
551 int net_rpc_getsid(int argc, const char **argv) 
552 {
553         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
554                                rpc_getsid_internals,
555                                argc, argv);
556 }
557
558 /****************************************************************************/
559
560 /**
561  * Basic usage function for 'net rpc user'
562  * @param argc  Standard main() style argc.
563  * @param argv  Standard main() style argv.  Initial components are already
564  *              stripped.
565  **/
566
567 static int rpc_user_usage(int argc, const char **argv)
568 {
569         return net_help_user(argc, argv);
570 }
571
572 /** 
573  * Add a new user to a remote RPC server
574  *
575  * All parameters are provided by the run_rpc_command function, except for
576  * argc, argv which are passes through. 
577  *
578  * @param domain_sid The domain sid acquired from the remote server
579  * @param cli A cli_state connected to the server.
580  * @param mem_ctx Talloc context, destoyed on completion of the function.
581  * @param argc  Standard main() style argc
582  * @param argv  Standard main() style argv.  Initial components are already
583  *              stripped
584  *
585  * @return Normal NTSTATUS return.
586  **/
587
588 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
589                                 const char *domain_name, 
590                                 struct cli_state *cli,
591                                 struct rpc_pipe_client *pipe_hnd,
592                                 TALLOC_CTX *mem_ctx, 
593                                 int argc, const char **argv)
594 {
595         
596         POLICY_HND connect_pol, domain_pol, user_pol;
597         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
598         const char *acct_name;
599         struct lsa_String lsa_acct_name;
600         uint32 acb_info;
601         uint32 acct_flags, user_rid;
602         uint32_t access_granted = 0;
603
604         if (argc < 1) {
605                 d_printf("User must be specified\n");
606                 rpc_user_usage(argc, argv);
607                 return NT_STATUS_OK;
608         }
609
610         acct_name = argv[0];
611         init_lsa_String(&lsa_acct_name, acct_name);
612
613         /* Get sam policy handle */
614
615         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
616                                       pipe_hnd->cli->desthost,
617                                       MAXIMUM_ALLOWED_ACCESS,
618                                       &connect_pol);
619         if (!NT_STATUS_IS_OK(result)) {
620                 goto done;
621         }
622         
623         /* Get domain policy handle */
624
625         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
626                                         &connect_pol,
627                                         MAXIMUM_ALLOWED_ACCESS,
628                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
629                                         &domain_pol);
630         if (!NT_STATUS_IS_OK(result)) {
631                 goto done;
632         }
633
634         /* Create domain user */
635
636         acb_info = ACB_NORMAL;
637         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
638                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
639                      SAMR_USER_ACCESS_SET_PASSWORD |
640                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
641                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
642
643         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
644                                          &domain_pol,
645                                          &lsa_acct_name,
646                                          acb_info,
647                                          acct_flags,
648                                          &user_pol,
649                                          &access_granted,
650                                          &user_rid);
651
652         if (!NT_STATUS_IS_OK(result)) {
653                 goto done;
654         }
655
656         if (argc == 2) {
657
658                 uint32 *user_rids, num_rids, *name_types;
659                 uint32 flags = 0x000003e8; /* Unknown */
660                 SAM_USERINFO_CTR ctr;
661                 SAM_USER_INFO_24 p24;
662                 uchar pwbuf[516];
663
664                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
665                                                   flags, 1, &acct_name,
666                                                   &num_rids, &user_rids,
667                                                   &name_types);
668
669                 if (!NT_STATUS_IS_OK(result)) {
670                         goto done;
671                 }
672
673                 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
674                                               &domain_pol,
675                                               MAXIMUM_ALLOWED_ACCESS,
676                                               user_rids[0],
677                                               &user_pol);
678
679                 if (!NT_STATUS_IS_OK(result)) {
680                         goto done;
681                 }
682
683                 /* Set password on account */
684
685                 ZERO_STRUCT(ctr);
686                 ZERO_STRUCT(p24);
687
688                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
689
690                 init_sam_user_info24(&p24, (char *)pwbuf,24);
691
692                 ctr.switch_value = 24;
693                 ctr.info.id24 = &p24;
694
695                 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 
696                                                &cli->user_session_key, &ctr);
697
698                 if (!NT_STATUS_IS_OK(result)) {
699                         d_fprintf(stderr, "Failed to set password for user %s - %s\n", 
700                                  acct_name, nt_errstr(result));
701
702                         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
703                                                         &user_pol);
704
705                         if (!NT_STATUS_IS_OK(result)) {
706                                 d_fprintf(stderr, "Failed to delete user %s - %s\n", 
707                                          acct_name, nt_errstr(result));
708                                  return result;
709                         }
710                 }
711
712         }
713  done:
714         if (!NT_STATUS_IS_OK(result)) {
715                 d_fprintf(stderr, "Failed to add user '%s' with %s.\n",
716                           acct_name, nt_errstr(result));
717         } else {
718                 d_printf("Added user '%s'.\n", acct_name);
719         }
720         return result;
721 }
722
723 /** 
724  * Add a new user to a remote RPC server
725  *
726  * @param argc  Standard main() style argc
727  * @param argv  Standard main() style argv.  Initial components are already
728  *              stripped
729  *
730  * @return A shell status integer (0 for success)
731  **/
732
733 static int rpc_user_add(int argc, const char **argv) 
734 {
735         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_add_internals,
736                                argc, argv);
737 }
738
739 /** 
740  * Delete a user from a remote RPC server
741  *
742  * All parameters are provided by the run_rpc_command function, except for
743  * argc, argv which are passes through. 
744  *
745  * @param domain_sid The domain sid acquired from the remote server
746  * @param cli A cli_state connected to the server.
747  * @param mem_ctx Talloc context, destoyed on completion of the function.
748  * @param argc  Standard main() style argc
749  * @param argv  Standard main() style argv.  Initial components are already
750  *              stripped
751  *
752  * @return Normal NTSTATUS return.
753  **/
754
755 static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, 
756                                         const char *domain_name, 
757                                         struct cli_state *cli, 
758                                         struct rpc_pipe_client *pipe_hnd,
759                                         TALLOC_CTX *mem_ctx, 
760                                         int argc,
761                                         const char **argv)
762 {
763         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
764         POLICY_HND connect_pol, domain_pol, user_pol;
765         const char *acct_name;
766
767         if (argc < 1) {
768                 d_printf("User must be specified\n");
769                 rpc_user_usage(argc, argv);
770                 return NT_STATUS_OK;
771         }
772
773         acct_name = argv[0];
774
775         /* Get sam policy and domain handles */
776
777         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
778                                       pipe_hnd->cli->desthost,
779                                       MAXIMUM_ALLOWED_ACCESS,
780                                       &connect_pol);
781
782         if (!NT_STATUS_IS_OK(result)) {
783                 goto done;
784         }
785
786         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
787                                         &connect_pol,
788                                         MAXIMUM_ALLOWED_ACCESS,
789                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
790                                         &domain_pol);
791
792         if (!NT_STATUS_IS_OK(result)) {
793                 goto done;
794         }
795
796         /* Get handle on user */
797
798         {
799                 uint32 *user_rids, num_rids, *name_types;
800                 uint32 flags = 0x000003e8; /* Unknown */
801
802                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
803                                                flags, 1, &acct_name,
804                                                &num_rids, &user_rids,
805                                                &name_types);
806
807                 if (!NT_STATUS_IS_OK(result)) {
808                         goto done;
809                 }
810
811                 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
812                                               &domain_pol,
813                                               MAXIMUM_ALLOWED_ACCESS,
814                                               user_rids[0],
815                                               &user_pol);
816
817                 if (!NT_STATUS_IS_OK(result)) {
818                         goto done;
819                 }
820         }
821
822         /* Delete user */
823
824         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
825                                         &user_pol);
826
827         if (!NT_STATUS_IS_OK(result)) {
828                 goto done;
829         }
830
831  done:
832         if (!NT_STATUS_IS_OK(result)) {
833                 d_fprintf(stderr, "Failed to delete user '%s' with %s.\n",
834                           acct_name, nt_errstr(result));
835         } else {
836                 d_printf("Deleted user '%s'.\n", acct_name);
837         }
838
839         return result;
840 }
841
842 /** 
843  * Rename a user on a remote RPC server
844  *
845  * All parameters are provided by the run_rpc_command function, except for
846  * argc, argv which are passes through. 
847  *
848  * @param domain_sid The domain sid acquired from the remote server
849  * @param cli A cli_state connected to the server.
850  * @param mem_ctx Talloc context, destoyed on completion of the function.
851  * @param argc  Standard main() style argc
852  * @param argv  Standard main() style argv.  Initial components are already
853  *              stripped
854  *
855  * @return Normal NTSTATUS return.
856  **/
857
858 static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid,
859                                         const char *domain_name, 
860                                         struct cli_state *cli,
861                                         struct rpc_pipe_client *pipe_hnd,
862                                         TALLOC_CTX *mem_ctx, 
863                                         int argc,
864                                         const char **argv)
865 {
866         POLICY_HND connect_pol, domain_pol, user_pol;
867         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
868         uint32 info_level = 7;
869         const char *old_name, *new_name;
870         uint32 *user_rid;
871         uint32 flags = 0x000003e8; /* Unknown */
872         uint32 num_rids, *name_types;
873         uint32 num_names = 1;
874         const char **names;
875         SAM_USERINFO_CTR *user_ctr;
876         SAM_USERINFO_CTR ctr;
877         SAM_USER_INFO_7 info7;
878
879         if (argc != 2) {
880                 d_printf("Old and new username must be specified\n");
881                 rpc_user_usage(argc, argv);
882                 return NT_STATUS_OK;
883         }
884
885         old_name = argv[0];
886         new_name = argv[1];
887
888         ZERO_STRUCT(ctr);
889         ZERO_STRUCT(user_ctr);
890
891         /* Get sam policy handle */
892
893         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
894                                       pipe_hnd->cli->desthost,
895                                       MAXIMUM_ALLOWED_ACCESS,
896                                       &connect_pol);
897
898         if (!NT_STATUS_IS_OK(result)) {
899                 goto done;
900         }
901         
902         /* Get domain policy handle */
903
904         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
905                                         &connect_pol,
906                                         MAXIMUM_ALLOWED_ACCESS,
907                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
908                                         &domain_pol);
909         if (!NT_STATUS_IS_OK(result)) {
910                 goto done;
911         }
912
913         if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
914                 result = NT_STATUS_NO_MEMORY;
915                 goto done;
916         }
917         names[0] = old_name;
918         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
919                                        flags, num_names, names,
920                                        &num_rids, &user_rid, &name_types);
921         if (!NT_STATUS_IS_OK(result)) {
922                 goto done;
923         }
924
925         /* Open domain user */
926         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
927                                       &domain_pol,
928                                       MAXIMUM_ALLOWED_ACCESS,
929                                       user_rid[0],
930                                       &user_pol);
931
932         if (!NT_STATUS_IS_OK(result)) {
933                 goto done;
934         }
935
936         /* Query user info */
937         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
938                                          info_level, &user_ctr);
939
940         if (!NT_STATUS_IS_OK(result)) {
941                 goto done;
942         }
943
944         ctr.switch_value = info_level;
945         ctr.info.id7 = &info7;
946
947         init_sam_user_info7(&info7, new_name);
948
949         /* Set new name */
950         result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol,
951                                        info_level, &cli->user_session_key, &ctr);
952
953         if (!NT_STATUS_IS_OK(result)) {
954                 goto done;
955         }
956
957  done:
958         if (!NT_STATUS_IS_OK(result)) {
959                 d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n", old_name, new_name, 
960                          nt_errstr(result));
961         } else {
962                 d_printf("Renamed user from %s to %s\n", old_name, new_name);
963         }
964         return result;
965 }
966
967 /** 
968  * Rename a user on a remote RPC server
969  *
970  * @param argc  Standard main() style argc
971  * @param argv  Standard main() style argv.  Initial components are already
972  *              stripped
973  *
974  * @return A shell status integer (0 for success)
975  **/
976
977 static int rpc_user_rename(int argc, const char **argv) 
978 {
979         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_rename_internals,
980                                argc, argv);
981 }
982
983 /** 
984  * Delete a user from a remote RPC server
985  *
986  * @param argc  Standard main() style argc
987  * @param argv  Standard main() style argv.  Initial components are already
988  *              stripped
989  *
990  * @return A shell status integer (0 for success)
991  **/
992
993 static int rpc_user_delete(int argc, const char **argv) 
994 {
995         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_del_internals,
996                                argc, argv);
997 }
998
999 /** 
1000  * Set a password for a user on a remote RPC server
1001  *
1002  * All parameters are provided by the run_rpc_command function, except for
1003  * argc, argv which are passes through. 
1004  *
1005  * @param domain_sid The domain sid acquired from the remote server
1006  * @param cli A cli_state connected to the server.
1007  * @param mem_ctx Talloc context, destoyed on completion of the function.
1008  * @param argc  Standard main() style argc
1009  * @param argv  Standard main() style argv.  Initial components are already
1010  *              stripped
1011  *
1012  * @return Normal NTSTATUS return.
1013  **/
1014
1015 static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, 
1016                                         const char *domain_name, 
1017                                         struct cli_state *cli, 
1018                                         struct rpc_pipe_client *pipe_hnd,
1019                                         TALLOC_CTX *mem_ctx, 
1020                                         int argc,
1021                                         const char **argv)
1022 {
1023         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1024         POLICY_HND connect_pol, domain_pol, user_pol;
1025         SAM_USERINFO_CTR ctr;
1026         SAM_USER_INFO_24 p24;
1027         uchar pwbuf[516];
1028         const char *user;
1029         const char *new_password;
1030         char *prompt = NULL;
1031
1032         if (argc < 1) {
1033                 d_printf("User must be specified\n");
1034                 rpc_user_usage(argc, argv);
1035                 return NT_STATUS_OK;
1036         }
1037         
1038         user = argv[0];
1039
1040         if (argv[1]) {
1041                 new_password = argv[1];
1042         } else {
1043                 asprintf(&prompt, "Enter new password for %s:", user);
1044                 new_password = getpass(prompt);
1045                 SAFE_FREE(prompt);
1046         }
1047
1048         /* Get sam policy and domain handles */
1049
1050         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1051                                       pipe_hnd->cli->desthost,
1052                                       MAXIMUM_ALLOWED_ACCESS,
1053                                       &connect_pol);
1054
1055         if (!NT_STATUS_IS_OK(result)) {
1056                 goto done;
1057         }
1058
1059         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1060                                         &connect_pol,
1061                                         MAXIMUM_ALLOWED_ACCESS,
1062                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1063                                         &domain_pol);
1064
1065         if (!NT_STATUS_IS_OK(result)) {
1066                 goto done;
1067         }
1068
1069         /* Get handle on user */
1070
1071         {
1072                 uint32 *user_rids, num_rids, *name_types;
1073                 uint32 flags = 0x000003e8; /* Unknown */
1074
1075                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1076                                                flags, 1, &user,
1077                                                &num_rids, &user_rids,
1078                                                &name_types);
1079
1080                 if (!NT_STATUS_IS_OK(result)) {
1081                         goto done;
1082                 }
1083
1084                 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1085                                               &domain_pol,
1086                                               MAXIMUM_ALLOWED_ACCESS,
1087                                               user_rids[0],
1088                                               &user_pol);
1089
1090                 if (!NT_STATUS_IS_OK(result)) {
1091                         goto done;
1092                 }
1093         }
1094
1095         /* Set password on account */
1096
1097         ZERO_STRUCT(ctr);
1098         ZERO_STRUCT(p24);
1099
1100         encode_pw_buffer(pwbuf, new_password, STR_UNICODE);
1101
1102         init_sam_user_info24(&p24, (char *)pwbuf,24);
1103
1104         ctr.switch_value = 24;
1105         ctr.info.id24 = &p24;
1106
1107         result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 
1108                                        &cli->user_session_key, &ctr);
1109
1110         if (!NT_STATUS_IS_OK(result)) {
1111                 goto done;
1112         }
1113
1114         /* Display results */
1115
1116  done:
1117         return result;
1118
1119 }       
1120
1121 /** 
1122  * Set a user's password on a remote RPC server
1123  *
1124  * @param argc  Standard main() style argc
1125  * @param argv  Standard main() style argv.  Initial components are already
1126  *              stripped
1127  *
1128  * @return A shell status integer (0 for success)
1129  **/
1130
1131 static int rpc_user_password(int argc, const char **argv) 
1132 {
1133         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_password_internals,
1134                                argc, argv);
1135 }
1136
1137 /** 
1138  * List user's groups on a remote RPC server
1139  *
1140  * All parameters are provided by the run_rpc_command function, except for
1141  * argc, argv which are passes through. 
1142  *
1143  * @param domain_sid The domain sid acquired from the remote server
1144  * @param cli A cli_state connected to the server.
1145  * @param mem_ctx Talloc context, destoyed on completion of the function.
1146  * @param argc  Standard main() style argc
1147  * @param argv  Standard main() style argv.  Initial components are already
1148  *              stripped
1149  *
1150  * @return Normal NTSTATUS return.
1151  **/
1152
1153 static NTSTATUS rpc_user_info_internals(const DOM_SID *domain_sid,
1154                         const char *domain_name, 
1155                         struct cli_state *cli,
1156                         struct rpc_pipe_client *pipe_hnd,
1157                         TALLOC_CTX *mem_ctx,
1158                         int argc,
1159                         const char **argv)
1160 {
1161         POLICY_HND connect_pol, domain_pol, user_pol;
1162         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1163         uint32 *rids, num_rids, *name_types, num_names;
1164         uint32 flags = 0x000003e8; /* Unknown */
1165         int i;
1166         char **names;
1167         DOM_GID *user_gids;
1168
1169         if (argc < 1) {
1170                 d_printf("User must be specified\n");
1171                 rpc_user_usage(argc, argv);
1172                 return NT_STATUS_OK;
1173         }
1174         /* Get sam policy handle */
1175
1176         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1177                                       pipe_hnd->cli->desthost,
1178                                       MAXIMUM_ALLOWED_ACCESS,
1179                                       &connect_pol);
1180         if (!NT_STATUS_IS_OK(result)) goto done;
1181         
1182         /* Get domain policy handle */
1183
1184         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1185                                         &connect_pol,
1186                                         MAXIMUM_ALLOWED_ACCESS,
1187                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1188                                         &domain_pol);
1189         if (!NT_STATUS_IS_OK(result)) goto done;
1190
1191         /* Get handle on user */
1192
1193         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1194                                        flags, 1, &argv[0],
1195                                        &num_rids, &rids, &name_types);
1196
1197         if (!NT_STATUS_IS_OK(result)) goto done;
1198
1199         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1200                                       &domain_pol,
1201                                       MAXIMUM_ALLOWED_ACCESS,
1202                                       rids[0],
1203                                       &user_pol);
1204         if (!NT_STATUS_IS_OK(result)) goto done;
1205
1206         result = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, &user_pol,
1207                                            &num_rids, &user_gids);
1208
1209         if (!NT_STATUS_IS_OK(result)) goto done;
1210
1211         /* Look up rids */
1212
1213         if (num_rids) {
1214                 if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1215                         result = NT_STATUS_NO_MEMORY;
1216                         goto done;
1217                 }
1218
1219                 for (i = 0; i < num_rids; i++)
1220                         rids[i] = user_gids[i].g_rid;
1221
1222                 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, &domain_pol,
1223                                               num_rids, rids,
1224                                               &num_names, &names, &name_types);
1225
1226                 if (!NT_STATUS_IS_OK(result)) {
1227                         goto done;
1228                 }
1229
1230                 /* Display results */
1231
1232                 for (i = 0; i < num_names; i++)
1233                         printf("%s\n", names[i]);
1234         }
1235  done:
1236         return result;
1237 }
1238
1239 /** 
1240  * List a user's groups from a remote RPC server
1241  *
1242  * @param argc  Standard main() style argc
1243  * @param argv  Standard main() style argv.  Initial components are already
1244  *              stripped
1245  *
1246  * @return A shell status integer (0 for success)
1247  **/
1248
1249 static int rpc_user_info(int argc, const char **argv) 
1250 {
1251         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_info_internals,
1252                                argc, argv);
1253 }
1254
1255 /** 
1256  * List users on a remote RPC server
1257  *
1258  * All parameters are provided by the run_rpc_command function, except for
1259  * argc, argv which are passes through. 
1260  *
1261  * @param domain_sid The domain sid acquired from the remote server
1262  * @param cli A cli_state connected to the server.
1263  * @param mem_ctx Talloc context, destoyed on completion of the function.
1264  * @param argc  Standard main() style argc
1265  * @param argv  Standard main() style argv.  Initial components are already
1266  *              stripped
1267  *
1268  * @return Normal NTSTATUS return.
1269  **/
1270
1271 static NTSTATUS rpc_user_list_internals(const DOM_SID *domain_sid,
1272                                         const char *domain_name, 
1273                                         struct cli_state *cli,
1274                                         struct rpc_pipe_client *pipe_hnd,
1275                                         TALLOC_CTX *mem_ctx,
1276                                         int argc,
1277                                         const char **argv)
1278 {
1279         POLICY_HND connect_pol, domain_pol;
1280         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1281         uint32 start_idx=0, num_entries, i, loop_count = 0;
1282         SAM_DISPINFO_CTR ctr;
1283         SAM_DISPINFO_1 info1;
1284
1285         /* Get sam policy handle */
1286
1287         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1288                                       pipe_hnd->cli->desthost,
1289                                       MAXIMUM_ALLOWED_ACCESS,
1290                                       &connect_pol);
1291         if (!NT_STATUS_IS_OK(result)) {
1292                 goto done;
1293         }
1294         
1295         /* Get domain policy handle */
1296
1297         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1298                                         &connect_pol,
1299                                         MAXIMUM_ALLOWED_ACCESS,
1300                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1301                                         &domain_pol);
1302         if (!NT_STATUS_IS_OK(result)) {
1303                 goto done;
1304         }
1305
1306         /* Query domain users */
1307         ZERO_STRUCT(ctr);
1308         ZERO_STRUCT(info1);
1309         ctr.sam.info1 = &info1;
1310         if (opt_long_list_entries)
1311                 d_printf("\nUser name             Comment"\
1312                          "\n-----------------------------\n");
1313         do {
1314                 fstring user, desc;
1315                 uint32 max_entries, max_size;
1316
1317                 get_query_dispinfo_params(
1318                         loop_count, &max_entries, &max_size);
1319
1320                 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
1321                                                  &start_idx, 1, &num_entries,
1322                                                  max_entries, max_size, &ctr);
1323                 loop_count++;
1324
1325                 for (i = 0; i < num_entries; i++) {
1326                         unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user));
1327                         if (opt_long_list_entries) 
1328                                 unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc));
1329                         
1330                         if (opt_long_list_entries)
1331                                 printf("%-21.21s %s\n", user, desc);
1332                         else
1333                                 printf("%s\n", user);
1334                 }
1335         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1336
1337  done:
1338         return result;
1339 }
1340
1341 /** 
1342  * 'net rpc user' entrypoint.
1343  * @param argc  Standard main() style argc
1344  * @param argc  Standard main() style argv.  Initial components are already
1345  *              stripped
1346  **/
1347
1348 int net_rpc_user(int argc, const char **argv) 
1349 {
1350         struct functable func[] = {
1351                 {"add", rpc_user_add},
1352                 {"info", rpc_user_info},
1353                 {"delete", rpc_user_delete},
1354                 {"password", rpc_user_password},
1355                 {"rename", rpc_user_rename},
1356                 {NULL, NULL}
1357         };
1358         
1359         if (argc == 0) {
1360                 return run_rpc_command(NULL,PI_SAMR, 0, 
1361                                        rpc_user_list_internals,
1362                                        argc, argv);
1363         }
1364
1365         return net_run_function(argc, argv, func, rpc_user_usage);
1366 }
1367
1368 static NTSTATUS rpc_sh_user_list(TALLOC_CTX *mem_ctx,
1369                                  struct rpc_sh_ctx *ctx,
1370                                  struct rpc_pipe_client *pipe_hnd,
1371                                  int argc, const char **argv)
1372 {
1373         return rpc_user_list_internals(ctx->domain_sid, ctx->domain_name,
1374                                        ctx->cli, pipe_hnd, mem_ctx,
1375                                        argc, argv);
1376 }
1377
1378 static NTSTATUS rpc_sh_user_info(TALLOC_CTX *mem_ctx,
1379                                  struct rpc_sh_ctx *ctx,
1380                                  struct rpc_pipe_client *pipe_hnd,
1381                                  int argc, const char **argv)
1382 {
1383         return rpc_user_info_internals(ctx->domain_sid, ctx->domain_name,
1384                                        ctx->cli, pipe_hnd, mem_ctx,
1385                                        argc, argv);
1386 }
1387
1388 static NTSTATUS rpc_sh_handle_user(TALLOC_CTX *mem_ctx,
1389                                    struct rpc_sh_ctx *ctx,
1390                                    struct rpc_pipe_client *pipe_hnd,
1391                                    int argc, const char **argv,
1392                                    NTSTATUS (*fn)(
1393                                            TALLOC_CTX *mem_ctx,
1394                                            struct rpc_sh_ctx *ctx,
1395                                            struct rpc_pipe_client *pipe_hnd,
1396                                            const POLICY_HND *user_hnd,
1397                                            int argc, const char **argv))
1398                                            
1399 {
1400         POLICY_HND connect_pol, domain_pol, user_pol;
1401         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1402         DOM_SID sid;
1403         uint32 rid;
1404         enum lsa_SidType type;
1405
1406         if (argc == 0) {
1407                 d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
1408                 return NT_STATUS_INVALID_PARAMETER;
1409         }
1410
1411         ZERO_STRUCT(connect_pol);
1412         ZERO_STRUCT(domain_pol);
1413         ZERO_STRUCT(user_pol);
1414
1415         result = net_rpc_lookup_name(mem_ctx, pipe_hnd->cli, argv[0],
1416                                      NULL, NULL, &sid, &type);
1417         if (!NT_STATUS_IS_OK(result)) {
1418                 d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
1419                           nt_errstr(result));
1420                 goto done;
1421         }
1422
1423         if (type != SID_NAME_USER) {
1424                 d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
1425                           sid_type_lookup(type));
1426                 result = NT_STATUS_NO_SUCH_USER;
1427                 goto done;
1428         }
1429
1430         if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1431                 d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
1432                 result = NT_STATUS_NO_SUCH_USER;
1433                 goto done;
1434         }
1435
1436         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1437                                       pipe_hnd->cli->desthost,
1438                                       MAXIMUM_ALLOWED_ACCESS,
1439                                       &connect_pol);
1440         if (!NT_STATUS_IS_OK(result)) {
1441                 goto done;
1442         }
1443
1444         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1445                                         &connect_pol,
1446                                         MAXIMUM_ALLOWED_ACCESS,
1447                                         ctx->domain_sid,
1448                                         &domain_pol);
1449         if (!NT_STATUS_IS_OK(result)) {
1450                 goto done;
1451         }
1452
1453         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1454                                       &domain_pol,
1455                                       MAXIMUM_ALLOWED_ACCESS,
1456                                       rid,
1457                                       &user_pol);
1458         if (!NT_STATUS_IS_OK(result)) {
1459                 goto done;
1460         }
1461
1462         result = fn(mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1463
1464  done:
1465         if (is_valid_policy_hnd(&user_pol)) {
1466                 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1467         }
1468         if (is_valid_policy_hnd(&domain_pol)) {
1469                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
1470         }
1471         if (is_valid_policy_hnd(&connect_pol)) {
1472                 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1473         }
1474         return result;
1475 }
1476
1477 static NTSTATUS rpc_sh_user_show_internals(TALLOC_CTX *mem_ctx,
1478                                            struct rpc_sh_ctx *ctx,
1479                                            struct rpc_pipe_client *pipe_hnd,
1480                                            const POLICY_HND *user_hnd,
1481                                            int argc, const char **argv)
1482 {
1483         NTSTATUS result;
1484         SAM_USERINFO_CTR *ctr;
1485         SAM_USER_INFO_21 *info;
1486
1487         if (argc != 0) {
1488                 d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
1489                 return NT_STATUS_INVALID_PARAMETER;
1490         }
1491
1492         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1493                                             21, &ctr);
1494         if (!NT_STATUS_IS_OK(result)) {
1495                 return result;
1496         }
1497
1498         info = ctr->info.id21;
1499
1500         d_printf("user rid: %d, group rid: %d\n", info->user_rid,
1501                  info->group_rid);
1502
1503         return result;
1504 }
1505
1506 static NTSTATUS rpc_sh_user_show(TALLOC_CTX *mem_ctx,
1507                                  struct rpc_sh_ctx *ctx,
1508                                  struct rpc_pipe_client *pipe_hnd,
1509                                  int argc, const char **argv)
1510 {
1511         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1512                                   rpc_sh_user_show_internals);
1513 }
1514
1515 #define FETCHSTR(name, rec) \
1516 do { if (strequal(ctx->thiscmd, name)) { \
1517         oldval = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_##rec); } \
1518 } while (0);
1519
1520 #define SETSTR(name, rec, flag) \
1521 do { if (strequal(ctx->thiscmd, name)) { \
1522         init_unistr2(&usr->uni_##rec, argv[0], UNI_STR_TERMINATE); \
1523         init_uni_hdr(&usr->hdr_##rec, &usr->uni_##rec); \
1524         usr->fields_present |= ACCT_##flag; } \
1525 } while (0);
1526
1527 static NTSTATUS rpc_sh_user_str_edit_internals(TALLOC_CTX *mem_ctx,
1528                                                struct rpc_sh_ctx *ctx,
1529                                                struct rpc_pipe_client *pipe_hnd,
1530                                                const POLICY_HND *user_hnd,
1531                                                int argc, const char **argv)
1532 {
1533         NTSTATUS result;
1534         SAM_USERINFO_CTR *ctr;
1535         SAM_USER_INFO_21 *usr;
1536         const char *username;
1537         const char *oldval = "";
1538
1539         if (argc > 1) {
1540                 d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
1541                           ctx->whoami);
1542                 return NT_STATUS_INVALID_PARAMETER;
1543         }
1544
1545         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1546                                             21, &ctr);
1547         if (!NT_STATUS_IS_OK(result)) {
1548                 return result;
1549         }
1550
1551         usr = ctr->info.id21;
1552
1553         username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
1554
1555         FETCHSTR("fullname", full_name);
1556         FETCHSTR("homedir", home_dir);
1557         FETCHSTR("homedrive", dir_drive);
1558         FETCHSTR("logonscript", logon_script);
1559         FETCHSTR("profilepath", profile_path);
1560         FETCHSTR("description", acct_desc);
1561
1562         if (argc == 0) {
1563                 d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
1564                 goto done;
1565         }
1566
1567         ZERO_STRUCTP(usr);
1568
1569         if (strcmp(argv[0], "NULL") == 0) {
1570                 argv[0] = "";
1571         }
1572
1573         SETSTR("fullname", full_name, FULL_NAME);
1574         SETSTR("homedir", home_dir, HOME_DIR);
1575         SETSTR("homedrive", dir_drive, HOME_DRIVE);
1576         SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1577         SETSTR("profilepath", profile_path, PROFILE);
1578         SETSTR("description", acct_desc, DESCRIPTION);
1579
1580         result = rpccli_samr_set_userinfo2(
1581                 pipe_hnd, mem_ctx, user_hnd, 21,
1582                 &pipe_hnd->cli->user_session_key, ctr);
1583
1584         d_printf("Set %s's %s from [%s] to [%s]\n", username,
1585                  ctx->thiscmd, oldval, argv[0]);
1586
1587  done:
1588
1589         return result;
1590 }
1591
1592 #define HANDLEFLG(name, rec) \
1593 do { if (strequal(ctx->thiscmd, name)) { \
1594         oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1595         if (newval) { \
1596                 newflags = oldflags | ACB_##rec; \
1597         } else { \
1598                 newflags = oldflags & ~ACB_##rec; \
1599         } } } while (0);
1600
1601 static NTSTATUS rpc_sh_user_str_edit(TALLOC_CTX *mem_ctx,
1602                                      struct rpc_sh_ctx *ctx,
1603                                      struct rpc_pipe_client *pipe_hnd,
1604                                      int argc, const char **argv)
1605 {
1606         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1607                                   rpc_sh_user_str_edit_internals);
1608 }
1609
1610 static NTSTATUS rpc_sh_user_flag_edit_internals(TALLOC_CTX *mem_ctx,
1611                                                 struct rpc_sh_ctx *ctx,
1612                                                 struct rpc_pipe_client *pipe_hnd,
1613                                                 const POLICY_HND *user_hnd,
1614                                                 int argc, const char **argv)
1615 {
1616         NTSTATUS result;
1617         SAM_USERINFO_CTR *ctr;
1618         SAM_USER_INFO_21 *usr;
1619         const char *username;
1620         const char *oldval = "unknown";
1621         uint32 oldflags, newflags;
1622         bool newval;
1623
1624         if ((argc > 1) ||
1625             ((argc == 1) && !strequal(argv[0], "yes") &&
1626              !strequal(argv[0], "no"))) {
1627                 d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
1628                           ctx->whoami);
1629                 return NT_STATUS_INVALID_PARAMETER;
1630         }
1631
1632         newval = strequal(argv[0], "yes");
1633
1634         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1635                                             21, &ctr);
1636         if (!NT_STATUS_IS_OK(result)) {
1637                 return result;
1638         }
1639
1640         usr = ctr->info.id21;
1641
1642         username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
1643         oldflags = usr->acb_info;
1644         newflags = usr->acb_info;
1645
1646         HANDLEFLG("disabled", DISABLED);
1647         HANDLEFLG("pwnotreq", PWNOTREQ);
1648         HANDLEFLG("autolock", AUTOLOCK);
1649         HANDLEFLG("pwnoexp", PWNOEXP);
1650
1651         if (argc == 0) {
1652                 d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
1653                 goto done;
1654         }
1655
1656         ZERO_STRUCTP(usr);
1657
1658         usr->acb_info = newflags;
1659         usr->fields_present = ACCT_FLAGS;
1660
1661         result = rpccli_samr_set_userinfo2(
1662                 pipe_hnd, mem_ctx, user_hnd, 21,
1663                 &pipe_hnd->cli->user_session_key, ctr);
1664
1665         if (NT_STATUS_IS_OK(result)) {
1666                 d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
1667                          ctx->thiscmd, oldval, argv[0]);
1668         }
1669
1670  done:
1671
1672         return result;
1673 }
1674
1675 static NTSTATUS rpc_sh_user_flag_edit(TALLOC_CTX *mem_ctx,
1676                                       struct rpc_sh_ctx *ctx,
1677                                       struct rpc_pipe_client *pipe_hnd,
1678                                       int argc, const char **argv)
1679 {
1680         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1681                                   rpc_sh_user_flag_edit_internals);
1682 }
1683
1684 struct rpc_sh_cmd *net_rpc_user_edit_cmds(TALLOC_CTX *mem_ctx,
1685                                           struct rpc_sh_ctx *ctx)
1686 {
1687         static struct rpc_sh_cmd cmds[] = {
1688
1689                 { "fullname", NULL, PI_SAMR, rpc_sh_user_str_edit,
1690                   "Show/Set a user's full name" },
1691
1692                 { "homedir", NULL, PI_SAMR, rpc_sh_user_str_edit,
1693                   "Show/Set a user's home directory" },
1694
1695                 { "homedrive", NULL, PI_SAMR, rpc_sh_user_str_edit,
1696                   "Show/Set a user's home drive" },
1697
1698                 { "logonscript", NULL, PI_SAMR, rpc_sh_user_str_edit,
1699                   "Show/Set a user's logon script" },
1700
1701                 { "profilepath", NULL, PI_SAMR, rpc_sh_user_str_edit,
1702                   "Show/Set a user's profile path" },
1703
1704                 { "description", NULL, PI_SAMR, rpc_sh_user_str_edit,
1705                   "Show/Set a user's description" },
1706
1707                 { "disabled", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1708                   "Show/Set whether a user is disabled" },
1709
1710                 { "autolock", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1711                   "Show/Set whether a user locked out" },
1712
1713                 { "pwnotreq", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1714                   "Show/Set whether a user does not need a password" },
1715
1716                 { "pwnoexp", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1717                   "Show/Set whether a user's password does not expire" },
1718
1719                 { NULL, NULL, 0, NULL, NULL }
1720         };
1721
1722         return cmds;
1723 }
1724
1725 struct rpc_sh_cmd *net_rpc_user_cmds(TALLOC_CTX *mem_ctx,
1726                                      struct rpc_sh_ctx *ctx)
1727 {
1728         static struct rpc_sh_cmd cmds[] = {
1729
1730                 { "list", NULL, PI_SAMR, rpc_sh_user_list,
1731                   "List available users" },
1732
1733                 { "info", NULL, PI_SAMR, rpc_sh_user_info,
1734                   "List the domain groups a user is member of" },
1735
1736                 { "show", NULL, PI_SAMR, rpc_sh_user_show,
1737                   "Show info about a user" },
1738
1739                 { "edit", net_rpc_user_edit_cmds, 0, NULL, 
1740                   "Show/Modify a user's fields" },
1741
1742                 { NULL, NULL, 0, NULL, NULL }
1743         };
1744
1745         return cmds;
1746 }
1747
1748 /****************************************************************************/
1749
1750 /**
1751  * Basic usage function for 'net rpc group'
1752  * @param argc  Standard main() style argc.
1753  * @param argv  Standard main() style argv.  Initial components are already
1754  *              stripped.
1755  **/
1756
1757 static int rpc_group_usage(int argc, const char **argv)
1758 {
1759         return net_help_group(argc, argv);
1760 }
1761
1762 /**
1763  * Delete group on a remote RPC server
1764  *
1765  * All parameters are provided by the run_rpc_command function, except for
1766  * argc, argv which are passes through.
1767  *
1768  * @param domain_sid The domain sid acquired from the remote server
1769  * @param cli A cli_state connected to the server.
1770  * @param mem_ctx Talloc context, destoyed on completion of the function.
1771  * @param argc  Standard main() style argc
1772  * @param argv  Standard main() style argv.  Initial components are already
1773  *              stripped
1774  *
1775  * @return Normal NTSTATUS return.
1776  **/
1777                                                                                                              
1778 static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
1779                                         const char *domain_name,
1780                                         struct cli_state *cli,
1781                                         struct rpc_pipe_client *pipe_hnd,
1782                                         TALLOC_CTX *mem_ctx,
1783                                         int argc,
1784                                         const char **argv)
1785 {
1786         POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
1787         bool group_is_primary = False;
1788         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1789
1790         uint32 *group_rids, num_rids, *name_types, num_members, 
1791                *group_attrs, group_rid;
1792         uint32 flags = 0x000003e8; /* Unknown */
1793         /* char **names; */
1794         int i;
1795         /* DOM_GID *user_gids; */
1796         SAM_USERINFO_CTR *user_ctr;
1797         fstring temp;
1798
1799         if (argc < 1) {
1800                 d_printf("specify group\n");
1801                 rpc_group_usage(argc,argv);
1802                 return NT_STATUS_OK; /* ok? */
1803         }
1804
1805         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1806                                       pipe_hnd->cli->desthost,
1807                                       MAXIMUM_ALLOWED_ACCESS,
1808                                       &connect_pol);
1809
1810         if (!NT_STATUS_IS_OK(result)) {
1811                 d_fprintf(stderr, "Request samr_Connect2 failed\n");
1812                 goto done;
1813         }
1814
1815         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1816                                         &connect_pol,
1817                                         MAXIMUM_ALLOWED_ACCESS,
1818                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1819                                         &domain_pol);
1820
1821         if (!NT_STATUS_IS_OK(result)) {
1822                 d_fprintf(stderr, "Request open_domain failed\n");
1823                 goto done;
1824         }
1825         
1826         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1827                                        flags, 1, &argv[0],
1828                                        &num_rids, &group_rids,
1829                                        &name_types);
1830
1831         if (!NT_STATUS_IS_OK(result)) {
1832                 d_fprintf(stderr, "Lookup of '%s' failed\n",argv[0]);
1833                 goto done;
1834         }
1835
1836         switch (name_types[0])
1837         {
1838         case SID_NAME_DOM_GRP:
1839                 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1840                                                &domain_pol,
1841                                                MAXIMUM_ALLOWED_ACCESS,
1842                                                group_rids[0],
1843                                                &group_pol);
1844                 if (!NT_STATUS_IS_OK(result)) {
1845                         d_fprintf(stderr, "Request open_group failed");
1846                         goto done;
1847                 }
1848                 
1849                 group_rid = group_rids[0];
1850                 
1851                 result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
1852                                  &num_members, &group_rids,
1853                                  &group_attrs);
1854                 
1855                 if (!NT_STATUS_IS_OK(result)) {
1856                         d_fprintf(stderr, "Unable to query group members of %s",argv[0]);
1857                         goto done;
1858                 }
1859                 
1860                 if (opt_verbose) {
1861                         d_printf("Domain Group %s (rid: %d) has %d members\n",
1862                                 argv[0],group_rid,num_members);
1863                 }
1864
1865                 /* Check if group is anyone's primary group */
1866                 for (i = 0; i < num_members; i++)
1867                 {
1868                         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1869                                                       &domain_pol,
1870                                                       MAXIMUM_ALLOWED_ACCESS,
1871                                                       group_rids[i],
1872                                                       &user_pol);
1873         
1874                         if (!NT_STATUS_IS_OK(result)) {
1875                                 d_fprintf(stderr, "Unable to open group member %d\n",group_rids[i]);
1876                                 goto done;
1877                         }
1878         
1879                         ZERO_STRUCT(user_ctr);
1880
1881                         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
1882                                                          21, &user_ctr);
1883         
1884                         if (!NT_STATUS_IS_OK(result)) {
1885                                 d_fprintf(stderr, "Unable to lookup userinfo for group member %d\n",group_rids[i]);
1886                                 goto done;
1887                         }
1888         
1889                         if (user_ctr->info.id21->group_rid == group_rid) {
1890                                 unistr2_to_ascii(temp, &(user_ctr->info.id21)->uni_user_name, 
1891                                                 sizeof(temp));
1892                                 if (opt_verbose) 
1893                                         d_printf("Group is primary group of %s\n",temp);
1894                                 group_is_primary = True;
1895                         }
1896
1897                         rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1898                 }
1899                 
1900                 if (group_is_primary) {
1901                         d_fprintf(stderr, "Unable to delete group because some "
1902                                  "of it's members have it as primary group\n");
1903                         result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1904                         goto done;
1905                 }
1906      
1907                 /* remove all group members */
1908                 for (i = 0; i < num_members; i++)
1909                 {
1910                         if (opt_verbose) 
1911                                 d_printf("Remove group member %d...",group_rids[i]);
1912                         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1913                                                                &group_pol,
1914                                                                group_rids[i]);
1915
1916                         if (NT_STATUS_IS_OK(result)) {
1917                                 if (opt_verbose)
1918                                         d_printf("ok\n");
1919                         } else {
1920                                 if (opt_verbose)
1921                                         d_printf("failed\n");
1922                                 goto done;
1923                         }       
1924                 }
1925
1926                 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1927                                                        &group_pol);
1928
1929                 break;
1930         /* removing a local group is easier... */
1931         case SID_NAME_ALIAS:
1932                 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1933                                                &domain_pol,
1934                                                MAXIMUM_ALLOWED_ACCESS,
1935                                                group_rids[0],
1936                                                &group_pol);
1937
1938                 if (!NT_STATUS_IS_OK(result)) {
1939                         d_fprintf(stderr, "Request open_alias failed\n");
1940                         goto done;
1941                 }
1942
1943                 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1944                                                     &group_pol);
1945                 break;
1946         default:
1947                 d_fprintf(stderr, "%s is of type %s. This command is only for deleting local or global groups\n",
1948                         argv[0],sid_type_lookup(name_types[0]));
1949                 result = NT_STATUS_UNSUCCESSFUL;
1950                 goto done;
1951         }
1952          
1953         
1954         if (NT_STATUS_IS_OK(result)) {
1955                 if (opt_verbose)
1956                         d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types[0]),argv[0]);
1957         } else {
1958                 d_fprintf(stderr, "Deleting of %s failed: %s\n",argv[0],
1959                         get_friendly_nt_error_msg(result));
1960         }
1961         
1962  done:
1963         return result;  
1964         
1965 }
1966
1967 static int rpc_group_delete(int argc, const char **argv)
1968 {
1969         return run_rpc_command(NULL, PI_SAMR, 0, rpc_group_delete_internals,
1970                                argc,argv);
1971 }
1972
1973 static NTSTATUS rpc_group_add_internals(const DOM_SID *domain_sid,
1974                                         const char *domain_name, 
1975                                         struct cli_state *cli,
1976                                         struct rpc_pipe_client *pipe_hnd,
1977                                         TALLOC_CTX *mem_ctx,
1978                                         int argc,
1979                                         const char **argv)
1980 {
1981         POLICY_HND connect_pol, domain_pol, group_pol;
1982         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1983         GROUP_INFO_CTR group_info;
1984         struct lsa_String grp_name;
1985         uint32_t rid = 0;
1986
1987         if (argc != 1) {
1988                 d_printf("Group name must be specified\n");
1989                 rpc_group_usage(argc, argv);
1990                 return NT_STATUS_OK;
1991         }
1992
1993         init_lsa_String(&grp_name, argv[0]);
1994
1995         /* Get sam policy handle */
1996
1997         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1998                                       pipe_hnd->cli->desthost,
1999                                       MAXIMUM_ALLOWED_ACCESS,
2000                                       &connect_pol);
2001         if (!NT_STATUS_IS_OK(result)) goto done;
2002         
2003         /* Get domain policy handle */
2004
2005         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2006                                         &connect_pol,
2007                                         MAXIMUM_ALLOWED_ACCESS,
2008                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2009                                         &domain_pol);
2010         if (!NT_STATUS_IS_OK(result)) goto done;
2011
2012         /* Create the group */
2013
2014         result = rpccli_samr_CreateDomainGroup(pipe_hnd, mem_ctx,
2015                                                &domain_pol,
2016                                                &grp_name,
2017                                                MAXIMUM_ALLOWED_ACCESS,
2018                                                &group_pol,
2019                                                &rid);
2020         if (!NT_STATUS_IS_OK(result)) goto done;
2021
2022         if (strlen(opt_comment) == 0) goto done;
2023
2024         /* We've got a comment to set */
2025
2026         group_info.switch_value1 = 4;
2027         init_samr_group_info4(&group_info.group.info4, opt_comment);
2028
2029         result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &group_info);
2030         if (!NT_STATUS_IS_OK(result)) goto done;
2031         
2032  done:
2033         if (NT_STATUS_IS_OK(result))
2034                 DEBUG(5, ("add group succeeded\n"));
2035         else
2036                 d_fprintf(stderr, "add group failed: %s\n", nt_errstr(result));
2037
2038         return result;
2039 }
2040
2041 static NTSTATUS rpc_alias_add_internals(const DOM_SID *domain_sid,
2042                                         const char *domain_name, 
2043                                         struct cli_state *cli,
2044                                         struct rpc_pipe_client *pipe_hnd,
2045                                         TALLOC_CTX *mem_ctx,
2046                                         int argc,
2047                                         const char **argv)
2048 {
2049         POLICY_HND connect_pol, domain_pol, alias_pol;
2050         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2051         ALIAS_INFO_CTR alias_info;
2052         struct lsa_String alias_name;
2053         uint32_t rid = 0;
2054
2055         if (argc != 1) {
2056                 d_printf("Alias name must be specified\n");
2057                 rpc_group_usage(argc, argv);
2058                 return NT_STATUS_OK;
2059         }
2060
2061         init_lsa_String(&alias_name, argv[0]);
2062
2063         /* Get sam policy handle */
2064
2065         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2066                                       pipe_hnd->cli->desthost,
2067                                       MAXIMUM_ALLOWED_ACCESS,
2068                                       &connect_pol);
2069         if (!NT_STATUS_IS_OK(result)) goto done;
2070         
2071         /* Get domain policy handle */
2072
2073         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2074                                         &connect_pol,
2075                                         MAXIMUM_ALLOWED_ACCESS,
2076                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2077                                         &domain_pol);
2078         if (!NT_STATUS_IS_OK(result)) goto done;
2079
2080         /* Create the group */
2081
2082         result = rpccli_samr_CreateDomAlias(pipe_hnd, mem_ctx,
2083                                             &domain_pol,
2084                                             &alias_name,
2085                                             MAXIMUM_ALLOWED_ACCESS,
2086                                             &alias_pol,
2087                                             &rid);
2088         if (!NT_STATUS_IS_OK(result)) goto done;
2089
2090         if (strlen(opt_comment) == 0) goto done;
2091
2092         /* We've got a comment to set */
2093
2094         alias_info.level = 3;
2095         init_samr_alias_info3(&alias_info.alias.info3, opt_comment);
2096
2097         result = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, &alias_pol, &alias_info);
2098         if (!NT_STATUS_IS_OK(result)) goto done;
2099         
2100  done:
2101         if (NT_STATUS_IS_OK(result))
2102                 DEBUG(5, ("add alias succeeded\n"));
2103         else
2104                 d_fprintf(stderr, "add alias failed: %s\n", nt_errstr(result));
2105
2106         return result;
2107 }
2108
2109 static int rpc_group_add(int argc, const char **argv)
2110 {
2111         if (opt_localgroup)
2112                 return run_rpc_command(NULL, PI_SAMR, 0,
2113                                        rpc_alias_add_internals,
2114                                        argc, argv);
2115
2116         return run_rpc_command(NULL, PI_SAMR, 0,
2117                                rpc_group_add_internals,
2118                                argc, argv);
2119 }
2120
2121 static NTSTATUS get_sid_from_name(struct cli_state *cli,
2122                                 TALLOC_CTX *mem_ctx,
2123                                 const char *name,
2124                                 DOM_SID *sid,
2125                                 enum lsa_SidType *type)
2126 {
2127         DOM_SID *sids = NULL;
2128         enum lsa_SidType *types = NULL;
2129         struct rpc_pipe_client *pipe_hnd;
2130         POLICY_HND lsa_pol;
2131         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2132
2133         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
2134         if (!pipe_hnd) {
2135                 goto done;
2136         }
2137
2138         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False,
2139                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2140
2141         if (!NT_STATUS_IS_OK(result)) {
2142                 goto done;
2143         }
2144
2145         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2146                                       &name, NULL, 1, &sids, &types);
2147
2148         if (NT_STATUS_IS_OK(result)) {
2149                 sid_copy(sid, &sids[0]);
2150                 *type = types[0];
2151         }
2152
2153         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
2154
2155  done:
2156         if (pipe_hnd) {
2157                 cli_rpc_pipe_close(pipe_hnd);
2158         }
2159
2160         if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
2161
2162                 /* Try as S-1-5-whatever */
2163
2164                 DOM_SID tmp_sid;
2165
2166                 if (string_to_sid(&tmp_sid, name)) {
2167                         sid_copy(sid, &tmp_sid);
2168                         *type = SID_NAME_UNKNOWN;
2169                         result = NT_STATUS_OK;
2170                 }
2171         }
2172
2173         return result;
2174 }
2175
2176 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2177                                 TALLOC_CTX *mem_ctx,
2178                                 const DOM_SID *group_sid,
2179                                 const char *member)
2180 {
2181         POLICY_HND connect_pol, domain_pol;
2182         NTSTATUS result;
2183         uint32 group_rid;
2184         POLICY_HND group_pol;
2185
2186         uint32 num_rids;
2187         uint32 *rids = NULL;
2188         uint32 *rid_types = NULL;
2189
2190         DOM_SID sid;
2191
2192         sid_copy(&sid, group_sid);
2193
2194         if (!sid_split_rid(&sid, &group_rid)) {
2195                 return NT_STATUS_UNSUCCESSFUL;
2196         }
2197
2198         /* Get sam policy handle */
2199         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2200                                       pipe_hnd->cli->desthost,
2201                                       MAXIMUM_ALLOWED_ACCESS,
2202                                       &connect_pol);
2203         if (!NT_STATUS_IS_OK(result)) {
2204                 return result;
2205         }
2206
2207         /* Get domain policy handle */
2208         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2209                                         &connect_pol,
2210                                         MAXIMUM_ALLOWED_ACCESS,
2211                                         &sid,
2212                                         &domain_pol);
2213         if (!NT_STATUS_IS_OK(result)) {
2214                 return result;
2215         }
2216
2217         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2218                                        1, &member,
2219                                        &num_rids, &rids, &rid_types);
2220
2221         if (!NT_STATUS_IS_OK(result)) {
2222                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2223                 goto done;
2224         }
2225
2226         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2227                                        &domain_pol,
2228                                        MAXIMUM_ALLOWED_ACCESS,
2229                                        group_rid,
2230                                        &group_pol);
2231
2232         if (!NT_STATUS_IS_OK(result)) {
2233                 goto done;
2234         }
2235
2236         result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
2237                                             &group_pol,
2238                                             rids[0],
2239                                             0x0005); /* unknown flags */
2240
2241  done:
2242         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2243         return result;
2244 }
2245
2246 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2247                                 TALLOC_CTX *mem_ctx,
2248                                 const DOM_SID *alias_sid,
2249                                 const char *member)
2250 {
2251         POLICY_HND connect_pol, domain_pol;
2252         NTSTATUS result;
2253         uint32 alias_rid;
2254         POLICY_HND alias_pol;
2255
2256         DOM_SID member_sid;
2257         enum lsa_SidType member_type;
2258
2259         DOM_SID sid;
2260
2261         sid_copy(&sid, alias_sid);
2262
2263         if (!sid_split_rid(&sid, &alias_rid)) {
2264                 return NT_STATUS_UNSUCCESSFUL;
2265         }
2266
2267         result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
2268                                    &member_sid, &member_type);
2269
2270         if (!NT_STATUS_IS_OK(result)) {
2271                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2272                 return result;
2273         }
2274
2275         /* Get sam policy handle */
2276         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2277                                       pipe_hnd->cli->desthost,
2278                                       MAXIMUM_ALLOWED_ACCESS,
2279                                       &connect_pol);
2280         if (!NT_STATUS_IS_OK(result)) {
2281                 goto done;
2282         }
2283
2284         /* Get domain policy handle */
2285         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2286                                         &connect_pol,
2287                                         MAXIMUM_ALLOWED_ACCESS,
2288                                         &sid,
2289                                         &domain_pol);
2290         if (!NT_STATUS_IS_OK(result)) {
2291                 goto done;
2292         }
2293
2294         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2295                                        &domain_pol,
2296                                        MAXIMUM_ALLOWED_ACCESS,
2297                                        alias_rid,
2298                                        &alias_pol);
2299
2300         if (!NT_STATUS_IS_OK(result)) {
2301                 return result;
2302         }
2303
2304         result = rpccli_samr_add_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
2305
2306         if (!NT_STATUS_IS_OK(result)) {
2307                 return result;
2308         }
2309
2310  done:
2311         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2312         return result;
2313 }
2314
2315 static NTSTATUS rpc_group_addmem_internals(const DOM_SID *domain_sid,
2316                                         const char *domain_name, 
2317                                         struct cli_state *cli,
2318                                         struct rpc_pipe_client *pipe_hnd,
2319                                         TALLOC_CTX *mem_ctx,
2320                                         int argc,
2321                                         const char **argv)
2322 {
2323         DOM_SID group_sid;
2324         enum lsa_SidType group_type;
2325
2326         if (argc != 2) {
2327                 d_printf("Usage: 'net rpc group addmem <group> <member>\n");
2328                 return NT_STATUS_UNSUCCESSFUL;
2329         }
2330
2331         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2332                                                &group_sid, &group_type))) {
2333                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2334                 return NT_STATUS_UNSUCCESSFUL;
2335         }
2336
2337         if (group_type == SID_NAME_DOM_GRP) {
2338                 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2339                                                    &group_sid, argv[1]);
2340
2341                 if (!NT_STATUS_IS_OK(result)) {
2342                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
2343                                  argv[1], argv[0], nt_errstr(result));
2344                 }
2345                 return result;
2346         }
2347
2348         if (group_type == SID_NAME_ALIAS) {
2349                 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2350                                                    &group_sid, argv[1]);
2351
2352                 if (!NT_STATUS_IS_OK(result)) {
2353                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
2354                                  argv[1], argv[0], nt_errstr(result));
2355                 }
2356                 return result;
2357         }
2358
2359         d_fprintf(stderr, "Can only add members to global or local groups "
2360                  "which %s is not\n", argv[0]);
2361
2362         return NT_STATUS_UNSUCCESSFUL;
2363 }
2364
2365 static int rpc_group_addmem(int argc, const char **argv)
2366 {
2367         return run_rpc_command(NULL, PI_SAMR, 0,
2368                                rpc_group_addmem_internals,
2369                                argc, argv);
2370 }
2371
2372 static NTSTATUS rpc_del_groupmem(struct rpc_pipe_client *pipe_hnd,
2373                                 TALLOC_CTX *mem_ctx,
2374                                 const DOM_SID *group_sid,
2375                                 const char *member)
2376 {
2377         POLICY_HND connect_pol, domain_pol;
2378         NTSTATUS result;
2379         uint32 group_rid;
2380         POLICY_HND group_pol;
2381
2382         uint32 num_rids;
2383         uint32 *rids = NULL;
2384         uint32 *rid_types = NULL;
2385
2386         DOM_SID sid;
2387
2388         sid_copy(&sid, group_sid);
2389
2390         if (!sid_split_rid(&sid, &group_rid))
2391                 return NT_STATUS_UNSUCCESSFUL;
2392
2393         /* Get sam policy handle */
2394         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2395                                       pipe_hnd->cli->desthost,
2396                                       MAXIMUM_ALLOWED_ACCESS,
2397                                       &connect_pol);
2398         if (!NT_STATUS_IS_OK(result))
2399                 return result;
2400
2401         /* Get domain policy handle */
2402         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2403                                         &connect_pol,
2404                                         MAXIMUM_ALLOWED_ACCESS,
2405                                         &sid,
2406                                         &domain_pol);
2407         if (!NT_STATUS_IS_OK(result))
2408                 return result;
2409
2410         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2411                                        1, &member,
2412                                        &num_rids, &rids, &rid_types);
2413
2414         if (!NT_STATUS_IS_OK(result)) {
2415                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2416                 goto done;
2417         }
2418
2419         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2420                                        &domain_pol,
2421                                        MAXIMUM_ALLOWED_ACCESS,
2422                                        group_rid,
2423                                        &group_pol);
2424
2425         if (!NT_STATUS_IS_OK(result))
2426                 goto done;
2427
2428         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
2429                                                &group_pol,
2430                                                rids[0]);
2431
2432  done:
2433         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2434         return result;
2435 }
2436
2437 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2438                                 TALLOC_CTX *mem_ctx,
2439                                 const DOM_SID *alias_sid,
2440                                 const char *member)
2441 {
2442         POLICY_HND connect_pol, domain_pol;
2443         NTSTATUS result;
2444         uint32 alias_rid;
2445         POLICY_HND alias_pol;
2446
2447         DOM_SID member_sid;
2448         enum lsa_SidType member_type;
2449
2450         DOM_SID sid;
2451
2452         sid_copy(&sid, alias_sid);
2453
2454         if (!sid_split_rid(&sid, &alias_rid))
2455                 return NT_STATUS_UNSUCCESSFUL;
2456
2457         result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
2458                                    &member_sid, &member_type);
2459
2460         if (!NT_STATUS_IS_OK(result)) {
2461                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2462                 return result;
2463         }
2464
2465         /* Get sam policy handle */
2466         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2467                                       pipe_hnd->cli->desthost,
2468                                       MAXIMUM_ALLOWED_ACCESS,
2469                                       &connect_pol);
2470         if (!NT_STATUS_IS_OK(result)) {
2471                 goto done;
2472         }
2473
2474         /* Get domain policy handle */
2475         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2476                                         &connect_pol,
2477                                         MAXIMUM_ALLOWED_ACCESS,
2478                                         &sid,
2479                                         &domain_pol);
2480         if (!NT_STATUS_IS_OK(result)) {
2481                 goto done;
2482         }
2483
2484         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2485                                        &domain_pol,
2486                                        MAXIMUM_ALLOWED_ACCESS,
2487                                        alias_rid,
2488                                        &alias_pol);
2489
2490         if (!NT_STATUS_IS_OK(result))
2491                 return result;
2492
2493         result = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
2494
2495         if (!NT_STATUS_IS_OK(result))
2496                 return result;
2497
2498  done:
2499         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2500         return result;
2501 }
2502
2503 static NTSTATUS rpc_group_delmem_internals(const DOM_SID *domain_sid,
2504                                         const char *domain_name, 
2505                                         struct cli_state *cli,
2506                                         struct rpc_pipe_client *pipe_hnd,
2507                                         TALLOC_CTX *mem_ctx,
2508                                         int argc,
2509                                         const char **argv)
2510 {
2511         DOM_SID group_sid;
2512         enum lsa_SidType group_type;
2513
2514         if (argc != 2) {
2515                 d_printf("Usage: 'net rpc group delmem <group> <member>\n");
2516                 return NT_STATUS_UNSUCCESSFUL;
2517         }
2518
2519         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2520                                                &group_sid, &group_type))) {
2521                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2522                 return NT_STATUS_UNSUCCESSFUL;
2523         }
2524
2525         if (group_type == SID_NAME_DOM_GRP) {
2526                 NTSTATUS result = rpc_del_groupmem(pipe_hnd, mem_ctx,
2527                                                    &group_sid, argv[1]);
2528
2529                 if (!NT_STATUS_IS_OK(result)) {
2530                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2531                                  argv[1], argv[0], nt_errstr(result));
2532                 }
2533                 return result;
2534         }
2535
2536         if (group_type == SID_NAME_ALIAS) {
2537                 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx, 
2538                                                    &group_sid, argv[1]);
2539
2540                 if (!NT_STATUS_IS_OK(result)) {
2541                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2542                                  argv[1], argv[0], nt_errstr(result));
2543                 }
2544                 return result;
2545         }
2546
2547         d_fprintf(stderr, "Can only delete members from global or local groups "
2548                  "which %s is not\n", argv[0]);
2549
2550         return NT_STATUS_UNSUCCESSFUL;
2551 }
2552
2553 static int rpc_group_delmem(int argc, const char **argv)
2554 {
2555         return run_rpc_command(NULL, PI_SAMR, 0,
2556                                rpc_group_delmem_internals,
2557                                argc, argv);
2558 }
2559
2560 /** 
2561  * List groups on a remote RPC server
2562  *
2563  * All parameters are provided by the run_rpc_command function, except for
2564  * argc, argv which are passes through. 
2565  *
2566  * @param domain_sid The domain sid acquired from the remote server
2567  * @param cli A cli_state connected to the server.
2568  * @param mem_ctx Talloc context, destoyed on completion of the function.
2569  * @param argc  Standard main() style argc
2570  * @param argv  Standard main() style argv.  Initial components are already
2571  *              stripped
2572  *
2573  * @return Normal NTSTATUS return.
2574  **/
2575
2576 static NTSTATUS rpc_group_list_internals(const DOM_SID *domain_sid,
2577                                         const char *domain_name, 
2578                                         struct cli_state *cli,
2579                                         struct rpc_pipe_client *pipe_hnd,
2580                                         TALLOC_CTX *mem_ctx,
2581                                         int argc,
2582                                         const char **argv)
2583 {
2584         POLICY_HND connect_pol, domain_pol;
2585         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2586         uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2587         struct acct_info *groups;
2588         bool global = False;
2589         bool local = False;
2590         bool builtin = False;
2591
2592         if (argc == 0) {
2593                 global = True;
2594                 local = True;
2595                 builtin = True;
2596         }
2597
2598         for (i=0; i<argc; i++) {
2599                 if (strequal(argv[i], "global"))
2600                         global = True;
2601
2602                 if (strequal(argv[i], "local"))
2603                         local = True;
2604
2605                 if (strequal(argv[i], "builtin"))
2606                         builtin = True;
2607         }
2608
2609         /* Get sam policy handle */
2610
2611         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2612                                       pipe_hnd->cli->desthost,
2613                                       MAXIMUM_ALLOWED_ACCESS,
2614                                       &connect_pol);
2615         if (!NT_STATUS_IS_OK(result)) {
2616                 goto done;
2617         }
2618         
2619         /* Get domain policy handle */
2620
2621         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2622                                         &connect_pol,
2623                                         MAXIMUM_ALLOWED_ACCESS,
2624                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2625                                         &domain_pol);
2626         if (!NT_STATUS_IS_OK(result)) {
2627                 goto done;
2628         }
2629
2630         /* Query domain groups */
2631         if (opt_long_list_entries)
2632                 d_printf("\nGroup name            Comment"\
2633                          "\n-----------------------------\n");
2634         do {
2635                 SAM_DISPINFO_CTR ctr;
2636                 SAM_DISPINFO_3 info3;
2637                 uint32 max_size;
2638
2639                 ZERO_STRUCT(ctr);
2640                 ZERO_STRUCT(info3);
2641                 ctr.sam.info3 = &info3;
2642
2643                 if (!global) break;
2644
2645                 get_query_dispinfo_params(
2646                         loop_count, &max_entries, &max_size);
2647
2648                 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
2649                                                  &start_idx, 3, &num_entries,
2650                                                  max_entries, max_size, &ctr);
2651
2652                 if (!NT_STATUS_IS_OK(result) &&
2653                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2654                         break;
2655                                                  
2656                 for (i = 0; i < num_entries; i++) {
2657
2658                         fstring group, desc;
2659
2660                         unistr2_to_ascii(group, &(&ctr.sam.info3->str[i])->uni_grp_name, sizeof(group));
2661                         unistr2_to_ascii(desc, &(&ctr.sam.info3->str[i])->uni_grp_desc, sizeof(desc));
2662                         
2663                         if (opt_long_list_entries)
2664                                 printf("%-21.21s %-50.50s\n",
2665                                        group, desc);
2666                         else
2667                                 printf("%s\n", group);
2668                 }
2669         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2670         /* query domain aliases */
2671         start_idx = 0;
2672         do {
2673                 if (!local) break;
2674
2675                 /* The max_size field in cli_samr_enum_als_groups is more like
2676                  * an account_control field with indiviual bits what to
2677                  * retrieve. Set this to 0xffff as NT4 usrmgr.exe does to get
2678                  * everything. I'm too lazy (sorry) to get this through to
2679                  * rpc_parse/ etc.  Volker */
2680
2681                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2682                                                   &start_idx, 0xffff,
2683                                                   &groups, &num_entries);
2684
2685                 if (!NT_STATUS_IS_OK(result) &&
2686                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2687                         break;
2688                                                  
2689                 for (i = 0; i < num_entries; i++) {
2690
2691                         char *description = NULL;
2692
2693                         if (opt_long_list_entries) {
2694
2695                                 POLICY_HND alias_pol;
2696                                 ALIAS_INFO_CTR ctr;
2697
2698                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2699                                                                            &domain_pol,
2700                                                                            0x8,
2701                                                                            groups[i].rid,
2702                                                                            &alias_pol))) &&
2703                                     (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
2704                                                                                &alias_pol, 3,
2705                                                                                &ctr))) &&
2706                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2707                                                                     &alias_pol)))) {
2708                                         description = unistr2_to_ascii_talloc(mem_ctx,
2709                                                                    ctr.alias.info3.description.string);
2710                                 }
2711                         }
2712                         
2713                         if (description != NULL) {
2714                                 printf("%-21.21s %-50.50s\n", 
2715                                        groups[i].acct_name,
2716                                        description);
2717                         } else {
2718                                 printf("%s\n", groups[i].acct_name);
2719                         }
2720                 }
2721         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2722         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2723         /* Get builtin policy handle */
2724
2725         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2726                                         &connect_pol,
2727                                         MAXIMUM_ALLOWED_ACCESS,
2728                                         CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2729                                         &domain_pol);
2730         if (!NT_STATUS_IS_OK(result)) {
2731                 goto done;
2732         }
2733         /* query builtin aliases */
2734         start_idx = 0;
2735         do {
2736                 if (!builtin) break;
2737
2738                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2739                                                   &start_idx, max_entries,
2740                                                   &groups, &num_entries);
2741                                                  
2742                 if (!NT_STATUS_IS_OK(result) &&
2743                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2744                         break;
2745                                                  
2746                 for (i = 0; i < num_entries; i++) {
2747
2748                         char *description = NULL;
2749
2750                         if (opt_long_list_entries) {
2751
2752                                 POLICY_HND alias_pol;
2753                                 ALIAS_INFO_CTR ctr;
2754
2755                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2756                                                                            &domain_pol,
2757                                                                            0x8,
2758                                                                            groups[i].rid,
2759                                                                            &alias_pol))) &&
2760                                     (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
2761                                                                                &alias_pol, 3,
2762                                                                                &ctr))) &&
2763                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2764                                                                     &alias_pol)))) {
2765                                         description = unistr2_to_ascii_talloc(mem_ctx,
2766                                                                    ctr.alias.info3.description.string);
2767                                 }
2768                         }
2769                         
2770                         if (description != NULL) {
2771                                 printf("%-21.21s %-50.50s\n", 
2772                                        groups[i].acct_name,
2773                                        description);
2774                         } else {
2775                                 printf("%s\n", groups[i].acct_name);
2776                         }
2777                 }
2778         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2779
2780  done:
2781         return result;
2782 }
2783
2784 static int rpc_group_list(int argc, const char **argv)
2785 {
2786         return run_rpc_command(NULL, PI_SAMR, 0,
2787                                rpc_group_list_internals,
2788                                argc, argv);
2789 }
2790
2791 static NTSTATUS rpc_list_group_members(struct rpc_pipe_client *pipe_hnd,
2792                                         TALLOC_CTX *mem_ctx,
2793                                         const char *domain_name,
2794                                         const DOM_SID *domain_sid,
2795                                         POLICY_HND *domain_pol,
2796                                         uint32 rid)
2797 {
2798         NTSTATUS result;
2799         POLICY_HND group_pol;
2800         uint32 num_members, *group_rids, *group_attrs;
2801         uint32 num_names;
2802         char **names;
2803         uint32 *name_types;
2804         int i;
2805
2806         fstring sid_str;
2807         sid_to_fstring(sid_str, domain_sid);
2808
2809         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2810                                        domain_pol,
2811                                        MAXIMUM_ALLOWED_ACCESS,
2812                                        rid,
2813                                        &group_pol);
2814
2815         if (!NT_STATUS_IS_OK(result))
2816                 return result;
2817
2818         result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
2819                                          &num_members, &group_rids,
2820                                          &group_attrs);
2821
2822         if (!NT_STATUS_IS_OK(result))
2823                 return result;
2824
2825         while (num_members > 0) {
2826                 int this_time = 512;
2827
2828                 if (num_members < this_time)
2829                         this_time = num_members;
2830
2831                 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, domain_pol,
2832                                               this_time, group_rids,
2833                                               &num_names, &names, &name_types);
2834
2835                 if (!NT_STATUS_IS_OK(result))
2836                         return result;
2837
2838                 /* We only have users as members, but make the output
2839                    the same as the output of alias members */
2840
2841                 for (i = 0; i < this_time; i++) {
2842
2843                         if (opt_long_list_entries) {
2844                                 printf("%s-%d %s\\%s %d\n", sid_str,
2845                                        group_rids[i], domain_name, names[i],
2846                                        SID_NAME_USER);
2847                         } else {
2848                                 printf("%s\\%s\n", domain_name, names[i]);
2849                         }
2850                 }
2851
2852                 num_members -= this_time;
2853                 group_rids += 512;
2854         }
2855
2856         return NT_STATUS_OK;
2857 }
2858
2859 static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
2860                                         TALLOC_CTX *mem_ctx,
2861                                         POLICY_HND *domain_pol,
2862                                         uint32 rid)
2863 {
2864         NTSTATUS result;
2865         struct rpc_pipe_client *lsa_pipe;
2866         POLICY_HND alias_pol, lsa_pol;
2867         uint32 num_members;
2868         DOM_SID *alias_sids;
2869         char **domains;
2870         char **names;
2871         enum lsa_SidType *types;
2872         int i;
2873
2874         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2875                                        domain_pol,
2876                                        MAXIMUM_ALLOWED_ACCESS,
2877                                        rid,
2878                                        &alias_pol);
2879
2880         if (!NT_STATUS_IS_OK(result))
2881                 return result;
2882
2883         result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, &alias_pol,
2884                                          &num_members, &alias_sids);
2885
2886         if (!NT_STATUS_IS_OK(result)) {
2887                 d_fprintf(stderr, "Couldn't list alias members\n");
2888                 return result;
2889         }
2890
2891         if (num_members == 0) {
2892                 return NT_STATUS_OK;
2893         }
2894
2895         lsa_pipe = cli_rpc_pipe_open_noauth(pipe_hnd->cli, PI_LSARPC, &result);
2896         if (!lsa_pipe) {
2897                 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
2898                         nt_errstr(result) );
2899                 return result;
2900         }
2901
2902         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
2903                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2904
2905         if (!NT_STATUS_IS_OK(result)) {
2906                 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
2907                 cli_rpc_pipe_close(lsa_pipe);
2908                 return result;
2909         }
2910
2911         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol, num_members,
2912                                      alias_sids, 
2913                                      &domains, &names, &types);
2914
2915         if (!NT_STATUS_IS_OK(result) &&
2916             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2917                 d_fprintf(stderr, "Couldn't lookup SIDs\n");
2918                 cli_rpc_pipe_close(lsa_pipe);
2919                 return result;
2920         }
2921
2922         for (i = 0; i < num_members; i++) {
2923                 fstring sid_str;
2924                 sid_to_fstring(sid_str, &alias_sids[i]);
2925
2926                 if (opt_long_list_entries) {
2927                         printf("%s %s\\%s %d\n", sid_str, 
2928                                domains[i] ? domains[i] : "*unknown*", 
2929                                names[i] ? names[i] : "*unknown*", types[i]);
2930                 } else {
2931                         if (domains[i])
2932                                 printf("%s\\%s\n", domains[i], names[i]);
2933                         else
2934                                 printf("%s\n", sid_str);
2935                 }
2936         }
2937
2938         cli_rpc_pipe_close(lsa_pipe);
2939         return NT_STATUS_OK;
2940 }
2941  
2942 static NTSTATUS rpc_group_members_internals(const DOM_SID *domain_sid,
2943                                         const char *domain_name, 
2944                                         struct cli_state *cli,
2945                                         struct rpc_pipe_client *pipe_hnd,
2946                                         TALLOC_CTX *mem_ctx,
2947                                         int argc,
2948                                         const char **argv)
2949 {
2950         NTSTATUS result;
2951         POLICY_HND connect_pol, domain_pol;
2952         uint32 num_rids, *rids, *rid_types;
2953
2954         /* Get sam policy handle */
2955
2956         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2957                                       pipe_hnd->cli->desthost,
2958                                       MAXIMUM_ALLOWED_ACCESS,
2959                                       &connect_pol);
2960
2961         if (!NT_STATUS_IS_OK(result))
2962                 return result;
2963         
2964         /* Get domain policy handle */
2965
2966         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2967                                         &connect_pol,
2968                                         MAXIMUM_ALLOWED_ACCESS,
2969                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2970                                         &domain_pol);
2971
2972         if (!NT_STATUS_IS_OK(result))
2973                 return result;
2974
2975         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2976                                        1, argv, &num_rids, &rids, &rid_types);
2977
2978         if (!NT_STATUS_IS_OK(result)) {
2979
2980                 /* Ok, did not find it in the global sam, try with builtin */
2981
2982                 DOM_SID sid_Builtin;
2983
2984                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2985
2986                 string_to_sid(&sid_Builtin, "S-1-5-32");                
2987
2988                 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2989                                                 &connect_pol,
2990                                                 MAXIMUM_ALLOWED_ACCESS,
2991                                                 &sid_Builtin,
2992                                                 &domain_pol);
2993
2994                 if (!NT_STATUS_IS_OK(result)) {
2995                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2996                         return result;
2997                 }
2998
2999                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
3000                                                1, argv, &num_rids,
3001                                                &rids, &rid_types);
3002
3003                 if (!NT_STATUS_IS_OK(result)) {
3004                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
3005                         return result;
3006                 }
3007         }
3008
3009         if (num_rids != 1) {
3010                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
3011                 return result;
3012         }
3013
3014         if (rid_types[0] == SID_NAME_DOM_GRP) {
3015                 return rpc_list_group_members(pipe_hnd, mem_ctx, domain_name,
3016                                               domain_sid, &domain_pol,
3017                                               rids[0]);
3018         }
3019
3020         if (rid_types[0] == SID_NAME_ALIAS) {
3021                 return rpc_list_alias_members(pipe_hnd, mem_ctx, &domain_pol,
3022                                               rids[0]);
3023         }
3024
3025         return NT_STATUS_NO_SUCH_GROUP;
3026 }
3027
3028 static int rpc_group_members(int argc, const char **argv)
3029 {
3030         if (argc != 1) {
3031                 return rpc_group_usage(argc, argv);
3032         }
3033
3034         return run_rpc_command(NULL, PI_SAMR, 0,
3035                                rpc_group_members_internals,
3036                                argc, argv);
3037 }
3038
3039 static NTSTATUS rpc_group_rename_internals(const DOM_SID *domain_sid,
3040                                         const char *domain_name, 
3041                                         struct cli_state *cli,
3042                                         struct rpc_pipe_client *pipe_hnd,
3043                                         TALLOC_CTX *mem_ctx,
3044                                         int argc,
3045                                         const char **argv)
3046 {
3047         NTSTATUS result;
3048         POLICY_HND connect_pol, domain_pol, group_pol;
3049         uint32 num_rids, *rids, *rid_types;
3050         GROUP_INFO_CTR ctr;
3051
3052         if (argc != 2) {
3053                 d_printf("Usage: 'net rpc group rename group newname'\n");
3054                 return NT_STATUS_UNSUCCESSFUL;
3055         }
3056
3057         /* Get sam policy handle */
3058
3059         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
3060                                       pipe_hnd->cli->desthost,
3061                                       MAXIMUM_ALLOWED_ACCESS,
3062                                       &connect_pol);
3063
3064         if (!NT_STATUS_IS_OK(result))
3065                 return result;
3066         
3067         /* Get domain policy handle */
3068
3069         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3070                                         &connect_pol,
3071                                         MAXIMUM_ALLOWED_ACCESS,
3072                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
3073                                         &domain_pol);
3074
3075         if (!NT_STATUS_IS_OK(result))
3076                 return result;
3077
3078         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
3079                                        1, argv, &num_rids, &rids, &rid_types);
3080
3081         if (num_rids != 1) {
3082                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
3083                 return result;
3084         }
3085
3086         if (rid_types[0] != SID_NAME_DOM_GRP) {
3087                 d_fprintf(stderr, "Can only rename domain groups\n");
3088                 return NT_STATUS_UNSUCCESSFUL;