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