r22489: Add a deletedomgroup command to rpcclient (samr).
[samba.git] / source3 / rpcclient / cmd_samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Andrew Tridgell              1992-2000,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7    Copyright (C) Elrond                            2000,
8    Copyright (C) Tim Potter                        2000
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "rpcclient.h"
27
28 extern DOM_SID domain_sid;
29
30 /****************************************************************************
31  display sam_user_info_7 structure
32  ****************************************************************************/
33 static void display_sam_user_info_7(SAM_USER_INFO_7 *usr)
34 {
35         fstring temp;
36
37         unistr2_to_ascii(temp, &usr->uni_name, sizeof(temp)-1);
38         printf("\tUser Name   :\t%s\n", temp);
39 }
40
41 /****************************************************************************
42  display sam_user_info_9 structure
43  ****************************************************************************/
44 static void display_sam_user_info_9(SAM_USER_INFO_9 *usr)
45 {
46         printf("\tPrimary group RID   :\tox%x\n", usr->rid_group);
47 }
48
49 /****************************************************************************
50  display sam_user_info_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         sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
704         if (sid2 == NULL)
705                 return NT_STATUS_NO_MEMORY;
706
707         for (i=0; i<num_sids; i++) {
708                 sid_copy(&sid2[i].sid, &sids[i]);
709                 sid2[i].num_auths = sid2[i].sid.num_auths;
710         }
711
712         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
713         strupper_m(server);
714                 
715         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
716                                    &connect_pol);
717
718         if (!NT_STATUS_IS_OK(result))
719                 goto done;
720
721         if (StrCaseCmp(argv[1], "domain")==0)
722                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
723                                               access_mask,
724                                               &domain_sid, &domain_pol);
725         else if (StrCaseCmp(argv[1], "builtin")==0)
726                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
727                                               access_mask,
728                                               &global_sid_Builtin,
729                                               &domain_pol);
730         else {
731                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
732                 return NT_STATUS_INVALID_PARAMETER;
733         }
734
735         if (!NT_STATUS_IS_OK(result))
736                 goto done;
737
738         result = rpccli_samr_query_useraliases(cli, mem_ctx, &domain_pol,
739                                             num_sids, sid2,
740                                             &num_aliases, &alias_rids);
741
742         if (!NT_STATUS_IS_OK(result))
743                 goto done;
744
745         for (i = 0; i < num_aliases; i++) {
746                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
747         }
748
749         rpccli_samr_close(cli, mem_ctx, &domain_pol);
750         rpccli_samr_close(cli, mem_ctx, &connect_pol);
751  done:
752         return result;
753 }
754
755 /* Query members of a group */
756
757 static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli, 
758                                         TALLOC_CTX *mem_ctx,
759                                         int argc, const char **argv) 
760 {
761         POLICY_HND connect_pol, domain_pol, group_pol;
762         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
763         uint32 num_members, *group_rids, *group_attrs, group_rid;
764         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
765         int i;
766         fstring                 server;
767         unsigned int old_timeout;
768         
769         if ((argc < 2) || (argc > 3)) {
770                 printf("Usage: %s rid [access mask]\n", argv[0]);
771                 return NT_STATUS_OK;
772         }
773
774         sscanf(argv[1], "%i", &group_rid);
775         
776         if (argc > 2)
777                 sscanf(argv[2], "%x", &access_mask);
778
779         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
780         strupper_m(server);
781
782         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
783                                    &connect_pol);
784
785         if (!NT_STATUS_IS_OK(result))
786                 goto done;
787
788         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
789                                       MAXIMUM_ALLOWED_ACCESS,
790                                       &domain_sid, &domain_pol);
791
792         if (!NT_STATUS_IS_OK(result))
793                 goto done;
794
795         result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
796                                      access_mask,
797                                      group_rid, &group_pol);
798
799         if (!NT_STATUS_IS_OK(result))
800                 goto done;
801
802         /* Make sure to wait for our DC's reply */
803         old_timeout = cli_set_timeout(cli->cli, MAX(cli->cli->timeout,30000)); /* 30 seconds. */
804
805         result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
806                                          &num_members, &group_rids,
807                                          &group_attrs);
808
809         cli_set_timeout(cli->cli, old_timeout);
810
811         if (!NT_STATUS_IS_OK(result))
812                 goto done;
813
814         for (i = 0; i < num_members; i++) {
815                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
816                        group_attrs[i]);
817         }
818
819         rpccli_samr_close(cli, mem_ctx, &group_pol);
820         rpccli_samr_close(cli, mem_ctx, &domain_pol);
821         rpccli_samr_close(cli, mem_ctx, &connect_pol);
822  done:
823         return result;
824 }
825
826 /* Enumerate domain users */
827
828 static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli, 
829                                         TALLOC_CTX *mem_ctx,
830                                         int argc, const char **argv) 
831 {
832         POLICY_HND connect_pol, domain_pol;
833         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
834         uint32 start_idx, size, num_dom_users, i;
835         char **dom_users;
836         uint32 *dom_rids;
837         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
838         uint32 acb_mask = ACB_NORMAL;
839         BOOL got_connect_pol = False, got_domain_pol = False;
840
841         if ((argc < 1) || (argc > 3)) {
842                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
843                 return NT_STATUS_OK;
844         }
845         
846         if (argc > 1)
847                 sscanf(argv[1], "%x", &access_mask);
848
849         if (argc > 2)
850                 sscanf(argv[2], "%x", &acb_mask);
851
852         /* Get sam policy handle */
853
854         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
855                                    &connect_pol);
856
857         if (!NT_STATUS_IS_OK(result))
858                 goto done;
859
860         got_connect_pol = True;
861
862         /* Get domain policy handle */
863
864         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
865                                       access_mask,
866                                       &domain_sid, &domain_pol);
867
868         if (!NT_STATUS_IS_OK(result))
869                 goto done;
870
871         got_domain_pol = True;
872
873         /* Enumerate domain users */
874
875         start_idx = 0;
876         size = 0xffff;
877
878         do {
879                 result = rpccli_samr_enum_dom_users(
880                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
881                         size, &dom_users, &dom_rids, &num_dom_users);
882
883                 if (NT_STATUS_IS_OK(result) ||
884                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
885
886                         for (i = 0; i < num_dom_users; i++)
887                                printf("user:[%s] rid:[0x%x]\n", 
888                                        dom_users[i], dom_rids[i]);
889                 }
890
891         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
892
893  done:
894         if (got_domain_pol)
895                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
896
897         if (got_connect_pol)
898                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
899
900         return result;
901 }
902
903 /* Enumerate domain groups */
904
905 static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli, 
906                                          TALLOC_CTX *mem_ctx,
907                                          int argc, const char **argv) 
908 {
909         POLICY_HND connect_pol, domain_pol;
910         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
911         uint32 start_idx, size, num_dom_groups, i;
912         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
913         struct acct_info *dom_groups;
914         BOOL got_connect_pol = False, got_domain_pol = False;
915
916         if ((argc < 1) || (argc > 2)) {
917                 printf("Usage: %s [access_mask]\n", argv[0]);
918                 return NT_STATUS_OK;
919         }
920         
921         if (argc > 1)
922                 sscanf(argv[1], "%x", &access_mask);
923
924         /* Get sam policy handle */
925
926         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
927                                    &connect_pol);
928
929         if (!NT_STATUS_IS_OK(result))
930                 goto done;
931
932         got_connect_pol = True;
933
934         /* Get domain policy handle */
935
936         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
937                                       access_mask,
938                                       &domain_sid, &domain_pol);
939
940         if (!NT_STATUS_IS_OK(result))
941                 goto done;
942
943         got_domain_pol = True;
944
945         /* Enumerate domain groups */
946
947         start_idx = 0;
948         size = 0xffff;
949
950         do {
951                 result = rpccli_samr_enum_dom_groups(
952                         cli, mem_ctx, &domain_pol, &start_idx, size,
953                         &dom_groups, &num_dom_groups);
954
955                 if (NT_STATUS_IS_OK(result) ||
956                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
957
958                         for (i = 0; i < num_dom_groups; i++)
959                                 printf("group:[%s] rid:[0x%x]\n", 
960                                        dom_groups[i].acct_name,
961                                        dom_groups[i].rid);
962                 }
963
964         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
965
966  done:
967         if (got_domain_pol)
968                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
969
970         if (got_connect_pol)
971                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
972
973         return result;
974 }
975
976 /* Enumerate alias groups */
977
978 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli, 
979                                          TALLOC_CTX *mem_ctx,
980                                          int argc, const char **argv) 
981 {
982         POLICY_HND connect_pol, domain_pol;
983         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
984         uint32 start_idx, size, num_als_groups, i;
985         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
986         struct acct_info *als_groups;
987         BOOL got_connect_pol = False, got_domain_pol = False;
988
989         if ((argc < 2) || (argc > 3)) {
990                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
991                 return NT_STATUS_OK;
992         }
993         
994         if (argc > 2)
995                 sscanf(argv[2], "%x", &access_mask);
996
997         /* Get sam policy handle */
998
999         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1000                                    &connect_pol);
1001
1002         if (!NT_STATUS_IS_OK(result))
1003                 goto done;
1004
1005         got_connect_pol = True;
1006
1007         /* Get domain policy handle */
1008
1009         if (StrCaseCmp(argv[1], "domain")==0)
1010                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1011                                               access_mask,
1012                                               &domain_sid, &domain_pol);
1013         else if (StrCaseCmp(argv[1], "builtin")==0)
1014                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1015                                               access_mask,
1016                                               &global_sid_Builtin, &domain_pol);
1017         else
1018                 return NT_STATUS_OK;
1019
1020         if (!NT_STATUS_IS_OK(result))
1021                 goto done;
1022
1023         got_domain_pol = True;
1024
1025         /* Enumerate alias groups */
1026
1027         start_idx = 0;
1028         size = 0xffff;          /* Number of groups to retrieve */
1029
1030         do {
1031                 result = rpccli_samr_enum_als_groups(
1032                         cli, mem_ctx, &domain_pol, &start_idx, size,
1033                         &als_groups, &num_als_groups);
1034
1035                 if (NT_STATUS_IS_OK(result) ||
1036                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1037
1038                         for (i = 0; i < num_als_groups; i++)
1039                                 printf("group:[%s] rid:[0x%x]\n", 
1040                                        als_groups[i].acct_name,
1041                                        als_groups[i].rid);
1042                 }
1043         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1044
1045  done:
1046         if (got_domain_pol)
1047                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
1048         
1049         if (got_connect_pol)
1050                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
1051         
1052         return result;
1053 }
1054
1055 /* Query alias membership */
1056
1057 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli, 
1058                                         TALLOC_CTX *mem_ctx,
1059                                         int argc, const char **argv) 
1060 {
1061         POLICY_HND connect_pol, domain_pol, alias_pol;
1062         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1063         uint32 alias_rid, num_members, i;
1064         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1065         DOM_SID *alias_sids;
1066
1067         if ((argc < 3) || (argc > 4)) {
1068                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1069                 return NT_STATUS_OK;
1070         }
1071
1072         sscanf(argv[2], "%i", &alias_rid);
1073         
1074         if (argc > 3)
1075                 sscanf(argv[3], "%x", &access_mask);
1076
1077         /* Open SAMR handle */
1078
1079         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1080                                    &connect_pol);
1081
1082         if (!NT_STATUS_IS_OK(result))
1083                 goto done;
1084
1085         /* Open handle on domain */
1086         
1087         if (StrCaseCmp(argv[1], "domain")==0)
1088                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1089                                               MAXIMUM_ALLOWED_ACCESS,
1090                                               &domain_sid, &domain_pol);
1091         else if (StrCaseCmp(argv[1], "builtin")==0)
1092                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1093                                               MAXIMUM_ALLOWED_ACCESS,
1094                                               &global_sid_Builtin, &domain_pol);
1095         else
1096                 return NT_STATUS_OK;
1097
1098         if (!NT_STATUS_IS_OK(result))
1099                 goto done;
1100
1101         /* Open handle on alias */
1102
1103         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1104                                      access_mask,
1105                                      alias_rid, &alias_pol);
1106         if (!NT_STATUS_IS_OK(result))
1107                 goto done;
1108
1109         result = rpccli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
1110                                          &num_members, &alias_sids);
1111
1112         if (!NT_STATUS_IS_OK(result))
1113                 goto done;
1114
1115         for (i = 0; i < num_members; i++) {
1116                 fstring sid_str;
1117
1118                 sid_to_string(sid_str, &alias_sids[i]);
1119                 printf("\tsid:[%s]\n", sid_str);
1120         }
1121
1122         rpccli_samr_close(cli, mem_ctx, &alias_pol);
1123         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1124         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1125  done:
1126         return result;
1127 }
1128
1129 /* Query delete an alias membership */
1130
1131 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli, 
1132                                       TALLOC_CTX *mem_ctx,
1133                                       int argc, const char **argv) 
1134 {
1135         POLICY_HND connect_pol, domain_pol, alias_pol;
1136         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1137         uint32 alias_rid;
1138         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1139
1140         if (argc != 3) {
1141                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1142                 return NT_STATUS_OK;
1143         }
1144
1145         alias_rid = strtoul(argv[2], NULL, 10);
1146         
1147         /* Open SAMR handle */
1148
1149         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1150                                    &connect_pol);
1151
1152         if (!NT_STATUS_IS_OK(result))
1153                 goto done;
1154
1155         /* Open handle on domain */
1156         
1157         if (StrCaseCmp(argv[1], "domain")==0)
1158                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1159                                               MAXIMUM_ALLOWED_ACCESS,
1160                                               &domain_sid, &domain_pol);
1161         else if (StrCaseCmp(argv[1], "builtin")==0)
1162                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1163                                               MAXIMUM_ALLOWED_ACCESS,
1164                                               &global_sid_Builtin, &domain_pol);
1165         else
1166                 return NT_STATUS_INVALID_PARAMETER;
1167
1168         if (!NT_STATUS_IS_OK(result))
1169                 goto done;
1170
1171         /* Open handle on alias */
1172
1173         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1174                                      access_mask,
1175                                      alias_rid, &alias_pol);
1176         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1177                 /* Probably this was a user name, try lookupnames */
1178                 uint32 num_rids;
1179                 uint32 *rids, *types;
1180                 
1181                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1182                                                   1000, 1, &argv[2],
1183                                                   &num_rids, &rids,
1184                                                   &types);
1185
1186                 if (NT_STATUS_IS_OK(result)) {
1187                         result = rpccli_samr_open_alias(cli, mem_ctx,
1188                                                        &domain_pol,
1189                                                        access_mask,
1190                                                        rids[0], &alias_pol);
1191                 }
1192         }
1193
1194         result = rpccli_samr_delete_dom_alias(cli, mem_ctx, &alias_pol);
1195
1196         if (!NT_STATUS_IS_OK(result))
1197                 goto done;
1198
1199         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1200         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1201  done:
1202         return result;
1203 }
1204
1205 /* Query display info */
1206
1207 static NTSTATUS cmd_samr_query_dispinfo_int(struct rpc_pipe_client *cli, 
1208                                             TALLOC_CTX *mem_ctx,
1209                                             int argc, const char **argv, 
1210                                             int opcode)
1211 {
1212         POLICY_HND connect_pol, domain_pol;
1213         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1214         uint32 start_idx=0, max_entries=250, max_size = (uint32) -1, num_entries, i;
1215         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1216         uint32 info_level = 1;
1217         SAM_DISPINFO_CTR ctr;
1218         SAM_DISPINFO_1 info1;
1219         SAM_DISPINFO_2 info2;
1220         SAM_DISPINFO_3 info3;
1221         SAM_DISPINFO_4 info4;
1222         SAM_DISPINFO_5 info5;
1223         int loop_count = 0;
1224         BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
1225
1226         if (argc > 6) {
1227                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1228                 return NT_STATUS_OK;
1229         }
1230
1231         if (argc >= 2)
1232                 sscanf(argv[1], "%i", &info_level);
1233         
1234         if (argc >= 3)
1235                 sscanf(argv[2], "%i", &start_idx);
1236         
1237         if (argc >= 4) {
1238                 sscanf(argv[3], "%i", &max_entries);
1239                 got_params = True;
1240         }
1241         
1242         if (argc >= 5) {
1243                 sscanf(argv[4], "%i", &max_size);
1244                 got_params = True;
1245         }
1246         
1247         if (argc >= 6)
1248                 sscanf(argv[5], "%x", &access_mask);
1249
1250
1251         /* Get sam policy handle */
1252
1253         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1254                                    &connect_pol);
1255
1256         if (!NT_STATUS_IS_OK(result))
1257                 goto done;
1258
1259         /* Get domain policy handle */
1260
1261         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1262                                       access_mask, 
1263                                       &domain_sid, &domain_pol);
1264
1265         if (!NT_STATUS_IS_OK(result))
1266                 goto done;
1267
1268         /* Query display info */
1269
1270         ZERO_STRUCT(ctr);
1271         ZERO_STRUCT(info1);
1272         
1273         switch (info_level) {
1274         case 1:
1275                 ZERO_STRUCT(info1);
1276                 ctr.sam.info1 = &info1;
1277                 break;
1278         case 2:
1279                 ZERO_STRUCT(info2);
1280                 ctr.sam.info2 = &info2;
1281                 break;
1282         case 3:
1283                 ZERO_STRUCT(info3);
1284                 ctr.sam.info3 = &info3;
1285                 break;
1286         case 4:
1287                 ZERO_STRUCT(info4);
1288                 ctr.sam.info4 = &info4;
1289                 break;
1290         case 5:
1291                 ZERO_STRUCT(info5);
1292                 ctr.sam.info5 = &info5;
1293                 break;
1294         }
1295
1296
1297         do {
1298
1299                 if (!got_params)
1300                         get_query_dispinfo_params(
1301                                 loop_count, &max_entries, &max_size);
1302
1303                 switch (opcode) {
1304                 case SAMR_QUERY_DISPINFO:
1305                         result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1306                                                             &start_idx, info_level,
1307                                                             &num_entries, max_entries, 
1308                                                             max_size, &ctr);
1309                         break;
1310                 case SAMR_QUERY_DISPINFO2:
1311                         result = rpccli_samr_query_dispinfo2(cli, mem_ctx, &domain_pol,
1312                                                              &start_idx, info_level,
1313                                                              &num_entries, max_entries, 
1314                                                              max_size, &ctr);
1315                         break;
1316                 case SAMR_QUERY_DISPINFO3:
1317                         result = rpccli_samr_query_dispinfo3(cli, mem_ctx, &domain_pol,
1318                                                              &start_idx, info_level,
1319                                                              &num_entries, max_entries, 
1320                                                              max_size, &ctr);
1321                         break;
1322                 default:
1323                         printf("unknown opcode: %d\n", opcode);
1324                         return NT_STATUS_INVALID_PARAMETER;
1325                         break;
1326                 }
1327
1328                 loop_count++;
1329
1330                 if (NT_STATUS_IS_ERR(result))
1331                         break;
1332
1333                 if (num_entries == 0) 
1334                         break;
1335
1336                 for (i = 0; i < num_entries; i++) {
1337                         switch (info_level) {
1338                         case 1:
1339                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1340                                 break;
1341                         case 2:
1342                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1343                                 break;
1344                         case 3:
1345                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1346                                 break;
1347                         case 4:
1348                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1349                                 break;
1350                         case 5:
1351                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1352                                 break;
1353                         }
1354                 }
1355         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1356
1357         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1358         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1359  done:
1360         return result;
1361 }
1362
1363 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
1364                                         TALLOC_CTX *mem_ctx,
1365                                         int argc, const char **argv)
1366 {
1367         return cmd_samr_query_dispinfo_int(cli, mem_ctx, argc, argv, SAMR_QUERY_DISPINFO);
1368 }
1369
1370 static NTSTATUS cmd_samr_query_dispinfo2(struct rpc_pipe_client *cli, 
1371                                          TALLOC_CTX *mem_ctx,
1372                                          int argc, const char **argv) 
1373 {
1374         return cmd_samr_query_dispinfo_int(cli, mem_ctx, argc, argv, SAMR_QUERY_DISPINFO2);
1375 }
1376
1377 static NTSTATUS cmd_samr_query_dispinfo3(struct rpc_pipe_client *cli, 
1378                                          TALLOC_CTX *mem_ctx,
1379                                          int argc, const char **argv) 
1380 {
1381         return cmd_samr_query_dispinfo_int(cli, mem_ctx, argc, argv, SAMR_QUERY_DISPINFO3);
1382 }
1383
1384 /* Query display info index */
1385
1386 static NTSTATUS cmd_samr_get_dispenum_index_int(struct rpc_pipe_client *cli, 
1387                                                 TALLOC_CTX *mem_ctx,
1388                                                 int argc, const char **argv,
1389                                                 int opcode)
1390 {
1391         POLICY_HND connect_pol, domain_pol;
1392         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1393         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1394         uint16 info_level = 1;
1395         uint32 idx;
1396
1397         if (argc < 2 || argc > 3) {
1398                 printf("Usage: %s name [info level]\n", argv[0]);
1399                 return NT_STATUS_OK;
1400         }
1401
1402         if (argc >= 3) {
1403                 sscanf(argv[2], "%hd", &info_level);
1404         }
1405
1406         /* Get sam policy handle */
1407
1408         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1409                                    &connect_pol);
1410
1411         if (!NT_STATUS_IS_OK(result)) {
1412                 goto done;
1413         }
1414
1415         /* Get domain policy handle */
1416
1417         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1418                                          access_mask, 
1419                                          &domain_sid, &domain_pol);
1420
1421         if (!NT_STATUS_IS_OK(result)) {
1422                 goto done;
1423         }
1424
1425         /* Query display info index */
1426
1427         switch (opcode) {
1428         case SAMR_GET_DISPENUM_INDEX:
1429                 result = rpccli_samr_get_dispenum_index(cli, mem_ctx, &domain_pol,
1430                                                         info_level, argv[1], &idx);
1431                 break;
1432         case SAMR_GET_DISPENUM_INDEX2:
1433                 result = rpccli_samr_get_dispenum_index2(cli, mem_ctx, &domain_pol,
1434                                                         info_level, argv[1], &idx);
1435                 break;
1436         default:
1437                 printf("unknown opcode\n");
1438                 return NT_STATUS_INVALID_PARAMETER;
1439         }
1440         
1441         if (NT_STATUS_IS_ERR(result)) {
1442                 goto done;
1443         };
1444
1445         printf("idx is: %d (0x%08x)\n", idx, idx);
1446
1447         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1448         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1449  done:
1450         return result;
1451 }
1452
1453 /* Query display info index */
1454
1455 static NTSTATUS cmd_samr_get_dispenum_index(struct rpc_pipe_client *cli, 
1456                                             TALLOC_CTX *mem_ctx,
1457                                             int argc, const char **argv)
1458 {
1459         return cmd_samr_get_dispenum_index_int(cli, mem_ctx, argc, argv, SAMR_GET_DISPENUM_INDEX);
1460 }
1461
1462 /* Query display info index2 */
1463
1464 static NTSTATUS cmd_samr_get_dispenum_index2(struct rpc_pipe_client *cli, 
1465                                              TALLOC_CTX *mem_ctx,
1466                                              int argc, const char **argv)
1467 {
1468         return cmd_samr_get_dispenum_index_int(cli, mem_ctx, argc, argv, SAMR_GET_DISPENUM_INDEX2);
1469 }
1470
1471 /* Query domain info */
1472
1473 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, 
1474                                        TALLOC_CTX *mem_ctx,
1475                                        int argc, const char **argv) 
1476 {
1477         POLICY_HND connect_pol, domain_pol;
1478         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1479         uint32 switch_level = 2;
1480         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1481         SAM_UNK_CTR ctr;
1482
1483         if (argc > 3) {
1484                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1485                 return NT_STATUS_OK;
1486         }
1487
1488         if (argc > 1)
1489                 sscanf(argv[1], "%i", &switch_level);
1490         
1491         if (argc > 2)
1492                 sscanf(argv[2], "%x", &access_mask);
1493
1494         /* Get sam policy handle */
1495
1496         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1497                                    &connect_pol);
1498
1499         if (!NT_STATUS_IS_OK(result))
1500                 goto done;
1501
1502         /* Get domain policy handle */
1503
1504         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1505                                       access_mask,
1506                                       &domain_sid, &domain_pol);
1507
1508         if (!NT_STATUS_IS_OK(result))
1509                 goto done;
1510
1511         /* Query domain info */
1512
1513         result = rpccli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1514                                          switch_level, &ctr);
1515
1516         if (!NT_STATUS_IS_OK(result))
1517                 goto done;
1518
1519         /* Display domain info */
1520
1521         switch (switch_level) {
1522         case 1:
1523                 display_sam_unk_info_1(&ctr.info.inf1);
1524                 break;
1525         case 2:
1526                 display_sam_unk_info_2(&ctr.info.inf2);
1527                 break;
1528         case 3:
1529                 display_sam_unk_info_3(&ctr.info.inf3);
1530                 break;
1531         case 4:
1532                 display_sam_unk_info_4(&ctr.info.inf4);
1533                 break;
1534         case 5:
1535                 display_sam_unk_info_5(&ctr.info.inf5);
1536                 break;
1537         case 6:
1538                 display_sam_unk_info_6(&ctr.info.inf6);
1539                 break;
1540         case 7:
1541                 display_sam_unk_info_7(&ctr.info.inf7);
1542                 break;
1543         case 8:
1544                 display_sam_unk_info_8(&ctr.info.inf8);
1545                 break;
1546         case 9:
1547                 display_sam_unk_info_9(&ctr.info.inf9);
1548                 break;
1549         case 12:
1550                 display_sam_unk_info_12(&ctr.info.inf12);
1551                 break;
1552         case 13:
1553                 display_sam_unk_info_13(&ctr.info.inf13);
1554                 break;
1555
1556         default:
1557                 printf("cannot display domain info for switch value %d\n",
1558                        switch_level);
1559                 break;
1560         }
1561
1562  done:
1563  
1564         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1565         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1566         return result;
1567 }
1568
1569 /* Create domain user */
1570
1571 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, 
1572                                          TALLOC_CTX *mem_ctx,
1573                                          int argc, const char **argv) 
1574 {
1575         POLICY_HND connect_pol, domain_pol, user_pol;
1576         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1577         const char *acct_name;
1578         uint32 acb_info;
1579         uint32 unknown, user_rid;
1580         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1581
1582         if ((argc < 2) || (argc > 3)) {
1583                 printf("Usage: %s username [access mask]\n", argv[0]);
1584                 return NT_STATUS_OK;
1585         }
1586
1587         acct_name = argv[1];
1588         
1589         if (argc > 2)
1590                 sscanf(argv[2], "%x", &access_mask);
1591
1592         /* Get sam policy handle */
1593
1594         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1595                                    &connect_pol);
1596
1597         if (!NT_STATUS_IS_OK(result))
1598                 goto done;
1599
1600         /* Get domain policy handle */
1601
1602         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1603                                       access_mask,
1604                                       &domain_sid, &domain_pol);
1605
1606         if (!NT_STATUS_IS_OK(result))
1607                 goto done;
1608
1609         /* Create domain user */
1610
1611         acb_info = ACB_NORMAL;
1612         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
1613
1614         result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1615                                           acct_name, acb_info, unknown,
1616                                           &user_pol, &user_rid);
1617
1618         if (!NT_STATUS_IS_OK(result))
1619                 goto done;
1620
1621         result = rpccli_samr_close(cli, mem_ctx, &user_pol);
1622         if (!NT_STATUS_IS_OK(result)) goto done;
1623
1624         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1625         if (!NT_STATUS_IS_OK(result)) goto done;
1626
1627         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1628         if (!NT_STATUS_IS_OK(result)) goto done;
1629
1630  done:
1631         return result;
1632 }
1633
1634 /* Create domain group */
1635
1636 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, 
1637                                           TALLOC_CTX *mem_ctx,
1638                                           int argc, const char **argv) 
1639 {
1640         POLICY_HND connect_pol, domain_pol, group_pol;
1641         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1642         const char *grp_name;
1643         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1644
1645         if ((argc < 2) || (argc > 3)) {
1646                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1647                 return NT_STATUS_OK;
1648         }
1649
1650         grp_name = argv[1];
1651         
1652         if (argc > 2)
1653                 sscanf(argv[2], "%x", &access_mask);
1654
1655         /* Get sam policy handle */
1656
1657         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1658                                    &connect_pol);
1659
1660         if (!NT_STATUS_IS_OK(result))
1661                 goto done;
1662
1663         /* Get domain policy handle */
1664
1665         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1666                                       access_mask,
1667                                       &domain_sid, &domain_pol);
1668
1669         if (!NT_STATUS_IS_OK(result))
1670                 goto done;
1671
1672         /* Create domain user */
1673
1674         result = rpccli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
1675                                            grp_name, MAXIMUM_ALLOWED_ACCESS,
1676                                            &group_pol);
1677
1678         if (!NT_STATUS_IS_OK(result))
1679                 goto done;
1680
1681         result = rpccli_samr_close(cli, mem_ctx, &group_pol);
1682         if (!NT_STATUS_IS_OK(result)) goto done;
1683
1684         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1685         if (!NT_STATUS_IS_OK(result)) goto done;
1686
1687         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1688         if (!NT_STATUS_IS_OK(result)) goto done;
1689
1690  done:
1691         return result;
1692 }
1693
1694 /* Create domain alias */
1695
1696 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli, 
1697                                           TALLOC_CTX *mem_ctx,
1698                                           int argc, const char **argv) 
1699 {
1700         POLICY_HND connect_pol, domain_pol, alias_pol;
1701         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1702         const char *alias_name;
1703         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1704
1705         if ((argc < 2) || (argc > 3)) {
1706                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1707                 return NT_STATUS_OK;
1708         }
1709
1710         alias_name = argv[1];
1711         
1712         if (argc > 2)
1713                 sscanf(argv[2], "%x", &access_mask);
1714
1715         /* Get sam policy handle */
1716
1717         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1718                                    &connect_pol);
1719
1720         if (!NT_STATUS_IS_OK(result))
1721                 goto done;
1722
1723         /* Get domain policy handle */
1724
1725         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1726                                          access_mask,
1727                                          &domain_sid, &domain_pol);
1728
1729         if (!NT_STATUS_IS_OK(result))
1730                 goto done;
1731
1732         /* Create domain user */
1733
1734         result = rpccli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
1735                                               alias_name, &alias_pol);
1736
1737         if (!NT_STATUS_IS_OK(result))
1738                 goto done;
1739
1740         result = rpccli_samr_close(cli, mem_ctx, &alias_pol);
1741         if (!NT_STATUS_IS_OK(result)) goto done;
1742
1743         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
1744         if (!NT_STATUS_IS_OK(result)) goto done;
1745
1746         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
1747         if (!NT_STATUS_IS_OK(result)) goto done;
1748
1749  done:
1750         return result;
1751 }
1752
1753 /* Lookup sam names */
1754
1755 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
1756                                       TALLOC_CTX *mem_ctx,
1757                                       int argc, const char **argv) 
1758 {
1759         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1760         POLICY_HND connect_pol, domain_pol;
1761         uint32 flags = 0x000003e8; /* Unknown */
1762         uint32 num_rids, num_names, *name_types, *rids;
1763         const char **names;
1764         int i;
1765
1766         if (argc < 3) {
1767                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1768                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1769                 printf("or check on the builtin SID: S-1-5-32\n");
1770                 return NT_STATUS_OK;
1771         }
1772
1773         /* Get sam policy and domain handles */
1774
1775         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1776                                    &connect_pol);
1777
1778         if (!NT_STATUS_IS_OK(result))
1779                 goto done;
1780
1781         if (StrCaseCmp(argv[1], "domain")==0)
1782                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1783                                               MAXIMUM_ALLOWED_ACCESS,
1784                                               &domain_sid, &domain_pol);
1785         else if (StrCaseCmp(argv[1], "builtin")==0)
1786                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1787                                               MAXIMUM_ALLOWED_ACCESS,
1788                                               &global_sid_Builtin, &domain_pol);
1789         else
1790                 return NT_STATUS_OK;
1791
1792         if (!NT_STATUS_IS_OK(result))
1793                 goto done;
1794
1795         /* Look up names */
1796
1797         num_names = argc - 2;
1798         if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
1799                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
1800                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
1801                 result = NT_STATUS_NO_MEMORY;
1802                 goto done;
1803         }
1804
1805         for (i = 0; i < argc - 2; i++)
1806                 names[i] = argv[i + 2];
1807
1808         result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1809                                        flags, num_names, names,
1810                                        &num_rids, &rids, &name_types);
1811
1812         if (!NT_STATUS_IS_OK(result))
1813                 goto done;
1814
1815         /* Display results */
1816
1817         for (i = 0; i < num_names; i++)
1818                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1819                        name_types[i]);
1820
1821         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1822         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1823  done:
1824         return result;
1825 }
1826
1827 /* Lookup sam rids */
1828
1829 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, 
1830                                      TALLOC_CTX *mem_ctx,
1831                                      int argc, const char **argv) 
1832 {
1833         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1834         POLICY_HND connect_pol, domain_pol;
1835         uint32 num_rids, num_names, *rids, *name_types;
1836         char **names;
1837         int i;
1838
1839         if (argc < 3) {
1840                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1841                 return NT_STATUS_OK;
1842         }
1843
1844         /* Get sam policy and domain handles */
1845
1846         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1847                                    &connect_pol);
1848
1849         if (!NT_STATUS_IS_OK(result))
1850                 goto done;
1851
1852         if (StrCaseCmp(argv[1], "domain")==0)
1853                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1854                                               MAXIMUM_ALLOWED_ACCESS,
1855                                               &domain_sid, &domain_pol);
1856         else if (StrCaseCmp(argv[1], "builtin")==0)
1857                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1858                                               MAXIMUM_ALLOWED_ACCESS,
1859                                               &global_sid_Builtin, &domain_pol);
1860         else
1861                 return NT_STATUS_OK;
1862
1863         if (!NT_STATUS_IS_OK(result))
1864                 goto done;
1865
1866         /* Look up rids */
1867
1868         num_rids = argc - 2;
1869         rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1870         if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1871                 rpccli_samr_close(cli, mem_ctx, &domain_pol);
1872                 rpccli_samr_close(cli, mem_ctx, &connect_pol);
1873                 result = NT_STATUS_NO_MEMORY;
1874                 goto done;
1875         }
1876
1877         for (i = 0; i < argc - 2; i++)
1878                 sscanf(argv[i + 2], "%i", &rids[i]);
1879
1880         result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
1881                                       &num_names, &names, &name_types);
1882
1883         if (!NT_STATUS_IS_OK(result) &&
1884             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1885                 goto done;
1886
1887         /* Display results */
1888
1889         for (i = 0; i < num_names; i++)
1890                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1891
1892         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1893         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1894  done:
1895         return result;
1896 }
1897
1898 /* Delete domain group */
1899
1900 static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli, 
1901                                          TALLOC_CTX *mem_ctx,
1902                                          int argc, const char **argv) 
1903 {
1904         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1905         POLICY_HND connect_pol, domain_pol, group_pol;
1906         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1907
1908         if ((argc < 2) || (argc > 3)) {
1909                 printf("Usage: %s groupname\n", argv[0]);
1910                 return NT_STATUS_OK;
1911         }
1912         
1913         if (argc > 2)
1914                 sscanf(argv[2], "%x", &access_mask);
1915
1916         /* Get sam policy and domain handles */
1917
1918         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1919                                    &connect_pol);
1920
1921         if (!NT_STATUS_IS_OK(result))
1922                 goto done;
1923
1924         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1925                                       MAXIMUM_ALLOWED_ACCESS,
1926                                       &domain_sid, &domain_pol);
1927
1928         if (!NT_STATUS_IS_OK(result))
1929                 goto done;
1930
1931         /* Get handle on group */
1932
1933         {
1934                 uint32 *group_rids, num_rids, *name_types;
1935                 uint32 flags = 0x000003e8; /* Unknown */
1936
1937                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1938                                                flags, 1, (const char **)&argv[1],
1939                                                &num_rids, &group_rids,
1940                                                &name_types);
1941
1942                 if (!NT_STATUS_IS_OK(result))
1943                         goto done;
1944
1945                 result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
1946                                                 access_mask,
1947                                                 group_rids[0], &group_pol);
1948
1949                 if (!NT_STATUS_IS_OK(result))
1950                         goto done;
1951         }
1952
1953         /* Delete user */
1954
1955         result = rpccli_samr_delete_dom_group(cli, mem_ctx, &group_pol);
1956
1957         if (!NT_STATUS_IS_OK(result))
1958                 goto done;
1959
1960         /* Display results */
1961
1962         rpccli_samr_close(cli, mem_ctx, &group_pol);
1963         rpccli_samr_close(cli, mem_ctx, &domain_pol);
1964         rpccli_samr_close(cli, mem_ctx, &connect_pol);
1965
1966  done:
1967         return result;
1968 }
1969
1970 /* Delete domain user */
1971
1972 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
1973                                          TALLOC_CTX *mem_ctx,
1974                                          int argc, const char **argv) 
1975 {
1976         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1977         POLICY_HND connect_pol, domain_pol, user_pol;
1978         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1979
1980         if ((argc < 2) || (argc > 3)) {
1981                 printf("Usage: %s username\n", argv[0]);
1982                 return NT_STATUS_OK;
1983         }
1984         
1985         if (argc > 2)
1986                 sscanf(argv[2], "%x", &access_mask);
1987
1988         /* Get sam policy and domain handles */
1989
1990         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1991                                    &connect_pol);
1992
1993         if (!NT_STATUS_IS_OK(result))
1994                 goto done;
1995
1996         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
1997                                       MAXIMUM_ALLOWED_ACCESS,
1998                                       &domain_sid, &domain_pol);
1999
2000         if (!NT_STATUS_IS_OK(result))
2001                 goto done;
2002
2003         /* Get handle on user */
2004
2005         {
2006                 uint32 *user_rids, num_rids, *name_types;
2007                 uint32 flags = 0x000003e8; /* Unknown */
2008
2009                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
2010                                                flags, 1, (const char **)&argv[1],
2011                                                &num_rids, &user_rids,
2012                                                &name_types);
2013
2014                 if (!NT_STATUS_IS_OK(result))
2015                         goto done;
2016
2017                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
2018                                             access_mask,
2019                                             user_rids[0], &user_pol);
2020
2021                 if (!NT_STATUS_IS_OK(result))
2022                         goto done;
2023         }
2024
2025         /* Delete user */
2026
2027         result = rpccli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
2028
2029         if (!NT_STATUS_IS_OK(result))
2030                 goto done;
2031
2032         /* Display results */
2033
2034         rpccli_samr_close(cli, mem_ctx, &user_pol);
2035         rpccli_samr_close(cli, mem_ctx, &domain_pol);
2036         rpccli_samr_close(cli, mem_ctx, &connect_pol);
2037
2038  done:
2039         return result;
2040 }
2041
2042 /**********************************************************************
2043  * Query user security object 
2044  */
2045 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, 
2046                                     TALLOC_CTX *mem_ctx,
2047                                     int argc, const char **argv) 
2048 {
2049         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
2050         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2051         uint32 sec_info = DACL_SECURITY_INFORMATION;
2052         fstring server;
2053         uint32 user_rid = 0;
2054         TALLOC_CTX *ctx = NULL;
2055         SEC_DESC_BUF *sec_desc_buf=NULL;
2056         BOOL domain = False;
2057
2058         ctx=talloc_init("cmd_samr_query_sec_obj");
2059         
2060         if ((argc < 1) || (argc > 3)) {
2061                 printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
2062                 printf("\tSpecify rid for security on user, -d for security on domain\n");
2063                 talloc_destroy(ctx);
2064                 return NT_STATUS_OK;
2065         }
2066         
2067         if (argc > 1) {
2068                 if (strcmp(argv[1], "-d") == 0)
2069                         domain = True;
2070                 else
2071                         sscanf(argv[1], "%i", &user_rid);
2072         }
2073
2074         if (argc == 3) {
2075                 sec_info = atoi(argv[2]);
2076         }
2077         
2078         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
2079         strupper_m(server);
2080         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2081                                    &connect_pol);
2082
2083         if (!NT_STATUS_IS_OK(result))
2084                 goto done;
2085
2086         if (domain || user_rid)
2087                 result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
2088                                               MAXIMUM_ALLOWED_ACCESS,
2089                                               &domain_sid, &domain_pol);
2090
2091         if (!NT_STATUS_IS_OK(result))
2092                 goto done;
2093
2094         if (user_rid)
2095                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
2096                                             MAXIMUM_ALLOWED_ACCESS,
2097                                             user_rid, &user_pol);
2098
2099         if (!NT_STATUS_IS_OK(result))
2100                 goto done;
2101
2102         /* Pick which query pol to use */
2103
2104         pol = &connect_pol;
2105
2106         if (domain)
2107                 pol = &domain_pol;
2108
2109         if (user_rid)
2110                 pol = &user_pol;
2111
2112         /* Query SAM security object */
2113
2114         result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, sec_info, ctx, 
2115                                         &sec_desc_buf);
2116
2117         if (!NT_STATUS_IS_OK(result))
2118                 goto done;
2119
2120         display_sec_desc(sec_desc_buf->sd);
2121
2122         rpccli_samr_close(cli, mem_ctx, &user_pol);
2123         rpccli_samr_close(cli, mem_ctx, &domain_pol);
2124         rpccli_samr_close(cli, mem_ctx, &connect_pol);
2125 done:
2126         talloc_destroy(ctx);
2127         return result;
2128 }
2129
2130 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli, 
2131                                            TALLOC_CTX *mem_ctx,
2132                                            int argc, const char **argv) 
2133 {
2134         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2135         POLICY_HND connect_pol, domain_pol, user_pol;
2136         uint16 min_pwd_length;
2137         uint32 password_properties, unknown1, rid;
2138
2139         if (argc != 2) {
2140                 printf("Usage: %s rid\n", argv[0]);
2141                 return NT_STATUS_OK;
2142         }
2143         
2144         sscanf(argv[1], "%i", &rid);
2145
2146         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2147                                    &connect_pol);
2148
2149         if (!NT_STATUS_IS_OK(result)) {
2150                 goto done;
2151         }
2152
2153         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
2154                                          MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol);
2155
2156         if (!NT_STATUS_IS_OK(result)) {
2157                 goto done;
2158         }
2159
2160         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
2161                                        MAXIMUM_ALLOWED_ACCESS,
2162                                        rid, &user_pol);
2163
2164         if (!NT_STATUS_IS_OK(result)) {
2165                 goto done;
2166         }
2167
2168         result = rpccli_samr_get_usrdom_pwinfo(cli, mem_ctx, &user_pol,
2169                                                &min_pwd_length, &password_properties, 
2170                                                &unknown1) ;
2171
2172         if (NT_STATUS_IS_OK(result)) {
2173                 printf("min_pwd_length: %d\n", min_pwd_length);
2174                 printf("unknown1: %d\n", unknown1);
2175                 display_password_properties(password_properties);
2176         }
2177
2178  done:
2179         rpccli_samr_close(cli, mem_ctx, &user_pol);
2180         rpccli_samr_close(cli, mem_ctx, &domain_pol);
2181         rpccli_samr_close(cli, mem_ctx, &connect_pol);
2182
2183         return result;
2184 }
2185
2186
2187 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, 
2188                                         TALLOC_CTX *mem_ctx,
2189                                         int argc, const char **argv) 
2190 {
2191         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2192         uint16 min_pwd_length;
2193         uint32 password_properties;
2194
2195         if (argc != 1) {
2196                 printf("Usage: %s\n", argv[0]);
2197                 return NT_STATUS_OK;
2198         }
2199
2200         result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &min_pwd_length, &password_properties) ;
2201         
2202         if (NT_STATUS_IS_OK(result)) {
2203                 printf("min_pwd_length: %d\n", min_pwd_length);
2204                 display_password_properties(password_properties);
2205         }
2206
2207         return result;
2208 }
2209
2210 /* Look up domain name */
2211
2212 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, 
2213                                        TALLOC_CTX *mem_ctx,
2214                                        int argc, const char **argv) 
2215 {
2216         POLICY_HND connect_pol, domain_pol;
2217         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2218         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2219         fstring domain_name,sid_string;
2220         DOM_SID sid;
2221         
2222         if (argc != 2) {
2223                 printf("Usage: %s domain_name\n", argv[0]);
2224                 return NT_STATUS_OK;
2225         }
2226         
2227         sscanf(argv[1], "%s", domain_name);
2228         
2229         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
2230         
2231         if (!NT_STATUS_IS_OK(result))
2232                 goto done;
2233
2234         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
2235                                       access_mask, &domain_sid, &domain_pol);
2236
2237         if (!NT_STATUS_IS_OK(result))
2238                 goto done;
2239         
2240         result = rpccli_samr_lookup_domain(
2241                 cli, mem_ctx, &connect_pol, domain_name, &sid);
2242
2243         sid_to_string(sid_string,&sid);
2244  
2245         if (NT_STATUS_IS_OK(result)) 
2246                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
2247                        domain_name,sid_string);
2248
2249         rpccli_samr_close(cli, mem_ctx, &domain_pol);
2250         rpccli_samr_close(cli, mem_ctx, &connect_pol);
2251 done:
2252         return result;
2253 }
2254
2255 /* Change user password */
2256
2257 static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli, 
2258                                     TALLOC_CTX *mem_ctx,
2259                                     int argc, const char **argv) 
2260 {
2261         POLICY_HND connect_pol, domain_pol;
2262         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2263         const char *user, *oldpass, *newpass;
2264         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2265
2266         if (argc < 3) {
2267                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2268                 return NT_STATUS_INVALID_PARAMETER;
2269         }
2270
2271         user = argv[1];
2272         oldpass = argv[2];
2273         newpass = argv[3];
2274         
2275         /* Get sam policy handle */
2276
2277         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2278                                    &connect_pol);
2279
2280         if (!NT_STATUS_IS_OK(result))
2281                 goto done;
2282
2283         /* Get domain policy handle */
2284
2285         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
2286                                       access_mask,
2287                                       &domain_sid, &domain_pol);
2288
2289         if (!NT_STATUS_IS_OK(result))
2290                 goto done;
2291
2292         /* Change user password */
2293         result = rpccli_samr_chgpasswd_user(cli, mem_ctx, user, newpass, oldpass);
2294
2295         if (!NT_STATUS_IS_OK(result))
2296                 goto done;
2297
2298         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
2299         if (!NT_STATUS_IS_OK(result)) goto done;
2300
2301         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
2302         if (!NT_STATUS_IS_OK(result)) goto done;
2303
2304  done:
2305         return result;
2306 }
2307
2308
2309 /* Change user password */
2310
2311 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli, 
2312                                     TALLOC_CTX *mem_ctx,
2313                                     int argc, const char **argv) 
2314 {
2315         POLICY_HND connect_pol, domain_pol;
2316         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2317         const char *user, *oldpass, *newpass;
2318         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2319         SAM_UNK_INFO_1 info;
2320         SAMR_CHANGE_REJECT reject;
2321
2322         if (argc < 3) {
2323                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2324                 return NT_STATUS_INVALID_PARAMETER;
2325         }
2326
2327         user = argv[1];
2328         oldpass = argv[2];
2329         newpass = argv[3];
2330         
2331         /* Get sam policy handle */
2332
2333         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2334                                    &connect_pol);
2335
2336         if (!NT_STATUS_IS_OK(result))
2337                 goto done;
2338
2339         /* Get domain policy handle */
2340
2341         result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
2342                                       access_mask,
2343                                       &domain_sid, &domain_pol);
2344
2345         if (!NT_STATUS_IS_OK(result))
2346                 goto done;
2347
2348         /* Change user password */
2349         result = rpccli_samr_chgpasswd3(cli, mem_ctx, user, newpass, oldpass, &info, &reject);
2350
2351         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2352         
2353                 display_sam_unk_info_1(&info);
2354
2355                 switch (reject.reject_reason) {
2356                         case REJECT_REASON_TOO_SHORT:
2357                                 d_printf("REJECT_REASON_TOO_SHORT\n");
2358                                 break;
2359                         case REJECT_REASON_IN_HISTORY:
2360                                 d_printf("REJECT_REASON_IN_HISTORY\n");
2361                                 break;
2362                         case REJECT_REASON_NOT_COMPLEX:
2363                                 d_printf("REJECT_REASON_NOT_COMPLEX\n");
2364                                 break;
2365                         case REJECT_REASON_OTHER:
2366                                 d_printf("REJECT_REASON_OTHER\n");
2367                                 break;
2368                         default:
2369                                 d_printf("unknown reject reason: %d\n", reject.reject_reason);
2370                                 break;
2371                 }
2372         }
2373
2374         if (!NT_STATUS_IS_OK(result))
2375                 goto done;
2376
2377         result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
2378         if (!NT_STATUS_IS_OK(result)) goto done;
2379
2380         result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
2381         if (!NT_STATUS_IS_OK(result)) goto done;
2382
2383  done:
2384         return result;
2385 }
2386
2387 /* List of commands exported by this module */
2388
2389 struct cmd_set samr_commands[] = {
2390
2391         { "SAMR" },
2392
2393         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
2394         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
2395         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
2396         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
2397         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
2398         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
2399         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
2400         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
2401         { "querydispinfo2",     RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo2,   NULL, PI_SAMR, NULL,    "Query display info 2",      "" },
2402         { "querydispinfo3",     RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo3,   NULL, PI_SAMR, NULL,    "Query display info 3",      "" },
2403         { "getdispenumindex",   RPC_RTYPE_NTSTATUS, cmd_samr_get_dispenum_index,        NULL, PI_SAMR, NULL,    "Query display info index",      "" },
2404         { "getdispenumindex2",  RPC_RTYPE_NTSTATUS, cmd_samr_get_dispenum_index2,       NULL, PI_SAMR, NULL,    "Query display info index",      "" },
2405         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
2406         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
2407         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
2408         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
2409
2410         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
2411         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
2412         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
2413         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
2414         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
2415         { "deletedomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group,      NULL, PI_SAMR, NULL,        "Delete domain group",     "" },
2416         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
2417         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
2418         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
2419         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
2420
2421         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
2422         { "chgpasswd2",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2,            NULL, PI_SAMR, NULL, "Change user password", "" },
2423         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
2424         { NULL }
2425 };