sync 3.0 branch with HEAD
[nivanova/samba-autobuild/.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  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, 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 (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, 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 (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         ZERO_STRUCT(group_ctr);
423
424         result = cli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
425                                           info_level, &group_ctr);
426         if (!NT_STATUS_IS_OK(result)) {
427                 goto done;
428         }
429
430         display_group_info_ctr(&group_ctr);
431
432 done:
433         return result;
434 }
435
436 /* Query groups a user is a member of */
437
438 static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, 
439                                           TALLOC_CTX *mem_ctx,
440                                           int argc, char **argv) 
441 {
442         POLICY_HND              connect_pol, 
443                                 domain_pol, 
444                                 user_pol;
445         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
446         uint32                  num_groups, 
447                                 user_rid;
448         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
449         DOM_GID                 *user_gids;
450         int                     i;
451         fstring                 server;
452         
453         if ((argc < 2) || (argc > 3)) {
454                 printf("Usage: %s rid [access mask]\n", argv[0]);
455                 return NT_STATUS_OK;
456         }
457
458         sscanf(argv[1], "%i", &user_rid);
459         
460         if (argc > 2)
461                 sscanf(argv[2], "%x", &access_mask);
462
463         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
464         strupper (server);
465                 
466         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
467                                    &connect_pol);
468
469         if (!NT_STATUS_IS_OK(result))
470                 goto done;
471
472         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
473                                       MAXIMUM_ALLOWED_ACCESS,
474                                       &domain_sid, &domain_pol);
475
476         if (!NT_STATUS_IS_OK(result))
477                 goto done;
478
479         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
480                                     access_mask,
481                                     user_rid, &user_pol);
482
483         if (!NT_STATUS_IS_OK(result))
484                 goto done;
485
486         result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
487                                            &num_groups, &user_gids);
488
489         if (!NT_STATUS_IS_OK(result))
490                 goto done;
491
492         for (i = 0; i < num_groups; i++) {
493                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n", 
494                        user_gids[i].g_rid, user_gids[i].attr);
495         }
496
497  done:
498         return result;
499 }
500
501 /* Query aliases a user is a member of */
502
503 static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, 
504                                           TALLOC_CTX *mem_ctx,
505                                           int argc, char **argv) 
506 {
507         POLICY_HND              connect_pol, domain_pol;
508         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
509         uint32                  user_rid, num_aliases, *alias_rids;
510         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
511         int                     i;
512         fstring                 server;
513         DOM_SID                 tmp_sid;
514         DOM_SID2                sid;
515         DOM_SID global_sid_Builtin;
516
517         string_to_sid(&global_sid_Builtin, "S-1-5-32");
518
519         if ((argc < 3) || (argc > 4)) {
520                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
521                 return NT_STATUS_OK;
522         }
523
524         sscanf(argv[2], "%i", &user_rid);
525         
526         if (argc > 3)
527                 sscanf(argv[3], "%x", &access_mask);
528
529         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
530         strupper (server);
531                 
532         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
533                                    &connect_pol);
534
535         if (!NT_STATUS_IS_OK(result))
536                 goto done;
537
538         if (StrCaseCmp(argv[1], "domain")==0)
539                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
540                                               access_mask,
541                                               &domain_sid, &domain_pol);
542         else if (StrCaseCmp(argv[1], "builtin")==0)
543                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
544                                               access_mask,
545                                               &global_sid_Builtin, &domain_pol);
546         else
547                 return NT_STATUS_OK;
548
549         if (!NT_STATUS_IS_OK(result))
550                 goto done;
551
552         sid_copy(&tmp_sid, &domain_sid);
553         sid_append_rid(&tmp_sid, user_rid);
554         init_dom_sid2(&sid, &tmp_sid);
555
556         result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, 1, &sid, &num_aliases, &alias_rids);
557
558         if (!NT_STATUS_IS_OK(result))
559                 goto done;
560
561         for (i = 0; i < num_aliases; i++) {
562                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
563         }
564
565  done:
566         return result;
567 }
568
569 /* Query members of a group */
570
571 static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, 
572                                         TALLOC_CTX *mem_ctx,
573                                         int argc, char **argv) 
574 {
575         POLICY_HND connect_pol, domain_pol, group_pol;
576         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
577         uint32 num_members, *group_rids, *group_attrs, group_rid;
578         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
579         int i;
580         fstring                 server;
581         
582         if ((argc < 2) || (argc > 3)) {
583                 printf("Usage: %s rid [access mask]\n", argv[0]);
584                 return NT_STATUS_OK;
585         }
586
587         sscanf(argv[1], "%i", &group_rid);
588         
589         if (argc > 2)
590                 sscanf(argv[2], "%x", &access_mask);
591
592         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
593         strupper (server);
594
595         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
596                                    &connect_pol);
597
598         if (!NT_STATUS_IS_OK(result))
599                 goto done;
600
601         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
602                                       MAXIMUM_ALLOWED_ACCESS,
603                                       &domain_sid, &domain_pol);
604
605         if (!NT_STATUS_IS_OK(result))
606                 goto done;
607
608         result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
609                                      access_mask,
610                                      group_rid, &group_pol);
611
612         if (!NT_STATUS_IS_OK(result))
613                 goto done;
614
615         result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
616                                          &num_members, &group_rids,
617                                          &group_attrs);
618
619         if (!NT_STATUS_IS_OK(result))
620                 goto done;
621
622         for (i = 0; i < num_members; i++) {
623                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
624                        group_attrs[i]);
625         }
626
627  done:
628         return result;
629 }
630
631 /* Enumerate domain groups */
632
633 static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, 
634                                          TALLOC_CTX *mem_ctx,
635                                          int argc, char **argv) 
636 {
637         POLICY_HND connect_pol, domain_pol;
638         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
639         uint32 start_idx, size, num_dom_groups, i;
640         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
641         struct acct_info *dom_groups;
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 groups */
674
675         start_idx = 0;
676         size = 0xffff;
677
678         do {
679                 result = cli_samr_enum_dom_groups(
680                         cli, mem_ctx, &domain_pol, &start_idx, size,
681                         &dom_groups, &num_dom_groups);
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_groups; i++)
687                                 printf("group:[%s] rid:[0x%x]\n", 
688                                        dom_groups[i].acct_name,
689                                        dom_groups[i].rid);
690                 }
691
692         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
693
694  done:
695         if (got_domain_pol)
696                 cli_samr_close(cli, mem_ctx, &domain_pol);
697
698         if (got_connect_pol)
699                 cli_samr_close(cli, mem_ctx, &connect_pol);
700
701         return result;
702 }
703
704 /* Enumerate alias groups */
705
706 static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, 
707                                          TALLOC_CTX *mem_ctx,
708                                          int argc, char **argv) 
709 {
710         POLICY_HND connect_pol, domain_pol;
711         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
712         uint32 start_idx, size, num_als_groups, i;
713         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
714         struct acct_info *als_groups;
715         DOM_SID global_sid_Builtin;
716         BOOL got_connect_pol = False, got_domain_pol = False;
717
718         string_to_sid(&global_sid_Builtin, "S-1-5-32");
719
720         if ((argc < 2) || (argc > 3)) {
721                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
722                 return NT_STATUS_OK;
723         }
724         
725         if (argc > 2)
726                 sscanf(argv[2], "%x", &access_mask);
727
728         /* Get sam policy handle */
729
730         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
731                                    &connect_pol);
732
733         if (!NT_STATUS_IS_OK(result))
734                 goto done;
735
736         got_connect_pol = True;
737
738         /* Get domain policy handle */
739
740         if (StrCaseCmp(argv[1], "domain")==0)
741                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
742                                               access_mask,
743                                               &domain_sid, &domain_pol);
744         else if (StrCaseCmp(argv[1], "builtin")==0)
745                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
746                                               access_mask,
747                                               &global_sid_Builtin, &domain_pol);
748         else
749                 return NT_STATUS_OK;
750
751         if (!NT_STATUS_IS_OK(result))
752                 goto done;
753
754         got_domain_pol = True;
755
756         /* Enumerate alias groups */
757
758         start_idx = 0;
759         size = 0xffff;          /* Number of groups to retrieve */
760
761         do {
762                 result = cli_samr_enum_als_groups(
763                         cli, mem_ctx, &domain_pol, &start_idx, size,
764                         &als_groups, &num_als_groups);
765
766                 if (NT_STATUS_IS_OK(result) ||
767                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
768
769                         for (i = 0; i < num_als_groups; i++)
770                                 printf("group:[%s] rid:[0x%x]\n", 
771                                        als_groups[i].acct_name,
772                                        als_groups[i].rid);
773                 }
774         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
775
776  done:
777         if (got_domain_pol)
778                 cli_samr_close(cli, mem_ctx, &domain_pol);
779         
780         if (got_connect_pol)
781                 cli_samr_close(cli, mem_ctx, &connect_pol);
782         
783         return result;
784 }
785
786 /* Query alias membership */
787
788 static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, 
789                                         TALLOC_CTX *mem_ctx,
790                                         int argc, char **argv) 
791 {
792         POLICY_HND connect_pol, domain_pol, alias_pol;
793         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
794         uint32 alias_rid, num_members, i;
795         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
796         DOM_SID *alias_sids;
797         DOM_SID global_sid_Builtin;
798         
799         string_to_sid(&global_sid_Builtin, "S-1-5-32");
800
801         if ((argc < 3) || (argc > 4)) {
802                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
803                 return NT_STATUS_OK;
804         }
805
806         sscanf(argv[2], "%i", &alias_rid);
807         
808         if (argc > 3)
809                 sscanf(argv[3], "%x", &access_mask);
810
811         /* Open SAMR handle */
812
813         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
814                                    &connect_pol);
815
816         if (!NT_STATUS_IS_OK(result))
817                 goto done;
818
819         /* Open handle on domain */
820         
821         if (StrCaseCmp(argv[1], "domain")==0)
822                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
823                                               MAXIMUM_ALLOWED_ACCESS,
824                                               &domain_sid, &domain_pol);
825         else if (StrCaseCmp(argv[1], "builtin")==0)
826                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
827                                               MAXIMUM_ALLOWED_ACCESS,
828                                               &global_sid_Builtin, &domain_pol);
829         else
830                 return NT_STATUS_OK;
831
832         if (!NT_STATUS_IS_OK(result))
833                 goto done;
834
835         /* Open handle on alias */
836
837         result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
838                                      access_mask,
839                                      alias_rid, &alias_pol);
840         if (!NT_STATUS_IS_OK(result))
841                 goto done;
842
843         result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
844                                          &num_members, &alias_sids);
845
846         if (!NT_STATUS_IS_OK(result))
847                 goto done;
848
849         for (i = 0; i < num_members; i++) {
850                 fstring sid_str;
851
852                 sid_to_string(sid_str, &alias_sids[i]);
853                 printf("\tsid:[%s]\n", sid_str);
854         }
855
856  done:
857         return result;
858 }
859
860 /* Query display info */
861
862 static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, 
863                                         TALLOC_CTX *mem_ctx,
864                                         int argc, char **argv) 
865 {
866         POLICY_HND connect_pol, domain_pol;
867         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
868         uint32 start_idx=0, max_entries=250, num_entries, i;
869         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
870         uint32 info_level = 1;
871         SAM_DISPINFO_CTR ctr;
872         SAM_DISPINFO_1 info1;
873         SAM_DISPINFO_2 info2;
874         SAM_DISPINFO_3 info3;
875         SAM_DISPINFO_4 info4;
876         SAM_DISPINFO_5 info5;
877
878         if (argc > 5) {
879                 printf("Usage: %s [info level] [start index] [max entries] [access mask]\n", argv[0]);
880                 return NT_STATUS_OK;
881         }
882
883         if (argc >= 2)
884                 sscanf(argv[1], "%i", &info_level);
885         
886         if (argc >= 3)
887                 sscanf(argv[2], "%i", &start_idx);
888         
889         if (argc >= 4)
890                 sscanf(argv[3], "%i", &max_entries);
891         
892         if (argc >= 5)
893                 sscanf(argv[4], "%x", &access_mask);
894
895         /* Get sam policy handle */
896
897         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
898                                    &connect_pol);
899
900         if (!NT_STATUS_IS_OK(result))
901                 goto done;
902
903         /* Get domain policy handle */
904
905         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
906                                       access_mask, 
907                                       &domain_sid, &domain_pol);
908
909         if (!NT_STATUS_IS_OK(result))
910                 goto done;
911
912         /* Query display info */
913
914         ZERO_STRUCT(ctr);
915         ZERO_STRUCT(info1);
916         
917         switch (info_level) {
918         case 1:
919                 ZERO_STRUCT(info1);
920                 ctr.sam.info1 = &info1;
921                 break;
922         case 2:
923                 ZERO_STRUCT(info2);
924                 ctr.sam.info2 = &info2;
925                 break;
926         case 3:
927                 ZERO_STRUCT(info3);
928                 ctr.sam.info3 = &info3;
929                 break;
930         case 4:
931                 ZERO_STRUCT(info4);
932                 ctr.sam.info4 = &info4;
933                 break;
934         case 5:
935                 ZERO_STRUCT(info5);
936                 ctr.sam.info5 = &info5;
937                 break;
938         }
939
940
941         while(1) {
942
943                 result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
944                                                  &start_idx, info_level,
945                                                  &num_entries, max_entries, &ctr);
946
947                 if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) 
948                         break;
949
950                 if (num_entries == 0) 
951                         break;
952
953                 for (i = 0; i < num_entries; i++) {
954                         switch (info_level) {
955                         case 1:
956                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
957                                 break;
958                         case 2:
959                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
960                                 break;
961                         case 3:
962                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
963                                 break;
964                         case 4:
965                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
966                                 break;
967                         case 5:
968                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
969                                 break;
970                         }
971                 }
972         }
973
974  done:
975         return result;
976 }
977
978 /* Query domain info */
979
980 static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, 
981                                        TALLOC_CTX *mem_ctx,
982                                        int argc, char **argv) 
983 {
984         POLICY_HND connect_pol, domain_pol;
985         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
986         uint32 switch_level = 2;
987         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
988         SAM_UNK_CTR ctr;
989
990         if (argc > 2) {
991                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
992                 return NT_STATUS_OK;
993         }
994
995         if (argc > 1)
996                 sscanf(argv[1], "%i", &switch_level);
997         
998         if (argc > 2)
999                 sscanf(argv[2], "%x", &access_mask);
1000
1001         /* Get sam policy handle */
1002
1003         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1004                                    &connect_pol);
1005
1006         if (!NT_STATUS_IS_OK(result))
1007                 goto done;
1008
1009         /* Get domain policy handle */
1010
1011         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1012                                       access_mask,
1013                                       &domain_sid, &domain_pol);
1014
1015         if (!NT_STATUS_IS_OK(result))
1016                 goto done;
1017
1018         /* Query domain info */
1019
1020         result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1021                                          switch_level, &ctr);
1022
1023         if (!NT_STATUS_IS_OK(result))
1024                 goto done;
1025
1026         /* Display domain info */
1027
1028         switch (switch_level) {
1029         case 1:
1030                 display_sam_unk_info_1(&ctr.info.inf1);
1031                 break;
1032         case 2:
1033                 display_sam_unk_info_2(&ctr.info.inf2);
1034                 break;
1035         default:
1036                 printf("cannot display domain info for switch value %d\n",
1037                        switch_level);
1038                 break;
1039         }
1040
1041  done:
1042  
1043         cli_samr_close(cli, mem_ctx, &domain_pol);
1044         cli_samr_close(cli, mem_ctx, &connect_pol);
1045         return result;
1046 }
1047
1048 /* Create domain user */
1049
1050 static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, 
1051                                          TALLOC_CTX *mem_ctx,
1052                                          int argc, char **argv) 
1053 {
1054         POLICY_HND connect_pol, domain_pol, user_pol;
1055         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1056         char *acct_name;
1057         uint16 acb_info;
1058         uint32 unknown, user_rid;
1059         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1060
1061         if ((argc < 2) || (argc > 3)) {
1062                 printf("Usage: %s username [access mask]\n", argv[0]);
1063                 return NT_STATUS_OK;
1064         }
1065
1066         acct_name = argv[1];
1067         
1068         if (argc > 2)
1069                 sscanf(argv[2], "%x", &access_mask);
1070
1071         /* Get sam policy handle */
1072
1073         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1074                                    &connect_pol);
1075
1076         if (!NT_STATUS_IS_OK(result))
1077                 goto done;
1078
1079         /* Get domain policy handle */
1080
1081         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1082                                       access_mask,
1083                                       &domain_sid, &domain_pol);
1084
1085         if (!NT_STATUS_IS_OK(result))
1086                 goto done;
1087
1088         /* Create domain user */
1089
1090         acb_info = ACB_NORMAL;
1091         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1092
1093         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1094                                           acct_name, acb_info, unknown,
1095                                           &user_pol, &user_rid);
1096
1097         if (!NT_STATUS_IS_OK(result))
1098                 goto done;
1099
1100  done:
1101         return result;
1102 }
1103
1104 /* Lookup sam names */
1105
1106 static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, 
1107                                       TALLOC_CTX *mem_ctx,
1108                                       int argc, char **argv) 
1109 {
1110         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1111         POLICY_HND connect_pol, domain_pol;
1112         uint32 flags = 0x000003e8; /* Unknown */
1113         uint32 num_rids, num_names, *name_types, *rids;
1114         const char **names;
1115         int i;
1116         DOM_SID global_sid_Builtin;
1117
1118         string_to_sid(&global_sid_Builtin, "S-1-5-32");
1119
1120         if (argc < 3) {
1121                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1122                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1123                 printf("or check on the builtin SID: S-1-5-32\n");
1124                 return NT_STATUS_OK;
1125         }
1126
1127         /* Get sam policy and domain handles */
1128
1129         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1130                                    &connect_pol);
1131
1132         if (!NT_STATUS_IS_OK(result))
1133                 goto done;
1134
1135         if (StrCaseCmp(argv[1], "domain")==0)
1136                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1137                                               MAXIMUM_ALLOWED_ACCESS,
1138                                               &domain_sid, &domain_pol);
1139         else if (StrCaseCmp(argv[1], "builtin")==0)
1140                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1141                                               MAXIMUM_ALLOWED_ACCESS,
1142                                               &global_sid_Builtin, &domain_pol);
1143         else
1144                 return NT_STATUS_OK;
1145
1146         if (!NT_STATUS_IS_OK(result))
1147                 goto done;
1148
1149         /* Look up names */
1150
1151         num_names = argc - 2;
1152         names = (const char **)talloc(mem_ctx, sizeof(char *) * num_names);
1153
1154         for (i = 0; i < argc - 2; i++)
1155                 names[i] = argv[i + 2];
1156
1157         result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1158                                        flags, num_names, names,
1159                                        &num_rids, &rids, &name_types);
1160
1161         if (!NT_STATUS_IS_OK(result))
1162                 goto done;
1163
1164         /* Display results */
1165
1166         for (i = 0; i < num_names; i++)
1167                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1168                        name_types[i]);
1169
1170  done:
1171         return result;
1172 }
1173
1174 /* Lookup sam rids */
1175
1176 static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, 
1177                                      TALLOC_CTX *mem_ctx,
1178                                      int argc, char **argv) 
1179 {
1180         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1181         POLICY_HND connect_pol, domain_pol;
1182         uint32 flags = 0x000003e8; /* Unknown */
1183         uint32 num_rids, num_names, *rids, *name_types;
1184         char **names;
1185         int i;
1186
1187         if (argc < 2) {
1188                 printf("Usage: %s rid1 [rid2 [rid3] [...]]\n", argv[0]);
1189                 return NT_STATUS_OK;
1190         }
1191
1192         /* Get sam policy and domain handles */
1193
1194         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1195                                    &connect_pol);
1196
1197         if (!NT_STATUS_IS_OK(result))
1198                 goto done;
1199
1200         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1201                                       MAXIMUM_ALLOWED_ACCESS,
1202                                       &domain_sid, &domain_pol);
1203
1204         if (!NT_STATUS_IS_OK(result))
1205                 goto done;
1206
1207         /* Look up rids */
1208
1209         num_rids = argc - 1;
1210         rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids);
1211
1212         for (i = 0; i < argc - 1; i++)
1213                 sscanf(argv[i + 1], "%i", &rids[i]);
1214
1215         result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
1216                                       flags, num_rids, rids,
1217                                       &num_names, &names, &name_types);
1218
1219         if (!NT_STATUS_IS_OK(result))
1220                 goto done;
1221
1222         /* Display results */
1223
1224         for (i = 0; i < num_names; i++)
1225                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1226
1227  done:
1228         return result;
1229 }
1230
1231 /* Delete domain user */
1232
1233 static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, 
1234                                          TALLOC_CTX *mem_ctx,
1235                                          int argc, char **argv) 
1236 {
1237         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1238         POLICY_HND connect_pol, domain_pol, user_pol;
1239         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1240
1241         if ((argc < 2) || (argc > 3)) {
1242                 printf("Usage: %s username\n", argv[0]);
1243                 return NT_STATUS_OK;
1244         }
1245         
1246         if (argc > 2)
1247                 sscanf(argv[2], "%x", &access_mask);
1248
1249         /* Get sam policy and domain handles */
1250
1251         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1252                                    &connect_pol);
1253
1254         if (!NT_STATUS_IS_OK(result))
1255                 goto done;
1256
1257         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1258                                       MAXIMUM_ALLOWED_ACCESS,
1259                                       &domain_sid, &domain_pol);
1260
1261         if (!NT_STATUS_IS_OK(result))
1262                 goto done;
1263
1264         /* Get handle on user */
1265
1266         {
1267                 uint32 *user_rids, num_rids, *name_types;
1268                 uint32 flags = 0x000003e8; /* Unknown */
1269
1270                 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1271                                                flags, 1, (const char **)&argv[1],
1272                                                &num_rids, &user_rids,
1273                                                &name_types);
1274
1275                 if (!NT_STATUS_IS_OK(result))
1276                         goto done;
1277
1278                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1279                                             access_mask,
1280                                             user_rids[0], &user_pol);
1281
1282                 if (!NT_STATUS_IS_OK(result))
1283                         goto done;
1284         }
1285
1286         /* Delete user */
1287
1288         result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
1289
1290         if (!NT_STATUS_IS_OK(result))
1291                 goto done;
1292
1293         /* Display results */
1294
1295  done:
1296         return result;
1297 }
1298
1299 /**********************************************************************
1300  * Query user security object 
1301  */
1302 static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, 
1303                                     TALLOC_CTX *mem_ctx,
1304                                     int argc, char **argv) 
1305 {
1306         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1307         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1308         uint32 info_level = 4;
1309         fstring server;
1310         uint32 user_rid = 0;
1311         TALLOC_CTX *ctx = NULL;
1312         SEC_DESC_BUF *sec_desc_buf=NULL;
1313         BOOL domain = False;
1314
1315         ctx=talloc_init();
1316         
1317         if ((argc < 1) || (argc > 2)) {
1318                 printf("Usage: %s [rid|-d]\n", argv[0]);
1319                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1320                 return NT_STATUS_OK;
1321         }
1322         
1323         if (argc > 1) {
1324                 if (strcmp(argv[1], "-d") == 0)
1325                         domain = True;
1326                 else
1327                         sscanf(argv[1], "%i", &user_rid);
1328         }
1329         
1330         slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
1331         strupper (server);
1332         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1333                                    &connect_pol);
1334
1335         if (!NT_STATUS_IS_OK(result))
1336                 goto done;
1337
1338         if (domain || user_rid)
1339                 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1340                                               MAXIMUM_ALLOWED_ACCESS,
1341                                               &domain_sid, &domain_pol);
1342
1343         if (!NT_STATUS_IS_OK(result))
1344                 goto done;
1345
1346         if (user_rid)
1347                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1348                                             MAXIMUM_ALLOWED_ACCESS,
1349                                             user_rid, &user_pol);
1350
1351         if (!NT_STATUS_IS_OK(result))
1352                 goto done;
1353
1354         /* Pick which query pol to use */
1355
1356         pol = &connect_pol;
1357
1358         if (domain)
1359                 pol = &domain_pol;
1360
1361         if (user_rid)
1362                 pol = &user_pol;
1363
1364         /* Query SAM security object */
1365
1366         result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
1367                                         &sec_desc_buf);
1368
1369         if (!NT_STATUS_IS_OK(result))
1370                 goto done;
1371
1372         display_sec_desc(sec_desc_buf->sec);
1373         
1374 done:
1375         talloc_destroy(ctx);
1376         return result;
1377 }
1378
1379 static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, 
1380                                         TALLOC_CTX *mem_ctx,
1381                                         int argc, char **argv) 
1382 {
1383         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1384         uint16 unk_0, unk_1, unk_2;
1385
1386         if (argc != 1) {
1387                 printf("Usage: %s\n", argv[0]);
1388                 return NT_STATUS_OK;
1389         }
1390
1391         result = cli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1, &unk_2);
1392         
1393         if (NT_STATUS_IS_OK(result)) {
1394                 printf("unk_0 = 0x%08x\n", unk_0);
1395                 printf("unk_1 = 0x%08x\n", unk_1);
1396                 printf("unk_2 = 0x%08x\n", unk_2);
1397         }
1398
1399         return result;
1400 }
1401
1402
1403 /* List of commands exported by this module */
1404
1405 struct cmd_set samr_commands[] = {
1406
1407         { "SAMR" },
1408
1409         { "queryuser",          cmd_samr_query_user,            PIPE_SAMR,      "Query user info",         "" },
1410         { "querygroup",         cmd_samr_query_group,           PIPE_SAMR,      "Query group info",        "" },
1411         { "queryusergroups",    cmd_samr_query_usergroups,      PIPE_SAMR,      "Query user groups",       "" },
1412         { "queryuseraliases",   cmd_samr_query_useraliases,     PIPE_SAMR,      "Query user aliases",      "" },
1413         { "querygroupmem",      cmd_samr_query_groupmem,        PIPE_SAMR,      "Query group membership",  "" },
1414         { "queryaliasmem",      cmd_samr_query_aliasmem,        PIPE_SAMR,      "Query alias membership",  "" },
1415         { "querydispinfo",      cmd_samr_query_dispinfo,        PIPE_SAMR,      "Query display info",      "" },
1416         { "querydominfo",       cmd_samr_query_dominfo,         PIPE_SAMR,      "Query domain info",       "" },
1417         { "enumdomgroups",      cmd_samr_enum_dom_groups,       PIPE_SAMR,      "Enumerate domain groups", "" },
1418         { "enumalsgroups",      cmd_samr_enum_als_groups,       PIPE_SAMR,      "Enumerate alias groups",  "" },
1419
1420         { "createdomuser",      cmd_samr_create_dom_user,       PIPE_SAMR,      "Create domain user",      "" },
1421         { "samlookupnames",     cmd_samr_lookup_names,          PIPE_SAMR,      "Look up names",           "" },
1422         { "samlookuprids",      cmd_samr_lookup_rids,           PIPE_SAMR,      "Look up names",           "" },
1423         { "deletedomuser",      cmd_samr_delete_dom_user,       PIPE_SAMR,      "Delete domain user",      "" },
1424         { "samquerysecobj",     cmd_samr_query_sec_obj,         PIPE_SAMR, "Query SAMR security object",   "" },
1425         { "getdompwinfo",       cmd_samr_get_dom_pwinfo,        PIPE_SAMR, "Retrieve domain password info", "" },
1426
1427         { NULL }
1428 };