Let rpccli_samr_chgpasswd3 use rpccli_samr_ChangePasswordUser3 internally.
[ira/wip.git] / source3 / rpcclient / cmd_samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Andrew Tridgell              1992-2000,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7    Copyright (C) Elrond                            2000,
8    Copyright (C) Tim Potter                        2000
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
24 #include "includes.h"
25 #include "rpcclient.h"
26
27 extern DOM_SID domain_sid;
28
29 static void init_lsa_String(struct lsa_String *name, const char *s)
30 {
31         name->string = s;
32 }
33
34 /****************************************************************************
35  display sam_user_info_7 structure
36  ****************************************************************************/
37 static void display_sam_user_info_7(SAM_USER_INFO_7 *usr)
38 {
39         fstring temp;
40
41         unistr2_to_ascii(temp, &usr->uni_name, sizeof(temp));
42         printf("\tUser Name   :\t%s\n", temp);
43 }
44
45 /****************************************************************************
46  display sam_user_info_9 structure
47  ****************************************************************************/
48 static void display_sam_user_info_9(SAM_USER_INFO_9 *usr)
49 {
50         printf("\tPrimary group RID   :\tox%x\n", usr->rid_group);
51 }
52
53 /****************************************************************************
54  display sam_user_info_16 structure
55  ****************************************************************************/
56 static void display_sam_user_info_16(SAM_USER_INFO_16 *usr)
57 {
58         printf("\tAcct Flags   :\tox%x\n", usr->acb_info);
59 }
60
61 /****************************************************************************
62  display sam_user_info_21 structure
63  ****************************************************************************/
64 static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
65 {
66         fstring temp;
67
68         unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp));
69         printf("\tUser Name   :\t%s\n", temp);
70         
71         unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp));
72         printf("\tFull Name   :\t%s\n", temp);
73         
74         unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp));
75         printf("\tHome Drive  :\t%s\n", temp);
76         
77         unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp));
78         printf("\tDir Drive   :\t%s\n", temp);
79         
80         unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp));
81         printf("\tProfile Path:\t%s\n", temp);
82         
83         unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp));
84         printf("\tLogon Script:\t%s\n", temp);
85         
86         unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp));
87         printf("\tDescription :\t%s\n", temp);
88         
89         unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp));
90         printf("\tWorkstations:\t%s\n", temp);
91         
92         unistr2_to_ascii(temp, &usr->uni_comment, sizeof(temp));
93         printf("\tUnknown Str :\t%s\n", temp);
94         
95         unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp));
96         printf("\tRemote Dial :\t%s\n", temp);
97         
98         printf("\tLogon Time               :\t%s\n", 
99                http_timestring(nt_time_to_unix(usr->logon_time)));
100         printf("\tLogoff Time              :\t%s\n", 
101                http_timestring(nt_time_to_unix(usr->logoff_time)));
102         printf("\tKickoff Time             :\t%s\n", 
103                http_timestring(nt_time_to_unix(usr->kickoff_time)));
104         printf("\tPassword last set Time   :\t%s\n", 
105                http_timestring(nt_time_to_unix(usr->pass_last_set_time)));
106         printf("\tPassword can change Time :\t%s\n", 
107                http_timestring(nt_time_to_unix(usr->pass_can_change_time)));
108         printf("\tPassword must change Time:\t%s\n", 
109                http_timestring(nt_time_to_unix(usr->pass_must_change_time)));
110         
111         printf("\tunknown_2[0..31]...\n"); /* user passwords? */
112         
113         printf("\tuser_rid :\t0x%x\n"  , usr->user_rid ); /* User ID */
114         printf("\tgroup_rid:\t0x%x\n"  , usr->group_rid); /* Group ID */
115         printf("\tacb_info :\t0x%08x\n", usr->acb_info ); /* Account Control Info */
116         
117         printf("\tfields_present:\t0x%08x\n", usr->fields_present); /* 0x00ff ffff */
118         printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
119         printf("\tbad_password_count:\t0x%08x\n", usr->bad_password_count);
120         printf("\tlogon_count:\t0x%08x\n", usr->logon_count);
121         
122         printf("\tpadding1[0..7]...\n");
123         
124         if (usr->ptr_logon_hrs) {
125                 printf("\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len);
126         }
127 }
128
129
130 static void display_password_properties(uint32_t password_properties)
131 {
132         printf("password_properties: 0x%08x\n", password_properties);
133                 
134         if (password_properties & DOMAIN_PASSWORD_COMPLEX)
135                 printf("\tDOMAIN_PASSWORD_COMPLEX\n");
136                         
137         if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
138                 printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
139                         
140         if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
141                 printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
142                         
143         if (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)
144                 printf("\tDOMAIN_PASSWORD_LOCKOUT_ADMINS\n");
145                         
146         if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
147                 printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
148                         
149         if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
150                 printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
151 }
152
153 static void display_sam_dom_info_1(struct samr_DomInfo1 *info1)
154 {
155         printf("Minimum password length:\t\t\t%d\n",
156                 info1->min_password_length);
157         printf("Password uniqueness (remember x passwords):\t%d\n",
158                 info1->password_history_length);
159         display_password_properties(info1->password_properties);
160         printf("password expire in:\t\t\t\t%s\n",
161                 display_time(info1->max_password_age));
162         printf("Min password age (allow changing in x days):\t%s\n",
163                 display_time(info1->min_password_age));
164 }
165
166 static void display_sam_dom_info_2(struct samr_DomInfo2 *info2)
167 {
168         printf("Domain:\t\t%s\n", info2->domain_name.string);
169         printf("Server:\t\t%s\n", info2->primary.string);
170         printf("Comment:\t%s\n", info2->comment.string);
171
172         printf("Total Users:\t%d\n", info2->num_users);
173         printf("Total Groups:\t%d\n", info2->num_groups);
174         printf("Total Aliases:\t%d\n", info2->num_aliases);
175
176         printf("Sequence No:\t%llu\n", (unsigned long long)info2->sequence_num);
177
178         printf("Force Logoff:\t%d\n",
179                 (int)nt_time_to_unix_abs(&info2->force_logoff_time));
180
181         printf("Unknown 2:\t0x%x\n", info2->unknown2);
182         printf("Server Role:\t%s\n", server_role_str(info2->role));
183         printf("Unknown 3:\t0x%x\n", info2->unknown3);
184 }
185
186 static void display_sam_dom_info_3(struct samr_DomInfo3 *info3)
187 {
188         printf("Force Logoff:\t%d\n",
189                 (int)nt_time_to_unix_abs(&info3->force_logoff_time));
190 }
191
192 static void display_sam_dom_info_4(struct samr_DomInfo4 *info4)
193 {
194         printf("Comment:\t%s\n", info4->comment.string);
195 }
196
197 static void display_sam_dom_info_5(struct samr_DomInfo5 *info5)
198 {
199         printf("Domain:\t\t%s\n", info5->domain_name.string);
200 }
201
202 static void display_sam_dom_info_6(struct samr_DomInfo6 *info6)
203 {
204         printf("Server:\t\t%s\n", info6->primary.string);
205 }
206
207 static void display_sam_dom_info_7(struct samr_DomInfo7 *info7)
208 {
209         printf("Server Role:\t%s\n", server_role_str(info7->role));
210 }
211
212 static void display_sam_dom_info_8(struct samr_DomInfo8 *info8)
213 {
214         printf("Sequence No:\t%llu\n", (unsigned long long)info8->sequence_num);
215         printf("Domain Create Time:\t%s\n", 
216                 http_timestring(nt_time_to_unix(info8->domain_create_time)));
217 }
218
219 static void display_sam_dom_info_9(struct samr_DomInfo9 *info9)
220 {
221         printf("unknown:\t%d (0x%08x)\n", info9->unknown, info9->unknown);
222 }
223
224 static void display_sam_dom_info_12(struct samr_DomInfo12 *info12)
225 {
226         printf("Bad password lockout duration:               %s\n",
227                 display_time(info12->lockout_duration));
228         printf("Reset Lockout after:                         %s\n",
229                 display_time(info12->lockout_window));
230         printf("Lockout after bad attempts:                  %d\n",
231                 info12->lockout_threshold);
232 }
233
234 static void display_sam_dom_info_13(struct samr_DomInfo13 *info13)
235 {
236         printf("Sequence No:\t%llu\n", (unsigned long long)info13->sequence_num);
237         printf("Domain Create Time:\t%s\n", 
238                 http_timestring(nt_time_to_unix(info13->domain_create_time)));
239         printf("Unknown1:\t%d\n", info13->unknown1);
240         printf("Unknown2:\t%d\n", info13->unknown2);
241
242 }
243
244 static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
245 {
246         fstring tmp;
247
248         printf("index: 0x%x ", e1->user_idx);
249         printf("RID: 0x%x ", e1->rid_user);
250         printf("acb: 0x%x ", e1->acb_info);
251
252         unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp));
253         printf("Account: %s\t", tmp);
254
255         unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp));
256         printf("Name: %s\t", tmp);
257
258         unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp));
259         printf("Desc: %s\n", tmp);
260 }
261
262 static void display_sam_info_2(SAM_ENTRY2 *e2, SAM_STR2 *s2)
263 {
264         fstring tmp;
265
266         printf("index: 0x%x ", e2->user_idx);
267         printf("RID: 0x%x ", e2->rid_user);
268         printf("acb: 0x%x ", e2->acb_info);
269         
270         unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp));
271         printf("Account: %s\t", tmp);
272
273         unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp));
274         printf("Name: %s\n", tmp);
275
276 }
277
278 static void display_sam_info_3(SAM_ENTRY3 *e3, SAM_STR3 *s3)
279 {
280         fstring tmp;
281
282         printf("index: 0x%x ", e3->grp_idx);
283         printf("RID: 0x%x ", e3->rid_grp);
284         printf("attr: 0x%x ", e3->attr);
285         
286         unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp));
287         printf("Account: %s\t", tmp);
288
289         unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp));
290         printf("Name: %s\n", tmp);
291
292 }
293
294 static void display_sam_info_4(SAM_ENTRY4 *e4, SAM_STR4 *s4)
295 {
296         int i;
297
298         printf("index: %d ", e4->user_idx);
299         
300         printf("Account: ");
301         for (i=0; i<s4->acct_name.str_str_len; i++)
302                 printf("%c", s4->acct_name.buffer[i]);
303         printf("\n");
304
305 }
306
307 static void display_sam_info_5(SAM_ENTRY5 *e5, SAM_STR5 *s5)
308 {
309         int i;
310
311         printf("index: 0x%x ", e5->grp_idx);
312         
313         printf("Account: ");
314         for (i=0; i<s5->grp_name.str_str_len; i++)
315                 printf("%c", s5->grp_name.buffer[i]);
316         printf("\n");
317
318 }
319
320 /****************************************************************************
321  Try samr_connect4 first, then samr_connect2 if it fails
322  ****************************************************************************/
323 static NTSTATUS try_samr_connects(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
324                                   uint32 access_mask, POLICY_HND *connect_pol)
325 {
326         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
327
328         result = rpccli_samr_Connect4(cli, mem_ctx,
329                                       cli->cli->desthost,
330                                       SAMR_CONNECT_W2K,
331                                       access_mask,
332                                       connect_pol);
333         if (!NT_STATUS_IS_OK(result)) {
334                 result = rpccli_samr_Connect2(cli, mem_ctx,
335                                               cli->cli->desthost,
336                                               access_mask,
337                                               connect_pol);
338         }
339         return result;
340 }
341
342 /**********************************************************************
343  * Query user information 
344  */
345 static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli, 
346                                     TALLOC_CTX *mem_ctx,
347                                     int argc, const char **argv) 
348 {
349         POLICY_HND connect_pol, domain_pol, user_pol;
350         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
351         uint32 info_level = 21;
352         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
353         SAM_USERINFO_CTR *user_ctr;
354         fstring server;
355         uint32 user_rid = 0;
356         
357         if ((argc < 2) || (argc > 4)) {
358                 printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
359                 return NT_STATUS_OK;
360         }
361         
362         sscanf(argv[1], "%i", &user_rid);
363         
364         if (argc > 2)
365                 sscanf(argv[2], "%i", &info_level);
366                 
367         if (argc > 3)
368                 sscanf(argv[3], "%x", &access_mask);
369         
370
371         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
372         strupper_m(server);
373         
374         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
375                                    &connect_pol);
376
377         if (!NT_STATUS_IS_OK(result))
378                 goto done;
379
380         result = rpccli_samr_OpenDomain(cli, mem_ctx,
381                                         &connect_pol,
382                                         MAXIMUM_ALLOWED_ACCESS,
383                                         &domain_sid,
384                                         &domain_pol);
385         if (!NT_STATUS_IS_OK(result))
386                 goto done;
387
388         result = rpccli_samr_OpenUser(cli, mem_ctx,
389                                       &domain_pol,
390                                       access_mask,
391                                       user_rid,
392                                       &user_pol);
393
394         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) &&
395             (user_rid == 0)) {
396
397                 /* Probably this was a user name, try lookupnames */
398                 uint32 num_rids;
399                 uint32 *rids, *types;
400                 
401                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
402                                                   1000, 1, &argv[1],
403                                                   &num_rids, &rids,
404                                                   &types);
405
406                 if (NT_STATUS_IS_OK(result)) {
407                         result = rpccli_samr_OpenUser(cli, mem_ctx,
408                                                       &domain_pol,
409                                                       access_mask,
410                                                       rids[0],
411                                                       &user_pol);
412                 }
413         }
414
415
416         if (!NT_STATUS_IS_OK(result))
417                 goto done;
418
419         ZERO_STRUCT(user_ctr);
420
421         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
422                                          info_level, &user_ctr);
423
424         if (!NT_STATUS_IS_OK(result))
425                 goto done;
426
427         switch (user_ctr->switch_value) {
428         case 7:
429                 display_sam_user_info_7(user_ctr->info.id7);
430                 break;
431         case 9:
432                 display_sam_user_info_9(user_ctr->info.id9);
433                 break;
434         case 16:
435                 display_sam_user_info_16(user_ctr->info.id16);
436                 break;
437         case 21:
438                 display_sam_user_info_21(user_ctr->info.id21);
439                 break;
440         default:
441                 printf("Unsupported infolevel: %d\n", info_level);
442                 break;
443         }
444
445         rpccli_samr_Close(cli, mem_ctx, &user_pol);
446         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
447         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
448
449 done:
450         return result;
451 }
452
453 /****************************************************************************
454  display group info
455  ****************************************************************************/
456 static void display_group_info1(GROUP_INFO1 *info1)
457 {
458         fstring temp;
459
460         unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp));
461         printf("\tGroup Name:\t%s\n", temp);
462         unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp));
463         printf("\tDescription:\t%s\n", temp);
464         printf("\tGroup Attribute:%d\n", info1->group_attr);
465         printf("\tNum Members:%d\n", info1->num_members);
466 }
467
468 /****************************************************************************
469  display group info
470  ****************************************************************************/
471 static void display_group_info2(GROUP_INFO2 *info2)
472 {
473         fstring name;
474
475         unistr2_to_ascii(name, &info2->uni_acct_name, sizeof(name));
476         printf("\tGroup Description:%s\n", name);
477 }
478
479
480 /****************************************************************************
481  display group info
482  ****************************************************************************/
483 static void display_group_info3(GROUP_INFO3 *info3)
484 {
485         printf("\tGroup Attribute:%d\n", info3->group_attr);
486 }
487
488
489 /****************************************************************************
490  display group info
491  ****************************************************************************/
492 static void display_group_info4(GROUP_INFO4 *info4)
493 {
494         fstring desc;
495
496         unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc));
497         printf("\tGroup Description:%s\n", desc);
498 }
499
500 /****************************************************************************
501  display group info
502  ****************************************************************************/
503 static void display_group_info5(GROUP_INFO5 *info5)
504 {
505         fstring temp;
506
507         unistr2_to_ascii(temp, &info5->uni_acct_name, sizeof(temp));
508         printf("\tGroup Name:\t%s\n", temp);
509         unistr2_to_ascii(temp, &info5->uni_acct_desc, sizeof(temp));
510         printf("\tDescription:\t%s\n", temp);
511         printf("\tGroup Attribute:%d\n", info5->group_attr);
512         printf("\tNum Members:%d\n", info5->num_members);
513 }
514
515 /****************************************************************************
516  display sam sync structure
517  ****************************************************************************/
518 static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
519 {
520         switch (ctr->switch_value1) {
521                 case 1:
522                         display_group_info1(&ctr->group.info1);
523                         break;
524                 case 2:
525                         display_group_info2(&ctr->group.info2);
526                         break;
527                 case 3:
528                         display_group_info3(&ctr->group.info3);
529                         break;
530                 case 4:
531                         display_group_info4(&ctr->group.info4);
532                         break;
533                 case 5:
534                         display_group_info5(&ctr->group.info5);
535                         break;
536
537         }
538 }
539
540 /***********************************************************************
541  * Query group information 
542  */
543 static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli, 
544                                      TALLOC_CTX *mem_ctx,
545                                      int argc, const char **argv) 
546 {
547         POLICY_HND connect_pol, domain_pol, group_pol;
548         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
549         uint32 info_level = 1;
550         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
551         GROUP_INFO_CTR *group_ctr;
552         fstring                 server; 
553         uint32 group_rid;
554         
555         if ((argc < 2) || (argc > 4)) {
556                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
557                 return NT_STATUS_OK;
558         }
559
560         sscanf(argv[1], "%i", &group_rid);
561         
562         if (argc > 2)
563                 sscanf(argv[2], "%i", &info_level);
564         
565         if (argc > 3)
566                 sscanf(argv[3], "%x", &access_mask);
567
568         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
569         strupper_m(server);
570
571         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
572                                    &connect_pol);
573
574         if (!NT_STATUS_IS_OK(result))
575                 goto done;
576
577         result = rpccli_samr_OpenDomain(cli, mem_ctx,
578                                         &connect_pol,
579                                         MAXIMUM_ALLOWED_ACCESS,
580                                         &domain_sid,
581                                         &domain_pol);
582
583         if (!NT_STATUS_IS_OK(result))
584                 goto done;
585
586         result = rpccli_samr_OpenGroup(cli, mem_ctx,
587                                        &domain_pol,
588                                        access_mask,
589                                        group_rid,
590                                        &group_pol);
591
592         if (!NT_STATUS_IS_OK(result))
593                 goto done;
594
595         result = rpccli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
596                                           info_level, &group_ctr);
597         if (!NT_STATUS_IS_OK(result)) {
598                 goto done;
599         }
600
601         display_group_info_ctr(group_ctr);
602
603         rpccli_samr_Close(cli, mem_ctx, &group_pol);
604         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
605         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
606 done:
607         return result;
608 }
609
610 /* Query groups a user is a member of */
611
612 static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli, 
613                                           TALLOC_CTX *mem_ctx,
614                                           int argc, const char **argv) 
615 {
616         POLICY_HND              connect_pol, 
617                                 domain_pol, 
618                                 user_pol;
619         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
620         uint32                  num_groups, 
621                                 user_rid;
622         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
623         DOM_GID                 *user_gids;
624         int                     i;
625         fstring                 server;
626         
627         if ((argc < 2) || (argc > 3)) {
628                 printf("Usage: %s rid [access mask]\n", argv[0]);
629                 return NT_STATUS_OK;
630         }
631
632         sscanf(argv[1], "%i", &user_rid);
633         
634         if (argc > 2)
635                 sscanf(argv[2], "%x", &access_mask);
636
637         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
638         strupper_m(server);
639                 
640         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
641                                    &connect_pol);
642
643         if (!NT_STATUS_IS_OK(result))
644                 goto done;
645
646         result = rpccli_samr_OpenDomain(cli, mem_ctx,
647                                         &connect_pol,
648                                         MAXIMUM_ALLOWED_ACCESS,
649                                         &domain_sid, &domain_pol);
650
651         if (!NT_STATUS_IS_OK(result))
652                 goto done;
653
654         result = rpccli_samr_OpenUser(cli, mem_ctx,
655                                       &domain_pol,
656                                       access_mask,
657                                       user_rid,
658                                       &user_pol);
659
660         if (!NT_STATUS_IS_OK(result))
661                 goto done;
662
663         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
664                                            &num_groups, &user_gids);
665
666         if (!NT_STATUS_IS_OK(result))
667                 goto done;
668
669         for (i = 0; i < num_groups; i++) {
670                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n", 
671                        user_gids[i].g_rid, user_gids[i].attr);
672         }
673
674         rpccli_samr_Close(cli, mem_ctx, &user_pol);
675         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
676         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
677  done:
678         return result;
679 }
680
681 /* Query aliases a user is a member of */
682
683 static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli, 
684                                            TALLOC_CTX *mem_ctx,
685                                            int argc, const char **argv) 
686 {
687         POLICY_HND              connect_pol, domain_pol;
688         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
689         DOM_SID                *sids;
690         size_t                     num_sids;
691         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
692         int                     i;
693         fstring                 server;
694         struct lsa_SidArray sid_array;
695         struct samr_Ids alias_rids;
696
697         if (argc < 3) {
698                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
699                 return NT_STATUS_INVALID_PARAMETER;
700         }
701
702         sids = NULL;
703         num_sids = 0;
704
705         for (i=2; i<argc; i++) {
706                 DOM_SID tmp_sid;
707                 if (!string_to_sid(&tmp_sid, argv[i])) {
708                         printf("%s is not a legal SID\n", argv[i]);
709                         return NT_STATUS_INVALID_PARAMETER;
710                 }
711                 result = add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
712                 if (!NT_STATUS_IS_OK(result)) {
713                         return result;
714                 }
715         }
716
717         if (num_sids) {
718                 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_sids);
719                 if (sid_array.sids == NULL)
720                         return NT_STATUS_NO_MEMORY;
721         } else {
722                 sid_array.sids = NULL;
723         }
724
725         for (i=0; i<num_sids; i++) {
726                 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[i]);
727                 if (!sid_array.sids[i].sid) {
728                         return NT_STATUS_NO_MEMORY;
729                 }
730         }
731
732         sid_array.num_sids = num_sids;
733
734         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
735         strupper_m(server);
736                 
737         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
738                                    &connect_pol);
739
740         if (!NT_STATUS_IS_OK(result))
741                 goto done;
742
743         if (StrCaseCmp(argv[1], "domain")==0)
744                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
745                                                 &connect_pol,
746                                                 access_mask,
747                                                 &domain_sid, &domain_pol);
748         else if (StrCaseCmp(argv[1], "builtin")==0)
749                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
750                                                 &connect_pol,
751                                                 access_mask,
752                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
753                                                 &domain_pol);
754         else {
755                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
756                 return NT_STATUS_INVALID_PARAMETER;
757         }
758
759         if (!NT_STATUS_IS_OK(result))
760                 goto done;
761
762         result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
763                                                 &domain_pol,
764                                                 &sid_array,
765                                                 &alias_rids);
766         if (!NT_STATUS_IS_OK(result))
767                 goto done;
768
769         for (i = 0; i < alias_rids.count; i++) {
770                 printf("\tgroup rid:[0x%x]\n", alias_rids.ids[i]);
771         }
772
773         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
774         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
775  done:
776         return result;
777 }
778
779 /* Query members of a group */
780
781 static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli, 
782                                         TALLOC_CTX *mem_ctx,
783                                         int argc, const char **argv) 
784 {
785         POLICY_HND connect_pol, domain_pol, group_pol;
786         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
787         uint32 group_rid;
788         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
789         int i;
790         fstring                 server;
791         unsigned int old_timeout;
792         struct samr_RidTypeArray *rids = NULL;
793
794         if ((argc < 2) || (argc > 3)) {
795                 printf("Usage: %s rid [access mask]\n", argv[0]);
796                 return NT_STATUS_OK;
797         }
798
799         sscanf(argv[1], "%i", &group_rid);
800         
801         if (argc > 2)
802                 sscanf(argv[2], "%x", &access_mask);
803
804         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
805         strupper_m(server);
806
807         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
808                                    &connect_pol);
809
810         if (!NT_STATUS_IS_OK(result))
811                 goto done;
812
813         result = rpccli_samr_OpenDomain(cli, mem_ctx,
814                                         &connect_pol,
815                                         MAXIMUM_ALLOWED_ACCESS,
816                                         &domain_sid,
817                                         &domain_pol);
818
819         if (!NT_STATUS_IS_OK(result))
820                 goto done;
821
822         result = rpccli_samr_OpenGroup(cli, mem_ctx,
823                                        &domain_pol,
824                                        access_mask,
825                                        group_rid,
826                                        &group_pol);
827
828         if (!NT_STATUS_IS_OK(result))
829                 goto done;
830
831         /* Make sure to wait for our DC's reply */
832         old_timeout = cli_set_timeout(cli->cli, MAX(cli->cli->timeout,30000)); /* 30 seconds. */
833
834         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
835                                               &group_pol,
836                                               &rids);
837
838         cli_set_timeout(cli->cli, old_timeout);
839
840         if (!NT_STATUS_IS_OK(result))
841                 goto done;
842
843         for (i = 0; i < rids->count; i++) {
844                 printf("\trid:[0x%x] attr:[0x%x]\n", rids->rids[i],
845                        rids->types[i]);
846         }
847
848         rpccli_samr_Close(cli, mem_ctx, &group_pol);
849         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
850         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
851  done:
852         return result;
853 }
854
855 /* Enumerate domain users */
856
857 static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli, 
858                                         TALLOC_CTX *mem_ctx,
859                                         int argc, const char **argv) 
860 {
861         POLICY_HND connect_pol, domain_pol;
862         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
863         uint32 start_idx, size, num_dom_users, i;
864         char **dom_users;
865         uint32 *dom_rids;
866         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
867         uint32 acb_mask = ACB_NORMAL;
868         bool got_connect_pol = False, got_domain_pol = False;
869
870         if ((argc < 1) || (argc > 3)) {
871                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
872                 return NT_STATUS_OK;
873         }
874         
875         if (argc > 1)
876                 sscanf(argv[1], "%x", &access_mask);
877
878         if (argc > 2)
879                 sscanf(argv[2], "%x", &acb_mask);
880
881         /* Get sam policy handle */
882
883         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
884                                    &connect_pol);
885
886         if (!NT_STATUS_IS_OK(result))
887                 goto done;
888
889         got_connect_pol = True;
890
891         /* Get domain policy handle */
892
893         result = rpccli_samr_OpenDomain(cli, mem_ctx,
894                                         &connect_pol,
895                                         access_mask,
896                                         &domain_sid,
897                                         &domain_pol);
898
899         if (!NT_STATUS_IS_OK(result))
900                 goto done;
901
902         got_domain_pol = True;
903
904         /* Enumerate domain users */
905
906         start_idx = 0;
907         size = 0xffff;
908
909         do {
910                 result = rpccli_samr_enum_dom_users(
911                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
912                         size, &dom_users, &dom_rids, &num_dom_users);
913
914                 if (NT_STATUS_IS_OK(result) ||
915                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
916
917                         for (i = 0; i < num_dom_users; i++)
918                                printf("user:[%s] rid:[0x%x]\n", 
919                                        dom_users[i], dom_rids[i]);
920                 }
921
922         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
923
924  done:
925         if (got_domain_pol)
926                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
927
928         if (got_connect_pol)
929                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
930
931         return result;
932 }
933
934 /* Enumerate domain groups */
935
936 static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli, 
937                                          TALLOC_CTX *mem_ctx,
938                                          int argc, const char **argv) 
939 {
940         POLICY_HND connect_pol, domain_pol;
941         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
942         uint32 start_idx, size, num_dom_groups, i;
943         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
944         struct acct_info *dom_groups;
945         bool got_connect_pol = False, got_domain_pol = False;
946
947         if ((argc < 1) || (argc > 2)) {
948                 printf("Usage: %s [access_mask]\n", argv[0]);
949                 return NT_STATUS_OK;
950         }
951         
952         if (argc > 1)
953                 sscanf(argv[1], "%x", &access_mask);
954
955         /* Get sam policy handle */
956
957         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
958                                    &connect_pol);
959
960         if (!NT_STATUS_IS_OK(result))
961                 goto done;
962
963         got_connect_pol = True;
964
965         /* Get domain policy handle */
966
967         result = rpccli_samr_OpenDomain(cli, mem_ctx,
968                                         &connect_pol,
969                                         access_mask,
970                                         &domain_sid,
971                                         &domain_pol);
972
973         if (!NT_STATUS_IS_OK(result))
974                 goto done;
975
976         got_domain_pol = True;
977
978         /* Enumerate domain groups */
979
980         start_idx = 0;
981         size = 0xffff;
982
983         do {
984                 result = rpccli_samr_enum_dom_groups(
985                         cli, mem_ctx, &domain_pol, &start_idx, size,
986                         &dom_groups, &num_dom_groups);
987
988                 if (NT_STATUS_IS_OK(result) ||
989                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
990
991                         for (i = 0; i < num_dom_groups; i++)
992                                 printf("group:[%s] rid:[0x%x]\n", 
993                                        dom_groups[i].acct_name,
994                                        dom_groups[i].rid);
995                 }
996
997         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
998
999  done:
1000         if (got_domain_pol)
1001                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1002
1003         if (got_connect_pol)
1004                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1005
1006         return result;
1007 }
1008
1009 /* Enumerate alias groups */
1010
1011 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli, 
1012                                          TALLOC_CTX *mem_ctx,
1013                                          int argc, const char **argv) 
1014 {
1015         POLICY_HND connect_pol, domain_pol;
1016         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1017         uint32 start_idx, size, num_als_groups, i;
1018         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1019         struct acct_info *als_groups;
1020         bool got_connect_pol = False, got_domain_pol = False;
1021
1022         if ((argc < 2) || (argc > 3)) {
1023                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
1024                 return NT_STATUS_OK;
1025         }
1026         
1027         if (argc > 2)
1028                 sscanf(argv[2], "%x", &access_mask);
1029
1030         /* Get sam policy handle */
1031
1032         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1033                                    &connect_pol);
1034
1035         if (!NT_STATUS_IS_OK(result))
1036                 goto done;
1037
1038         got_connect_pol = True;
1039
1040         /* Get domain policy handle */
1041
1042         if (StrCaseCmp(argv[1], "domain")==0)
1043                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1044                                                 &connect_pol,
1045                                                 access_mask,
1046                                                 &domain_sid,
1047                                                 &domain_pol);
1048         else if (StrCaseCmp(argv[1], "builtin")==0)
1049                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1050                                                 &connect_pol,
1051                                                 access_mask,
1052                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1053                                                 &domain_pol);
1054         else
1055                 return NT_STATUS_OK;
1056
1057         if (!NT_STATUS_IS_OK(result))
1058                 goto done;
1059
1060         got_domain_pol = True;
1061
1062         /* Enumerate alias groups */
1063
1064         start_idx = 0;
1065         size = 0xffff;          /* Number of groups to retrieve */
1066
1067         do {
1068                 result = rpccli_samr_enum_als_groups(
1069                         cli, mem_ctx, &domain_pol, &start_idx, size,
1070                         &als_groups, &num_als_groups);
1071
1072                 if (NT_STATUS_IS_OK(result) ||
1073                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1074
1075                         for (i = 0; i < num_als_groups; i++)
1076                                 printf("group:[%s] rid:[0x%x]\n", 
1077                                        als_groups[i].acct_name,
1078                                        als_groups[i].rid);
1079                 }
1080         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1081
1082  done:
1083         if (got_domain_pol)
1084                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1085         
1086         if (got_connect_pol)
1087                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1088         
1089         return result;
1090 }
1091
1092 /* Query alias membership */
1093
1094 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli, 
1095                                         TALLOC_CTX *mem_ctx,
1096                                         int argc, const char **argv) 
1097 {
1098         POLICY_HND connect_pol, domain_pol, alias_pol;
1099         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1100         uint32 alias_rid, i;
1101         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1102         struct lsa_SidArray sid_array;
1103
1104         if ((argc < 3) || (argc > 4)) {
1105                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1106                 return NT_STATUS_OK;
1107         }
1108
1109         sscanf(argv[2], "%i", &alias_rid);
1110         
1111         if (argc > 3)
1112                 sscanf(argv[3], "%x", &access_mask);
1113
1114         /* Open SAMR handle */
1115
1116         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1117                                    &connect_pol);
1118
1119         if (!NT_STATUS_IS_OK(result))
1120                 goto done;
1121
1122         /* Open handle on domain */
1123         
1124         if (StrCaseCmp(argv[1], "domain")==0)
1125                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1126                                                 &connect_pol,
1127                                                 MAXIMUM_ALLOWED_ACCESS,
1128                                                 &domain_sid,
1129                                                 &domain_pol);
1130         else if (StrCaseCmp(argv[1], "builtin")==0)
1131                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1132                                                 &connect_pol,
1133                                                 MAXIMUM_ALLOWED_ACCESS,
1134                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1135                                                 &domain_pol);
1136         else
1137                 return NT_STATUS_OK;
1138
1139         if (!NT_STATUS_IS_OK(result))
1140                 goto done;
1141
1142         /* Open handle on alias */
1143
1144         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1145                                        &domain_pol,
1146                                        access_mask,
1147                                        alias_rid,
1148                                        &alias_pol);
1149         if (!NT_STATUS_IS_OK(result))
1150                 goto done;
1151
1152         result = rpccli_samr_GetMembersInAlias(cli, mem_ctx,
1153                                                &alias_pol,
1154                                                &sid_array);
1155
1156         if (!NT_STATUS_IS_OK(result))
1157                 goto done;
1158
1159         for (i = 0; i < sid_array.num_sids; i++) {
1160                 fstring sid_str;
1161
1162                 sid_to_fstring(sid_str, sid_array.sids[i].sid);
1163                 printf("\tsid:[%s]\n", sid_str);
1164         }
1165
1166         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1167         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1168         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1169  done:
1170         return result;
1171 }
1172
1173 /* Query alias info */
1174
1175 static NTSTATUS cmd_samr_query_aliasinfo(struct rpc_pipe_client *cli,
1176                                          TALLOC_CTX *mem_ctx,
1177                                          int argc, const char **argv)
1178 {
1179         POLICY_HND connect_pol, domain_pol, alias_pol;
1180         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1181         uint32_t alias_rid;
1182         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1183         union samr_AliasInfo *info = NULL;
1184         enum samr_AliasInfoEnum level = ALIASINFOALL;
1185
1186         if ((argc < 3) || (argc > 4)) {
1187                 printf("Usage: %s builtin|domain rid [level] [access mask]\n",
1188                         argv[0]);
1189                 return NT_STATUS_OK;
1190         }
1191
1192         sscanf(argv[2], "%i", &alias_rid);
1193
1194         if (argc > 3) {
1195                 level = atoi(argv[3]);
1196         }
1197
1198         if (argc > 4) {
1199                 sscanf(argv[4], "%x", &access_mask);
1200         }
1201
1202         /* Open SAMR handle */
1203
1204         result = try_samr_connects(cli, mem_ctx,
1205                                    SEC_FLAG_MAXIMUM_ALLOWED,
1206                                    &connect_pol);
1207
1208         if (!NT_STATUS_IS_OK(result)) {
1209                 goto done;
1210         }
1211
1212         /* Open handle on domain */
1213
1214         if (strequal(argv[1], "domain")) {
1215
1216                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1217                                                 &connect_pol,
1218                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1219                                                 &domain_sid,
1220                                                 &domain_pol);
1221
1222         } else if (strequal(argv[1], "builtin")) {
1223
1224                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1225                                                 &connect_pol,
1226                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1227                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1228                                                 &domain_pol);
1229
1230         } else {
1231                 return NT_STATUS_OK;
1232         }
1233
1234         if (!NT_STATUS_IS_OK(result)) {
1235                 goto done;
1236         }
1237
1238         /* Open handle on alias */
1239
1240         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1241                                        &domain_pol,
1242                                        access_mask,
1243                                        alias_rid,
1244                                        &alias_pol);
1245         if (!NT_STATUS_IS_OK(result)) {
1246                 goto done;
1247         }
1248
1249         result = rpccli_samr_QueryAliasInfo(cli, mem_ctx,
1250                                             &alias_pol,
1251                                             level,
1252                                             &info);
1253
1254         if (!NT_STATUS_IS_OK(result)) {
1255                 goto done;
1256         }
1257
1258         switch (level) {
1259                 case ALIASINFOALL:
1260                         printf("Name: %s\n", info->all.name.string);
1261                         printf("Description: %s\n", info->all.description.string);
1262                         printf("Num Members: %d\n", info->all.num_members);
1263                         break;
1264                 case ALIASINFONAME:
1265                         printf("Name: %s\n", info->name.string);
1266                         break;
1267                 case ALIASINFODESCRIPTION:
1268                         printf("Description: %s\n", info->description.string);
1269                         break;
1270                 default:
1271                         break;
1272         }
1273
1274         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1275         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1276         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1277  done:
1278         return result;
1279 }
1280
1281
1282 /* Query delete an alias membership */
1283
1284 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli, 
1285                                       TALLOC_CTX *mem_ctx,
1286                                       int argc, const char **argv) 
1287 {
1288         POLICY_HND connect_pol, domain_pol, alias_pol;
1289         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1290         uint32 alias_rid;
1291         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1292
1293         if (argc != 3) {
1294                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1295                 return NT_STATUS_OK;
1296         }
1297
1298         alias_rid = strtoul(argv[2], NULL, 10);
1299         
1300         /* Open SAMR handle */
1301
1302         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1303                                    &connect_pol);
1304
1305         if (!NT_STATUS_IS_OK(result))
1306                 goto done;
1307
1308         /* Open handle on domain */
1309         
1310         if (StrCaseCmp(argv[1], "domain")==0)
1311                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1312                                                 &connect_pol,
1313                                                 MAXIMUM_ALLOWED_ACCESS,
1314                                                 &domain_sid,
1315                                                 &domain_pol);
1316         else if (StrCaseCmp(argv[1], "builtin")==0)
1317                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1318                                                 &connect_pol,
1319                                                 MAXIMUM_ALLOWED_ACCESS,
1320                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1321                                                 &domain_pol);
1322         else
1323                 return NT_STATUS_INVALID_PARAMETER;
1324
1325         if (!NT_STATUS_IS_OK(result))
1326                 goto done;
1327
1328         /* Open handle on alias */
1329
1330         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1331                                        &domain_pol,
1332                                        access_mask,
1333                                        alias_rid,
1334                                        &alias_pol);
1335         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1336                 /* Probably this was a user name, try lookupnames */
1337                 uint32 num_rids;
1338                 uint32 *rids, *types;
1339                 
1340                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1341                                                   1000, 1, &argv[2],
1342                                                   &num_rids, &rids,
1343                                                   &types);
1344
1345                 if (NT_STATUS_IS_OK(result)) {
1346                         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1347                                                        &domain_pol,
1348                                                        access_mask,
1349                                                        rids[0],
1350                                                        &alias_pol);
1351                 }
1352         }
1353
1354         result = rpccli_samr_DeleteDomAlias(cli, mem_ctx,
1355                                             &alias_pol);
1356
1357         if (!NT_STATUS_IS_OK(result))
1358                 goto done;
1359
1360         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1361         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1362  done:
1363         return result;
1364 }
1365
1366 /* Query display info */
1367
1368 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
1369                                         TALLOC_CTX *mem_ctx,
1370                                         int argc, const char **argv) 
1371 {
1372         POLICY_HND connect_pol, domain_pol;
1373         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1374         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
1375         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1376         uint32 info_level = 1;
1377         SAM_DISPINFO_CTR ctr;
1378         SAM_DISPINFO_1 info1;
1379         SAM_DISPINFO_2 info2;
1380         SAM_DISPINFO_3 info3;
1381         SAM_DISPINFO_4 info4;
1382         SAM_DISPINFO_5 info5;
1383         int loop_count = 0;
1384         bool got_params = False; /* Use get_query_dispinfo_params() or not? */
1385
1386         if (argc > 6) {
1387                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1388                 return NT_STATUS_OK;
1389         }
1390
1391         if (argc >= 2)
1392                 sscanf(argv[1], "%i", &info_level);
1393         
1394         if (argc >= 3)
1395                 sscanf(argv[2], "%i", &start_idx);
1396         
1397         if (argc >= 4) {
1398                 sscanf(argv[3], "%i", &max_entries);
1399                 got_params = True;
1400         }
1401         
1402         if (argc >= 5) {
1403                 sscanf(argv[4], "%i", &max_size);
1404                 got_params = True;
1405         }
1406         
1407         if (argc >= 6)
1408                 sscanf(argv[5], "%x", &access_mask);
1409
1410         /* Get sam policy handle */
1411
1412         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1413                                    &connect_pol);
1414
1415         if (!NT_STATUS_IS_OK(result))
1416                 goto done;
1417
1418         /* Get domain policy handle */
1419
1420         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1421                                         &connect_pol,
1422                                         access_mask,
1423                                         &domain_sid,
1424                                         &domain_pol);
1425
1426         if (!NT_STATUS_IS_OK(result))
1427                 goto done;
1428
1429         /* Query display info */
1430
1431         ZERO_STRUCT(ctr);
1432         ZERO_STRUCT(info1);
1433         
1434         switch (info_level) {
1435         case 1:
1436                 ZERO_STRUCT(info1);
1437                 ctr.sam.info1 = &info1;
1438                 break;
1439         case 2:
1440                 ZERO_STRUCT(info2);
1441                 ctr.sam.info2 = &info2;
1442                 break;
1443         case 3:
1444                 ZERO_STRUCT(info3);
1445                 ctr.sam.info3 = &info3;
1446                 break;
1447         case 4:
1448                 ZERO_STRUCT(info4);
1449                 ctr.sam.info4 = &info4;
1450                 break;
1451         case 5:
1452                 ZERO_STRUCT(info5);
1453                 ctr.sam.info5 = &info5;
1454                 break;
1455         }
1456
1457
1458         do {
1459
1460                 if (!got_params)
1461                         get_query_dispinfo_params(
1462                                 loop_count, &max_entries, &max_size);
1463                 
1464                 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1465                                                  &start_idx, info_level,
1466                                                  &num_entries, max_entries, 
1467                                                  max_size, &ctr);
1468
1469                 loop_count++;
1470
1471                 if (NT_STATUS_IS_ERR(result))
1472                         break;
1473
1474                 if (num_entries == 0) 
1475                         break;
1476
1477                 for (i = 0; i < num_entries; i++) {
1478                         switch (info_level) {
1479                         case 1:
1480                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1481                                 break;
1482                         case 2:
1483                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1484                                 break;
1485                         case 3:
1486                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1487                                 break;
1488                         case 4:
1489                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1490                                 break;
1491                         case 5:
1492                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1493                                 break;
1494                         }
1495                 }
1496         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1497
1498         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1499         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1500  done:
1501         return result;
1502 }
1503
1504 /* Query domain info */
1505
1506 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, 
1507                                        TALLOC_CTX *mem_ctx,
1508                                        int argc, const char **argv) 
1509 {
1510         POLICY_HND connect_pol, domain_pol;
1511         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1512         uint32 switch_level = 2;
1513         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1514         union samr_DomainInfo *info = NULL;
1515
1516         if (argc > 3) {
1517                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1518                 return NT_STATUS_OK;
1519         }
1520
1521         if (argc > 1)
1522                 sscanf(argv[1], "%i", &switch_level);
1523         
1524         if (argc > 2)
1525                 sscanf(argv[2], "%x", &access_mask);
1526
1527         /* Get sam policy handle */
1528
1529         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1530                                    &connect_pol);
1531
1532         if (!NT_STATUS_IS_OK(result))
1533                 goto done;
1534
1535         /* Get domain policy handle */
1536
1537         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1538                                         &connect_pol,
1539                                         access_mask,
1540                                         &domain_sid,
1541                                         &domain_pol);
1542
1543         if (!NT_STATUS_IS_OK(result))
1544                 goto done;
1545
1546         /* Query domain info */
1547
1548         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1549                                              &domain_pol,
1550                                              switch_level,
1551                                              &info);
1552
1553         if (!NT_STATUS_IS_OK(result))
1554                 goto done;
1555
1556         /* Display domain info */
1557
1558         switch (switch_level) {
1559         case 1:
1560                 display_sam_dom_info_1(&info->info1);
1561                 break;
1562         case 2:
1563                 display_sam_dom_info_2(&info->info2);
1564                 break;
1565         case 3:
1566                 display_sam_dom_info_3(&info->info3);
1567                 break;
1568         case 4:
1569                 display_sam_dom_info_4(&info->info4);
1570                 break;
1571         case 5:
1572                 display_sam_dom_info_5(&info->info5);
1573                 break;
1574         case 6:
1575                 display_sam_dom_info_6(&info->info6);
1576                 break;
1577         case 7:
1578                 display_sam_dom_info_7(&info->info7);
1579                 break;
1580         case 8:
1581                 display_sam_dom_info_8(&info->info8);
1582                 break;
1583         case 9:
1584                 display_sam_dom_info_9(&info->info9);
1585                 break;
1586         case 12:
1587                 display_sam_dom_info_12(&info->info12);
1588                 break;
1589         case 13:
1590                 display_sam_dom_info_13(&info->info13);
1591                 break;
1592
1593         default:
1594                 printf("cannot display domain info for switch value %d\n",
1595                        switch_level);
1596                 break;
1597         }
1598
1599  done:
1600
1601         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1602         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1603         return result;
1604 }
1605
1606 /* Create domain user */
1607
1608 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, 
1609                                          TALLOC_CTX *mem_ctx,
1610                                          int argc, const char **argv) 
1611 {
1612         POLICY_HND connect_pol, domain_pol, user_pol;
1613         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1614         struct lsa_String acct_name;
1615         uint32 acb_info;
1616         uint32 acct_flags, user_rid;
1617         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1618         uint32_t access_granted = 0;
1619
1620         if ((argc < 2) || (argc > 3)) {
1621                 printf("Usage: %s username [access mask]\n", argv[0]);
1622                 return NT_STATUS_OK;
1623         }
1624
1625         init_lsa_String(&acct_name, argv[1]);
1626
1627         if (argc > 2)
1628                 sscanf(argv[2], "%x", &access_mask);
1629
1630         /* Get sam policy handle */
1631
1632         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1633                                    &connect_pol);
1634
1635         if (!NT_STATUS_IS_OK(result))
1636                 goto done;
1637
1638         /* Get domain policy handle */
1639
1640         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1641                                         &connect_pol,
1642                                         access_mask,
1643                                         &domain_sid,
1644                                         &domain_pol);
1645
1646         if (!NT_STATUS_IS_OK(result))
1647                 goto done;
1648
1649         /* Create domain user */
1650
1651         acb_info = ACB_NORMAL;
1652         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
1653                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
1654                      SAMR_USER_ACCESS_SET_PASSWORD |
1655                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
1656                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
1657
1658         result = rpccli_samr_CreateUser2(cli, mem_ctx,
1659                                          &domain_pol,
1660                                          &acct_name,
1661                                          acb_info,
1662                                          acct_flags,
1663                                          &user_pol,
1664                                          &access_granted,
1665                                          &user_rid);
1666
1667         if (!NT_STATUS_IS_OK(result))
1668                 goto done;
1669
1670         result = rpccli_samr_Close(cli, mem_ctx, &user_pol);
1671         if (!NT_STATUS_IS_OK(result)) goto done;
1672
1673         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1674         if (!NT_STATUS_IS_OK(result)) goto done;
1675
1676         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1677         if (!NT_STATUS_IS_OK(result)) goto done;
1678
1679  done:
1680         return result;
1681 }
1682
1683 /* Create domain group */
1684
1685 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, 
1686                                           TALLOC_CTX *mem_ctx,
1687                                           int argc, const char **argv) 
1688 {
1689         POLICY_HND connect_pol, domain_pol, group_pol;
1690         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1691         struct lsa_String grp_name;
1692         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1693         uint32_t rid = 0;
1694
1695         if ((argc < 2) || (argc > 3)) {
1696                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1697                 return NT_STATUS_OK;
1698         }
1699
1700         init_lsa_String(&grp_name, argv[1]);
1701
1702         if (argc > 2)
1703                 sscanf(argv[2], "%x", &access_mask);
1704
1705         /* Get sam policy handle */
1706
1707         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1708                                    &connect_pol);
1709
1710         if (!NT_STATUS_IS_OK(result))
1711                 goto done;
1712
1713         /* Get domain policy handle */
1714
1715         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1716                                         &connect_pol,
1717                                         access_mask,
1718                                         &domain_sid,
1719                                         &domain_pol);
1720
1721         if (!NT_STATUS_IS_OK(result))
1722                 goto done;
1723
1724         /* Create domain user */
1725         result = rpccli_samr_CreateDomainGroup(cli, mem_ctx,
1726                                                &domain_pol,
1727                                                &grp_name,
1728                                                MAXIMUM_ALLOWED_ACCESS,
1729                                                &group_pol,
1730                                                &rid);
1731
1732         if (!NT_STATUS_IS_OK(result))
1733                 goto done;
1734
1735         result = rpccli_samr_Close(cli, mem_ctx, &group_pol);
1736         if (!NT_STATUS_IS_OK(result)) goto done;
1737
1738         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1739         if (!NT_STATUS_IS_OK(result)) goto done;
1740
1741         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1742         if (!NT_STATUS_IS_OK(result)) goto done;
1743
1744  done:
1745         return result;
1746 }
1747
1748 /* Create domain alias */
1749
1750 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli, 
1751                                           TALLOC_CTX *mem_ctx,
1752                                           int argc, const char **argv) 
1753 {
1754         POLICY_HND connect_pol, domain_pol, alias_pol;
1755         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1756         struct lsa_String alias_name;
1757         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1758         uint32_t rid = 0;
1759
1760         if ((argc < 2) || (argc > 3)) {
1761                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1762                 return NT_STATUS_OK;
1763         }
1764
1765         init_lsa_String(&alias_name, argv[1]);
1766
1767         if (argc > 2)
1768                 sscanf(argv[2], "%x", &access_mask);
1769
1770         /* Get sam policy handle */
1771
1772         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1773                                    &connect_pol);
1774
1775         if (!NT_STATUS_IS_OK(result))
1776                 goto done;
1777
1778         /* Get domain policy handle */
1779
1780         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1781                                         &connect_pol,
1782                                         access_mask,
1783                                         &domain_sid,
1784                                         &domain_pol);
1785
1786         if (!NT_STATUS_IS_OK(result))
1787                 goto done;
1788
1789         /* Create domain user */
1790
1791         result = rpccli_samr_CreateDomAlias(cli, mem_ctx,
1792                                             &domain_pol,
1793                                             &alias_name,
1794                                             MAXIMUM_ALLOWED_ACCESS,
1795                                             &alias_pol,
1796                                             &rid);
1797
1798         if (!NT_STATUS_IS_OK(result))
1799                 goto done;
1800
1801         result = rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1802         if (!NT_STATUS_IS_OK(result)) goto done;
1803
1804         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1805         if (!NT_STATUS_IS_OK(result)) goto done;
1806
1807         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1808         if (!NT_STATUS_IS_OK(result)) goto done;
1809
1810  done:
1811         return result;
1812 }
1813
1814 /* Lookup sam names */
1815
1816 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
1817                                       TALLOC_CTX *mem_ctx,
1818                                       int argc, const char **argv) 
1819 {
1820         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1821         POLICY_HND connect_pol, domain_pol;
1822         uint32 flags = 0x000003e8; /* Unknown */
1823         uint32 num_rids, num_names, *name_types, *rids;
1824         const char **names;
1825         int i;
1826
1827         if (argc < 3) {
1828                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1829                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1830                 printf("or check on the builtin SID: S-1-5-32\n");
1831                 return NT_STATUS_OK;
1832         }
1833
1834         /* Get sam policy and domain handles */
1835
1836         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1837                                    &connect_pol);
1838
1839         if (!NT_STATUS_IS_OK(result))
1840                 goto done;
1841
1842         if (StrCaseCmp(argv[1], "domain")==0)
1843                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1844                                                 &connect_pol,
1845                                                 MAXIMUM_ALLOWED_ACCESS,
1846                                                 &domain_sid,
1847                                                 &domain_pol);
1848         else if (StrCaseCmp(argv[1], "builtin")==0)
1849                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1850                                                 &connect_pol,
1851                                                 MAXIMUM_ALLOWED_ACCESS,
1852                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1853                                                 &domain_pol);
1854         else
1855                 return NT_STATUS_OK;
1856
1857         if (!NT_STATUS_IS_OK(result))
1858                 goto done;
1859
1860         /* Look up names */
1861
1862         num_names = argc - 2;
1863
1864         if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
1865                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1866                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1867                 result = NT_STATUS_NO_MEMORY;
1868                 goto done;
1869         }
1870
1871         for (i = 0; i < num_names; i++)
1872                 names[i] = argv[i + 2];
1873
1874         result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1875                                        flags, num_names, names,
1876                                        &num_rids, &rids, &name_types);
1877
1878         if (!NT_STATUS_IS_OK(result))
1879                 goto done;
1880
1881         /* Display results */
1882
1883         for (i = 0; i < num_names; i++)
1884                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1885                        name_types[i]);
1886
1887         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1888         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1889  done:
1890         return result;
1891 }
1892
1893 /* Lookup sam rids */
1894
1895 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, 
1896                                      TALLOC_CTX *mem_ctx,
1897                                      int argc, const char **argv) 
1898 {
1899         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1900         POLICY_HND connect_pol, domain_pol;
1901         uint32 num_rids, num_names, *rids, *name_types;
1902         char **names;
1903         int i;
1904
1905         if (argc < 3) {
1906                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1907                 return NT_STATUS_OK;
1908         }
1909
1910         /* Get sam policy and domain handles */
1911
1912         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1913                                    &connect_pol);
1914
1915         if (!NT_STATUS_IS_OK(result))
1916                 goto done;
1917
1918         if (StrCaseCmp(argv[1], "domain")==0)
1919                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1920                                                 &connect_pol,
1921                                                 MAXIMUM_ALLOWED_ACCESS,
1922                                                 &domain_sid,
1923                                                 &domain_pol);
1924         else if (StrCaseCmp(argv[1], "builtin")==0)
1925                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1926                                                 &connect_pol,
1927                                                 MAXIMUM_ALLOWED_ACCESS,
1928                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1929                                                 &domain_pol);
1930         else
1931                 return NT_STATUS_OK;
1932
1933         if (!NT_STATUS_IS_OK(result))
1934                 goto done;
1935
1936         /* Look up rids */
1937
1938         num_rids = argc - 2;
1939
1940         if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1941                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1942                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1943                 result = NT_STATUS_NO_MEMORY;
1944                 goto done;
1945         }
1946
1947         for (i = 0; i < argc - 2; i++)
1948                 sscanf(argv[i + 2], "%i", &rids[i]);
1949
1950         result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
1951                                       &num_names, &names, &name_types);
1952
1953         if (!NT_STATUS_IS_OK(result) &&
1954             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1955                 goto done;
1956
1957         /* Display results */
1958
1959         for (i = 0; i < num_names; i++)
1960                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1961
1962         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1963         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1964  done:
1965         return result;
1966 }
1967
1968 /* Delete domain group */
1969
1970 static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli, 
1971                                          TALLOC_CTX *mem_ctx,
1972                                          int argc, const char **argv) 
1973 {
1974         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1975         POLICY_HND connect_pol, domain_pol, group_pol;
1976         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1977
1978         if ((argc < 2) || (argc > 3)) {
1979                 printf("Usage: %s groupname\n", argv[0]);
1980                 return NT_STATUS_OK;
1981         }
1982         
1983         if (argc > 2)
1984                 sscanf(argv[2], "%x", &access_mask);
1985
1986         /* Get sam policy and domain handles */
1987
1988         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1989                                    &connect_pol);
1990
1991         if (!NT_STATUS_IS_OK(result))
1992                 goto done;
1993
1994         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1995                                         &connect_pol,
1996                                         MAXIMUM_ALLOWED_ACCESS,
1997                                         &domain_sid,
1998                                         &domain_pol);
1999
2000         if (!NT_STATUS_IS_OK(result))
2001                 goto done;
2002
2003         /* Get handle on group */
2004
2005         {
2006                 uint32 *group_rids, num_rids, *name_types;
2007                 uint32 flags = 0x000003e8; /* Unknown */
2008
2009                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
2010                                                flags, 1, (const char **)&argv[1],
2011                                                &num_rids, &group_rids,
2012                                                &name_types);
2013
2014                 if (!NT_STATUS_IS_OK(result))
2015                         goto done;
2016
2017                 result = rpccli_samr_OpenGroup(cli, mem_ctx,
2018                                                &domain_pol,
2019                                                access_mask,
2020                                                group_rids[0],
2021                                                &group_pol);
2022
2023                 if (!NT_STATUS_IS_OK(result))
2024                         goto done;
2025         }
2026
2027         /* Delete group */
2028
2029         result = rpccli_samr_DeleteDomainGroup(cli, mem_ctx,
2030                                                &group_pol);
2031
2032         if (!NT_STATUS_IS_OK(result))
2033                 goto done;
2034
2035         /* Display results */
2036
2037         rpccli_samr_Close(cli, mem_ctx, &group_pol);
2038         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2039         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2040
2041  done:
2042         return result;
2043 }
2044
2045 /* Delete domain user */
2046
2047 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
2048                                          TALLOC_CTX *mem_ctx,
2049                                          int argc, const char **argv) 
2050 {
2051         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2052         POLICY_HND connect_pol, domain_pol, user_pol;
2053         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2054
2055         if ((argc < 2) || (argc > 3)) {
2056                 printf("Usage: %s username\n", argv[0]);
2057                 return NT_STATUS_OK;
2058         }
2059         
2060         if (argc > 2)
2061                 sscanf(argv[2], "%x", &access_mask);
2062
2063         /* Get sam policy and domain handles */
2064
2065         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2066                                    &connect_pol);
2067
2068         if (!NT_STATUS_IS_OK(result))
2069                 goto done;
2070
2071         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2072                                         &connect_pol,
2073                                         MAXIMUM_ALLOWED_ACCESS,
2074                                         &domain_sid,
2075                                         &domain_pol);
2076
2077         if (!NT_STATUS_IS_OK(result))
2078                 goto done;
2079
2080         /* Get handle on user */
2081
2082         {
2083                 uint32 *user_rids, num_rids, *name_types;
2084                 uint32 flags = 0x000003e8; /* Unknown */
2085
2086                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
2087                                                flags, 1, (const char **)&argv[1],
2088                                                &num_rids, &user_rids,
2089                                                &name_types);
2090
2091                 if (!NT_STATUS_IS_OK(result))
2092                         goto done;
2093
2094                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2095                                               &domain_pol,
2096                                               access_mask,
2097                                               user_rids[0],
2098                                               &user_pol);
2099
2100                 if (!NT_STATUS_IS_OK(result))
2101                         goto done;
2102         }
2103
2104         /* Delete user */
2105
2106         result = rpccli_samr_DeleteUser(cli, mem_ctx,
2107                                         &user_pol);
2108
2109         if (!NT_STATUS_IS_OK(result))
2110                 goto done;
2111
2112         /* Display results */
2113
2114         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2115         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2116         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2117
2118  done:
2119         return result;
2120 }
2121
2122 /**********************************************************************
2123  * Query user security object 
2124  */
2125 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, 
2126                                     TALLOC_CTX *mem_ctx,
2127                                     int argc, const char **argv) 
2128 {
2129         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
2130         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2131         uint32 sec_info = DACL_SECURITY_INFORMATION;
2132         fstring server;
2133         uint32 user_rid = 0;
2134         TALLOC_CTX *ctx = NULL;
2135         SEC_DESC_BUF *sec_desc_buf=NULL;
2136         bool domain = False;
2137
2138         ctx=talloc_init("cmd_samr_query_sec_obj");
2139         
2140         if ((argc < 1) || (argc > 3)) {
2141                 printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
2142                 printf("\tSpecify rid for security on user, -d for security on domain\n");
2143                 talloc_destroy(ctx);
2144                 return NT_STATUS_OK;
2145         }
2146         
2147         if (argc > 1) {
2148                 if (strcmp(argv[1], "-d") == 0)
2149                         domain = True;
2150                 else
2151                         sscanf(argv[1], "%i", &user_rid);
2152         }
2153
2154         if (argc == 3) {
2155                 sec_info = atoi(argv[2]);
2156         }
2157         
2158         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
2159         strupper_m(server);
2160         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2161                                    &connect_pol);
2162
2163         if (!NT_STATUS_IS_OK(result))
2164                 goto done;
2165
2166         if (domain || user_rid)
2167                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
2168                                                 &connect_pol,
2169                                                 MAXIMUM_ALLOWED_ACCESS,
2170                                                 &domain_sid,
2171                                                 &domain_pol);
2172
2173         if (!NT_STATUS_IS_OK(result))
2174                 goto done;
2175
2176         if (user_rid)
2177                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2178                                               &domain_pol,
2179                                               MAXIMUM_ALLOWED_ACCESS,
2180                                               user_rid,
2181                                               &user_pol);
2182
2183         if (!NT_STATUS_IS_OK(result))
2184                 goto done;
2185
2186         /* Pick which query pol to use */
2187
2188         pol = &connect_pol;
2189
2190         if (domain)
2191                 pol = &domain_pol;
2192
2193         if (user_rid)
2194                 pol = &user_pol;
2195
2196         /* Query SAM security object */
2197
2198         result = rpccli_samr_QuerySecurity(cli, mem_ctx,
2199                                            pol,
2200                                            sec_info,
2201                                            &sec_desc_buf);
2202
2203         if (!NT_STATUS_IS_OK(result))
2204                 goto done;
2205
2206         display_sec_desc(sec_desc_buf->sd);
2207
2208         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2209         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2210         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2211 done:
2212         talloc_destroy(ctx);
2213         return result;
2214 }
2215
2216 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli, 
2217                                            TALLOC_CTX *mem_ctx,
2218                                            int argc, const char **argv) 
2219 {
2220         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2221         POLICY_HND connect_pol, domain_pol, user_pol;
2222         struct samr_PwInfo info;
2223         uint32_t rid;
2224
2225         if (argc != 2) {
2226                 printf("Usage: %s rid\n", argv[0]);
2227                 return NT_STATUS_OK;
2228         }
2229
2230         sscanf(argv[1], "%i", &rid);
2231
2232         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2233                                    &connect_pol);
2234
2235         if (!NT_STATUS_IS_OK(result)) {
2236                 goto done;
2237         }
2238
2239         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2240                                         &connect_pol,
2241                                         MAXIMUM_ALLOWED_ACCESS,
2242                                         &domain_sid,
2243                                         &domain_pol);
2244
2245         if (!NT_STATUS_IS_OK(result)) {
2246                 goto done;
2247         }
2248
2249         result = rpccli_samr_OpenUser(cli, mem_ctx,
2250                                       &domain_pol,
2251                                       MAXIMUM_ALLOWED_ACCESS,
2252                                       rid,
2253                                       &user_pol);
2254
2255         if (!NT_STATUS_IS_OK(result)) {
2256                 goto done;
2257         }
2258
2259         result = rpccli_samr_GetUserPwInfo(cli, mem_ctx, &user_pol, &info);
2260         if (NT_STATUS_IS_OK(result)) {
2261                 printf("min_password_length: %d\n", info.min_password_length);
2262                 printf("%s\n",
2263                         NDR_PRINT_STRUCT_STRING(mem_ctx,
2264                                 samr_PasswordProperties, &info.password_properties));
2265         }
2266
2267  done:
2268         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2269         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2270         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2271
2272         return result;
2273 }
2274
2275 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
2276                                         TALLOC_CTX *mem_ctx,
2277                                         int argc, const char **argv)
2278 {
2279         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2280         struct lsa_String domain_name;
2281         struct samr_PwInfo info;
2282
2283         if (argc < 1 || argc > 3) {
2284                 printf("Usage: %s <domain>\n", argv[0]);
2285                 return NT_STATUS_OK;
2286         }
2287
2288         init_lsa_String(&domain_name, argv[1]);
2289
2290         result = rpccli_samr_GetDomPwInfo(cli, mem_ctx, &domain_name, &info);
2291
2292         if (NT_STATUS_IS_OK(result)) {
2293                 printf("min_password_length: %d\n", info.min_password_length);
2294                 display_password_properties(info.password_properties);
2295         }
2296
2297         return result;
2298 }
2299
2300 /* Look up domain name */
2301
2302 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, 
2303                                        TALLOC_CTX *mem_ctx,
2304                                        int argc, const char **argv) 
2305 {
2306         POLICY_HND connect_pol, domain_pol;
2307         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2308         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2309         fstring sid_string;
2310         struct lsa_String domain_name;
2311         DOM_SID *sid = NULL;
2312
2313         if (argc != 2) {
2314                 printf("Usage: %s domain_name\n", argv[0]);
2315                 return NT_STATUS_OK;
2316         }
2317
2318         init_lsa_String(&domain_name, argv[1]);
2319
2320         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
2321         
2322         if (!NT_STATUS_IS_OK(result))
2323                 goto done;
2324
2325         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2326                                         &connect_pol,
2327                                         access_mask,
2328                                         &domain_sid,
2329                                         &domain_pol);
2330
2331         if (!NT_STATUS_IS_OK(result))
2332                 goto done;
2333
2334         result = rpccli_samr_LookupDomain(cli, mem_ctx,
2335                                           &connect_pol,
2336                                           &domain_name,
2337                                           &sid);
2338
2339         if (NT_STATUS_IS_OK(result)) {
2340                 sid_to_fstring(sid_string, sid);
2341                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
2342                        argv[1], sid_string);
2343         }
2344
2345         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2346         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2347 done:
2348         return result;
2349 }
2350
2351 /* Change user password */
2352
2353 static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli, 
2354                                     TALLOC_CTX *mem_ctx,
2355                                     int argc, const char **argv) 
2356 {
2357         POLICY_HND connect_pol, domain_pol;
2358         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2359         const char *user, *oldpass, *newpass;
2360         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2361
2362         if (argc < 3) {
2363                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2364                 return NT_STATUS_INVALID_PARAMETER;
2365         }
2366
2367         user = argv[1];
2368         oldpass = argv[2];
2369         newpass = argv[3];
2370
2371         /* Get sam policy handle */
2372
2373         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2374                                    &connect_pol);
2375
2376         if (!NT_STATUS_IS_OK(result))
2377                 goto done;
2378
2379         /* Get domain policy handle */
2380
2381         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2382                                         &connect_pol,
2383                                         access_mask,
2384                                         &domain_sid,
2385                                         &domain_pol);
2386
2387         if (!NT_STATUS_IS_OK(result))
2388                 goto done;
2389
2390         /* Change user password */
2391         result = rpccli_samr_chgpasswd_user(cli, mem_ctx, user, newpass, oldpass);
2392
2393         if (!NT_STATUS_IS_OK(result))
2394                 goto done;
2395
2396         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2397         if (!NT_STATUS_IS_OK(result)) goto done;
2398
2399         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2400         if (!NT_STATUS_IS_OK(result)) goto done;
2401
2402  done:
2403         return result;
2404 }
2405
2406
2407 /* Change user password */
2408
2409 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli,
2410                                     TALLOC_CTX *mem_ctx,
2411                                     int argc, const char **argv)
2412 {
2413         POLICY_HND connect_pol, domain_pol;
2414         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2415         const char *user, *oldpass, *newpass;
2416         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2417         struct samr_DomInfo1 *info = NULL;
2418         struct samr_ChangeReject *reject = NULL;
2419
2420         if (argc < 3) {
2421                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2422                 return NT_STATUS_INVALID_PARAMETER;
2423         }
2424
2425         user = argv[1];
2426         oldpass = argv[2];
2427         newpass = argv[3];
2428         
2429         /* Get sam policy handle */
2430
2431         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2432                                    &connect_pol);
2433
2434         if (!NT_STATUS_IS_OK(result))
2435                 goto done;
2436
2437         /* Get domain policy handle */
2438
2439         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2440                                         &connect_pol,
2441                                         access_mask,
2442                                         &domain_sid,
2443                                         &domain_pol);
2444
2445         if (!NT_STATUS_IS_OK(result))
2446                 goto done;
2447
2448         /* Change user password */
2449         result = rpccli_samr_chgpasswd3(cli, mem_ctx,
2450                                         user,
2451                                         newpass,
2452                                         oldpass,
2453                                         &info,
2454                                         &reject);
2455
2456         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2457
2458                 display_sam_dom_info_1(info);
2459
2460                 switch (reject->reason) {
2461                         case SAMR_REJECT_TOO_SHORT:
2462                                 d_printf("SAMR_REJECT_TOO_SHORT\n");
2463                                 break;
2464                         case SAMR_REJECT_IN_HISTORY:
2465                                 d_printf("SAMR_REJECT_IN_HISTORY\n");
2466                                 break;
2467                         case SAMR_REJECT_COMPLEXITY:
2468                                 d_printf("SAMR_REJECT_COMPLEXITY\n");
2469                                 break;
2470                         case SAMR_REJECT_OTHER:
2471                                 d_printf("SAMR_REJECT_OTHER\n");
2472                                 break;
2473                         default:
2474                                 d_printf("unknown reject reason: %d\n",
2475                                         reject->reason);
2476                                 break;
2477                 }
2478         }
2479
2480         if (!NT_STATUS_IS_OK(result))
2481                 goto done;
2482
2483         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2484         if (!NT_STATUS_IS_OK(result)) goto done;
2485
2486         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2487         if (!NT_STATUS_IS_OK(result)) goto done;
2488
2489  done:
2490         return result;
2491 }
2492
2493 /* List of commands exported by this module */
2494
2495 struct cmd_set samr_commands[] = {
2496
2497         { "SAMR" },
2498
2499         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
2500         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
2501         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
2502         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
2503         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
2504         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
2505         { "queryaliasinfo",     RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasinfo,   NULL, PI_SAMR, NULL,    "Query alias info",       "" },
2506         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
2507         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
2508         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
2509         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
2510         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
2511         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
2512
2513         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
2514         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
2515         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
2516         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
2517         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
2518         { "deletedomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group,      NULL, PI_SAMR, NULL,        "Delete domain group",     "" },
2519         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
2520         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
2521         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
2522         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
2523
2524         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
2525         { "chgpasswd2",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2,            NULL, PI_SAMR, NULL, "Change user password", "" },
2526         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
2527         { NULL }
2528 };