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