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