r4839: Allow to set acb_mask in rpcclient's enumdomusers (for debugging).
[kai/samba.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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27
28 extern DOM_SID domain_sid;
29
30 /****************************************************************************
31  display sam_user_info_21 structure
32  ****************************************************************************/
33 static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
34 {
35         fstring temp;
36
37         unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp)-1);
38         printf("\tUser Name   :\t%s\n", temp);
39         
40         unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp)-1);
41         printf("\tFull Name   :\t%s\n", temp);
42         
43         unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp)-1);
44         printf("\tHome Drive  :\t%s\n", temp);
45         
46         unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp)-1);
47         printf("\tDir Drive   :\t%s\n", temp);
48         
49         unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp)-1);
50         printf("\tProfile Path:\t%s\n", temp);
51         
52         unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp)-1);
53         printf("\tLogon Script:\t%s\n", temp);
54         
55         unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp)-1);
56         printf("\tDescription :\t%s\n", temp);
57         
58         unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
59         printf("\tWorkstations:\t%s\n", temp);
60         
61         unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1);
62         printf("\tUnknown Str :\t%s\n", temp);
63         
64         unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
65         printf("\tRemote Dial :\t%s\n", temp);
66         
67         printf("\tLogon Time               :\t%s\n", 
68                http_timestring(nt_time_to_unix(&usr->logon_time)));
69         printf("\tLogoff Time              :\t%s\n", 
70                http_timestring(nt_time_to_unix(&usr->logoff_time)));
71         printf("\tKickoff Time             :\t%s\n", 
72                http_timestring(nt_time_to_unix(&usr->kickoff_time)));
73         printf("\tPassword last set Time   :\t%s\n", 
74                http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
75         printf("\tPassword can change Time :\t%s\n", 
76                http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
77         printf("\tPassword must change Time:\t%s\n", 
78                http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
79         
80         printf("\tunknown_2[0..31]...\n"); /* user passwords? */
81         
82         printf("\tuser_rid :\t0x%x\n"  , usr->user_rid ); /* User ID */
83         printf("\tgroup_rid:\t0x%x\n"  , usr->group_rid); /* Group ID */
84         printf("\tacb_info :\t0x%04x\n", usr->acb_info ); /* Account Control Info */
85         
86         printf("\tfields_present:\t0x%08x\n", usr->fields_present); /* 0x00ff ffff */
87         printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
88         printf("\tbad_password_count:\t0x%08x\n", usr->bad_password_count);
89         printf("\tlogon_count:\t0x%08x\n", usr->logon_count);
90         
91         printf("\tpadding1[0..7]...\n");
92         
93         if (usr->ptr_logon_hrs) {
94                 printf("\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len);
95         }
96 }
97
98 static const char *display_time(NTTIME nttime)
99 {
100         static fstring string;
101
102         float high;
103         float low;
104         int sec;
105         int days, hours, mins, secs;
106
107         if (nttime.high==0 && nttime.low==0)
108                 return "Now";
109
110         if (nttime.high==0x80000000 && nttime.low==0)
111                 return "Never";
112
113         high = 65536;   
114         high = high/10000;
115         high = high*65536;
116         high = high/1000;
117         high = high * (~nttime.high);
118
119         low = ~nttime.low;      
120         low = low/(1000*1000*10);
121
122         sec=high+low;
123
124         days=sec/(60*60*24);
125         hours=(sec - (days*60*60*24)) / (60*60);
126         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
127         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
128
129         fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
130         return (string);
131 }
132
133 static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1)
134 {
135         
136         printf("Minimum password length:                     %d\n", info1->min_length_password);
137         printf("Password uniqueness (remember x passwords):  %d\n", info1->password_history);
138         printf("flag:                                        ");
139         if(info1->flag&&2==2) printf("users must open a session to change password ");
140         printf("\n");
141
142         printf("password expire in:                          %s\n", display_time(info1->expire));
143         printf("Min password age (allow changing in x days): %s\n", display_time(info1->min_passwordage));
144 }
145
146 static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
147 {
148         fstring name;
149
150         unistr2_to_ascii(name, &info2->uni_domain, sizeof(name) - 1); 
151         printf("Domain:\t%s\n", name);
152
153         unistr2_to_ascii(name, &info2->uni_server, sizeof(name) - 1); 
154         printf("Server:\t%s\n", name);
155
156         unistr2_to_ascii(name, &info2->uni_comment, sizeof(name) - 1); 
157         printf("Comment:\t%s\n", name);
158
159         printf("Total Users:\t%d\n", info2->num_domain_usrs);
160         printf("Total Groups:\t%d\n", info2->num_domain_grps);
161         printf("Total Aliases:\t%d\n", info2->num_local_grps);
162         
163         printf("Sequence No:\t%d\n", info2->seq_num.low);
164
165         printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info2->logout));
166
167         printf("Unknown 4:\t0x%x\n", info2->unknown_4);
168         printf("Unknown 5:\t0x%x\n", info2->unknown_5);
169         printf("Unknown 6:\t0x%x\n", info2->unknown_6);
170 }
171
172 static void display_sam_unk_info_8(SAM_UNK_INFO_8 *info8)
173 {
174         printf("Sequence No:\t%d\n", info8->seq_num.low);
175         printf("Domain Create Time:\t%s\n", 
176                 http_timestring(nt_time_to_unix(&info8->domain_create_time)));
177
178 }
179
180 static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
181 {
182         printf("Bad password lockout duration:               %s\n", display_time(info12->duration));
183         printf("Reset Lockout after:                         %s\n", display_time(info12->reset_count));
184         printf("Lockout after bad attempts:                  %d\n", info12->bad_attempt_lockout);
185 }
186
187 static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
188 {
189         fstring tmp;
190
191         printf("index: 0x%x ", e1->user_idx);
192         printf("RID: 0x%x ", e1->rid_user);
193         printf("acb: 0x%x ", e1->acb_info);
194
195         unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp)-1);
196         printf("Account: %s\t", tmp);
197
198         unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp)-1);
199         printf("Name: %s\t", tmp);
200
201         unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp)-1);
202         printf("Desc: %s\n", tmp);
203 }
204
205 static void display_sam_info_2(SAM_ENTRY2 *e2, SAM_STR2 *s2)
206 {
207         fstring tmp;
208
209         printf("index: 0x%x ", e2->user_idx);
210         printf("RID: 0x%x ", e2->rid_user);
211         printf("acb: 0x%x ", e2->acb_info);
212         
213         unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp)-1);
214         printf("Account: %s\t", tmp);
215
216         unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp)-1);
217         printf("Name: %s\n", tmp);
218
219 }
220
221 static void display_sam_info_3(SAM_ENTRY3 *e3, SAM_STR3 *s3)
222 {
223         fstring tmp;
224
225         printf("index: 0x%x ", e3->grp_idx);
226         printf("RID: 0x%x ", e3->rid_grp);
227         printf("attr: 0x%x ", e3->attr);
228         
229         unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp)-1);
230         printf("Account: %s\t", tmp);
231
232         unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp)-1);
233         printf("Name: %s\n", tmp);
234
235 }
236
237 static void display_sam_info_4(SAM_ENTRY4 *e4, SAM_STR4 *s4)
238 {
239         int i;
240
241         printf("index: %d ", e4->user_idx);
242         
243         printf("Account: ");
244         for (i=0; i<s4->acct_name.str_str_len; i++)
245                 printf("%c", s4->acct_name.buffer[i]);
246         printf("\n");
247
248 }
249
250 static void display_sam_info_5(SAM_ENTRY5 *e5, SAM_STR5 *s5)
251 {
252         int i;
253
254         printf("index: 0x%x ", e5->grp_idx);
255         
256         printf("Account: ");
257         for (i=0; i<s5->grp_name.str_str_len; i++)
258                 printf("%c", s5->grp_name.buffer[i]);
259         printf("\n");
260
261 }
262
263 /****************************************************************************
264  Try samr_connect4 first, then samr_conenct if it fails
265  ****************************************************************************/
266 static NTSTATUS try_samr_connects(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
267                                   uint32 access_mask, POLICY_HND *connect_pol)
268 {
269         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
270         
271         result = cli_samr_connect4(cli, mem_ctx, access_mask, connect_pol);
272         if (!NT_STATUS_IS_OK(result)) {
273                 result = cli_samr_connect(cli, mem_ctx, access_mask,
274                                           connect_pol);
275         }
276         return result;
277 }
278
279 /**********************************************************************
280  * Query user information 
281  */
282 static NTSTATUS cmd_samr_query_user(struct cli_state *cli, 
283                                     TALLOC_CTX *mem_ctx,
284                                     int argc, const char **argv) 
285 {
286         POLICY_HND connect_pol, domain_pol, user_pol;
287         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
288         uint32 info_level = 21;
289         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
290         SAM_USERINFO_CTR *user_ctr;
291         fstring server;
292         uint32 user_rid;
293         
294         if ((argc < 2) || (argc > 4)) {
295                 printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
296                 return NT_STATUS_OK;
297         }
298         
299         sscanf(argv[1], "%i", &user_rid);
300         
301         if (argc > 2)
302                 sscanf(argv[2], "%i", &info_level);
303                 
304         if (argc > 3)
305                 sscanf(argv[3], "%x", &access_mask);
306         
307
308         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
309         strupper_m(server);
310         
311         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
312                                    &connect_pol);
313
314         if (!NT_STATUS_IS_OK(result))
315                 goto done;
316
317         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
318                                       MAXIMUM_ALLOWED_ACCESS,
319                                       &domain_sid, &domain_pol);
320
321         if (!NT_STATUS_IS_OK(result))
322                 goto done;
323
324         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
325                                     access_mask,
326                                     user_rid, &user_pol);
327
328         if (!NT_STATUS_IS_OK(result))
329                 goto done;
330
331         ZERO_STRUCT(user_ctr);
332
333         result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
334                                          info_level, &user_ctr);
335
336         if (!NT_STATUS_IS_OK(result))
337                 goto done;
338
339         display_sam_user_info_21(user_ctr->info.id21);
340
341 done:
342         return result;
343 }
344
345 /****************************************************************************
346  display group info
347  ****************************************************************************/
348 static void display_group_info1(GROUP_INFO1 *info1)
349 {
350         fstring temp;
351
352         unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp)-1);
353         printf("\tGroup Name:\t%s\n", temp);
354         unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1);
355         printf("\tDescription:\t%s\n", temp);
356         printf("\tunk1:%d\n", info1->unknown_1);
357         printf("\tNum Members:%d\n", info1->num_members);
358 }
359
360 /****************************************************************************
361  display group info
362  ****************************************************************************/
363 static void display_group_info4(GROUP_INFO4 *info4)
364 {
365         fstring desc;
366
367         unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc)-1);
368         printf("\tGroup Description:%s\n", desc);
369 }
370
371 /****************************************************************************
372  display sam sync structure
373  ****************************************************************************/
374 static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
375 {
376         switch (ctr->switch_value1) {
377             case 1: {
378                     display_group_info1(&ctr->group.info1);
379                     break;
380             }
381             case 4: {
382                     display_group_info4(&ctr->group.info4);
383                     break;
384             }
385         }
386 }
387
388 /***********************************************************************
389  * Query group information 
390  */
391 static NTSTATUS cmd_samr_query_group(struct cli_state *cli, 
392                                      TALLOC_CTX *mem_ctx,
393                                      int argc, const char **argv) 
394 {
395         POLICY_HND connect_pol, domain_pol, group_pol;
396         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
397         uint32 info_level = 1;
398         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
399         GROUP_INFO_CTR *group_ctr;
400         fstring                 server; 
401         uint32 group_rid;
402         
403         if ((argc < 2) || (argc > 4)) {
404                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
405                 return NT_STATUS_OK;
406         }
407
408         sscanf(argv[1], "%i", &group_rid);
409         
410         if (argc > 2)
411                 sscanf(argv[2], "%i", &info_level);
412         
413         if (argc > 3)
414                 sscanf(argv[3], "%x", &access_mask);
415
416         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
417         strupper_m(server);
418
419         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
420                                    &connect_pol);
421
422         if (!NT_STATUS_IS_OK(result))
423                 goto done;
424
425         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
426                                       MAXIMUM_ALLOWED_ACCESS,
427                                       &domain_sid, &domain_pol);
428
429         if (!NT_STATUS_IS_OK(result))
430                 goto done;
431
432         result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
433                                      access_mask,
434                                      group_rid, &group_pol);
435
436         if (!NT_STATUS_IS_OK(result))
437                 goto done;
438
439         result = cli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
440                                           info_level, &group_ctr);
441         if (!NT_STATUS_IS_OK(result)) {
442                 goto done;
443         }
444
445         display_group_info_ctr(group_ctr);
446
447 done:
448         return result;
449 }
450
451 /* Query groups a user is a member of */
452
453 static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, 
454                                           TALLOC_CTX *mem_ctx,
455                                           int argc, const char **argv) 
456 {
457         POLICY_HND              connect_pol, 
458                                 domain_pol, 
459                                 user_pol;
460         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
461         uint32                  num_groups, 
462                                 user_rid;
463         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
464         DOM_GID                 *user_gids;
465         int                     i;
466         fstring                 server;
467         
468         if ((argc < 2) || (argc > 3)) {
469                 printf("Usage: %s rid [access mask]\n", argv[0]);
470                 return NT_STATUS_OK;
471         }
472
473         sscanf(argv[1], "%i", &user_rid);
474         
475         if (argc > 2)
476                 sscanf(argv[2], "%x", &access_mask);
477
478         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
479         strupper_m(server);
480                 
481         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
482                                    &connect_pol);
483
484         if (!NT_STATUS_IS_OK(result))
485                 goto done;
486
487         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
488                                       MAXIMUM_ALLOWED_ACCESS,
489                                       &domain_sid, &domain_pol);
490
491         if (!NT_STATUS_IS_OK(result))
492                 goto done;
493
494         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
495                                     access_mask,
496                                     user_rid, &user_pol);
497
498         if (!NT_STATUS_IS_OK(result))
499                 goto done;
500
501         result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
502                                            &num_groups, &user_gids);
503
504         if (!NT_STATUS_IS_OK(result))
505                 goto done;
506
507         for (i = 0; i < num_groups; i++) {
508                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n", 
509                        user_gids[i].g_rid, user_gids[i].attr);
510         }
511
512  done:
513         return result;
514 }
515
516 /* Query aliases a user is a member of */
517
518 static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, 
519                                            TALLOC_CTX *mem_ctx,
520                                            int argc, const char **argv) 
521 {
522         POLICY_HND              connect_pol, domain_pol;
523         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
524         uint32                  user_rid, num_aliases, *alias_rids;
525         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
526         int                     i;
527         fstring                 server;
528         DOM_SID                 tmp_sid;
529         DOM_SID2                sid;
530         DOM_SID global_sid_Builtin;
531
532         string_to_sid(&global_sid_Builtin, "S-1-5-32");
533
534         if ((argc < 3) || (argc > 4)) {
535                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
536                 return NT_STATUS_OK;
537         }
538
539         sscanf(argv[2], "%i", &user_rid);
540         
541         if (argc > 3)
542                 sscanf(argv[3], "%x", &access_mask);
543
544         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
545         strupper_m(server);
546                 
547         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
548                                    &connect_pol);
549
550         if (!NT_STATUS_IS_OK(result))
551                 goto done;
552
553         if (StrCaseCmp(argv[1], "domain")==0)
554                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
555                                               access_mask,
556                                               &domain_sid, &domain_pol);
557         else if (StrCaseCmp(argv[1], "builtin")==0)
558                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
559                                               access_mask,
560                                               &global_sid_Builtin, &domain_pol);
561         else
562                 return NT_STATUS_OK;
563
564         if (!NT_STATUS_IS_OK(result))
565                 goto done;
566
567         sid_copy(&tmp_sid, &domain_sid);
568         sid_append_rid(&tmp_sid, user_rid);
569         init_dom_sid2(&sid, &tmp_sid);
570
571         result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, 1, &sid, &num_aliases, &alias_rids);
572
573         if (!NT_STATUS_IS_OK(result))
574                 goto done;
575
576         for (i = 0; i < num_aliases; i++) {
577                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
578         }
579
580  done:
581         return result;
582 }
583
584 /* Query members of a group */
585
586 static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, 
587                                         TALLOC_CTX *mem_ctx,
588                                         int argc, const char **argv) 
589 {
590         POLICY_HND connect_pol, domain_pol, group_pol;
591         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
592         uint32 num_members, *group_rids, *group_attrs, group_rid;
593         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
594         int i;
595         fstring                 server;
596         
597         if ((argc < 2) || (argc > 3)) {
598                 printf("Usage: %s rid [access mask]\n", argv[0]);
599                 return NT_STATUS_OK;
600         }
601
602         sscanf(argv[1], "%i", &group_rid);
603         
604         if (argc > 2)
605                 sscanf(argv[2], "%x", &access_mask);
606
607         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
608         strupper_m(server);
609
610         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
611                                    &connect_pol);
612
613         if (!NT_STATUS_IS_OK(result))
614                 goto done;
615
616         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
617                                       MAXIMUM_ALLOWED_ACCESS,
618                                       &domain_sid, &domain_pol);
619
620         if (!NT_STATUS_IS_OK(result))
621                 goto done;
622
623         result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
624                                      access_mask,
625                                      group_rid, &group_pol);
626
627         if (!NT_STATUS_IS_OK(result))
628                 goto done;
629
630         result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
631                                          &num_members, &group_rids,
632                                          &group_attrs);
633
634         if (!NT_STATUS_IS_OK(result))
635                 goto done;
636
637         for (i = 0; i < num_members; i++) {
638                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
639                        group_attrs[i]);
640         }
641
642  done:
643         return result;
644 }
645
646 /* Enumerate domain users */
647
648 static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli, 
649                                         TALLOC_CTX *mem_ctx,
650                                         int argc, const char **argv) 
651 {
652         POLICY_HND connect_pol, domain_pol;
653         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
654         uint32 start_idx, size, num_dom_users, i;
655         char **dom_users;
656         uint32 *dom_rids;
657         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
658         uint16 acb_mask = ACB_NORMAL;
659         BOOL got_connect_pol = False, got_domain_pol = False;
660
661         if ((argc < 1) || (argc > 3)) {
662                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
663                 return NT_STATUS_OK;
664         }
665         
666         if (argc > 1)
667                 sscanf(argv[1], "%x", &access_mask);
668
669         if (argc > 2)
670                 sscanf(argv[2], "%x", &acb_mask);
671
672         /* Get sam policy handle */
673
674         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
675                                    &connect_pol);
676
677         if (!NT_STATUS_IS_OK(result))
678                 goto done;
679
680         got_connect_pol = True;
681
682         /* Get domain policy handle */
683
684         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
685                                       access_mask,
686                                       &domain_sid, &domain_pol);
687
688         if (!NT_STATUS_IS_OK(result))
689                 goto done;
690
691         got_domain_pol = True;
692
693         /* Enumerate domain users */
694
695         start_idx = 0;
696         size = 0xffff;
697
698         do {
699                 result = cli_samr_enum_dom_users(
700                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
701                         size, &dom_users, &dom_rids, &num_dom_users);
702
703                 if (NT_STATUS_IS_OK(result) ||
704                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
705
706                         for (i = 0; i < num_dom_users; i++)
707                                printf("user:[%s] rid:[0x%x]\n", 
708                                        dom_users[i], dom_rids[i]);
709                 }
710
711         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
712
713  done:
714         if (got_domain_pol)
715                 cli_samr_close(cli, mem_ctx, &domain_pol);
716
717         if (got_connect_pol)
718                 cli_samr_close(cli, mem_ctx, &connect_pol);
719
720         return result;
721 }
722
723 /* Enumerate domain groups */
724
725 static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, 
726                                          TALLOC_CTX *mem_ctx,
727                                          int argc, const char **argv) 
728 {
729         POLICY_HND connect_pol, domain_pol;
730         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
731         uint32 start_idx, size, num_dom_groups, i;
732         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
733         struct acct_info *dom_groups;
734         BOOL got_connect_pol = False, got_domain_pol = False;
735
736         if ((argc < 1) || (argc > 2)) {
737                 printf("Usage: %s [access_mask]\n", argv[0]);
738                 return NT_STATUS_OK;
739         }
740         
741         if (argc > 1)
742                 sscanf(argv[1], "%x", &access_mask);
743
744         /* Get sam policy handle */
745
746         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
747                                    &connect_pol);
748
749         if (!NT_STATUS_IS_OK(result))
750                 goto done;
751
752         got_connect_pol = True;
753
754         /* Get domain policy handle */
755
756         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
757                                       access_mask,
758                                       &domain_sid, &domain_pol);
759
760         if (!NT_STATUS_IS_OK(result))
761                 goto done;
762
763         got_domain_pol = True;
764
765         /* Enumerate domain groups */
766
767         start_idx = 0;
768         size = 0xffff;
769
770         do {
771                 result = cli_samr_enum_dom_groups(
772                         cli, mem_ctx, &domain_pol, &start_idx, size,
773                         &dom_groups, &num_dom_groups);
774
775                 if (NT_STATUS_IS_OK(result) ||
776                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
777
778                         for (i = 0; i < num_dom_groups; i++)
779                                 printf("group:[%s] rid:[0x%x]\n", 
780                                        dom_groups[i].acct_name,
781                                        dom_groups[i].rid);
782                 }
783
784         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
785
786  done:
787         if (got_domain_pol)
788                 cli_samr_close(cli, mem_ctx, &domain_pol);
789
790         if (got_connect_pol)
791                 cli_samr_close(cli, mem_ctx, &connect_pol);
792
793         return result;
794 }
795
796 /* Enumerate alias groups */
797
798 static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, 
799                                          TALLOC_CTX *mem_ctx,
800                                          int argc, const char **argv) 
801 {
802         POLICY_HND connect_pol, domain_pol;
803         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
804         uint32 start_idx, size, num_als_groups, i;
805         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
806         struct acct_info *als_groups;
807         DOM_SID global_sid_Builtin;
808         BOOL got_connect_pol = False, got_domain_pol = False;
809
810         string_to_sid(&global_sid_Builtin, "S-1-5-32");
811
812         if ((argc < 2) || (argc > 3)) {
813                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
814                 return NT_STATUS_OK;
815         }
816         
817         if (argc > 2)
818                 sscanf(argv[2], "%x", &access_mask);
819
820         /* Get sam policy handle */
821
822         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
823                                    &connect_pol);
824
825         if (!NT_STATUS_IS_OK(result))
826                 goto done;
827
828         got_connect_pol = True;
829
830         /* Get domain policy handle */
831
832         if (StrCaseCmp(argv[1], "domain")==0)
833                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
834                                               access_mask,
835                                               &domain_sid, &domain_pol);
836         else if (StrCaseCmp(argv[1], "builtin")==0)
837                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
838                                               access_mask,
839                                               &global_sid_Builtin, &domain_pol);
840         else
841                 return NT_STATUS_OK;
842
843         if (!NT_STATUS_IS_OK(result))
844                 goto done;
845
846         got_domain_pol = True;
847
848         /* Enumerate alias groups */
849
850         start_idx = 0;
851         size = 0xffff;          /* Number of groups to retrieve */
852
853         do {
854                 result = cli_samr_enum_als_groups(
855                         cli, mem_ctx, &domain_pol, &start_idx, size,
856                         &als_groups, &num_als_groups);
857
858                 if (NT_STATUS_IS_OK(result) ||
859                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
860
861                         for (i = 0; i < num_als_groups; i++)
862                                 printf("group:[%s] rid:[0x%x]\n", 
863                                        als_groups[i].acct_name,
864                                        als_groups[i].rid);
865                 }
866         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
867
868  done:
869         if (got_domain_pol)
870                 cli_samr_close(cli, mem_ctx, &domain_pol);
871         
872         if (got_connect_pol)
873                 cli_samr_close(cli, mem_ctx, &connect_pol);
874         
875         return result;
876 }
877
878 /* Query alias membership */
879
880 static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, 
881                                         TALLOC_CTX *mem_ctx,
882                                         int argc, const char **argv) 
883 {
884         POLICY_HND connect_pol, domain_pol, alias_pol;
885         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
886         uint32 alias_rid, num_members, i;
887         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
888         DOM_SID *alias_sids;
889         DOM_SID global_sid_Builtin;
890         
891         string_to_sid(&global_sid_Builtin, "S-1-5-32");
892
893         if ((argc < 3) || (argc > 4)) {
894                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
895                 return NT_STATUS_OK;
896         }
897
898         sscanf(argv[2], "%i", &alias_rid);
899         
900         if (argc > 3)
901                 sscanf(argv[3], "%x", &access_mask);
902
903         /* Open SAMR handle */
904
905         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
906                                    &connect_pol);
907
908         if (!NT_STATUS_IS_OK(result))
909                 goto done;
910
911         /* Open handle on domain */
912         
913         if (StrCaseCmp(argv[1], "domain")==0)
914                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
915                                               MAXIMUM_ALLOWED_ACCESS,
916                                               &domain_sid, &domain_pol);
917         else if (StrCaseCmp(argv[1], "builtin")==0)
918                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
919                                               MAXIMUM_ALLOWED_ACCESS,
920                                               &global_sid_Builtin, &domain_pol);
921         else
922                 return NT_STATUS_OK;
923
924         if (!NT_STATUS_IS_OK(result))
925                 goto done;
926
927         /* Open handle on alias */
928
929         result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
930                                      access_mask,
931                                      alias_rid, &alias_pol);
932         if (!NT_STATUS_IS_OK(result))
933                 goto done;
934
935         result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
936                                          &num_members, &alias_sids);
937
938         if (!NT_STATUS_IS_OK(result))
939                 goto done;
940
941         for (i = 0; i < num_members; i++) {
942                 fstring sid_str;
943
944                 sid_to_string(sid_str, &alias_sids[i]);
945                 printf("\tsid:[%s]\n", sid_str);
946         }
947
948  done:
949         return result;
950 }
951
952 /* Query display info */
953
954 static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, 
955                                         TALLOC_CTX *mem_ctx,
956                                         int argc, const char **argv) 
957 {
958         POLICY_HND connect_pol, domain_pol;
959         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
960         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
961         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
962         uint32 info_level = 1;
963         SAM_DISPINFO_CTR ctr;
964         SAM_DISPINFO_1 info1;
965         SAM_DISPINFO_2 info2;
966         SAM_DISPINFO_3 info3;
967         SAM_DISPINFO_4 info4;
968         SAM_DISPINFO_5 info5;
969         int loop_count = 0;
970         BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
971
972         if (argc > 5) {
973                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
974                 return NT_STATUS_OK;
975         }
976
977         if (argc >= 2)
978                 sscanf(argv[1], "%i", &info_level);
979         
980         if (argc >= 3)
981                 sscanf(argv[2], "%i", &start_idx);
982         
983         if (argc >= 4) {
984                 sscanf(argv[3], "%i", &max_entries);
985                 got_params = True;
986         }
987         
988         if (argc >= 5) {
989                 sscanf(argv[4], "%i", &max_size);
990                 got_params = True;
991         }
992         
993         if (argc >= 6)
994                 sscanf(argv[5], "%x", &access_mask);
995
996         /* Get sam policy handle */
997
998         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
999                                    &connect_pol);
1000
1001         if (!NT_STATUS_IS_OK(result))
1002                 goto done;
1003
1004         /* Get domain policy handle */
1005
1006         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1007                                       access_mask, 
1008                                       &domain_sid, &domain_pol);
1009
1010         if (!NT_STATUS_IS_OK(result))
1011                 goto done;
1012
1013         /* Query display info */
1014
1015         ZERO_STRUCT(ctr);
1016         ZERO_STRUCT(info1);
1017         
1018         switch (info_level) {
1019         case 1:
1020                 ZERO_STRUCT(info1);
1021                 ctr.sam.info1 = &info1;
1022                 break;
1023         case 2:
1024                 ZERO_STRUCT(info2);
1025                 ctr.sam.info2 = &info2;
1026                 break;
1027         case 3:
1028                 ZERO_STRUCT(info3);
1029                 ctr.sam.info3 = &info3;
1030                 break;
1031         case 4:
1032                 ZERO_STRUCT(info4);
1033                 ctr.sam.info4 = &info4;
1034                 break;
1035         case 5:
1036                 ZERO_STRUCT(info5);
1037                 ctr.sam.info5 = &info5;
1038                 break;
1039         }
1040
1041
1042         while(1) {
1043
1044                 if (!got_params)
1045                         get_query_dispinfo_params(
1046                                 loop_count, &max_entries, &max_size);
1047                 
1048                 result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1049                                                  &start_idx, info_level,
1050                                                  &num_entries, max_entries, 
1051                                                  max_size, &ctr);
1052
1053                 loop_count++;
1054
1055                 if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) 
1056                         break;
1057
1058                 if (num_entries == 0) 
1059                         break;
1060
1061                 for (i = 0; i < num_entries; i++) {
1062                         switch (info_level) {
1063                         case 1:
1064                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1065                                 break;
1066                         case 2:
1067                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1068                                 break;
1069                         case 3:
1070                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1071                                 break;
1072                         case 4:
1073                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1074                                 break;
1075                         case 5:
1076                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1077                                 break;
1078                         }
1079                 }
1080         }
1081
1082  done:
1083         return result;
1084 }
1085
1086 /* Query domain info */
1087
1088 static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, 
1089                                        TALLOC_CTX *mem_ctx,
1090                                        int argc, const char **argv) 
1091 {
1092         POLICY_HND connect_pol, domain_pol;
1093         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1094         uint32 switch_level = 2;
1095         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1096         SAM_UNK_CTR ctr;
1097
1098         if (argc > 2) {
1099                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1100                 return NT_STATUS_OK;
1101         }
1102
1103         if (argc > 1)
1104                 sscanf(argv[1], "%i", &switch_level);
1105         
1106         if (argc > 2)
1107                 sscanf(argv[2], "%x", &access_mask);
1108
1109         /* Get sam policy handle */
1110
1111         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1112                                    &connect_pol);
1113
1114         if (!NT_STATUS_IS_OK(result))
1115                 goto done;
1116
1117         /* Get domain policy handle */
1118
1119         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1120                                       access_mask,
1121                                       &domain_sid, &domain_pol);
1122
1123         if (!NT_STATUS_IS_OK(result))
1124                 goto done;
1125
1126         /* Query domain info */
1127
1128         result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1129                                          switch_level, &ctr);
1130
1131         if (!NT_STATUS_IS_OK(result))
1132                 goto done;
1133
1134         /* Display domain info */
1135
1136         switch (switch_level) {
1137         case 1:
1138                 display_sam_unk_info_1(&ctr.info.inf1);
1139                 break;
1140         case 2:
1141                 display_sam_unk_info_2(&ctr.info.inf2);
1142                 break;
1143         case 8:
1144                 display_sam_unk_info_8(&ctr.info.inf8);
1145                 break;
1146         case 12:
1147                 display_sam_unk_info_12(&ctr.info.inf12);
1148                 break;
1149         default:
1150                 printf("cannot display domain info for switch value %d\n",
1151                        switch_level);
1152                 break;
1153         }
1154
1155  done:
1156  
1157         cli_samr_close(cli, mem_ctx, &domain_pol);
1158         cli_samr_close(cli, mem_ctx, &connect_pol);
1159         return result;
1160 }
1161
1162 /* Create domain user */
1163
1164 static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, 
1165                                          TALLOC_CTX *mem_ctx,
1166                                          int argc, const char **argv) 
1167 {
1168         POLICY_HND connect_pol, domain_pol, user_pol;
1169         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1170         const char *acct_name;
1171         uint16 acb_info;
1172         uint32 unknown, user_rid;
1173         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1174
1175         if ((argc < 2) || (argc > 3)) {
1176                 printf("Usage: %s username [access mask]\n", argv[0]);
1177                 return NT_STATUS_OK;
1178         }
1179
1180         acct_name = argv[1];
1181         
1182         if (argc > 2)
1183                 sscanf(argv[2], "%x", &access_mask);
1184
1185         /* Get sam policy handle */
1186
1187         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1188                                    &connect_pol);
1189
1190         if (!NT_STATUS_IS_OK(result))
1191                 goto done;
1192
1193         /* Get domain policy handle */
1194
1195         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1196                                       access_mask,
1197                                       &domain_sid, &domain_pol);
1198
1199         if (!NT_STATUS_IS_OK(result))
1200                 goto done;
1201
1202         /* Create domain user */
1203
1204         acb_info = ACB_NORMAL;
1205         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1206
1207         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1208                                           acct_name, acb_info, unknown,
1209                                           &user_pol, &user_rid);
1210
1211         if (!NT_STATUS_IS_OK(result))
1212                 goto done;
1213
1214  done:
1215         return result;
1216 }
1217
1218 /* Lookup sam names */
1219
1220 static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, 
1221                                       TALLOC_CTX *mem_ctx,
1222                                       int argc, const char **argv) 
1223 {
1224         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1225         POLICY_HND connect_pol, domain_pol;
1226         uint32 flags = 0x000003e8; /* Unknown */
1227         uint32 num_rids, num_names, *name_types, *rids;
1228         const char **names;
1229         int i;
1230         DOM_SID global_sid_Builtin;
1231
1232         string_to_sid(&global_sid_Builtin, "S-1-5-32");
1233
1234         if (argc < 3) {
1235                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1236                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1237                 printf("or check on the builtin SID: S-1-5-32\n");
1238                 return NT_STATUS_OK;
1239         }
1240
1241         /* Get sam policy and domain handles */
1242
1243         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1244                                    &connect_pol);
1245
1246         if (!NT_STATUS_IS_OK(result))
1247                 goto done;
1248
1249         if (StrCaseCmp(argv[1], "domain")==0)
1250                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1251                                               MAXIMUM_ALLOWED_ACCESS,
1252                                               &domain_sid, &domain_pol);
1253         else if (StrCaseCmp(argv[1], "builtin")==0)
1254                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1255                                               MAXIMUM_ALLOWED_ACCESS,
1256                                               &global_sid_Builtin, &domain_pol);
1257         else
1258                 return NT_STATUS_OK;
1259
1260         if (!NT_STATUS_IS_OK(result))
1261                 goto done;
1262
1263         /* Look up names */
1264
1265         num_names = argc - 2;
1266         names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
1267
1268         for (i = 0; i < argc - 2; i++)
1269                 names[i] = argv[i + 2];
1270
1271         result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1272                                        flags, num_names, names,
1273                                        &num_rids, &rids, &name_types);
1274
1275         if (!NT_STATUS_IS_OK(result))
1276                 goto done;
1277
1278         /* Display results */
1279
1280         for (i = 0; i < num_names; i++)
1281                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1282                        name_types[i]);
1283
1284  done:
1285         return result;
1286 }
1287
1288 /* Lookup sam rids */
1289
1290 static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, 
1291                                      TALLOC_CTX *mem_ctx,
1292                                      int argc, const char **argv) 
1293 {
1294         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1295         POLICY_HND connect_pol, domain_pol;
1296         uint32 flags = 0x000003e8; /* Unknown */
1297         uint32 num_rids, num_names, *rids, *name_types;
1298         char **names;
1299         int i;
1300
1301         if (argc < 2) {
1302                 printf("Usage: %s rid1 [rid2 [rid3] [...]]\n", argv[0]);
1303                 return NT_STATUS_OK;
1304         }
1305
1306         /* Get sam policy and domain handles */
1307
1308         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1309                                    &connect_pol);
1310
1311         if (!NT_STATUS_IS_OK(result))
1312                 goto done;
1313
1314         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1315                                       MAXIMUM_ALLOWED_ACCESS,
1316                                       &domain_sid, &domain_pol);
1317
1318         if (!NT_STATUS_IS_OK(result))
1319                 goto done;
1320
1321         /* Look up rids */
1322
1323         num_rids = argc - 1;
1324         rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1325
1326         for (i = 0; i < argc - 1; i++)
1327                 sscanf(argv[i + 1], "%i", &rids[i]);
1328
1329         result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
1330                                       flags, num_rids, rids,
1331                                       &num_names, &names, &name_types);
1332
1333         if (!NT_STATUS_IS_OK(result))
1334                 goto done;
1335
1336         /* Display results */
1337
1338         for (i = 0; i < num_names; i++)
1339                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1340
1341  done:
1342         return result;
1343 }
1344
1345 /* Delete domain user */
1346
1347 static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, 
1348                                          TALLOC_CTX *mem_ctx,
1349                                          int argc, const char **argv) 
1350 {
1351         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1352         POLICY_HND connect_pol, domain_pol, user_pol;
1353         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1354
1355         if ((argc < 2) || (argc > 3)) {
1356                 printf("Usage: %s username\n", argv[0]);
1357                 return NT_STATUS_OK;
1358         }
1359         
1360         if (argc > 2)
1361                 sscanf(argv[2], "%x", &access_mask);
1362
1363         /* Get sam policy and domain handles */
1364
1365         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1366                                    &connect_pol);
1367
1368         if (!NT_STATUS_IS_OK(result))
1369                 goto done;
1370
1371         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1372                                       MAXIMUM_ALLOWED_ACCESS,
1373                                       &domain_sid, &domain_pol);
1374
1375         if (!NT_STATUS_IS_OK(result))
1376                 goto done;
1377
1378         /* Get handle on user */
1379
1380         {
1381                 uint32 *user_rids, num_rids, *name_types;
1382                 uint32 flags = 0x000003e8; /* Unknown */
1383
1384                 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1385                                                flags, 1, (const char **)&argv[1],
1386                                                &num_rids, &user_rids,
1387                                                &name_types);
1388
1389                 if (!NT_STATUS_IS_OK(result))
1390                         goto done;
1391
1392                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1393                                             access_mask,
1394                                             user_rids[0], &user_pol);
1395
1396                 if (!NT_STATUS_IS_OK(result))
1397                         goto done;
1398         }
1399
1400         /* Delete user */
1401
1402         result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
1403
1404         if (!NT_STATUS_IS_OK(result))
1405                 goto done;
1406
1407         /* Display results */
1408
1409  done:
1410         return result;
1411 }
1412
1413 /**********************************************************************
1414  * Query user security object 
1415  */
1416 static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, 
1417                                     TALLOC_CTX *mem_ctx,
1418                                     int argc, const char **argv) 
1419 {
1420         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1421         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1422         uint32 info_level = 4;
1423         fstring server;
1424         uint32 user_rid = 0;
1425         TALLOC_CTX *ctx = NULL;
1426         SEC_DESC_BUF *sec_desc_buf=NULL;
1427         BOOL domain = False;
1428
1429         ctx=talloc_init("cmd_samr_query_sec_obj");
1430         
1431         if ((argc < 1) || (argc > 2)) {
1432                 printf("Usage: %s [rid|-d]\n", argv[0]);
1433                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1434                 return NT_STATUS_OK;
1435         }
1436         
1437         if (argc > 1) {
1438                 if (strcmp(argv[1], "-d") == 0)
1439                         domain = True;
1440                 else
1441                         sscanf(argv[1], "%i", &user_rid);
1442         }
1443         
1444         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1445         strupper_m(server);
1446         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1447                                    &connect_pol);
1448
1449         if (!NT_STATUS_IS_OK(result))
1450                 goto done;
1451
1452         if (domain || user_rid)
1453                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1454                                               MAXIMUM_ALLOWED_ACCESS,
1455                                               &domain_sid, &domain_pol);
1456
1457         if (!NT_STATUS_IS_OK(result))
1458                 goto done;
1459
1460         if (user_rid)
1461                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1462                                             MAXIMUM_ALLOWED_ACCESS,
1463                                             user_rid, &user_pol);
1464
1465         if (!NT_STATUS_IS_OK(result))
1466                 goto done;
1467
1468         /* Pick which query pol to use */
1469
1470         pol = &connect_pol;
1471
1472         if (domain)
1473                 pol = &domain_pol;
1474
1475         if (user_rid)
1476                 pol = &user_pol;
1477
1478         /* Query SAM security object */
1479
1480         result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
1481                                         &sec_desc_buf);
1482
1483         if (!NT_STATUS_IS_OK(result))
1484                 goto done;
1485
1486         display_sec_desc(sec_desc_buf->sec);
1487         
1488 done:
1489         talloc_destroy(ctx);
1490         return result;
1491 }
1492
1493 static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, 
1494                                         TALLOC_CTX *mem_ctx,
1495                                         int argc, const char **argv) 
1496 {
1497         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1498         uint16 unk_0, unk_1;
1499
1500         if (argc != 1) {
1501                 printf("Usage: %s\n", argv[0]);
1502                 return NT_STATUS_OK;
1503         }
1504
1505         result = cli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1) ;
1506         
1507         if (NT_STATUS_IS_OK(result)) {
1508                 printf("unk_0 = 0x%08x\n", unk_0);
1509                 printf("unk_1 = 0x%08x\n", unk_1);
1510         }
1511
1512         return result;
1513 }
1514
1515 /* Look up domain name */
1516
1517 static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli, 
1518                                        TALLOC_CTX *mem_ctx,
1519                                        int argc, const char **argv) 
1520 {
1521         POLICY_HND connect_pol, domain_pol;
1522         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1523         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1524         fstring domain_name,sid_string;
1525         DOM_SID sid;
1526         
1527         if (argc != 2) {
1528                 printf("Usage: %s domain_name\n", argv[0]);
1529                 return NT_STATUS_OK;
1530         }
1531         
1532         sscanf(argv[1], "%s", domain_name);
1533         
1534         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
1535         
1536         if (!NT_STATUS_IS_OK(result))
1537                 goto done;
1538
1539         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1540                                       access_mask, &domain_sid, &domain_pol);
1541
1542         if (!NT_STATUS_IS_OK(result))
1543                 goto done;
1544         
1545         result = cli_samr_lookup_domain(
1546                 cli, mem_ctx, &connect_pol, domain_name, &sid);
1547
1548         sid_to_string(sid_string,&sid);
1549  
1550         if (NT_STATUS_IS_OK(result)) 
1551                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
1552                        domain_name,sid_string);
1553
1554 done:
1555         return result;
1556 }
1557
1558
1559 /* List of commands exported by this module */
1560
1561 struct cmd_set samr_commands[] = {
1562
1563         { "SAMR" },
1564
1565         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR,  "Query user info",         "" },
1566         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR,  "Query group info",        "" },
1567         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR,  "Query user groups",       "" },
1568         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR,  "Query user aliases",      "" },
1569         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR,  "Query group membership",  "" },
1570         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR,  "Query alias membership",  "" },
1571         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR,  "Query display info",      "" },
1572         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR,  "Query domain info",       "" },
1573         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR,        "Enumerate domain users", "" },
1574         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR,      "Enumerate domain groups", "" },
1575         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR,      "Enumerate alias groups",  "" },
1576
1577         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR,      "Create domain user",      "" },
1578         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR,      "Look up names",           "" },
1579         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR,      "Look up names",           "" },
1580         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR,      "Delete domain user",      "" },
1581         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, "Query SAMR security object",   "" },
1582         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, "Retrieve domain password info", "" },
1583
1584         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, "Lookup Domain Name", "" },
1585         { NULL }
1586 };