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