updated the 3.0 branch from the head branch - ready for alpha18
[kai/samba.git] / source3 / rpcclient / cmd_samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Andrew Tridgell              1992-2000,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7    Copyright (C) Elrond                            2000,
8    Copyright (C) Tim Potter                        2000
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27
28 extern DOM_SID domain_sid;
29
30 /****************************************************************************
31  display sam_user_info_21 structure
32  ****************************************************************************/
33 static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
34 {
35         fstring temp;
36
37         unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp)-1);
38         printf("\tUser Name   :\t%s\n", temp);
39         
40         unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp)-1);
41         printf("\tFull Name   :\t%s\n", temp);
42         
43         unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp)-1);
44         printf("\tHome Drive  :\t%s\n", temp);
45         
46         unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp)-1);
47         printf("\tDir Drive   :\t%s\n", temp);
48         
49         unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp)-1);
50         printf("\tProfile Path:\t%s\n", temp);
51         
52         unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp)-1);
53         printf("\tLogon Script:\t%s\n", temp);
54         
55         unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp)-1);
56         printf("\tDescription :\t%s\n", temp);
57         
58         unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
59         printf("\tWorkstations:\t%s\n", temp);
60         
61         unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1);
62         printf("\tUnknown Str :\t%s\n", temp);
63         
64         unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
65         printf("\tRemote Dial :\t%s\n", temp);
66         
67         printf("\tLogon Time               :\t%s\n", 
68                http_timestring(nt_time_to_unix(&usr->logon_time)));
69         printf("\tLogoff Time              :\t%s\n", 
70                http_timestring(nt_time_to_unix(&usr->logoff_time)));
71         printf("\tKickoff Time             :\t%s\n", 
72                http_timestring(nt_time_to_unix(&usr->kickoff_time)));
73         printf("\tPassword last set Time   :\t%s\n", 
74                http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
75         printf("\tPassword can change Time :\t%s\n", 
76                http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
77         printf("\tPassword must change Time:\t%s\n", 
78                http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
79         
80         printf("\tunknown_2[0..31]...\n"); /* user passwords? */
81         
82         printf("\tuser_rid :\t0x%x\n"  , usr->user_rid ); /* User ID */
83         printf("\tgroup_rid:\t0x%x\n"  , usr->group_rid); /* Group ID */
84         printf("\tacb_info :\t0x%04x\n", usr->acb_info ); /* Account Control Info */
85         
86         printf("\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 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         snprintf(string, sizeof(string)-1, "%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  * Query user information 
248  */
249 static NTSTATUS cmd_samr_query_user(struct cli_state *cli, 
250                                     TALLOC_CTX *mem_ctx,
251                                     int argc, char **argv) 
252 {
253         POLICY_HND connect_pol, domain_pol, user_pol;
254         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
255         uint32 info_level = 21;
256         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
257         SAM_USERINFO_CTR *user_ctr;
258         fstring server;
259         uint32 user_rid;
260         
261         if ((argc < 2) || (argc > 4)) {
262                 printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
263                 return NT_STATUS_OK;
264         }
265         
266         sscanf(argv[1], "%i", &user_rid);
267         
268         if (argc > 2)
269                 sscanf(argv[2], "%i", &info_level);
270                 
271         if (argc > 3)
272                 sscanf(argv[3], "%x", &access_mask);
273         
274
275         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
276         strupper (server);
277         
278         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
279                                   &connect_pol);
280
281         if (!NT_STATUS_IS_OK(result))
282                 goto done;
283
284         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
285                                       MAXIMUM_ALLOWED_ACCESS,
286                                       &domain_sid, &domain_pol);
287
288         if (!NT_STATUS_IS_OK(result))
289                 goto done;
290
291         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
292                                     access_mask,
293                                     user_rid, &user_pol);
294
295         if (!NT_STATUS_IS_OK(result))
296                 goto done;
297
298         ZERO_STRUCT(user_ctr);
299
300         result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
301                                          info_level, &user_ctr);
302
303         if (!NT_STATUS_IS_OK(result))
304                 goto done;
305
306         display_sam_user_info_21(user_ctr->info.id21);
307
308 done:
309         return result;
310 }
311
312 /****************************************************************************
313  display group info
314  ****************************************************************************/
315 static void display_group_info1(GROUP_INFO1 *info1)
316 {
317         fstring temp;
318
319         unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp)-1);
320         printf("\tGroup Name:\t%s\n", temp);
321         unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1);
322         printf("\tDescription:\t%s\n", temp);
323         printf("\tunk1:%d\n", info1->unknown_1);
324         printf("\tNum Members:%d\n", info1->num_members);
325 }
326
327 /****************************************************************************
328  display group info
329  ****************************************************************************/
330 static void display_group_info4(GROUP_INFO4 *info4)
331 {
332         fstring desc;
333
334         unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc)-1);
335         printf("\tGroup Description:%s\n", desc);
336 }
337
338 /****************************************************************************
339  display sam sync structure
340  ****************************************************************************/
341 static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
342 {
343         switch (ctr->switch_value1) {
344             case 1: {
345                     display_group_info1(&ctr->group.info1);
346                     break;
347             }
348             case 4: {
349                     display_group_info4(&ctr->group.info4);
350                     break;
351             }
352         }
353 }
354
355 /***********************************************************************
356  * Query group information 
357  */
358 static NTSTATUS cmd_samr_query_group(struct cli_state *cli, 
359                                      TALLOC_CTX *mem_ctx,
360                                      int argc, char **argv) 
361 {
362         POLICY_HND connect_pol, domain_pol, group_pol;
363         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
364         uint32 info_level = 1;
365         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
366         GROUP_INFO_CTR group_ctr;
367         fstring                 server; 
368         uint32 group_rid;
369         
370         if ((argc < 2) || (argc > 4)) {
371                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
372                 return NT_STATUS_OK;
373         }
374
375         sscanf(argv[1], "%i", &group_rid);
376         
377         if (argc > 2)
378                 sscanf(argv[2], "%i", &info_level);
379         
380         if (argc > 3)
381                 sscanf(argv[3], "%x", &access_mask);
382
383         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
384         strupper (server);
385
386         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
387                                   &connect_pol);
388
389         if (!NT_STATUS_IS_OK(result))
390                 goto done;
391
392         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
393                                       MAXIMUM_ALLOWED_ACCESS,
394                                       &domain_sid, &domain_pol);
395
396         if (!NT_STATUS_IS_OK(result))
397                 goto done;
398
399         result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
400                                      access_mask,
401                                      group_rid, &group_pol);
402
403         if (!NT_STATUS_IS_OK(result))
404                 goto done;
405
406         ZERO_STRUCT(group_ctr);
407
408         result = cli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
409                                           info_level, &group_ctr);
410         if (!NT_STATUS_IS_OK(result)) {
411                 goto done;
412         }
413
414         display_group_info_ctr(&group_ctr);
415
416 done:
417         return result;
418 }
419
420 /* Query groups a user is a member of */
421
422 static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, 
423                                           TALLOC_CTX *mem_ctx,
424                                           int argc, char **argv) 
425 {
426         POLICY_HND              connect_pol, 
427                                 domain_pol, 
428                                 user_pol;
429         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
430         uint32                  num_groups, 
431                                 user_rid;
432         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
433         DOM_GID                 *user_gids;
434         int                     i;
435         fstring                 server;
436         
437         if ((argc < 2) || (argc > 3)) {
438                 printf("Usage: %s rid [access mask]\n", argv[0]);
439                 return NT_STATUS_OK;
440         }
441
442         sscanf(argv[1], "%i", &user_rid);
443         
444         if (argc > 2)
445                 sscanf(argv[2], "%x", &access_mask);
446
447         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
448         strupper (server);
449                 
450         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
451                                   &connect_pol);
452
453         if (!NT_STATUS_IS_OK(result))
454                 goto done;
455
456         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
457                                       MAXIMUM_ALLOWED_ACCESS,
458                                       &domain_sid, &domain_pol);
459
460         if (!NT_STATUS_IS_OK(result))
461                 goto done;
462
463         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
464                                     access_mask,
465                                     user_rid, &user_pol);
466
467         if (!NT_STATUS_IS_OK(result))
468                 goto done;
469
470         result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
471                                            &num_groups, &user_gids);
472
473         if (!NT_STATUS_IS_OK(result))
474                 goto done;
475
476         for (i = 0; i < num_groups; i++) {
477                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n", 
478                        user_gids[i].g_rid, user_gids[i].attr);
479         }
480
481  done:
482         return result;
483 }
484
485 /* Query aliases a user is a member of */
486
487 static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, 
488                                           TALLOC_CTX *mem_ctx,
489                                           int argc, char **argv) 
490 {
491         POLICY_HND              connect_pol, domain_pol;
492         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
493         uint32                  user_rid, num_aliases, *alias_rids;
494         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
495         int                     i;
496         fstring                 server;
497         DOM_SID                 tmp_sid;
498         DOM_SID2                sid;
499         DOM_SID global_sid_Builtin;
500
501         string_to_sid(&global_sid_Builtin, "S-1-5-32");
502
503         if ((argc < 3) || (argc > 4)) {
504                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
505                 return NT_STATUS_OK;
506         }
507
508         sscanf(argv[2], "%i", &user_rid);
509         
510         if (argc > 3)
511                 sscanf(argv[3], "%x", &access_mask);
512
513         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
514         strupper (server);
515                 
516         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
517                                   &connect_pol);
518
519         if (!NT_STATUS_IS_OK(result))
520                 goto done;
521
522         if (StrCaseCmp(argv[1], "domain")==0)
523                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
524                                               access_mask,
525                                               &domain_sid, &domain_pol);
526         else if (StrCaseCmp(argv[1], "builtin")==0)
527                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
528                                               access_mask,
529                                               &global_sid_Builtin, &domain_pol);
530         else
531                 return NT_STATUS_OK;
532
533         if (!NT_STATUS_IS_OK(result))
534                 goto done;
535
536         sid_copy(&tmp_sid, &domain_sid);
537         sid_append_rid(&tmp_sid, user_rid);
538         init_dom_sid2(&sid, &tmp_sid);
539
540         result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, 1, &sid, &num_aliases, &alias_rids);
541
542         if (!NT_STATUS_IS_OK(result))
543                 goto done;
544
545         for (i = 0; i < num_aliases; i++) {
546                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
547         }
548
549  done:
550         return result;
551 }
552
553 /* Query members of a group */
554
555 static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, 
556                                         TALLOC_CTX *mem_ctx,
557                                         int argc, char **argv) 
558 {
559         POLICY_HND connect_pol, domain_pol, group_pol;
560         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
561         uint32 num_members, *group_rids, *group_attrs, group_rid;
562         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
563         int i;
564         fstring                 server;
565         
566         if ((argc < 2) || (argc > 3)) {
567                 printf("Usage: %s rid [access mask]\n", argv[0]);
568                 return NT_STATUS_OK;
569         }
570
571         sscanf(argv[1], "%i", &group_rid);
572         
573         if (argc > 2)
574                 sscanf(argv[2], "%x", &access_mask);
575
576         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
577         strupper (server);
578
579         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
580                                   &connect_pol);
581
582         if (!NT_STATUS_IS_OK(result))
583                 goto done;
584
585         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
586                                       MAXIMUM_ALLOWED_ACCESS,
587                                       &domain_sid, &domain_pol);
588
589         if (!NT_STATUS_IS_OK(result))
590                 goto done;
591
592         result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
593                                      access_mask,
594                                      group_rid, &group_pol);
595
596         if (!NT_STATUS_IS_OK(result))
597                 goto done;
598
599         result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
600                                          &num_members, &group_rids,
601                                          &group_attrs);
602
603         if (!NT_STATUS_IS_OK(result))
604                 goto done;
605
606         for (i = 0; i < num_members; i++) {
607                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
608                        group_attrs[i]);
609         }
610
611  done:
612         return result;
613 }
614
615 /* Enumerate domain groups */
616
617 static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, 
618                                          TALLOC_CTX *mem_ctx,
619                                          int argc, char **argv) 
620 {
621         POLICY_HND connect_pol, domain_pol;
622         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
623         uint32 start_idx, size, num_dom_groups, i;
624         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
625         struct acct_info *dom_groups;
626         BOOL got_connect_pol = False, got_domain_pol = False;
627
628         if ((argc < 1) || (argc > 2)) {
629                 printf("Usage: %s [access_mask]\n", argv[0]);
630                 return NT_STATUS_OK;
631         }
632         
633         if (argc > 1)
634                 sscanf(argv[1], "%x", &access_mask);
635
636         /* Get sam policy handle */
637
638         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
639                                   &connect_pol);
640
641         if (!NT_STATUS_IS_OK(result))
642                 goto done;
643
644         got_connect_pol = True;
645
646         /* Get domain policy handle */
647
648         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
649                                       access_mask,
650                                       &domain_sid, &domain_pol);
651
652         if (!NT_STATUS_IS_OK(result))
653                 goto done;
654
655         got_domain_pol = True;
656
657         /* Enumerate domain groups */
658
659         start_idx = 0;
660         size = 0xffff;
661
662         do {
663                 result = cli_samr_enum_dom_groups(
664                         cli, mem_ctx, &domain_pol, &start_idx, size,
665                         &dom_groups, &num_dom_groups);
666
667                 if (NT_STATUS_IS_OK(result) ||
668                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
669
670                         for (i = 0; i < num_dom_groups; i++)
671                                 printf("group:[%s] rid:[0x%x]\n", 
672                                        dom_groups[i].acct_name,
673                                        dom_groups[i].rid);
674                 }
675
676         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
677
678  done:
679         if (got_domain_pol)
680                 cli_samr_close(cli, mem_ctx, &domain_pol);
681
682         if (got_connect_pol)
683                 cli_samr_close(cli, mem_ctx, &connect_pol);
684
685         return result;
686 }
687
688 /* Enumerate alias groups */
689
690 static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, 
691                                          TALLOC_CTX *mem_ctx,
692                                          int argc, char **argv) 
693 {
694         POLICY_HND connect_pol, domain_pol;
695         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
696         uint32 start_idx, size, num_als_groups, i;
697         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
698         struct acct_info *als_groups;
699         DOM_SID global_sid_Builtin;
700         BOOL got_connect_pol = False, got_domain_pol = False;
701
702         string_to_sid(&global_sid_Builtin, "S-1-5-32");
703
704         if ((argc < 2) || (argc > 3)) {
705                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
706                 return NT_STATUS_OK;
707         }
708         
709         if (argc > 2)
710                 sscanf(argv[2], "%x", &access_mask);
711
712         /* Get sam policy handle */
713
714         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
715                                   &connect_pol);
716
717         if (!NT_STATUS_IS_OK(result))
718                 goto done;
719
720         got_connect_pol = True;
721
722         /* Get domain policy handle */
723
724         if (StrCaseCmp(argv[1], "domain")==0)
725                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
726                                               access_mask,
727                                               &domain_sid, &domain_pol);
728         else if (StrCaseCmp(argv[1], "builtin")==0)
729                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
730                                               access_mask,
731                                               &global_sid_Builtin, &domain_pol);
732         else
733                 return NT_STATUS_OK;
734
735         if (!NT_STATUS_IS_OK(result))
736                 goto done;
737
738         got_domain_pol = True;
739
740         /* Enumerate alias groups */
741
742         start_idx = 0;
743         size = 0xffff;          /* Number of groups to retrieve */
744
745         do {
746                 result = cli_samr_enum_als_groups(
747                         cli, mem_ctx, &domain_pol, &start_idx, size,
748                         &als_groups, &num_als_groups);
749
750                 if (NT_STATUS_IS_OK(result) ||
751                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
752
753                         for (i = 0; i < num_als_groups; i++)
754                                 printf("group:[%s] rid:[0x%x]\n", 
755                                        als_groups[i].acct_name,
756                                        als_groups[i].rid);
757                 }
758         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
759
760  done:
761         if (got_domain_pol)
762                 cli_samr_close(cli, mem_ctx, &domain_pol);
763         
764         if (got_connect_pol)
765                 cli_samr_close(cli, mem_ctx, &connect_pol);
766         
767         return result;
768 }
769
770 /* Query alias membership */
771
772 static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, 
773                                         TALLOC_CTX *mem_ctx,
774                                         int argc, char **argv) 
775 {
776         POLICY_HND connect_pol, domain_pol, alias_pol;
777         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
778         uint32 alias_rid, num_members, i;
779         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
780         DOM_SID *alias_sids;
781         DOM_SID global_sid_Builtin;
782         
783         string_to_sid(&global_sid_Builtin, "S-1-5-32");
784
785         if ((argc < 3) || (argc > 4)) {
786                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
787                 return NT_STATUS_OK;
788         }
789
790         sscanf(argv[2], "%i", &alias_rid);
791         
792         if (argc > 3)
793                 sscanf(argv[3], "%x", &access_mask);
794
795         /* Open SAMR handle */
796
797         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
798                                   &connect_pol);
799
800         if (!NT_STATUS_IS_OK(result))
801                 goto done;
802
803         /* Open handle on domain */
804         
805         if (StrCaseCmp(argv[1], "domain")==0)
806                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
807                                               MAXIMUM_ALLOWED_ACCESS,
808                                               &domain_sid, &domain_pol);
809         else if (StrCaseCmp(argv[1], "builtin")==0)
810                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
811                                               MAXIMUM_ALLOWED_ACCESS,
812                                               &global_sid_Builtin, &domain_pol);
813         else
814                 return NT_STATUS_OK;
815
816         if (!NT_STATUS_IS_OK(result))
817                 goto done;
818
819         /* Open handle on alias */
820
821         result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
822                                      access_mask,
823                                      alias_rid, &alias_pol);
824         if (!NT_STATUS_IS_OK(result))
825                 goto done;
826
827         result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
828                                          &num_members, &alias_sids);
829
830         if (!NT_STATUS_IS_OK(result))
831                 goto done;
832
833         for (i = 0; i < num_members; i++) {
834                 fstring sid_str;
835
836                 sid_to_string(sid_str, &alias_sids[i]);
837                 printf("\tsid:[%s]\n", sid_str);
838         }
839
840  done:
841         return result;
842 }
843
844 /* Query display info */
845
846 static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, 
847                                         TALLOC_CTX *mem_ctx,
848                                         int argc, char **argv) 
849 {
850         POLICY_HND connect_pol, domain_pol;
851         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
852         uint32 start_idx=0, max_entries=250, num_entries, i;
853         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
854         uint32 info_level = 1;
855         SAM_DISPINFO_CTR ctr;
856         SAM_DISPINFO_1 info1;
857         SAM_DISPINFO_2 info2;
858         SAM_DISPINFO_3 info3;
859         SAM_DISPINFO_4 info4;
860         SAM_DISPINFO_5 info5;
861
862         if (argc > 5) {
863                 printf("Usage: %s [info level] [start index] [max entries] [access mask]\n", argv[0]);
864                 return NT_STATUS_OK;
865         }
866
867         if (argc >= 2)
868                 sscanf(argv[1], "%i", &info_level);
869         
870         if (argc >= 3)
871                 sscanf(argv[2], "%i", &start_idx);
872         
873         if (argc >= 4)
874                 sscanf(argv[3], "%i", &max_entries);
875         
876         if (argc >= 5)
877                 sscanf(argv[4], "%x", &access_mask);
878
879         /* Get sam policy handle */
880
881         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol);
882
883         if (!NT_STATUS_IS_OK(result))
884                 goto done;
885
886         /* Get domain policy handle */
887
888         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
889                                       access_mask, 
890                                       &domain_sid, &domain_pol);
891
892         if (!NT_STATUS_IS_OK(result))
893                 goto done;
894
895         /* Query display info */
896
897         ZERO_STRUCT(ctr);
898         ZERO_STRUCT(info1);
899         
900         switch (info_level) {
901         case 1:
902                 ZERO_STRUCT(info1);
903                 ctr.sam.info1 = &info1;
904                 break;
905         case 2:
906                 ZERO_STRUCT(info2);
907                 ctr.sam.info2 = &info2;
908                 break;
909         case 3:
910                 ZERO_STRUCT(info3);
911                 ctr.sam.info3 = &info3;
912                 break;
913         case 4:
914                 ZERO_STRUCT(info4);
915                 ctr.sam.info4 = &info4;
916                 break;
917         case 5:
918                 ZERO_STRUCT(info5);
919                 ctr.sam.info5 = &info5;
920                 break;
921         }
922
923
924         while(1) {
925
926                 result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
927                                                  &start_idx, info_level,
928                                                  &num_entries, max_entries, &ctr);
929
930                 if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) 
931                         break;
932
933                 if (num_entries == 0) 
934                         break;
935
936                 for (i = 0; i < num_entries; i++) {
937                         switch (info_level) {
938                         case 1:
939                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
940                                 break;
941                         case 2:
942                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
943                                 break;
944                         case 3:
945                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
946                                 break;
947                         case 4:
948                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
949                                 break;
950                         case 5:
951                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
952                                 break;
953                         }
954                 }
955         }
956
957  done:
958         return result;
959 }
960
961 /* Query domain info */
962
963 static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, 
964                                        TALLOC_CTX *mem_ctx,
965                                        int argc, char **argv) 
966 {
967         POLICY_HND connect_pol, domain_pol;
968         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
969         uint32 switch_level = 2;
970         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
971         SAM_UNK_CTR ctr;
972
973         if (argc > 2) {
974                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
975                 return NT_STATUS_OK;
976         }
977
978         if (argc > 1)
979                 sscanf(argv[1], "%i", &switch_level);
980         
981         if (argc > 2)
982                 sscanf(argv[2], "%x", &access_mask);
983
984         /* Get sam policy handle */
985
986         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
987                                   &connect_pol);
988
989         if (!NT_STATUS_IS_OK(result))
990                 goto done;
991
992         /* Get domain policy handle */
993
994         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
995                                       access_mask,
996                                       &domain_sid, &domain_pol);
997
998         if (!NT_STATUS_IS_OK(result))
999                 goto done;
1000
1001         /* Query domain info */
1002
1003         result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1004                                          switch_level, &ctr);
1005
1006         if (!NT_STATUS_IS_OK(result))
1007                 goto done;
1008
1009         /* Display domain info */
1010
1011         switch (switch_level) {
1012         case 1:
1013                 display_sam_unk_info_1(&ctr.info.inf1);
1014                 break;
1015         case 2:
1016                 display_sam_unk_info_2(&ctr.info.inf2);
1017                 break;
1018         default:
1019                 printf("cannot display domain info for switch value %d\n",
1020                        switch_level);
1021                 break;
1022         }
1023
1024  done:
1025  
1026         cli_samr_close(cli, mem_ctx, &domain_pol);
1027         cli_samr_close(cli, mem_ctx, &connect_pol);
1028         return result;
1029 }
1030
1031 /* Create domain user */
1032
1033 static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, 
1034                                          TALLOC_CTX *mem_ctx,
1035                                          int argc, char **argv) 
1036 {
1037         POLICY_HND connect_pol, domain_pol, user_pol;
1038         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1039         char *acct_name;
1040         uint16 acb_info;
1041         uint32 unknown, user_rid;
1042         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1043
1044         if ((argc < 2) || (argc > 3)) {
1045                 printf("Usage: %s username [access mask]\n", argv[0]);
1046                 return NT_STATUS_OK;
1047         }
1048
1049         acct_name = argv[1];
1050         
1051         if (argc > 2)
1052                 sscanf(argv[2], "%x", &access_mask);
1053
1054         /* Get sam policy handle */
1055
1056         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1057                                   &connect_pol);
1058
1059         if (!NT_STATUS_IS_OK(result))
1060                 goto done;
1061
1062         /* Get domain policy handle */
1063
1064         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1065                                       access_mask,
1066                                       &domain_sid, &domain_pol);
1067
1068         if (!NT_STATUS_IS_OK(result))
1069                 goto done;
1070
1071         /* Create domain user */
1072
1073         acb_info = ACB_NORMAL;
1074         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1075
1076         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1077                                           acct_name, acb_info, unknown,
1078                                           &user_pol, &user_rid);
1079
1080         if (!NT_STATUS_IS_OK(result))
1081                 goto done;
1082
1083  done:
1084         return result;
1085 }
1086
1087 /* Lookup sam names */
1088
1089 static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, 
1090                                       TALLOC_CTX *mem_ctx,
1091                                       int argc, char **argv) 
1092 {
1093         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1094         POLICY_HND connect_pol, domain_pol;
1095         uint32 flags = 0x000003e8; /* Unknown */
1096         uint32 num_rids, num_names, *name_types, *rids;
1097         const char **names;
1098         int i;
1099         DOM_SID global_sid_Builtin;
1100
1101         string_to_sid(&global_sid_Builtin, "S-1-5-32");
1102
1103         if (argc < 3) {
1104                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1105                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1106                 printf("or check on the builtin SID: S-1-5-32\n");
1107                 return NT_STATUS_OK;
1108         }
1109
1110         /* Get sam policy and domain handles */
1111
1112         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1113                                   &connect_pol);
1114
1115         if (!NT_STATUS_IS_OK(result))
1116                 goto done;
1117
1118         if (StrCaseCmp(argv[1], "domain")==0)
1119                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1120                                               MAXIMUM_ALLOWED_ACCESS,
1121                                               &domain_sid, &domain_pol);
1122         else if (StrCaseCmp(argv[1], "builtin")==0)
1123                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1124                                               MAXIMUM_ALLOWED_ACCESS,
1125                                               &global_sid_Builtin, &domain_pol);
1126         else
1127                 return NT_STATUS_OK;
1128
1129         if (!NT_STATUS_IS_OK(result))
1130                 goto done;
1131
1132         /* Look up names */
1133
1134         num_names = argc - 2;
1135         names = (const char **)talloc(mem_ctx, sizeof(char *) * num_names);
1136
1137         for (i = 0; i < argc - 2; i++)
1138                 names[i] = argv[i + 2];
1139
1140         result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1141                                        flags, num_names, names,
1142                                        &num_rids, &rids, &name_types);
1143
1144         if (!NT_STATUS_IS_OK(result))
1145                 goto done;
1146
1147         /* Display results */
1148
1149         for (i = 0; i < num_names; i++)
1150                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1151                        name_types[i]);
1152
1153  done:
1154         return result;
1155 }
1156
1157 /* Lookup sam rids */
1158
1159 static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, 
1160                                      TALLOC_CTX *mem_ctx,
1161                                      int argc, char **argv) 
1162 {
1163         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1164         POLICY_HND connect_pol, domain_pol;
1165         uint32 flags = 0x000003e8; /* Unknown */
1166         uint32 num_rids, num_names, *rids, *name_types;
1167         char **names;
1168         int i;
1169
1170         if (argc < 2) {
1171                 printf("Usage: %s rid1 [rid2 [rid3] [...]]\n", argv[0]);
1172                 return NT_STATUS_OK;
1173         }
1174
1175         /* Get sam policy and domain handles */
1176
1177         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1178                                   &connect_pol);
1179
1180         if (!NT_STATUS_IS_OK(result))
1181                 goto done;
1182
1183         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1184                                       MAXIMUM_ALLOWED_ACCESS,
1185                                       &domain_sid, &domain_pol);
1186
1187         if (!NT_STATUS_IS_OK(result))
1188                 goto done;
1189
1190         /* Look up rids */
1191
1192         num_rids = argc - 1;
1193         rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids);
1194
1195         for (i = 0; i < argc - 1; i++)
1196                 sscanf(argv[i + 1], "%i", &rids[i]);
1197
1198         result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
1199                                       flags, num_rids, rids,
1200                                       &num_names, &names, &name_types);
1201
1202         if (!NT_STATUS_IS_OK(result))
1203                 goto done;
1204
1205         /* Display results */
1206
1207         for (i = 0; i < num_names; i++)
1208                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1209
1210  done:
1211         return result;
1212 }
1213
1214 /* Delete domain user */
1215
1216 static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, 
1217                                          TALLOC_CTX *mem_ctx,
1218                                          int argc, char **argv) 
1219 {
1220         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1221         POLICY_HND connect_pol, domain_pol, user_pol;
1222         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1223
1224         if ((argc < 2) || (argc > 3)) {
1225                 printf("Usage: %s username\n", argv[0]);
1226                 return NT_STATUS_OK;
1227         }
1228         
1229         if (argc > 2)
1230                 sscanf(argv[2], "%x", &access_mask);
1231
1232         /* Get sam policy and domain handles */
1233
1234         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1235                                   &connect_pol);
1236
1237         if (!NT_STATUS_IS_OK(result))
1238                 goto done;
1239
1240         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1241                                       MAXIMUM_ALLOWED_ACCESS,
1242                                       &domain_sid, &domain_pol);
1243
1244         if (!NT_STATUS_IS_OK(result))
1245                 goto done;
1246
1247         /* Get handle on user */
1248
1249         {
1250                 uint32 *user_rids, num_rids, *name_types;
1251                 uint32 flags = 0x000003e8; /* Unknown */
1252
1253                 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1254                                                flags, 1, (const char **)&argv[1],
1255                                                &num_rids, &user_rids,
1256                                                &name_types);
1257
1258                 if (!NT_STATUS_IS_OK(result))
1259                         goto done;
1260
1261                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1262                                             access_mask,
1263                                             user_rids[0], &user_pol);
1264
1265                 if (!NT_STATUS_IS_OK(result))
1266                         goto done;
1267         }
1268
1269         /* Delete user */
1270
1271         result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
1272
1273         if (!NT_STATUS_IS_OK(result))
1274                 goto done;
1275
1276         /* Display results */
1277
1278  done:
1279         return result;
1280 }
1281
1282 /**********************************************************************
1283  * Query user security object 
1284  */
1285 static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, 
1286                                     TALLOC_CTX *mem_ctx,
1287                                     int argc, char **argv) 
1288 {
1289         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1290         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1291         uint32 info_level = 4;
1292         fstring server;
1293         uint32 user_rid = 0;
1294         TALLOC_CTX *ctx = NULL;
1295         SEC_DESC_BUF *sec_desc_buf=NULL;
1296         BOOL domain = False;
1297
1298         ctx=talloc_init();
1299         
1300         if ((argc < 1) || (argc > 2)) {
1301                 printf("Usage: %s [rid|-d]\n", argv[0]);
1302                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1303                 return NT_STATUS_OK;
1304         }
1305         
1306         if (argc > 1) {
1307                 if (strcmp(argv[1], "-d") == 0)
1308                         domain = True;
1309                 else
1310                         sscanf(argv[1], "%i", &user_rid);
1311         }
1312         
1313         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1314         strupper (server);
1315         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1316                                   &connect_pol);
1317
1318         if (!NT_STATUS_IS_OK(result))
1319                 goto done;
1320
1321         if (domain || user_rid)
1322                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1323                                               MAXIMUM_ALLOWED_ACCESS,
1324                                               &domain_sid, &domain_pol);
1325
1326         if (!NT_STATUS_IS_OK(result))
1327                 goto done;
1328
1329         if (user_rid)
1330                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1331                                             MAXIMUM_ALLOWED_ACCESS,
1332                                             user_rid, &user_pol);
1333
1334         if (!NT_STATUS_IS_OK(result))
1335                 goto done;
1336
1337         /* Pick which query pol to use */
1338
1339         pol = &connect_pol;
1340
1341         if (domain)
1342                 pol = &domain_pol;
1343
1344         if (user_rid)
1345                 pol = &user_pol;
1346
1347         /* Query SAM security object */
1348
1349         result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
1350                                         &sec_desc_buf);
1351
1352         if (!NT_STATUS_IS_OK(result))
1353                 goto done;
1354
1355         display_sec_desc(sec_desc_buf->sec);
1356         
1357 done:
1358         talloc_destroy(ctx);
1359         return result;
1360 }
1361
1362 static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, 
1363                                         TALLOC_CTX *mem_ctx,
1364                                         int argc, char **argv) 
1365 {
1366         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1367         uint16 unk_0, unk_1, unk_2;
1368
1369         if (argc != 1) {
1370                 printf("Usage: %s\n", argv[0]);
1371                 return NT_STATUS_OK;
1372         }
1373
1374         result = cli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1, &unk_2);
1375         
1376         if (NT_STATUS_IS_OK(result)) {
1377                 printf("unk_0 = 0x%08x\n", unk_0);
1378                 printf("unk_1 = 0x%08x\n", unk_1);
1379                 printf("unk_2 = 0x%08x\n", unk_2);
1380         }
1381
1382         return result;
1383 }
1384
1385
1386 /* List of commands exported by this module */
1387
1388 struct cmd_set samr_commands[] = {
1389
1390         { "SAMR" },
1391
1392         { "queryuser",          cmd_samr_query_user,            PIPE_SAMR,      "Query user info",         "" },
1393         { "querygroup",         cmd_samr_query_group,           PIPE_SAMR,      "Query group info",        "" },
1394         { "queryusergroups",    cmd_samr_query_usergroups,      PIPE_SAMR,      "Query user groups",       "" },
1395         { "queryuseraliases",   cmd_samr_query_useraliases,     PIPE_SAMR,      "Query user aliases",      "" },
1396         { "querygroupmem",      cmd_samr_query_groupmem,        PIPE_SAMR,      "Query group membership",  "" },
1397         { "queryaliasmem",      cmd_samr_query_aliasmem,        PIPE_SAMR,      "Query alias membership",  "" },
1398         { "querydispinfo",      cmd_samr_query_dispinfo,        PIPE_SAMR,      "Query display info",      "" },
1399         { "querydominfo",       cmd_samr_query_dominfo,         PIPE_SAMR,      "Query domain info",       "" },
1400         { "enumdomgroups",      cmd_samr_enum_dom_groups,       PIPE_SAMR,      "Enumerate domain groups", "" },
1401         { "enumalsgroups",      cmd_samr_enum_als_groups,       PIPE_SAMR,      "Enumerate alias groups",  "" },
1402
1403         { "createdomuser",      cmd_samr_create_dom_user,       PIPE_SAMR,      "Create domain user",      "" },
1404         { "samlookupnames",     cmd_samr_lookup_names,          PIPE_SAMR,      "Look up names",           "" },
1405         { "samlookuprids",      cmd_samr_lookup_rids,           PIPE_SAMR,      "Look up names",           "" },
1406         { "deletedomuser",      cmd_samr_delete_dom_user,       PIPE_SAMR,      "Delete domain user",      "" },
1407         { "samquerysecobj",     cmd_samr_query_sec_obj,         PIPE_SAMR, "Query SAMR security object",   "" },
1408         { "getdompwinfo",       cmd_samr_get_dom_pwinfo,        PIPE_SAMR, "Retrieve domain password info", "" },
1409
1410         { NULL }
1411 };