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