r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
[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_7 structure
32  ****************************************************************************/
33 static void display_sam_user_info_7(SAM_USER_INFO_7 *usr)
34 {
35         fstring temp;
36
37         unistr2_to_ascii(temp, &usr->uni_name, sizeof(temp)-1);
38         printf("\tUser Name   :\t%s\n", temp);
39 }
40
41 /****************************************************************************
42  display sam_user_info_9 structure
43  ****************************************************************************/
44 static void display_sam_user_info_9(SAM_USER_INFO_9 *usr)
45 {
46         printf("\tPrimary group RID   :\tox%x\n", usr->rid_group);
47 }
48
49 /****************************************************************************
50  display sam_user_info_21 structure
51  ****************************************************************************/
52 static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
53 {
54         fstring temp;
55
56         unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp)-1);
57         printf("\tUser Name   :\t%s\n", temp);
58         
59         unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp)-1);
60         printf("\tFull Name   :\t%s\n", temp);
61         
62         unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp)-1);
63         printf("\tHome Drive  :\t%s\n", temp);
64         
65         unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp)-1);
66         printf("\tDir Drive   :\t%s\n", temp);
67         
68         unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp)-1);
69         printf("\tProfile Path:\t%s\n", temp);
70         
71         unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp)-1);
72         printf("\tLogon Script:\t%s\n", temp);
73         
74         unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp)-1);
75         printf("\tDescription :\t%s\n", temp);
76         
77         unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1);
78         printf("\tWorkstations:\t%s\n", temp);
79         
80         unistr2_to_ascii(temp, &usr->uni_comment, sizeof(temp)-1);
81         printf("\tUnknown Str :\t%s\n", temp);
82         
83         unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1);
84         printf("\tRemote Dial :\t%s\n", temp);
85         
86         printf("\tLogon Time               :\t%s\n", 
87                http_timestring(nt_time_to_unix(&usr->logon_time)));
88         printf("\tLogoff Time              :\t%s\n", 
89                http_timestring(nt_time_to_unix(&usr->logoff_time)));
90         printf("\tKickoff Time             :\t%s\n", 
91                http_timestring(nt_time_to_unix(&usr->kickoff_time)));
92         printf("\tPassword last set Time   :\t%s\n", 
93                http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
94         printf("\tPassword can change Time :\t%s\n", 
95                http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
96         printf("\tPassword must change Time:\t%s\n", 
97                http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
98         
99         printf("\tunknown_2[0..31]...\n"); /* user passwords? */
100         
101         printf("\tuser_rid :\t0x%x\n"  , usr->user_rid ); /* User ID */
102         printf("\tgroup_rid:\t0x%x\n"  , usr->group_rid); /* Group ID */
103         printf("\tacb_info :\t0x%08x\n", usr->acb_info ); /* Account Control Info */
104         
105         printf("\tfields_present:\t0x%08x\n", usr->fields_present); /* 0x00ff ffff */
106         printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
107         printf("\tbad_password_count:\t0x%08x\n", usr->bad_password_count);
108         printf("\tlogon_count:\t0x%08x\n", usr->logon_count);
109         
110         printf("\tpadding1[0..7]...\n");
111         
112         if (usr->ptr_logon_hrs) {
113                 printf("\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len);
114         }
115 }
116
117 static const char *display_time(NTTIME nttime)
118 {
119         static fstring string;
120
121         float high;
122         float low;
123         int sec;
124         int days, hours, mins, secs;
125
126         if (nttime.high==0 && nttime.low==0)
127                 return "Now";
128
129         if (nttime.high==0x80000000 && nttime.low==0)
130                 return "Never";
131
132         high = 65536;   
133         high = high/10000;
134         high = high*65536;
135         high = high/1000;
136         high = high * (~nttime.high);
137
138         low = ~nttime.low;      
139         low = low/(1000*1000*10);
140
141         sec=high+low;
142
143         days=sec/(60*60*24);
144         hours=(sec - (days*60*60*24)) / (60*60);
145         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
146         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
147
148         fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
149         return (string);
150 }
151
152 static void display_password_properties(uint32 password_properties) 
153 {
154         printf("password_properties: 0x%08x\n", password_properties);
155                 
156         if (password_properties & DOMAIN_PASSWORD_COMPLEX)
157                 printf("\tDOMAIN_PASSWORD_COMPLEX\n");
158                         
159         if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
160                 printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
161                         
162         if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
163                 printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
164                         
165         if (password_properties & DOMAIN_LOCKOUT_ADMINS)
166                 printf("\tDOMAIN_LOCKOUT_ADMINS\n");
167                         
168         if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
169                 printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
170                         
171         if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
172                 printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
173 }
174
175 static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1)
176 {
177         
178         printf("Minimum password length:\t\t\t%d\n", info1->min_length_password);
179         printf("Password uniqueness (remember x passwords):\t%d\n", info1->password_history);
180         display_password_properties(info1->password_properties);
181         printf("password expire in:\t\t\t\t%s\n", display_time(info1->expire));
182         printf("Min password age (allow changing in x days):\t%s\n", display_time(info1->min_passwordage));
183 }
184
185 static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
186 {
187         fstring name;
188
189         unistr2_to_ascii(name, &info2->uni_domain, sizeof(name) - 1); 
190         printf("Domain:\t\t%s\n", name);
191
192         unistr2_to_ascii(name, &info2->uni_server, sizeof(name) - 1); 
193         printf("Server:\t\t%s\n", name);
194
195         unistr2_to_ascii(name, &info2->uni_comment, sizeof(name) - 1); 
196         printf("Comment:\t%s\n", name);
197
198         printf("Total Users:\t%d\n", info2->num_domain_usrs);
199         printf("Total Groups:\t%d\n", info2->num_domain_grps);
200         printf("Total Aliases:\t%d\n", info2->num_local_grps);
201         
202         printf("Sequence No:\t%d\n", info2->seq_num.low);
203
204         printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info2->logout));
205
206         printf("Unknown 4:\t0x%x\n", info2->unknown_4);
207         printf("Server Role:\t%s\n", server_role_str(info2->server_role));
208         printf("Unknown 6:\t0x%x\n", info2->unknown_6);
209 }
210
211 static void display_sam_unk_info_3(SAM_UNK_INFO_3 *info3)
212 {
213         printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info3->logout));
214 }
215
216 static void display_sam_unk_info_4(SAM_UNK_INFO_4 *info4)
217 {
218         fstring name;
219
220         unistr2_to_ascii(name, &info4->uni_comment, sizeof(name) - 1); 
221         printf("Comment:\t%s\n", name);
222 }
223
224 static void display_sam_unk_info_5(SAM_UNK_INFO_5 *info5)
225 {
226         fstring name;
227
228         unistr2_to_ascii(name, &info5->uni_domain, sizeof(name) - 1); 
229         printf("Domain:\t\t%s\n", name);
230 }
231
232 static void display_sam_unk_info_6(SAM_UNK_INFO_6 *info6)
233 {
234         fstring name;
235
236         unistr2_to_ascii(name, &info6->uni_server, sizeof(name) - 1); 
237         printf("Server:\t\t%s\n", name);
238 }
239
240 static void display_sam_unk_info_7(SAM_UNK_INFO_7 *info7)
241 {
242         printf("Server Role:\t%s\n", server_role_str(info7->server_role));
243 }
244
245 static void display_sam_unk_info_8(SAM_UNK_INFO_8 *info8)
246 {
247         printf("Sequence No:\t%d\n", info8->seq_num.low);
248         printf("Domain Create Time:\t%s\n", 
249                 http_timestring(nt_time_to_unix(&info8->domain_create_time)));
250 }
251
252 static void display_sam_unk_info_9(SAM_UNK_INFO_9 *info9)
253 {
254         printf("unknown:\t%d (0x%08x)\n", info9->unknown, info9->unknown);
255 }
256
257 static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
258 {
259         printf("Bad password lockout duration:               %s\n", display_time(info12->duration));
260         printf("Reset Lockout after:                         %s\n", display_time(info12->reset_count));
261         printf("Lockout after bad attempts:                  %d\n", info12->bad_attempt_lockout);
262 }
263
264 static void display_sam_unk_info_13(SAM_UNK_INFO_13 *info13)
265 {
266         printf("Sequence No:\t%d\n", info13->seq_num.low);
267         printf("Domain Create Time:\t%s\n", 
268                 http_timestring(nt_time_to_unix(&info13->domain_create_time)));
269         printf("Unknown1:\t%d\n", info13->unknown1);
270         printf("Unknown2:\t%d\n", info13->unknown2);
271
272 }
273
274 static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
275 {
276         fstring tmp;
277
278         printf("index: 0x%x ", e1->user_idx);
279         printf("RID: 0x%x ", e1->rid_user);
280         printf("acb: 0x%x ", e1->acb_info);
281
282         unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp)-1);
283         printf("Account: %s\t", tmp);
284
285         unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp)-1);
286         printf("Name: %s\t", tmp);
287
288         unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp)-1);
289         printf("Desc: %s\n", tmp);
290 }
291
292 static void display_sam_info_2(SAM_ENTRY2 *e2, SAM_STR2 *s2)
293 {
294         fstring tmp;
295
296         printf("index: 0x%x ", e2->user_idx);
297         printf("RID: 0x%x ", e2->rid_user);
298         printf("acb: 0x%x ", e2->acb_info);
299         
300         unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp)-1);
301         printf("Account: %s\t", tmp);
302
303         unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp)-1);
304         printf("Name: %s\n", tmp);
305
306 }
307
308 static void display_sam_info_3(SAM_ENTRY3 *e3, SAM_STR3 *s3)
309 {
310         fstring tmp;
311
312         printf("index: 0x%x ", e3->grp_idx);
313         printf("RID: 0x%x ", e3->rid_grp);
314         printf("attr: 0x%x ", e3->attr);
315         
316         unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp)-1);
317         printf("Account: %s\t", tmp);
318
319         unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp)-1);
320         printf("Name: %s\n", tmp);
321
322 }
323
324 static void display_sam_info_4(SAM_ENTRY4 *e4, SAM_STR4 *s4)
325 {
326         int i;
327
328         printf("index: %d ", e4->user_idx);
329         
330         printf("Account: ");
331         for (i=0; i<s4->acct_name.str_str_len; i++)
332                 printf("%c", s4->acct_name.buffer[i]);
333         printf("\n");
334
335 }
336
337 static void display_sam_info_5(SAM_ENTRY5 *e5, SAM_STR5 *s5)
338 {
339         int i;
340
341         printf("index: 0x%x ", e5->grp_idx);
342         
343         printf("Account: ");
344         for (i=0; i<s5->grp_name.str_str_len; i++)
345                 printf("%c", s5->grp_name.buffer[i]);
346         printf("\n");
347
348 }
349
350 /****************************************************************************
351  Try samr_connect4 first, then samr_conenct if it fails
352  ****************************************************************************/
353 static NTSTATUS try_samr_connects(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
354                                   uint32 access_mask, POLICY_HND *connect_pol)
355 {
356         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
357         
358         result = rpccli_samr_connect4(cli, mem_ctx, access_mask, connect_pol);
359         if (!NT_STATUS_IS_OK(result)) {
360                 result = rpccli_samr_connect(cli, mem_ctx, access_mask,
361                                           connect_pol);
362         }
363         return result;
364 }
365
366 /**********************************************************************
367  * Query user information 
368  */
369 static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli, 
370                                     TALLOC_CTX *mem_ctx,
371                                     int argc, const char **argv) 
372 {
373         POLICY_HND connect_pol, domain_pol, user_pol;
374         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
375         uint32 info_level = 21;
376         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
377         SAM_USERINFO_CTR *user_ctr;
378         fstring server;
379         uint32 user_rid;
380         
381         if ((argc < 2) || (argc > 4)) {
382                 printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
383                 return NT_STATUS_OK;
384         }
385         
386         user_rid = strtoul(argv[1], NULL, 10);
387         
388         if (argc > 2)
389                 sscanf(argv[2], "%i", &info_level);
390                 
391         if (argc > 3)
392                 sscanf(argv[3], "%x", &access_mask);
393         
394
395         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
396         strupper_m(server);
397         
398         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
399                                    &connect_pol);
400
401         if (!NT_STATUS_IS_OK(result))
402                 goto done;
403
404         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
405                                       MAXIMUM_ALLOWED_ACCESS,
406                                       &domain_sid, &domain_pol);
407
408         if (!NT_STATUS_IS_OK(result))
409                 goto done;
410
411         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
412                                     access_mask,
413                                     user_rid, &user_pol);
414
415         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) &&
416             (user_rid == 0)) {
417
418                 /* Probably this was a user name, try lookupnames */
419                 uint32 num_rids;
420                 uint32 *rids, *types;
421                 
422                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
423                                                   1000, 1, &argv[1],
424                                                   &num_rids, &rids,
425                                                   &types);
426
427                 if (NT_STATUS_IS_OK(result)) {
428                         result = rpccli_samr_open_user(cli, mem_ctx,
429                                                        &domain_pol,
430                                                        access_mask,
431                                                        rids[0], &user_pol);
432                 }
433         }
434
435
436         if (!NT_STATUS_IS_OK(result))
437                 goto done;
438
439         ZERO_STRUCT(user_ctr);
440
441         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
442                                          info_level, &user_ctr);
443
444         if (!NT_STATUS_IS_OK(result))
445                 goto done;
446
447         switch (user_ctr->switch_value) {
448         case 21:
449                 display_sam_user_info_21(user_ctr->info.id21);
450                 break;
451         case 7:
452                 display_sam_user_info_7(user_ctr->info.id7);
453                 break;
454         case 9:
455                 display_sam_user_info_9(user_ctr->info.id9);
456                 break;
457         default:
458                 printf("Unsupported infolevel: %d\n", info_level);
459                 break;
460         }
461
462         rpccli_samr_close(cli, mem_ctx, &user_pol);
463         rpccli_samr_close(cli, mem_ctx, &domain_pol);
464         rpccli_samr_close(cli, mem_ctx, &connect_pol);
465
466 done:
467         return result;
468 }
469
470 /****************************************************************************
471  display group info
472  ****************************************************************************/
473 static void display_group_info1(GROUP_INFO1 *info1)
474 {
475         fstring temp;
476
477         unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp)-1);
478         printf("\tGroup Name:\t%s\n", temp);
479         unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1);
480         printf("\tDescription:\t%s\n", temp);
481         printf("\tGroup Attribute:%d\n", info1->group_attr);
482         printf("\tNum Members:%d\n", info1->num_members);
483 }
484
485 /****************************************************************************
486  display group info
487  ****************************************************************************/
488 static void display_group_info2(GROUP_INFO2 *info2)
489 {
490         fstring name;
491
492         unistr2_to_ascii(name, &info2->uni_acct_name, sizeof(name)-1);
493         printf("\tGroup Description:%s\n", name);
494 }
495
496
497 /****************************************************************************
498  display group info
499  ****************************************************************************/
500 static void display_group_info3(GROUP_INFO3 *info3)
501 {
502         printf("\tGroup Attribute:%d\n", info3->group_attr);
503 }
504
505
506 /****************************************************************************
507  display group info
508  ****************************************************************************/
509 static void display_group_info4(GROUP_INFO4 *info4)
510 {
511         fstring desc;
512
513         unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc)-1);
514         printf("\tGroup Description:%s\n", desc);
515 }
516
517 /****************************************************************************
518  display group info
519  ****************************************************************************/
520 static void display_group_info5(GROUP_INFO5 *info5)
521 {
522         fstring temp;
523
524         unistr2_to_ascii(temp, &info5->uni_acct_name, sizeof(temp)-1);
525         printf("\tGroup Name:\t%s\n", temp);
526         unistr2_to_ascii(temp, &info5->uni_acct_desc, sizeof(temp)-1);
527         printf("\tDescription:\t%s\n", temp);
528         printf("\tGroup Attribute:%d\n", info5->group_attr);
529         printf("\tNum Members:%d\n", info5->num_members);
530 }
531
532 /****************************************************************************
533  display sam sync structure
534  ****************************************************************************/
535 static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
536 {
537         switch (ctr->switch_value1) {
538                 case 1:
539                         display_group_info1(&ctr->group.info1);
540                         break;
541                 case 2:
542                         display_group_info2(&ctr->group.info2);
543                         break;
544                 case 3:
545                         display_group_info3(&ctr->group.info3);
546                         break;
547                 case 4:
548                         display_group_info4(&ctr->group.info4);
549                         break;
550                 case 5:
551                         display_group_info5(&ctr->group.info5);
552                         break;
553
554         }
555 }
556
557 /***********************************************************************
558  * Query group information 
559  */
560 static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli, 
561                                      TALLOC_CTX *mem_ctx,
562                                      int argc, const char **argv) 
563 {
564         POLICY_HND connect_pol, domain_pol, group_pol;
565         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
566         uint32 info_level = 1;
567         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
568         GROUP_INFO_CTR *group_ctr;
569         fstring                 server; 
570         uint32 group_rid;
571         
572         if ((argc < 2) || (argc > 4)) {
573                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
574                 return NT_STATUS_OK;
575         }
576
577         sscanf(argv[1], "%i", &group_rid);
578         
579         if (argc > 2)
580                 sscanf(argv[2], "%i", &info_level);
581         
582         if (argc > 3)
583                 sscanf(argv[3], "%x", &access_mask);
584
585         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
586         strupper_m(server);
587
588         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
589                                    &connect_pol);
590
591         if (!NT_STATUS_IS_OK(result))
592                 goto done;
593
594         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
595                                       MAXIMUM_ALLOWED_ACCESS,
596                                       &domain_sid, &domain_pol);
597
598         if (!NT_STATUS_IS_OK(result))
599                 goto done;
600
601         result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
602                                      access_mask,
603                                      group_rid, &group_pol);
604
605         if (!NT_STATUS_IS_OK(result))
606                 goto done;
607
608         result = rpccli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
609                                           info_level, &group_ctr);
610         if (!NT_STATUS_IS_OK(result)) {
611                 goto done;
612         }
613
614         display_group_info_ctr(group_ctr);
615
616         rpccli_samr_close(cli, mem_ctx, &group_pol);
617         rpccli_samr_close(cli, mem_ctx, &domain_pol);
618         rpccli_samr_close(cli, mem_ctx, &connect_pol);
619 done:
620         return result;
621 }
622
623 /* Query groups a user is a member of */
624
625 static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli, 
626                                           TALLOC_CTX *mem_ctx,
627                                           int argc, const char **argv) 
628 {
629         POLICY_HND              connect_pol, 
630                                 domain_pol, 
631                                 user_pol;
632         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
633         uint32                  num_groups, 
634                                 user_rid;
635         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
636         DOM_GID                 *user_gids;
637         int                     i;
638         fstring                 server;
639         
640         if ((argc < 2) || (argc > 3)) {
641                 printf("Usage: %s rid [access mask]\n", argv[0]);
642                 return NT_STATUS_OK;
643         }
644
645         sscanf(argv[1], "%i", &user_rid);
646         
647         if (argc > 2)
648                 sscanf(argv[2], "%x", &access_mask);
649
650         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
651         strupper_m(server);
652                 
653         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
654                                    &connect_pol);
655
656         if (!NT_STATUS_IS_OK(result))
657                 goto done;
658
659         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
660                                       MAXIMUM_ALLOWED_ACCESS,
661                                       &domain_sid, &domain_pol);
662
663         if (!NT_STATUS_IS_OK(result))
664                 goto done;
665
666         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
667                                     access_mask,
668                                     user_rid, &user_pol);
669
670         if (!NT_STATUS_IS_OK(result))
671                 goto done;
672
673         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
674                                            &num_groups, &user_gids);
675
676         if (!NT_STATUS_IS_OK(result))
677                 goto done;
678
679         for (i = 0; i < num_groups; i++) {
680                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n", 
681                        user_gids[i].g_rid, user_gids[i].attr);
682         }
683
684         rpccli_samr_close(cli, mem_ctx, &user_pol);
685         rpccli_samr_close(cli, mem_ctx, &domain_pol);
686         rpccli_samr_close(cli, mem_ctx, &connect_pol);
687  done:
688         return result;
689 }
690
691 /* Query aliases a user is a member of */
692
693 static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli, 
694                                            TALLOC_CTX *mem_ctx,
695                                            int argc, const char **argv) 
696 {
697         POLICY_HND              connect_pol, domain_pol;
698         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
699         DOM_SID                *sids;
700         size_t                     num_sids;
701         uint32                  num_aliases, *alias_rids;
702         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
703         int                     i;
704         fstring                 server;
705         DOM_SID2               *sid2;
706
707         if (argc < 3) {
708                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
709                 return NT_STATUS_INVALID_PARAMETER;
710         }
711
712         sids = NULL;
713         num_sids = 0;
714
715         for (i=2; i<argc; i++) {
716                 DOM_SID tmp_sid;
717                 if (!string_to_sid(&tmp_sid, argv[i])) {
718                         printf("%s is not a legal SID\n", argv[i]);
719                         return NT_STATUS_INVALID_PARAMETER;
720                 }
721                 add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
722         }
723
724         sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
725         if (sid2 == NULL)
726                 return NT_STATUS_NO_MEMORY;
727
728         for (i=0; i<num_sids; i++) {
729                 sid_copy(&sid2[i].sid, &sids[i]);
730                 sid2[i].num_auths = sid2[i].sid.num_auths;
731         }
732
733         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
734         strupper_m(server);
735                 
736         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
737                                    &connect_pol);
738
739         if (!NT_STATUS_IS_OK(result))
740                 goto done;
741
742         if (StrCaseCmp(argv[1], "domain")==0)
743                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
744                                               access_mask,
745                                               &domain_sid, &domain_pol);
746         else if (StrCaseCmp(argv[1], "builtin")==0)
747                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
748                                               access_mask,
749                                               &global_sid_Builtin,
750                                               &domain_pol);
751         else {
752                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
753                 return NT_STATUS_INVALID_PARAMETER;
754         }
755
756         if (!NT_STATUS_IS_OK(result))
757                 goto done;
758
759         result = rpccli_samr_query_useraliases(cli, mem_ctx, &domain_pol,
760                                             num_sids, sid2,
761                                             &num_aliases, &alias_rids);
762
763         if (!NT_STATUS_IS_OK(result))
764                 goto done;
765
766         for (i = 0; i < num_aliases; i++) {
767                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
768         }
769
770         rpccli_samr_close(cli, mem_ctx, &domain_pol);
771         rpccli_samr_close(cli, mem_ctx, &connect_pol);
772  done:
773         return result;
774 }
775
776 /* Query members of a group */
777
778 static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli, 
779                                         TALLOC_CTX *mem_ctx,
780                                         int argc, const char **argv) 
781 {
782         POLICY_HND connect_pol, domain_pol, group_pol;
783         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
784         uint32 num_members, *group_rids, *group_attrs, group_rid;
785         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
786         int i;
787         fstring                 server;
788         
789         if ((argc < 2) || (argc > 3)) {
790                 printf("Usage: %s rid [access mask]\n", argv[0]);
791                 return NT_STATUS_OK;
792         }
793
794         sscanf(argv[1], "%i", &group_rid);
795         
796         if (argc > 2)
797                 sscanf(argv[2], "%x", &access_mask);
798
799         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
800         strupper_m(server);
801
802         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
803                                    &connect_pol);
804
805         if (!NT_STATUS_IS_OK(result))
806                 goto done;
807
808         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
809                                       MAXIMUM_ALLOWED_ACCESS,
810                                       &domain_sid, &domain_pol);
811
812         if (!NT_STATUS_IS_OK(result))
813                 goto done;
814
815         result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
816                                      access_mask,
817                                      group_rid, &group_pol);
818
819         if (!NT_STATUS_IS_OK(result))
820                 goto done;
821
822         result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
823                                          &num_members, &group_rids,
824                                          &group_attrs);
825
826         if (!NT_STATUS_IS_OK(result))
827                 goto done;
828
829         for (i = 0; i < num_members; i++) {
830                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
831                        group_attrs[i]);
832         }
833
834         rpccli_samr_close(cli, mem_ctx, &group_pol);
835         rpccli_samr_close(cli, mem_ctx, &domain_pol);
836         rpccli_samr_close(cli, mem_ctx, &connect_pol);
837  done:
838         return result;
839 }
840
841 /* Enumerate domain users */
842
843 static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli, 
844                                         TALLOC_CTX *mem_ctx,
845                                         int argc, const char **argv) 
846 {
847         POLICY_HND connect_pol, domain_pol;
848         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
849         uint32 start_idx, size, num_dom_users, i;
850         char **dom_users;
851         uint32 *dom_rids;
852         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
853         uint32 acb_mask = ACB_NORMAL;
854         BOOL got_connect_pol = False, got_domain_pol = False;
855
856         if ((argc < 1) || (argc > 3)) {
857                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
858                 return NT_STATUS_OK;
859         }
860         
861         if (argc > 1)
862                 sscanf(argv[1], "%x", &access_mask);
863
864         if (argc > 2)
865                 sscanf(argv[2], "%x", &acb_mask);
866
867         /* Get sam policy handle */
868
869         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
870                                    &connect_pol);
871
872         if (!NT_STATUS_IS_OK(result))
873                 goto done;
874
875         got_connect_pol = True;
876
877         /* Get domain policy handle */
878
879         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
880                                       access_mask,
881                                       &domain_sid, &domain_pol);
882
883         if (!NT_STATUS_IS_OK(result))
884                 goto done;
885
886         got_domain_pol = True;
887
888         /* Enumerate domain users */
889
890         start_idx = 0;
891         size = 0xffff;
892
893         do {
894                 result = rpccli_samr_enum_dom_users(
895                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
896                         size, &dom_users, &dom_rids, &num_dom_users);
897
898                 if (NT_STATUS_IS_OK(result) ||
899                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
900
901                         for (i = 0; i < num_dom_users; i++)
902                                printf("user:[%s] rid:[0x%x]\n", 
903                                        dom_users[i], dom_rids[i]);
904                 }
905
906         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
907
908  done:
909         if (got_domain_pol)
910                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
911
912         if (got_connect_pol)
913                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
914
915         return result;
916 }
917
918 /* Enumerate domain groups */
919
920 static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli, 
921                                          TALLOC_CTX *mem_ctx,
922                                          int argc, const char **argv) 
923 {
924         POLICY_HND connect_pol, domain_pol;
925         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
926         uint32 start_idx, size, num_dom_groups, i;
927         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
928         struct acct_info *dom_groups;
929         BOOL got_connect_pol = False, got_domain_pol = False;
930
931         if ((argc < 1) || (argc > 2)) {
932                 printf("Usage: %s [access_mask]\n", argv[0]);
933                 return NT_STATUS_OK;
934         }
935         
936         if (argc > 1)
937                 sscanf(argv[1], "%x", &access_mask);
938
939         /* Get sam policy handle */
940
941         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
942                                    &connect_pol);
943
944         if (!NT_STATUS_IS_OK(result))
945                 goto done;
946
947         got_connect_pol = True;
948
949         /* Get domain policy handle */
950
951         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
952                                       access_mask,
953                                       &domain_sid, &domain_pol);
954
955         if (!NT_STATUS_IS_OK(result))
956                 goto done;
957
958         got_domain_pol = True;
959
960         /* Enumerate domain groups */
961
962         start_idx = 0;
963         size = 0xffff;
964
965         do {
966                 result = rpccli_samr_enum_dom_groups(
967                         cli, mem_ctx, &domain_pol, &start_idx, size,
968                         &dom_groups, &num_dom_groups);
969
970                 if (NT_STATUS_IS_OK(result) ||
971                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
972
973                         for (i = 0; i < num_dom_groups; i++)
974                                 printf("group:[%s] rid:[0x%x]\n", 
975                                        dom_groups[i].acct_name,
976                                        dom_groups[i].rid);
977                 }
978
979         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
980
981  done:
982         if (got_domain_pol)
983                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
984
985         if (got_connect_pol)
986                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
987
988         return result;
989 }
990
991 /* Enumerate alias groups */
992
993 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli, 
994                                          TALLOC_CTX *mem_ctx,
995                                          int argc, const char **argv) 
996 {
997         POLICY_HND connect_pol, domain_pol;
998         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
999         uint32 start_idx, size, num_als_groups, i;
1000         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1001         struct acct_info *als_groups;
1002         BOOL got_connect_pol = False, got_domain_pol = False;
1003
1004         if ((argc < 2) || (argc > 3)) {
1005                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
1006                 return NT_STATUS_OK;
1007         }
1008         
1009         if (argc > 2)
1010                 sscanf(argv[2], "%x", &access_mask);
1011
1012         /* Get sam policy handle */
1013
1014         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1015                                    &connect_pol);
1016
1017         if (!NT_STATUS_IS_OK(result))
1018                 goto done;
1019
1020         got_connect_pol = True;
1021
1022         /* Get domain policy handle */
1023
1024         if (StrCaseCmp(argv[1], "domain")==0)
1025                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1026                                               access_mask,
1027                                               &domain_sid, &domain_pol);
1028         else if (StrCaseCmp(argv[1], "builtin")==0)
1029                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1030                                               access_mask,
1031                                               &global_sid_Builtin, &domain_pol);
1032         else
1033                 return NT_STATUS_OK;
1034
1035         if (!NT_STATUS_IS_OK(result))
1036                 goto done;
1037
1038         got_domain_pol = True;
1039
1040         /* Enumerate alias groups */
1041
1042         start_idx = 0;
1043         size = 0xffff;          /* Number of groups to retrieve */
1044
1045         do {
1046                 result = rpccli_samr_enum_als_groups(
1047                         cli, mem_ctx, &domain_pol, &start_idx, size,
1048                         &als_groups, &num_als_groups);
1049
1050                 if (NT_STATUS_IS_OK(result) ||
1051                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1052
1053                         for (i = 0; i < num_als_groups; i++)
1054                                 printf("group:[%s] rid:[0x%x]\n", 
1055                                        als_groups[i].acct_name,
1056                                        als_groups[i].rid);
1057                 }
1058         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1059
1060  done:
1061         if (got_domain_pol)
1062                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
1063         
1064         if (got_connect_pol)
1065                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
1066         
1067         return result;
1068 }
1069
1070 /* Query alias membership */
1071
1072 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli, 
1073                                         TALLOC_CTX *mem_ctx,
1074                                         int argc, const char **argv) 
1075 {
1076         POLICY_HND connect_pol, domain_pol, alias_pol;
1077         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1078         uint32 alias_rid, num_members, i;
1079         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1080         DOM_SID *alias_sids;
1081
1082         if ((argc < 3) || (argc > 4)) {
1083                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1084                 return NT_STATUS_OK;
1085         }
1086
1087         sscanf(argv[2], "%i", &alias_rid);
1088         
1089         if (argc > 3)
1090                 sscanf(argv[3], "%x", &access_mask);
1091
1092         /* Open SAMR handle */
1093
1094         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1095                                    &connect_pol);
1096
1097         if (!NT_STATUS_IS_OK(result))
1098                 goto done;
1099
1100         /* Open handle on domain */
1101         
1102         if (StrCaseCmp(argv[1], "domain")==0)
1103                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1104                                               MAXIMUM_ALLOWED_ACCESS,
1105                                               &domain_sid, &domain_pol);
1106         else if (StrCaseCmp(argv[1], "builtin")==0)
1107                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1108                                               MAXIMUM_ALLOWED_ACCESS,
1109                                               &global_sid_Builtin, &domain_pol);
1110         else
1111                 return NT_STATUS_OK;
1112
1113         if (!NT_STATUS_IS_OK(result))
1114                 goto done;
1115
1116         /* Open handle on alias */
1117
1118         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1119                                      access_mask,
1120                                      alias_rid, &alias_pol);
1121         if (!NT_STATUS_IS_OK(result))
1122                 goto done;
1123
1124         result = rpccli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
1125                                          &num_members, &alias_sids);
1126
1127         if (!NT_STATUS_IS_OK(result))
1128                 goto done;
1129
1130         for (i = 0; i < num_members; i++) {
1131                 fstring sid_str;
1132
1133                 sid_to_string(sid_str, &alias_sids[i]);
1134                 printf("\tsid:[%s]\n", sid_str);
1135         }
1136
1137         rpccli_samr_close(cli, mem_ctx, &alias_pol);
1138         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1139         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1140  done:
1141         return result;
1142 }
1143
1144 /* Query delete an alias membership */
1145
1146 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli, 
1147                                       TALLOC_CTX *mem_ctx,
1148                                       int argc, const char **argv) 
1149 {
1150         POLICY_HND connect_pol, domain_pol, alias_pol;
1151         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1152         uint32 alias_rid;
1153         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1154
1155         if (argc != 3) {
1156                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1157                 return NT_STATUS_OK;
1158         }
1159
1160         alias_rid = strtoul(argv[2], NULL, 10);
1161         
1162         /* Open SAMR handle */
1163
1164         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1165                                    &connect_pol);
1166
1167         if (!NT_STATUS_IS_OK(result))
1168                 goto done;
1169
1170         /* Open handle on domain */
1171         
1172         if (StrCaseCmp(argv[1], "domain")==0)
1173                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1174                                               MAXIMUM_ALLOWED_ACCESS,
1175                                               &domain_sid, &domain_pol);
1176         else if (StrCaseCmp(argv[1], "builtin")==0)
1177                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1178                                               MAXIMUM_ALLOWED_ACCESS,
1179                                               &global_sid_Builtin, &domain_pol);
1180         else
1181                 return NT_STATUS_INVALID_PARAMETER;
1182
1183         if (!NT_STATUS_IS_OK(result))
1184                 goto done;
1185
1186         /* Open handle on alias */
1187
1188         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1189                                      access_mask,
1190                                      alias_rid, &alias_pol);
1191         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1192                 /* Probably this was a user name, try lookupnames */
1193                 uint32 num_rids;
1194                 uint32 *rids, *types;
1195                 
1196                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1197                                                   1000, 1, &argv[2],
1198                                                   &num_rids, &rids,
1199                                                   &types);
1200
1201                 if (NT_STATUS_IS_OK(result)) {
1202                         result = rpccli_samr_open_alias(cli, mem_ctx,
1203                                                        &domain_pol,
1204                                                        access_mask,
1205                                                        rids[0], &alias_pol);
1206                 }
1207         }
1208
1209         result = rpccli_samr_delete_dom_alias(cli, mem_ctx, &alias_pol);
1210
1211         if (!NT_STATUS_IS_OK(result))
1212                 goto done;
1213
1214         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1215         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1216  done:
1217         return result;
1218 }
1219
1220 /* Query display info */
1221
1222 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
1223                                         TALLOC_CTX *mem_ctx,
1224                                         int argc, const char **argv) 
1225 {
1226         POLICY_HND connect_pol, domain_pol;
1227         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1228         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
1229         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1230         uint32 info_level = 1;
1231         SAM_DISPINFO_CTR ctr;
1232         SAM_DISPINFO_1 info1;
1233         SAM_DISPINFO_2 info2;
1234         SAM_DISPINFO_3 info3;
1235         SAM_DISPINFO_4 info4;
1236         SAM_DISPINFO_5 info5;
1237         int loop_count = 0;
1238         BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
1239
1240         if (argc > 6) {
1241                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1242                 return NT_STATUS_OK;
1243         }
1244
1245         if (argc >= 2)
1246                 sscanf(argv[1], "%i", &info_level);
1247         
1248         if (argc >= 3)
1249                 sscanf(argv[2], "%i", &start_idx);
1250         
1251         if (argc >= 4) {
1252                 sscanf(argv[3], "%i", &max_entries);
1253                 got_params = True;
1254         }
1255         
1256         if (argc >= 5) {
1257                 sscanf(argv[4], "%i", &max_size);
1258                 got_params = True;
1259         }
1260         
1261         if (argc >= 6)
1262                 sscanf(argv[5], "%x", &access_mask);
1263
1264         /* Get sam policy handle */
1265
1266         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1267                                    &connect_pol);
1268
1269         if (!NT_STATUS_IS_OK(result))
1270                 goto done;
1271
1272         /* Get domain policy handle */
1273
1274         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1275                                       access_mask, 
1276                                       &domain_sid, &domain_pol);
1277
1278         if (!NT_STATUS_IS_OK(result))
1279                 goto done;
1280
1281         /* Query display info */
1282
1283         ZERO_STRUCT(ctr);
1284         ZERO_STRUCT(info1);
1285         
1286         switch (info_level) {
1287         case 1:
1288                 ZERO_STRUCT(info1);
1289                 ctr.sam.info1 = &info1;
1290                 break;
1291         case 2:
1292                 ZERO_STRUCT(info2);
1293                 ctr.sam.info2 = &info2;
1294                 break;
1295         case 3:
1296                 ZERO_STRUCT(info3);
1297                 ctr.sam.info3 = &info3;
1298                 break;
1299         case 4:
1300                 ZERO_STRUCT(info4);
1301                 ctr.sam.info4 = &info4;
1302                 break;
1303         case 5:
1304                 ZERO_STRUCT(info5);
1305                 ctr.sam.info5 = &info5;
1306                 break;
1307         }
1308
1309
1310         do {
1311
1312                 if (!got_params)
1313                         get_query_dispinfo_params(
1314                                 loop_count, &max_entries, &max_size);
1315                 
1316                 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1317                                                  &start_idx, info_level,
1318                                                  &num_entries, max_entries, 
1319                                                  max_size, &ctr);
1320
1321                 loop_count++;
1322
1323                 if (NT_STATUS_IS_ERR(result))
1324                         break;
1325
1326                 if (num_entries == 0) 
1327                         break;
1328
1329                 for (i = 0; i < num_entries; i++) {
1330                         switch (info_level) {
1331                         case 1:
1332                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1333                                 break;
1334                         case 2:
1335                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1336                                 break;
1337                         case 3:
1338                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1339                                 break;
1340                         case 4:
1341                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1342                                 break;
1343                         case 5:
1344                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1345                                 break;
1346                         }
1347                 }
1348         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1349
1350         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1351         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1352  done:
1353         return result;
1354 }
1355
1356 /* Query domain info */
1357
1358 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, 
1359                                        TALLOC_CTX *mem_ctx,
1360                                        int argc, const char **argv) 
1361 {
1362         POLICY_HND connect_pol, domain_pol;
1363         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1364         uint32 switch_level = 2;
1365         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1366         SAM_UNK_CTR ctr;
1367
1368         if (argc > 3) {
1369                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1370                 return NT_STATUS_OK;
1371         }
1372
1373         if (argc > 1)
1374                 sscanf(argv[1], "%i", &switch_level);
1375         
1376         if (argc > 2)
1377                 sscanf(argv[2], "%x", &access_mask);
1378
1379         /* Get sam policy handle */
1380
1381         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1382                                    &connect_pol);
1383
1384         if (!NT_STATUS_IS_OK(result))
1385                 goto done;
1386
1387         /* Get domain policy handle */
1388
1389         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1390                                       access_mask,
1391                                       &domain_sid, &domain_pol);
1392
1393         if (!NT_STATUS_IS_OK(result))
1394                 goto done;
1395
1396         /* Query domain info */
1397
1398         result = rpccli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1399                                          switch_level, &ctr);
1400
1401         if (!NT_STATUS_IS_OK(result))
1402                 goto done;
1403
1404         /* Display domain info */
1405
1406         switch (switch_level) {
1407         case 1:
1408                 display_sam_unk_info_1(&ctr.info.inf1);
1409                 break;
1410         case 2:
1411                 display_sam_unk_info_2(&ctr.info.inf2);
1412                 break;
1413         case 3:
1414                 display_sam_unk_info_3(&ctr.info.inf3);
1415                 break;
1416         case 4:
1417                 display_sam_unk_info_4(&ctr.info.inf4);
1418                 break;
1419         case 5:
1420                 display_sam_unk_info_5(&ctr.info.inf5);
1421                 break;
1422         case 6:
1423                 display_sam_unk_info_6(&ctr.info.inf6);
1424                 break;
1425         case 7:
1426                 display_sam_unk_info_7(&ctr.info.inf7);
1427                 break;
1428         case 8:
1429                 display_sam_unk_info_8(&ctr.info.inf8);
1430                 break;
1431         case 9:
1432                 display_sam_unk_info_9(&ctr.info.inf9);
1433                 break;
1434         case 12:
1435                 display_sam_unk_info_12(&ctr.info.inf12);
1436                 break;
1437         case 13:
1438                 display_sam_unk_info_13(&ctr.info.inf13);
1439                 break;
1440
1441         default:
1442                 printf("cannot display domain info for switch value %d\n",
1443                        switch_level);
1444                 break;
1445         }
1446
1447  done:
1448  
1449         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1450         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1451         return result;
1452 }
1453
1454 /* Create domain user */
1455
1456 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, 
1457                                          TALLOC_CTX *mem_ctx,
1458                                          int argc, const char **argv) 
1459 {
1460         POLICY_HND connect_pol, domain_pol, user_pol;
1461         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1462         const char *acct_name;
1463         uint32 acb_info;
1464         uint32 unknown, user_rid;
1465         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1466
1467         if ((argc < 2) || (argc > 3)) {
1468                 printf("Usage: %s username [access mask]\n", argv[0]);
1469                 return NT_STATUS_OK;
1470         }
1471
1472         acct_name = argv[1];
1473         
1474         if (argc > 2)
1475                 sscanf(argv[2], "%x", &access_mask);
1476
1477         /* Get sam policy handle */
1478
1479         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1480                                    &connect_pol);
1481
1482         if (!NT_STATUS_IS_OK(result))
1483                 goto done;
1484
1485         /* Get domain policy handle */
1486
1487         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1488                                       access_mask,
1489                                       &domain_sid, &domain_pol);
1490
1491         if (!NT_STATUS_IS_OK(result))
1492                 goto done;
1493
1494         /* Create domain user */
1495
1496         acb_info = ACB_NORMAL;
1497         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1498
1499         result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1500                                           acct_name, acb_info, unknown,
1501                                           &user_pol, &user_rid);
1502
1503         if (!NT_STATUS_IS_OK(result))
1504                 goto done;
1505
1506         result = rpccli_samr_close(cli, mem_ctx, &user_pol);
1507         if (!NT_STATUS_IS_OK(result)) goto done;
1508
1509         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1510         if (!NT_STATUS_IS_OK(result)) goto done;
1511
1512         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1513         if (!NT_STATUS_IS_OK(result)) goto done;
1514
1515  done:
1516         return result;
1517 }
1518
1519 /* Create domain group */
1520
1521 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, 
1522                                           TALLOC_CTX *mem_ctx,
1523                                           int argc, const char **argv) 
1524 {
1525         POLICY_HND connect_pol, domain_pol, group_pol;
1526         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1527         const char *grp_name;
1528         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1529
1530         if ((argc < 2) || (argc > 3)) {
1531                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1532                 return NT_STATUS_OK;
1533         }
1534
1535         grp_name = argv[1];
1536         
1537         if (argc > 2)
1538                 sscanf(argv[2], "%x", &access_mask);
1539
1540         /* Get sam policy handle */
1541
1542         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1543                                    &connect_pol);
1544
1545         if (!NT_STATUS_IS_OK(result))
1546                 goto done;
1547
1548         /* Get domain policy handle */
1549
1550         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1551                                       access_mask,
1552                                       &domain_sid, &domain_pol);
1553
1554         if (!NT_STATUS_IS_OK(result))
1555                 goto done;
1556
1557         /* Create domain user */
1558
1559         result = rpccli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
1560                                            grp_name, MAXIMUM_ALLOWED_ACCESS,
1561                                            &group_pol);
1562
1563         if (!NT_STATUS_IS_OK(result))
1564                 goto done;
1565
1566         result = rpccli_samr_close(cli, mem_ctx, &group_pol);
1567         if (!NT_STATUS_IS_OK(result)) goto done;
1568
1569         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1570         if (!NT_STATUS_IS_OK(result)) goto done;
1571
1572         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1573         if (!NT_STATUS_IS_OK(result)) goto done;
1574
1575  done:
1576         return result;
1577 }
1578
1579 /* Create domain alias */
1580
1581 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli, 
1582                                           TALLOC_CTX *mem_ctx,
1583                                           int argc, const char **argv) 
1584 {
1585         POLICY_HND connect_pol, domain_pol, alias_pol;
1586         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1587         const char *alias_name;
1588         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1589
1590         if ((argc < 2) || (argc > 3)) {
1591                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1592                 return NT_STATUS_OK;
1593         }
1594
1595         alias_name = argv[1];
1596         
1597         if (argc > 2)
1598                 sscanf(argv[2], "%x", &access_mask);
1599
1600         /* Get sam policy handle */
1601
1602         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1603                                    &connect_pol);
1604
1605         if (!NT_STATUS_IS_OK(result))
1606                 goto done;
1607
1608         /* Get domain policy handle */
1609
1610         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1611                                          access_mask,
1612                                          &domain_sid, &domain_pol);
1613
1614         if (!NT_STATUS_IS_OK(result))
1615                 goto done;
1616
1617         /* Create domain user */
1618
1619         result = rpccli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
1620                                               alias_name, &alias_pol);
1621
1622         if (!NT_STATUS_IS_OK(result))
1623                 goto done;
1624
1625         result = rpccli_samr_close(cli, mem_ctx, &alias_pol);
1626         if (!NT_STATUS_IS_OK(result)) goto done;
1627
1628         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1629         if (!NT_STATUS_IS_OK(result)) goto done;
1630
1631         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1632         if (!NT_STATUS_IS_OK(result)) goto done;
1633
1634  done:
1635         return result;
1636 }
1637
1638 /* Lookup sam names */
1639
1640 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
1641                                       TALLOC_CTX *mem_ctx,
1642                                       int argc, const char **argv) 
1643 {
1644         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1645         POLICY_HND connect_pol, domain_pol;
1646         uint32 flags = 0x000003e8; /* Unknown */
1647         uint32 num_rids, num_names, *name_types, *rids;
1648         const char **names;
1649         int i;
1650
1651         if (argc < 3) {
1652                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1653                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1654                 printf("or check on the builtin SID: S-1-5-32\n");
1655                 return NT_STATUS_OK;
1656         }
1657
1658         /* Get sam policy and domain handles */
1659
1660         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1661                                    &connect_pol);
1662
1663         if (!NT_STATUS_IS_OK(result))
1664                 goto done;
1665
1666         if (StrCaseCmp(argv[1], "domain")==0)
1667                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1668                                               MAXIMUM_ALLOWED_ACCESS,
1669                                               &domain_sid, &domain_pol);
1670         else if (StrCaseCmp(argv[1], "builtin")==0)
1671                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1672                                               MAXIMUM_ALLOWED_ACCESS,
1673                                               &global_sid_Builtin, &domain_pol);
1674         else
1675                 return NT_STATUS_OK;
1676
1677         if (!NT_STATUS_IS_OK(result))
1678                 goto done;
1679
1680         /* Look up names */
1681
1682         num_names = argc - 2;
1683         if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
1684                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
1685                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
1686                 result = NT_STATUS_NO_MEMORY;
1687                 goto done;
1688         }
1689
1690         for (i = 0; i < argc - 2; i++)
1691                 names[i] = argv[i + 2];
1692
1693         result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1694                                        flags, num_names, names,
1695                                        &num_rids, &rids, &name_types);
1696
1697         if (!NT_STATUS_IS_OK(result))
1698                 goto done;
1699
1700         /* Display results */
1701
1702         for (i = 0; i < num_names; i++)
1703                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1704                        name_types[i]);
1705
1706         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1707         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1708  done:
1709         return result;
1710 }
1711
1712 /* Lookup sam rids */
1713
1714 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, 
1715                                      TALLOC_CTX *mem_ctx,
1716                                      int argc, const char **argv) 
1717 {
1718         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1719         POLICY_HND connect_pol, domain_pol;
1720         uint32 num_rids, num_names, *rids, *name_types;
1721         char **names;
1722         int i;
1723
1724         if (argc < 3) {
1725                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1726                 return NT_STATUS_OK;
1727         }
1728
1729         /* Get sam policy and domain handles */
1730
1731         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1732                                    &connect_pol);
1733
1734         if (!NT_STATUS_IS_OK(result))
1735                 goto done;
1736
1737         if (StrCaseCmp(argv[1], "domain")==0)
1738                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1739                                               MAXIMUM_ALLOWED_ACCESS,
1740                                               &domain_sid, &domain_pol);
1741         else if (StrCaseCmp(argv[1], "builtin")==0)
1742                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1743                                               MAXIMUM_ALLOWED_ACCESS,
1744                                               &global_sid_Builtin, &domain_pol);
1745         else
1746                 return NT_STATUS_OK;
1747
1748         if (!NT_STATUS_IS_OK(result))
1749                 goto done;
1750
1751         /* Look up rids */
1752
1753         num_rids = argc - 2;
1754         rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1755         if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1756                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
1757                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
1758                 result = NT_STATUS_NO_MEMORY;
1759                 goto done;
1760         }
1761
1762         for (i = 0; i < argc - 2; i++)
1763                 sscanf(argv[i + 2], "%i", &rids[i]);
1764
1765         result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
1766                                       &num_names, &names, &name_types);
1767
1768         if (!NT_STATUS_IS_OK(result) &&
1769             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1770                 goto done;
1771
1772         /* Display results */
1773
1774         for (i = 0; i < num_names; i++)
1775                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1776
1777         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1778         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1779  done:
1780         return result;
1781 }
1782
1783 /* Delete domain user */
1784
1785 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
1786                                          TALLOC_CTX *mem_ctx,
1787                                          int argc, const char **argv) 
1788 {
1789         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1790         POLICY_HND connect_pol, domain_pol, user_pol;
1791         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1792
1793         if ((argc < 2) || (argc > 3)) {
1794                 printf("Usage: %s username\n", argv[0]);
1795                 return NT_STATUS_OK;
1796         }
1797         
1798         if (argc > 2)
1799                 sscanf(argv[2], "%x", &access_mask);
1800
1801         /* Get sam policy and domain handles */
1802
1803         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1804                                    &connect_pol);
1805
1806         if (!NT_STATUS_IS_OK(result))
1807                 goto done;
1808
1809         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1810                                       MAXIMUM_ALLOWED_ACCESS,
1811                                       &domain_sid, &domain_pol);
1812
1813         if (!NT_STATUS_IS_OK(result))
1814                 goto done;
1815
1816         /* Get handle on user */
1817
1818         {
1819                 uint32 *user_rids, num_rids, *name_types;
1820                 uint32 flags = 0x000003e8; /* Unknown */
1821
1822                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1823                                                flags, 1, (const char **)&argv[1],
1824                                                &num_rids, &user_rids,
1825                                                &name_types);
1826
1827                 if (!NT_STATUS_IS_OK(result))
1828                         goto done;
1829
1830                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1831                                             access_mask,
1832                                             user_rids[0], &user_pol);
1833
1834                 if (!NT_STATUS_IS_OK(result))
1835                         goto done;
1836         }
1837
1838         /* Delete user */
1839
1840         result = rpccli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
1841
1842         if (!NT_STATUS_IS_OK(result))
1843                 goto done;
1844
1845         /* Display results */
1846
1847         rpccli_samr_close(cli, mem_ctx, &user_pol);
1848         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1849         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1850
1851  done:
1852         return result;
1853 }
1854
1855 /**********************************************************************
1856  * Query user security object 
1857  */
1858 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, 
1859                                     TALLOC_CTX *mem_ctx,
1860                                     int argc, const char **argv) 
1861 {
1862         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1863         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1864         uint32 sec_info = DACL_SECURITY_INFORMATION;
1865         fstring server;
1866         uint32 user_rid = 0;
1867         TALLOC_CTX *ctx = NULL;
1868         SEC_DESC_BUF *sec_desc_buf=NULL;
1869         BOOL domain = False;
1870
1871         ctx=talloc_init("cmd_samr_query_sec_obj");
1872         
1873         if ((argc < 1) || (argc > 3)) {
1874                 printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
1875                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1876                 return NT_STATUS_OK;
1877         }
1878         
1879         if (argc > 1) {
1880                 if (strcmp(argv[1], "-d") == 0)
1881                         domain = True;
1882                 else
1883                         sscanf(argv[1], "%i", &user_rid);
1884         }
1885
1886         if (argc == 3) {
1887                 sec_info = atoi(argv[2]);
1888         }
1889         
1890         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
1891         strupper_m(server);
1892         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1893                                    &connect_pol);
1894
1895         if (!NT_STATUS_IS_OK(result))
1896                 goto done;
1897
1898         if (domain || user_rid)
1899                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1900                                               MAXIMUM_ALLOWED_ACCESS,
1901                                               &domain_sid, &domain_pol);
1902
1903         if (!NT_STATUS_IS_OK(result))
1904                 goto done;
1905
1906         if (user_rid)
1907                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1908                                             MAXIMUM_ALLOWED_ACCESS,
1909                                             user_rid, &user_pol);
1910
1911         if (!NT_STATUS_IS_OK(result))
1912                 goto done;
1913
1914         /* Pick which query pol to use */
1915
1916         pol = &connect_pol;
1917
1918         if (domain)
1919                 pol = &domain_pol;
1920
1921         if (user_rid)
1922                 pol = &user_pol;
1923
1924         /* Query SAM security object */
1925
1926         result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, sec_info, ctx, 
1927                                         &sec_desc_buf);
1928
1929         if (!NT_STATUS_IS_OK(result))
1930                 goto done;
1931
1932         display_sec_desc(sec_desc_buf->sec);
1933
1934         rpccli_samr_close(cli, mem_ctx, &user_pol);
1935         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1936         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1937 done:
1938         talloc_destroy(ctx);
1939         return result;
1940 }
1941
1942 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli, 
1943                                            TALLOC_CTX *mem_ctx,
1944                                            int argc, const char **argv) 
1945 {
1946         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1947         POLICY_HND connect_pol, domain_pol, user_pol;
1948         uint16 min_pwd_length;
1949         uint32 password_properties, unknown1, rid;
1950
1951         if (argc != 2) {
1952                 printf("Usage: %s rid\n", argv[0]);
1953                 return NT_STATUS_OK;
1954         }
1955         
1956         sscanf(argv[1], "%i", &rid);
1957
1958         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1959                                    &connect_pol);
1960
1961         if (!NT_STATUS_IS_OK(result)) {
1962                 goto done;
1963         }
1964
1965         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1966                                          MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol);
1967
1968         if (!NT_STATUS_IS_OK(result)) {
1969                 goto done;
1970         }
1971
1972         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1973                                        MAXIMUM_ALLOWED_ACCESS,
1974                                        rid, &user_pol);
1975
1976         if (!NT_STATUS_IS_OK(result)) {
1977                 goto done;
1978         }
1979
1980         result = rpccli_samr_get_usrdom_pwinfo(cli, mem_ctx, &user_pol,
1981                                                &min_pwd_length, &password_properties, 
1982                                                &unknown1) ;
1983
1984         if (NT_STATUS_IS_OK(result)) {
1985                 printf("min_pwd_length: %d\n", min_pwd_length);
1986                 printf("unknown1: %d\n", unknown1);
1987                 display_password_properties(password_properties);
1988         }
1989
1990  done:
1991         rpccli_samr_close(cli, mem_ctx, &user_pol);
1992         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1993         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1994
1995         return result;
1996 }
1997
1998
1999 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, 
2000                                         TALLOC_CTX *mem_ctx,
2001                                         int argc, const char **argv) 
2002 {
2003         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2004         uint16 min_pwd_length;
2005         uint32 password_properties;
2006
2007         if (argc != 1) {
2008                 printf("Usage: %s\n", argv[0]);
2009                 return NT_STATUS_OK;
2010         }
2011
2012         result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &min_pwd_length, &password_properties) ;
2013         
2014         if (NT_STATUS_IS_OK(result)) {
2015                 printf("min_pwd_length: %d\n", min_pwd_length);
2016                 display_password_properties(password_properties);
2017         }
2018
2019         return result;
2020 }
2021
2022 /* Look up domain name */
2023
2024 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, 
2025                                        TALLOC_CTX *mem_ctx,
2026                                        int argc, const char **argv) 
2027 {
2028         POLICY_HND connect_pol, domain_pol;
2029         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2030         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2031         fstring domain_name,sid_string;
2032         DOM_SID sid;
2033         
2034         if (argc != 2) {
2035                 printf("Usage: %s domain_name\n", argv[0]);
2036                 return NT_STATUS_OK;
2037         }
2038         
2039         sscanf(argv[1], "%s", domain_name);
2040         
2041         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
2042         
2043         if (!NT_STATUS_IS_OK(result))
2044                 goto done;
2045
2046         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
2047                                       access_mask, &domain_sid, &domain_pol);
2048
2049         if (!NT_STATUS_IS_OK(result))
2050                 goto done;
2051         
2052         result = rpccli_samr_lookup_domain(
2053                 cli, mem_ctx, &connect_pol, domain_name, &sid);
2054
2055         sid_to_string(sid_string,&sid);
2056  
2057         if (NT_STATUS_IS_OK(result)) 
2058                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
2059                        domain_name,sid_string);
2060
2061         rpccli_samr_close(cli, mem_ctx, &domain_pol);
2062         rpccli_samr_close(cli, mem_ctx, &connect_pol);
2063 done:
2064         return result;
2065 }
2066
2067 /* Change user password */
2068
2069 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli, 
2070                                     TALLOC_CTX *mem_ctx,
2071                                     int argc, const char **argv) 
2072 {
2073         POLICY_HND connect_pol, domain_pol;
2074         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2075         const char *user, *oldpass, *newpass;
2076         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2077         SAM_UNK_INFO_1 info;
2078         SAMR_CHANGE_REJECT reject;
2079
2080         if (argc < 3) {
2081                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2082                 return NT_STATUS_INVALID_PARAMETER;
2083         }
2084
2085         user = argv[1];
2086         oldpass = argv[2];
2087         newpass = argv[3];
2088         
2089         /* Get sam policy handle */
2090
2091         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2092                                    &connect_pol);
2093
2094         if (!NT_STATUS_IS_OK(result))
2095                 goto done;
2096
2097         /* Get domain policy handle */
2098
2099         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
2100                                       access_mask,
2101                                       &domain_sid, &domain_pol);
2102
2103         if (!NT_STATUS_IS_OK(result))
2104                 goto done;
2105
2106         /* Change user password */
2107         result = rpccli_samr_chgpasswd3(cli, mem_ctx, user, newpass, oldpass, &info, &reject);
2108
2109         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2110         
2111                 display_sam_unk_info_1(&info);
2112
2113                 switch (reject.reject_reason) {
2114                         case REJECT_REASON_TOO_SHORT:
2115                                 d_printf("REJECT_REASON_TOO_SHORT\n");
2116                                 break;
2117                         case REJECT_REASON_IN_HISTORY:
2118                                 d_printf("REJECT_REASON_IN_HISTORY\n");
2119                                 break;
2120                         case REJECT_REASON_NOT_COMPLEX:
2121                                 d_printf("REJECT_REASON_NOT_COMPLEX\n");
2122                                 break;
2123                         case REJECT_REASON_OTHER:
2124                                 d_printf("REJECT_REASON_OTHER\n");
2125                                 break;
2126                         default:
2127                                 d_printf("unknown reject reason: %d\n", reject.reject_reason);
2128                                 break;
2129                 }
2130         }
2131
2132         if (!NT_STATUS_IS_OK(result))
2133                 goto done;
2134
2135         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
2136         if (!NT_STATUS_IS_OK(result)) goto done;
2137
2138         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
2139         if (!NT_STATUS_IS_OK(result)) goto done;
2140
2141  done:
2142         return result;
2143 }
2144
2145 /* List of commands exported by this module */
2146
2147 struct cmd_set samr_commands[] = {
2148
2149         { "SAMR" },
2150
2151         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
2152         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
2153         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
2154         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
2155         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
2156         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
2157         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
2158         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
2159         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
2160         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
2161         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
2162         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
2163
2164         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
2165         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
2166         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
2167         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
2168         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
2169         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
2170         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
2171         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
2172         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
2173
2174         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
2175         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
2176         { NULL }
2177 };