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