Use rpccli_samr_OpenDomain() all over the place.
[ira/wip.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));
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));
64         printf("\tUser Name   :\t%s\n", temp);
65         
66         unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp));
67         printf("\tFull Name   :\t%s\n", temp);
68         
69         unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp));
70         printf("\tHome Drive  :\t%s\n", temp);
71         
72         unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp));
73         printf("\tDir Drive   :\t%s\n", temp);
74         
75         unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp));
76         printf("\tProfile Path:\t%s\n", temp);
77         
78         unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp));
79         printf("\tLogon Script:\t%s\n", temp);
80         
81         unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp));
82         printf("\tDescription :\t%s\n", temp);
83         
84         unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp));
85         printf("\tWorkstations:\t%s\n", temp);
86         
87         unistr2_to_ascii(temp, &usr->uni_comment, sizeof(temp));
88         printf("\tUnknown Str :\t%s\n", temp);
89         
90         unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp));
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_t 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_PASSWORD_LOCKOUT_ADMINS)
139                 printf("\tDOMAIN_PASSWORD_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));
163         printf("Domain:\t\t%s\n", name);
164
165         unistr2_to_ascii(name, &info2->uni_server, sizeof(name));
166         printf("Server:\t\t%s\n", name);
167
168         unistr2_to_ascii(name, &info2->uni_comment, sizeof(name));
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));
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));
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));
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));
256         printf("Account: %s\t", tmp);
257
258         unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp));
259         printf("Name: %s\t", tmp);
260
261         unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp));
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));
274         printf("Account: %s\t", tmp);
275
276         unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp));
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));
290         printf("Account: %s\t", tmp);
291
292         unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp));
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_OpenDomain(cli, mem_ctx,
378                                         &connect_pol,
379                                         MAXIMUM_ALLOWED_ACCESS,
380                                         &domain_sid,
381                                         &domain_pol);
382         if (!NT_STATUS_IS_OK(result))
383                 goto done;
384
385         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
386                                     access_mask,
387                                     user_rid, &user_pol);
388
389         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) &&
390             (user_rid == 0)) {
391
392                 /* Probably this was a user name, try lookupnames */
393                 uint32 num_rids;
394                 uint32 *rids, *types;
395                 
396                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
397                                                   1000, 1, &argv[1],
398                                                   &num_rids, &rids,
399                                                   &types);
400
401                 if (NT_STATUS_IS_OK(result)) {
402                         result = rpccli_samr_open_user(cli, mem_ctx,
403                                                        &domain_pol,
404                                                        access_mask,
405                                                        rids[0], &user_pol);
406                 }
407         }
408
409
410         if (!NT_STATUS_IS_OK(result))
411                 goto done;
412
413         ZERO_STRUCT(user_ctr);
414
415         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
416                                          info_level, &user_ctr);
417
418         if (!NT_STATUS_IS_OK(result))
419                 goto done;
420
421         switch (user_ctr->switch_value) {
422         case 7:
423                 display_sam_user_info_7(user_ctr->info.id7);
424                 break;
425         case 9:
426                 display_sam_user_info_9(user_ctr->info.id9);
427                 break;
428         case 16:
429                 display_sam_user_info_16(user_ctr->info.id16);
430                 break;
431         case 21:
432                 display_sam_user_info_21(user_ctr->info.id21);
433                 break;
434         default:
435                 printf("Unsupported infolevel: %d\n", info_level);
436                 break;
437         }
438
439         rpccli_samr_Close(cli, mem_ctx, &user_pol);
440         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
441         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
442
443 done:
444         return result;
445 }
446
447 /****************************************************************************
448  display group info
449  ****************************************************************************/
450 static void display_group_info1(GROUP_INFO1 *info1)
451 {
452         fstring temp;
453
454         unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp));
455         printf("\tGroup Name:\t%s\n", temp);
456         unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp));
457         printf("\tDescription:\t%s\n", temp);
458         printf("\tGroup Attribute:%d\n", info1->group_attr);
459         printf("\tNum Members:%d\n", info1->num_members);
460 }
461
462 /****************************************************************************
463  display group info
464  ****************************************************************************/
465 static void display_group_info2(GROUP_INFO2 *info2)
466 {
467         fstring name;
468
469         unistr2_to_ascii(name, &info2->uni_acct_name, sizeof(name));
470         printf("\tGroup Description:%s\n", name);
471 }
472
473
474 /****************************************************************************
475  display group info
476  ****************************************************************************/
477 static void display_group_info3(GROUP_INFO3 *info3)
478 {
479         printf("\tGroup Attribute:%d\n", info3->group_attr);
480 }
481
482
483 /****************************************************************************
484  display group info
485  ****************************************************************************/
486 static void display_group_info4(GROUP_INFO4 *info4)
487 {
488         fstring desc;
489
490         unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc));
491         printf("\tGroup Description:%s\n", desc);
492 }
493
494 /****************************************************************************
495  display group info
496  ****************************************************************************/
497 static void display_group_info5(GROUP_INFO5 *info5)
498 {
499         fstring temp;
500
501         unistr2_to_ascii(temp, &info5->uni_acct_name, sizeof(temp));
502         printf("\tGroup Name:\t%s\n", temp);
503         unistr2_to_ascii(temp, &info5->uni_acct_desc, sizeof(temp));
504         printf("\tDescription:\t%s\n", temp);
505         printf("\tGroup Attribute:%d\n", info5->group_attr);
506         printf("\tNum Members:%d\n", info5->num_members);
507 }
508
509 /****************************************************************************
510  display sam sync structure
511  ****************************************************************************/
512 static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
513 {
514         switch (ctr->switch_value1) {
515                 case 1:
516                         display_group_info1(&ctr->group.info1);
517                         break;
518                 case 2:
519                         display_group_info2(&ctr->group.info2);
520                         break;
521                 case 3:
522                         display_group_info3(&ctr->group.info3);
523                         break;
524                 case 4:
525                         display_group_info4(&ctr->group.info4);
526                         break;
527                 case 5:
528                         display_group_info5(&ctr->group.info5);
529                         break;
530
531         }
532 }
533
534 /***********************************************************************
535  * Query group information 
536  */
537 static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli, 
538                                      TALLOC_CTX *mem_ctx,
539                                      int argc, const char **argv) 
540 {
541         POLICY_HND connect_pol, domain_pol, group_pol;
542         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
543         uint32 info_level = 1;
544         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
545         GROUP_INFO_CTR *group_ctr;
546         fstring                 server; 
547         uint32 group_rid;
548         
549         if ((argc < 2) || (argc > 4)) {
550                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
551                 return NT_STATUS_OK;
552         }
553
554         sscanf(argv[1], "%i", &group_rid);
555         
556         if (argc > 2)
557                 sscanf(argv[2], "%i", &info_level);
558         
559         if (argc > 3)
560                 sscanf(argv[3], "%x", &access_mask);
561
562         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
563         strupper_m(server);
564
565         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
566                                    &connect_pol);
567
568         if (!NT_STATUS_IS_OK(result))
569                 goto done;
570
571         result = rpccli_samr_OpenDomain(cli, mem_ctx,
572                                         &connect_pol,
573                                         MAXIMUM_ALLOWED_ACCESS,
574                                         &domain_sid,
575                                         &domain_pol);
576
577         if (!NT_STATUS_IS_OK(result))
578                 goto done;
579
580         result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
581                                      access_mask,
582                                      group_rid, &group_pol);
583
584         if (!NT_STATUS_IS_OK(result))
585                 goto done;
586
587         result = rpccli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
588                                           info_level, &group_ctr);
589         if (!NT_STATUS_IS_OK(result)) {
590                 goto done;
591         }
592
593         display_group_info_ctr(group_ctr);
594
595         rpccli_samr_Close(cli, mem_ctx, &group_pol);
596         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
597         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
598 done:
599         return result;
600 }
601
602 /* Query groups a user is a member of */
603
604 static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli, 
605                                           TALLOC_CTX *mem_ctx,
606                                           int argc, const char **argv) 
607 {
608         POLICY_HND              connect_pol, 
609                                 domain_pol, 
610                                 user_pol;
611         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
612         uint32                  num_groups, 
613                                 user_rid;
614         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
615         DOM_GID                 *user_gids;
616         int                     i;
617         fstring                 server;
618         
619         if ((argc < 2) || (argc > 3)) {
620                 printf("Usage: %s rid [access mask]\n", argv[0]);
621                 return NT_STATUS_OK;
622         }
623
624         sscanf(argv[1], "%i", &user_rid);
625         
626         if (argc > 2)
627                 sscanf(argv[2], "%x", &access_mask);
628
629         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
630         strupper_m(server);
631                 
632         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
633                                    &connect_pol);
634
635         if (!NT_STATUS_IS_OK(result))
636                 goto done;
637
638         result = rpccli_samr_OpenDomain(cli, mem_ctx,
639                                         &connect_pol,
640                                         MAXIMUM_ALLOWED_ACCESS,
641                                         &domain_sid, &domain_pol);
642
643         if (!NT_STATUS_IS_OK(result))
644                 goto done;
645
646         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
647                                     access_mask,
648                                     user_rid, &user_pol);
649
650         if (!NT_STATUS_IS_OK(result))
651                 goto done;
652
653         result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
654                                            &num_groups, &user_gids);
655
656         if (!NT_STATUS_IS_OK(result))
657                 goto done;
658
659         for (i = 0; i < num_groups; i++) {
660                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n", 
661                        user_gids[i].g_rid, user_gids[i].attr);
662         }
663
664         rpccli_samr_Close(cli, mem_ctx, &user_pol);
665         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
666         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
667  done:
668         return result;
669 }
670
671 /* Query aliases a user is a member of */
672
673 static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli, 
674                                            TALLOC_CTX *mem_ctx,
675                                            int argc, const char **argv) 
676 {
677         POLICY_HND              connect_pol, domain_pol;
678         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
679         DOM_SID                *sids;
680         size_t                     num_sids;
681         uint32                  num_aliases, *alias_rids;
682         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
683         int                     i;
684         fstring                 server;
685         DOM_SID2               *sid2;
686
687         if (argc < 3) {
688                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
689                 return NT_STATUS_INVALID_PARAMETER;
690         }
691
692         sids = NULL;
693         num_sids = 0;
694
695         for (i=2; i<argc; i++) {
696                 DOM_SID tmp_sid;
697                 if (!string_to_sid(&tmp_sid, argv[i])) {
698                         printf("%s is not a legal SID\n", argv[i]);
699                         return NT_STATUS_INVALID_PARAMETER;
700                 }
701                 result = add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
702                 if (!NT_STATUS_IS_OK(result)) {
703                         return result;
704                 }
705         }
706
707         if (num_sids) {
708                 sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids);
709                 if (sid2 == NULL)
710                         return NT_STATUS_NO_MEMORY;
711         } else {
712                 sid2 = NULL;
713         }
714
715         for (i=0; i<num_sids; i++) {
716                 sid_copy(&sid2[i].sid, &sids[i]);
717                 sid2[i].num_auths = sid2[i].sid.num_auths;
718         }
719
720         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
721         strupper_m(server);
722                 
723         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
724                                    &connect_pol);
725
726         if (!NT_STATUS_IS_OK(result))
727                 goto done;
728
729         if (StrCaseCmp(argv[1], "domain")==0)
730                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
731                                                 &connect_pol,
732                                                 access_mask,
733                                                 &domain_sid, &domain_pol);
734         else if (StrCaseCmp(argv[1], "builtin")==0)
735                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
736                                                 &connect_pol,
737                                                 access_mask,
738                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
739                                                 &domain_pol);
740         else {
741                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
742                 return NT_STATUS_INVALID_PARAMETER;
743         }
744
745         if (!NT_STATUS_IS_OK(result))
746                 goto done;
747
748         result = rpccli_samr_query_useraliases(cli, mem_ctx, &domain_pol,
749                                             num_sids, sid2,
750                                             &num_aliases, &alias_rids);
751
752         if (!NT_STATUS_IS_OK(result))
753                 goto done;
754
755         for (i = 0; i < num_aliases; i++) {
756                 printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
757         }
758
759         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
760         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
761  done:
762         return result;
763 }
764
765 /* Query members of a group */
766
767 static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli, 
768                                         TALLOC_CTX *mem_ctx,
769                                         int argc, const char **argv) 
770 {
771         POLICY_HND connect_pol, domain_pol, group_pol;
772         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
773         uint32 num_members, *group_rids, *group_attrs, group_rid;
774         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
775         int i;
776         fstring                 server;
777         unsigned int old_timeout;
778         
779         if ((argc < 2) || (argc > 3)) {
780                 printf("Usage: %s rid [access mask]\n", argv[0]);
781                 return NT_STATUS_OK;
782         }
783
784         sscanf(argv[1], "%i", &group_rid);
785         
786         if (argc > 2)
787                 sscanf(argv[2], "%x", &access_mask);
788
789         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
790         strupper_m(server);
791
792         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
793                                    &connect_pol);
794
795         if (!NT_STATUS_IS_OK(result))
796                 goto done;
797
798         result = rpccli_samr_OpenDomain(cli, mem_ctx,
799                                         &connect_pol,
800                                         MAXIMUM_ALLOWED_ACCESS,
801                                         &domain_sid,
802                                         &domain_pol);
803
804         if (!NT_STATUS_IS_OK(result))
805                 goto done;
806
807         result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
808                                      access_mask,
809                                      group_rid, &group_pol);
810
811         if (!NT_STATUS_IS_OK(result))
812                 goto done;
813
814         /* Make sure to wait for our DC's reply */
815         old_timeout = cli_set_timeout(cli->cli, MAX(cli->cli->timeout,30000)); /* 30 seconds. */
816
817         result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
818                                          &num_members, &group_rids,
819                                          &group_attrs);
820
821         cli_set_timeout(cli->cli, old_timeout);
822
823         if (!NT_STATUS_IS_OK(result))
824                 goto done;
825
826         for (i = 0; i < num_members; i++) {
827                 printf("\trid:[0x%x] attr:[0x%x]\n", group_rids[i],
828                        group_attrs[i]);
829         }
830
831         rpccli_samr_Close(cli, mem_ctx, &group_pol);
832         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
833         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
834  done:
835         return result;
836 }
837
838 /* Enumerate domain users */
839
840 static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli, 
841                                         TALLOC_CTX *mem_ctx,
842                                         int argc, const char **argv) 
843 {
844         POLICY_HND connect_pol, domain_pol;
845         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
846         uint32 start_idx, size, num_dom_users, i;
847         char **dom_users;
848         uint32 *dom_rids;
849         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
850         uint32 acb_mask = ACB_NORMAL;
851         bool got_connect_pol = False, got_domain_pol = False;
852
853         if ((argc < 1) || (argc > 3)) {
854                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
855                 return NT_STATUS_OK;
856         }
857         
858         if (argc > 1)
859                 sscanf(argv[1], "%x", &access_mask);
860
861         if (argc > 2)
862                 sscanf(argv[2], "%x", &acb_mask);
863
864         /* Get sam policy handle */
865
866         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
867                                    &connect_pol);
868
869         if (!NT_STATUS_IS_OK(result))
870                 goto done;
871
872         got_connect_pol = True;
873
874         /* Get domain policy handle */
875
876         result = rpccli_samr_OpenDomain(cli, mem_ctx,
877                                         &connect_pol,
878                                         access_mask,
879                                         &domain_sid,
880                                         &domain_pol);
881
882         if (!NT_STATUS_IS_OK(result))
883                 goto done;
884
885         got_domain_pol = True;
886
887         /* Enumerate domain users */
888
889         start_idx = 0;
890         size = 0xffff;
891
892         do {
893                 result = rpccli_samr_enum_dom_users(
894                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
895                         size, &dom_users, &dom_rids, &num_dom_users);
896
897                 if (NT_STATUS_IS_OK(result) ||
898                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
899
900                         for (i = 0; i < num_dom_users; i++)
901                                printf("user:[%s] rid:[0x%x]\n", 
902                                        dom_users[i], dom_rids[i]);
903                 }
904
905         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
906
907  done:
908         if (got_domain_pol)
909                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
910
911         if (got_connect_pol)
912                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
913
914         return result;
915 }
916
917 /* Enumerate domain groups */
918
919 static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli, 
920                                          TALLOC_CTX *mem_ctx,
921                                          int argc, const char **argv) 
922 {
923         POLICY_HND connect_pol, domain_pol;
924         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
925         uint32 start_idx, size, num_dom_groups, i;
926         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
927         struct acct_info *dom_groups;
928         bool got_connect_pol = False, got_domain_pol = False;
929
930         if ((argc < 1) || (argc > 2)) {
931                 printf("Usage: %s [access_mask]\n", argv[0]);
932                 return NT_STATUS_OK;
933         }
934         
935         if (argc > 1)
936                 sscanf(argv[1], "%x", &access_mask);
937
938         /* Get sam policy handle */
939
940         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
941                                    &connect_pol);
942
943         if (!NT_STATUS_IS_OK(result))
944                 goto done;
945
946         got_connect_pol = True;
947
948         /* Get domain policy handle */
949
950         result = rpccli_samr_OpenDomain(cli, mem_ctx,
951                                         &connect_pol,
952                                         access_mask,
953                                         &domain_sid,
954                                         &domain_pol);
955
956         if (!NT_STATUS_IS_OK(result))
957                 goto done;
958
959         got_domain_pol = True;
960
961         /* Enumerate domain groups */
962
963         start_idx = 0;
964         size = 0xffff;
965
966         do {
967                 result = rpccli_samr_enum_dom_groups(
968                         cli, mem_ctx, &domain_pol, &start_idx, size,
969                         &dom_groups, &num_dom_groups);
970
971                 if (NT_STATUS_IS_OK(result) ||
972                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
973
974                         for (i = 0; i < num_dom_groups; i++)
975                                 printf("group:[%s] rid:[0x%x]\n", 
976                                        dom_groups[i].acct_name,
977                                        dom_groups[i].rid);
978                 }
979
980         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
981
982  done:
983         if (got_domain_pol)
984                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
985
986         if (got_connect_pol)
987                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
988
989         return result;
990 }
991
992 /* Enumerate alias groups */
993
994 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli, 
995                                          TALLOC_CTX *mem_ctx,
996                                          int argc, const char **argv) 
997 {
998         POLICY_HND connect_pol, domain_pol;
999         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1000         uint32 start_idx, size, num_als_groups, i;
1001         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1002         struct acct_info *als_groups;
1003         bool got_connect_pol = False, got_domain_pol = False;
1004
1005         if ((argc < 2) || (argc > 3)) {
1006                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
1007                 return NT_STATUS_OK;
1008         }
1009         
1010         if (argc > 2)
1011                 sscanf(argv[2], "%x", &access_mask);
1012
1013         /* Get sam policy handle */
1014
1015         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1016                                    &connect_pol);
1017
1018         if (!NT_STATUS_IS_OK(result))
1019                 goto done;
1020
1021         got_connect_pol = True;
1022
1023         /* Get domain policy handle */
1024
1025         if (StrCaseCmp(argv[1], "domain")==0)
1026                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1027                                                 &connect_pol,
1028                                                 access_mask,
1029                                                 &domain_sid,
1030                                                 &domain_pol);
1031         else if (StrCaseCmp(argv[1], "builtin")==0)
1032                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1033                                                 &connect_pol,
1034                                                 access_mask,
1035                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1036                                                 &domain_pol);
1037         else
1038                 return NT_STATUS_OK;
1039
1040         if (!NT_STATUS_IS_OK(result))
1041                 goto done;
1042
1043         got_domain_pol = True;
1044
1045         /* Enumerate alias groups */
1046
1047         start_idx = 0;
1048         size = 0xffff;          /* Number of groups to retrieve */
1049
1050         do {
1051                 result = rpccli_samr_enum_als_groups(
1052                         cli, mem_ctx, &domain_pol, &start_idx, size,
1053                         &als_groups, &num_als_groups);
1054
1055                 if (NT_STATUS_IS_OK(result) ||
1056                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1057
1058                         for (i = 0; i < num_als_groups; i++)
1059                                 printf("group:[%s] rid:[0x%x]\n", 
1060                                        als_groups[i].acct_name,
1061                                        als_groups[i].rid);
1062                 }
1063         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1064
1065  done:
1066         if (got_domain_pol)
1067                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1068         
1069         if (got_connect_pol)
1070                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1071         
1072         return result;
1073 }
1074
1075 /* Query alias membership */
1076
1077 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli, 
1078                                         TALLOC_CTX *mem_ctx,
1079                                         int argc, const char **argv) 
1080 {
1081         POLICY_HND connect_pol, domain_pol, alias_pol;
1082         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1083         uint32 alias_rid, num_members, i;
1084         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1085         DOM_SID *alias_sids;
1086
1087         if ((argc < 3) || (argc > 4)) {
1088                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1089                 return NT_STATUS_OK;
1090         }
1091
1092         sscanf(argv[2], "%i", &alias_rid);
1093         
1094         if (argc > 3)
1095                 sscanf(argv[3], "%x", &access_mask);
1096
1097         /* Open SAMR handle */
1098
1099         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1100                                    &connect_pol);
1101
1102         if (!NT_STATUS_IS_OK(result))
1103                 goto done;
1104
1105         /* Open handle on domain */
1106         
1107         if (StrCaseCmp(argv[1], "domain")==0)
1108                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1109                                                 &connect_pol,
1110                                                 MAXIMUM_ALLOWED_ACCESS,
1111                                                 &domain_sid,
1112                                                 &domain_pol);
1113         else if (StrCaseCmp(argv[1], "builtin")==0)
1114                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1115                                                 &connect_pol,
1116                                                 MAXIMUM_ALLOWED_ACCESS,
1117                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1118                                                 &domain_pol);
1119         else
1120                 return NT_STATUS_OK;
1121
1122         if (!NT_STATUS_IS_OK(result))
1123                 goto done;
1124
1125         /* Open handle on alias */
1126
1127         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1128                                      access_mask,
1129                                      alias_rid, &alias_pol);
1130         if (!NT_STATUS_IS_OK(result))
1131                 goto done;
1132
1133         result = rpccli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
1134                                          &num_members, &alias_sids);
1135
1136         if (!NT_STATUS_IS_OK(result))
1137                 goto done;
1138
1139         for (i = 0; i < num_members; i++) {
1140                 fstring sid_str;
1141
1142                 sid_to_fstring(sid_str, &alias_sids[i]);
1143                 printf("\tsid:[%s]\n", sid_str);
1144         }
1145
1146         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1147         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1148         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1149  done:
1150         return result;
1151 }
1152
1153 /* Query delete an alias membership */
1154
1155 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli, 
1156                                       TALLOC_CTX *mem_ctx,
1157                                       int argc, const char **argv) 
1158 {
1159         POLICY_HND connect_pol, domain_pol, alias_pol;
1160         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1161         uint32 alias_rid;
1162         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1163
1164         if (argc != 3) {
1165                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1166                 return NT_STATUS_OK;
1167         }
1168
1169         alias_rid = strtoul(argv[2], NULL, 10);
1170         
1171         /* Open SAMR handle */
1172
1173         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1174                                    &connect_pol);
1175
1176         if (!NT_STATUS_IS_OK(result))
1177                 goto done;
1178
1179         /* Open handle on domain */
1180         
1181         if (StrCaseCmp(argv[1], "domain")==0)
1182                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1183                                                 &connect_pol,
1184                                                 MAXIMUM_ALLOWED_ACCESS,
1185                                                 &domain_sid,
1186                                                 &domain_pol);
1187         else if (StrCaseCmp(argv[1], "builtin")==0)
1188                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1189                                                 &connect_pol,
1190                                                 MAXIMUM_ALLOWED_ACCESS,
1191                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1192                                                 &domain_pol);
1193         else
1194                 return NT_STATUS_INVALID_PARAMETER;
1195
1196         if (!NT_STATUS_IS_OK(result))
1197                 goto done;
1198
1199         /* Open handle on alias */
1200
1201         result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
1202                                      access_mask,
1203                                      alias_rid, &alias_pol);
1204         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1205                 /* Probably this was a user name, try lookupnames */
1206                 uint32 num_rids;
1207                 uint32 *rids, *types;
1208                 
1209                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1210                                                   1000, 1, &argv[2],
1211                                                   &num_rids, &rids,
1212                                                   &types);
1213
1214                 if (NT_STATUS_IS_OK(result)) {
1215                         result = rpccli_samr_open_alias(cli, mem_ctx,
1216                                                        &domain_pol,
1217                                                        access_mask,
1218                                                        rids[0], &alias_pol);
1219                 }
1220         }
1221
1222         result = rpccli_samr_DeleteDomAlias(cli, mem_ctx,
1223                                             &alias_pol);
1224
1225         if (!NT_STATUS_IS_OK(result))
1226                 goto done;
1227
1228         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1229         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1230  done:
1231         return result;
1232 }
1233
1234 /* Query display info */
1235
1236 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
1237                                         TALLOC_CTX *mem_ctx,
1238                                         int argc, const char **argv) 
1239 {
1240         POLICY_HND connect_pol, domain_pol;
1241         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1242         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i;
1243         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1244         uint32 info_level = 1;
1245         SAM_DISPINFO_CTR ctr;
1246         SAM_DISPINFO_1 info1;
1247         SAM_DISPINFO_2 info2;
1248         SAM_DISPINFO_3 info3;
1249         SAM_DISPINFO_4 info4;
1250         SAM_DISPINFO_5 info5;
1251         int loop_count = 0;
1252         bool got_params = False; /* Use get_query_dispinfo_params() or not? */
1253
1254         if (argc > 6) {
1255                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1256                 return NT_STATUS_OK;
1257         }
1258
1259         if (argc >= 2)
1260                 sscanf(argv[1], "%i", &info_level);
1261         
1262         if (argc >= 3)
1263                 sscanf(argv[2], "%i", &start_idx);
1264         
1265         if (argc >= 4) {
1266                 sscanf(argv[3], "%i", &max_entries);
1267                 got_params = True;
1268         }
1269         
1270         if (argc >= 5) {
1271                 sscanf(argv[4], "%i", &max_size);
1272                 got_params = True;
1273         }
1274         
1275         if (argc >= 6)
1276                 sscanf(argv[5], "%x", &access_mask);
1277
1278         /* Get sam policy handle */
1279
1280         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1281                                    &connect_pol);
1282
1283         if (!NT_STATUS_IS_OK(result))
1284                 goto done;
1285
1286         /* Get domain policy handle */
1287
1288         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1289                                         &connect_pol,
1290                                         access_mask,
1291                                         &domain_sid,
1292                                         &domain_pol);
1293
1294         if (!NT_STATUS_IS_OK(result))
1295                 goto done;
1296
1297         /* Query display info */
1298
1299         ZERO_STRUCT(ctr);
1300         ZERO_STRUCT(info1);
1301         
1302         switch (info_level) {
1303         case 1:
1304                 ZERO_STRUCT(info1);
1305                 ctr.sam.info1 = &info1;
1306                 break;
1307         case 2:
1308                 ZERO_STRUCT(info2);
1309                 ctr.sam.info2 = &info2;
1310                 break;
1311         case 3:
1312                 ZERO_STRUCT(info3);
1313                 ctr.sam.info3 = &info3;
1314                 break;
1315         case 4:
1316                 ZERO_STRUCT(info4);
1317                 ctr.sam.info4 = &info4;
1318                 break;
1319         case 5:
1320                 ZERO_STRUCT(info5);
1321                 ctr.sam.info5 = &info5;
1322                 break;
1323         }
1324
1325
1326         do {
1327
1328                 if (!got_params)
1329                         get_query_dispinfo_params(
1330                                 loop_count, &max_entries, &max_size);
1331                 
1332                 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1333                                                  &start_idx, info_level,
1334                                                  &num_entries, max_entries, 
1335                                                  max_size, &ctr);
1336
1337                 loop_count++;
1338
1339                 if (NT_STATUS_IS_ERR(result))
1340                         break;
1341
1342                 if (num_entries == 0) 
1343                         break;
1344
1345                 for (i = 0; i < num_entries; i++) {
1346                         switch (info_level) {
1347                         case 1:
1348                                 display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]);
1349                                 break;
1350                         case 2:
1351                                 display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]);
1352                                 break;
1353                         case 3:
1354                                 display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]);
1355                                 break;
1356                         case 4:
1357                                 display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]);
1358                                 break;
1359                         case 5:
1360                                 display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]);
1361                                 break;
1362                         }
1363                 }
1364         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1365
1366         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1367         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1368  done:
1369         return result;
1370 }
1371
1372 /* Query domain info */
1373
1374 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, 
1375                                        TALLOC_CTX *mem_ctx,
1376                                        int argc, const char **argv) 
1377 {
1378         POLICY_HND connect_pol, domain_pol;
1379         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1380         uint32 switch_level = 2;
1381         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1382         SAM_UNK_CTR ctr;
1383
1384         if (argc > 3) {
1385                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1386                 return NT_STATUS_OK;
1387         }
1388
1389         if (argc > 1)
1390                 sscanf(argv[1], "%i", &switch_level);
1391         
1392         if (argc > 2)
1393                 sscanf(argv[2], "%x", &access_mask);
1394
1395         /* Get sam policy handle */
1396
1397         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1398                                    &connect_pol);
1399
1400         if (!NT_STATUS_IS_OK(result))
1401                 goto done;
1402
1403         /* Get domain policy handle */
1404
1405         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1406                                         &connect_pol,
1407                                         access_mask,
1408                                         &domain_sid,
1409                                         &domain_pol);
1410
1411         if (!NT_STATUS_IS_OK(result))
1412                 goto done;
1413
1414         /* Query domain info */
1415
1416         result = rpccli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
1417                                          switch_level, &ctr);
1418
1419         if (!NT_STATUS_IS_OK(result))
1420                 goto done;
1421
1422         /* Display domain info */
1423
1424         switch (switch_level) {
1425         case 1:
1426                 display_sam_unk_info_1(&ctr.info.inf1);
1427                 break;
1428         case 2:
1429                 display_sam_unk_info_2(&ctr.info.inf2);
1430                 break;
1431         case 3:
1432                 display_sam_unk_info_3(&ctr.info.inf3);
1433                 break;
1434         case 4:
1435                 display_sam_unk_info_4(&ctr.info.inf4);
1436                 break;
1437         case 5:
1438                 display_sam_unk_info_5(&ctr.info.inf5);
1439                 break;
1440         case 6:
1441                 display_sam_unk_info_6(&ctr.info.inf6);
1442                 break;
1443         case 7:
1444                 display_sam_unk_info_7(&ctr.info.inf7);
1445                 break;
1446         case 8:
1447                 display_sam_unk_info_8(&ctr.info.inf8);
1448                 break;
1449         case 9:
1450                 display_sam_unk_info_9(&ctr.info.inf9);
1451                 break;
1452         case 12:
1453                 display_sam_unk_info_12(&ctr.info.inf12);
1454                 break;
1455         case 13:
1456                 display_sam_unk_info_13(&ctr.info.inf13);
1457                 break;
1458
1459         default:
1460                 printf("cannot display domain info for switch value %d\n",
1461                        switch_level);
1462                 break;
1463         }
1464
1465  done:
1466
1467         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1468         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1469         return result;
1470 }
1471
1472 /* Create domain user */
1473
1474 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, 
1475                                          TALLOC_CTX *mem_ctx,
1476                                          int argc, const char **argv) 
1477 {
1478         POLICY_HND connect_pol, domain_pol, user_pol;
1479         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1480         const char *acct_name;
1481         uint32 acb_info;
1482         uint32 acct_flags, user_rid;
1483         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1484
1485         if ((argc < 2) || (argc > 3)) {
1486                 printf("Usage: %s username [access mask]\n", argv[0]);
1487                 return NT_STATUS_OK;
1488         }
1489
1490         acct_name = argv[1];
1491
1492         if (argc > 2)
1493                 sscanf(argv[2], "%x", &access_mask);
1494
1495         /* Get sam policy handle */
1496
1497         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1498                                    &connect_pol);
1499
1500         if (!NT_STATUS_IS_OK(result))
1501                 goto done;
1502
1503         /* Get domain policy handle */
1504
1505         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1506                                         &connect_pol,
1507                                         access_mask,
1508                                         &domain_sid,
1509                                         &domain_pol);
1510
1511         if (!NT_STATUS_IS_OK(result))
1512                 goto done;
1513
1514         /* Create domain user */
1515
1516         acb_info = ACB_NORMAL;
1517         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
1518                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
1519                      SAMR_USER_ACCESS_SET_PASSWORD |
1520                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
1521                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
1522
1523         result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1524                                           acct_name, acb_info, acct_flags,
1525                                           &user_pol, &user_rid);
1526
1527         if (!NT_STATUS_IS_OK(result))
1528                 goto done;
1529
1530         result = rpccli_samr_Close(cli, mem_ctx, &user_pol);
1531         if (!NT_STATUS_IS_OK(result)) goto done;
1532
1533         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1534         if (!NT_STATUS_IS_OK(result)) goto done;
1535
1536         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1537         if (!NT_STATUS_IS_OK(result)) goto done;
1538
1539  done:
1540         return result;
1541 }
1542
1543 /* Create domain group */
1544
1545 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, 
1546                                           TALLOC_CTX *mem_ctx,
1547                                           int argc, const char **argv) 
1548 {
1549         POLICY_HND connect_pol, domain_pol, group_pol;
1550         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1551         const char *grp_name;
1552         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1553
1554         if ((argc < 2) || (argc > 3)) {
1555                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1556                 return NT_STATUS_OK;
1557         }
1558
1559         grp_name = argv[1];
1560         
1561         if (argc > 2)
1562                 sscanf(argv[2], "%x", &access_mask);
1563
1564         /* Get sam policy handle */
1565
1566         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1567                                    &connect_pol);
1568
1569         if (!NT_STATUS_IS_OK(result))
1570                 goto done;
1571
1572         /* Get domain policy handle */
1573
1574         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1575                                         &connect_pol,
1576                                         access_mask,
1577                                         &domain_sid,
1578                                         &domain_pol);
1579
1580         if (!NT_STATUS_IS_OK(result))
1581                 goto done;
1582
1583         /* Create domain user */
1584
1585         result = rpccli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
1586                                            grp_name, MAXIMUM_ALLOWED_ACCESS,
1587                                            &group_pol);
1588
1589         if (!NT_STATUS_IS_OK(result))
1590                 goto done;
1591
1592         result = rpccli_samr_Close(cli, mem_ctx, &group_pol);
1593         if (!NT_STATUS_IS_OK(result)) goto done;
1594
1595         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1596         if (!NT_STATUS_IS_OK(result)) goto done;
1597
1598         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1599         if (!NT_STATUS_IS_OK(result)) goto done;
1600
1601  done:
1602         return result;
1603 }
1604
1605 /* Create domain alias */
1606
1607 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli, 
1608                                           TALLOC_CTX *mem_ctx,
1609                                           int argc, const char **argv) 
1610 {
1611         POLICY_HND connect_pol, domain_pol, alias_pol;
1612         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1613         const char *alias_name;
1614         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1615
1616         if ((argc < 2) || (argc > 3)) {
1617                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1618                 return NT_STATUS_OK;
1619         }
1620
1621         alias_name = argv[1];
1622         
1623         if (argc > 2)
1624                 sscanf(argv[2], "%x", &access_mask);
1625
1626         /* Get sam policy handle */
1627
1628         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1629                                    &connect_pol);
1630
1631         if (!NT_STATUS_IS_OK(result))
1632                 goto done;
1633
1634         /* Get domain policy handle */
1635
1636         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1637                                         &connect_pol,
1638                                         access_mask,
1639                                         &domain_sid,
1640                                         &domain_pol);
1641
1642         if (!NT_STATUS_IS_OK(result))
1643                 goto done;
1644
1645         /* Create domain user */
1646
1647         result = rpccli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
1648                                               alias_name, &alias_pol);
1649
1650         if (!NT_STATUS_IS_OK(result))
1651                 goto done;
1652
1653         result = rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1654         if (!NT_STATUS_IS_OK(result)) goto done;
1655
1656         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1657         if (!NT_STATUS_IS_OK(result)) goto done;
1658
1659         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1660         if (!NT_STATUS_IS_OK(result)) goto done;
1661
1662  done:
1663         return result;
1664 }
1665
1666 /* Lookup sam names */
1667
1668 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
1669                                       TALLOC_CTX *mem_ctx,
1670                                       int argc, const char **argv) 
1671 {
1672         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1673         POLICY_HND connect_pol, domain_pol;
1674         uint32 flags = 0x000003e8; /* Unknown */
1675         uint32 num_rids, num_names, *name_types, *rids;
1676         const char **names;
1677         int i;
1678
1679         if (argc < 3) {
1680                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1681                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1682                 printf("or check on the builtin SID: S-1-5-32\n");
1683                 return NT_STATUS_OK;
1684         }
1685
1686         /* Get sam policy and domain handles */
1687
1688         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1689                                    &connect_pol);
1690
1691         if (!NT_STATUS_IS_OK(result))
1692                 goto done;
1693
1694         if (StrCaseCmp(argv[1], "domain")==0)
1695                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1696                                                 &connect_pol,
1697                                                 MAXIMUM_ALLOWED_ACCESS,
1698                                                 &domain_sid,
1699                                                 &domain_pol);
1700         else if (StrCaseCmp(argv[1], "builtin")==0)
1701                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1702                                                 &connect_pol,
1703                                                 MAXIMUM_ALLOWED_ACCESS,
1704                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1705                                                 &domain_pol);
1706         else
1707                 return NT_STATUS_OK;
1708
1709         if (!NT_STATUS_IS_OK(result))
1710                 goto done;
1711
1712         /* Look up names */
1713
1714         num_names = argc - 2;
1715
1716         if ((names = TALLOC_ARRAY(mem_ctx, const char *, num_names)) == NULL) {
1717                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1718                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1719                 result = NT_STATUS_NO_MEMORY;
1720                 goto done;
1721         }
1722
1723         for (i = 0; i < num_names; i++)
1724                 names[i] = argv[i + 2];
1725
1726         result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1727                                        flags, num_names, names,
1728                                        &num_rids, &rids, &name_types);
1729
1730         if (!NT_STATUS_IS_OK(result))
1731                 goto done;
1732
1733         /* Display results */
1734
1735         for (i = 0; i < num_names; i++)
1736                 printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
1737                        name_types[i]);
1738
1739         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1740         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1741  done:
1742         return result;
1743 }
1744
1745 /* Lookup sam rids */
1746
1747 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, 
1748                                      TALLOC_CTX *mem_ctx,
1749                                      int argc, const char **argv) 
1750 {
1751         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1752         POLICY_HND connect_pol, domain_pol;
1753         uint32 num_rids, num_names, *rids, *name_types;
1754         char **names;
1755         int i;
1756
1757         if (argc < 3) {
1758                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1759                 return NT_STATUS_OK;
1760         }
1761
1762         /* Get sam policy and domain handles */
1763
1764         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1765                                    &connect_pol);
1766
1767         if (!NT_STATUS_IS_OK(result))
1768                 goto done;
1769
1770         if (StrCaseCmp(argv[1], "domain")==0)
1771                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1772                                                 &connect_pol,
1773                                                 MAXIMUM_ALLOWED_ACCESS,
1774                                                 &domain_sid,
1775                                                 &domain_pol);
1776         else if (StrCaseCmp(argv[1], "builtin")==0)
1777                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1778                                                 &connect_pol,
1779                                                 MAXIMUM_ALLOWED_ACCESS,
1780                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1781                                                 &domain_pol);
1782         else
1783                 return NT_STATUS_OK;
1784
1785         if (!NT_STATUS_IS_OK(result))
1786                 goto done;
1787
1788         /* Look up rids */
1789
1790         num_rids = argc - 2;
1791
1792         if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1793                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1794                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1795                 result = NT_STATUS_NO_MEMORY;
1796                 goto done;
1797         }
1798
1799         for (i = 0; i < argc - 2; i++)
1800                 sscanf(argv[i + 2], "%i", &rids[i]);
1801
1802         result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
1803                                       &num_names, &names, &name_types);
1804
1805         if (!NT_STATUS_IS_OK(result) &&
1806             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1807                 goto done;
1808
1809         /* Display results */
1810
1811         for (i = 0; i < num_names; i++)
1812                 printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
1813
1814         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1815         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1816  done:
1817         return result;
1818 }
1819
1820 /* Delete domain group */
1821
1822 static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli, 
1823                                          TALLOC_CTX *mem_ctx,
1824                                          int argc, const char **argv) 
1825 {
1826         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1827         POLICY_HND connect_pol, domain_pol, group_pol;
1828         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1829
1830         if ((argc < 2) || (argc > 3)) {
1831                 printf("Usage: %s groupname\n", argv[0]);
1832                 return NT_STATUS_OK;
1833         }
1834         
1835         if (argc > 2)
1836                 sscanf(argv[2], "%x", &access_mask);
1837
1838         /* Get sam policy and domain handles */
1839
1840         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1841                                    &connect_pol);
1842
1843         if (!NT_STATUS_IS_OK(result))
1844                 goto done;
1845
1846         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1847                                         &connect_pol,
1848                                         MAXIMUM_ALLOWED_ACCESS,
1849                                         &domain_sid,
1850                                         &domain_pol);
1851
1852         if (!NT_STATUS_IS_OK(result))
1853                 goto done;
1854
1855         /* Get handle on group */
1856
1857         {
1858                 uint32 *group_rids, num_rids, *name_types;
1859                 uint32 flags = 0x000003e8; /* Unknown */
1860
1861                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1862                                                flags, 1, (const char **)&argv[1],
1863                                                &num_rids, &group_rids,
1864                                                &name_types);
1865
1866                 if (!NT_STATUS_IS_OK(result))
1867                         goto done;
1868
1869                 result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
1870                                                 access_mask,
1871                                                 group_rids[0], &group_pol);
1872
1873                 if (!NT_STATUS_IS_OK(result))
1874                         goto done;
1875         }
1876
1877         /* Delete group */
1878
1879         result = rpccli_samr_DeleteDomainGroup(cli, mem_ctx,
1880                                                &group_pol);
1881
1882         if (!NT_STATUS_IS_OK(result))
1883                 goto done;
1884
1885         /* Display results */
1886
1887         rpccli_samr_Close(cli, mem_ctx, &group_pol);
1888         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1889         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1890
1891  done:
1892         return result;
1893 }
1894
1895 /* Delete domain user */
1896
1897 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
1898                                          TALLOC_CTX *mem_ctx,
1899                                          int argc, const char **argv) 
1900 {
1901         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1902         POLICY_HND connect_pol, domain_pol, user_pol;
1903         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1904
1905         if ((argc < 2) || (argc > 3)) {
1906                 printf("Usage: %s username\n", argv[0]);
1907                 return NT_STATUS_OK;
1908         }
1909         
1910         if (argc > 2)
1911                 sscanf(argv[2], "%x", &access_mask);
1912
1913         /* Get sam policy and domain handles */
1914
1915         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1916                                    &connect_pol);
1917
1918         if (!NT_STATUS_IS_OK(result))
1919                 goto done;
1920
1921         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1922                                         &connect_pol,
1923                                         MAXIMUM_ALLOWED_ACCESS,
1924                                         &domain_sid,
1925                                         &domain_pol);
1926
1927         if (!NT_STATUS_IS_OK(result))
1928                 goto done;
1929
1930         /* Get handle on user */
1931
1932         {
1933                 uint32 *user_rids, num_rids, *name_types;
1934                 uint32 flags = 0x000003e8; /* Unknown */
1935
1936                 result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1937                                                flags, 1, (const char **)&argv[1],
1938                                                &num_rids, &user_rids,
1939                                                &name_types);
1940
1941                 if (!NT_STATUS_IS_OK(result))
1942                         goto done;
1943
1944                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
1945                                             access_mask,
1946                                             user_rids[0], &user_pol);
1947
1948                 if (!NT_STATUS_IS_OK(result))
1949                         goto done;
1950         }
1951
1952         /* Delete user */
1953
1954         result = rpccli_samr_DeleteUser(cli, mem_ctx,
1955                                         &user_pol);
1956
1957         if (!NT_STATUS_IS_OK(result))
1958                 goto done;
1959
1960         /* Display results */
1961
1962         rpccli_samr_Close(cli, mem_ctx, &user_pol);
1963         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1964         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1965
1966  done:
1967         return result;
1968 }
1969
1970 /**********************************************************************
1971  * Query user security object 
1972  */
1973 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, 
1974                                     TALLOC_CTX *mem_ctx,
1975                                     int argc, const char **argv) 
1976 {
1977         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
1978         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1979         uint32 sec_info = DACL_SECURITY_INFORMATION;
1980         fstring server;
1981         uint32 user_rid = 0;
1982         TALLOC_CTX *ctx = NULL;
1983         SEC_DESC_BUF *sec_desc_buf=NULL;
1984         bool domain = False;
1985
1986         ctx=talloc_init("cmd_samr_query_sec_obj");
1987         
1988         if ((argc < 1) || (argc > 3)) {
1989                 printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
1990                 printf("\tSpecify rid for security on user, -d for security on domain\n");
1991                 talloc_destroy(ctx);
1992                 return NT_STATUS_OK;
1993         }
1994         
1995         if (argc > 1) {
1996                 if (strcmp(argv[1], "-d") == 0)
1997                         domain = True;
1998                 else
1999                         sscanf(argv[1], "%i", &user_rid);
2000         }
2001
2002         if (argc == 3) {
2003                 sec_info = atoi(argv[2]);
2004         }
2005         
2006         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
2007         strupper_m(server);
2008         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2009                                    &connect_pol);
2010
2011         if (!NT_STATUS_IS_OK(result))
2012                 goto done;
2013
2014         if (domain || user_rid)
2015                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
2016                                                 &connect_pol,
2017                                                 MAXIMUM_ALLOWED_ACCESS,
2018                                                 &domain_sid,
2019                                                 &domain_pol);
2020
2021         if (!NT_STATUS_IS_OK(result))
2022                 goto done;
2023
2024         if (user_rid)
2025                 result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
2026                                             MAXIMUM_ALLOWED_ACCESS,
2027                                             user_rid, &user_pol);
2028
2029         if (!NT_STATUS_IS_OK(result))
2030                 goto done;
2031
2032         /* Pick which query pol to use */
2033
2034         pol = &connect_pol;
2035
2036         if (domain)
2037                 pol = &domain_pol;
2038
2039         if (user_rid)
2040                 pol = &user_pol;
2041
2042         /* Query SAM security object */
2043
2044         result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, sec_info, ctx, 
2045                                         &sec_desc_buf);
2046
2047         if (!NT_STATUS_IS_OK(result))
2048                 goto done;
2049
2050         display_sec_desc(sec_desc_buf->sd);
2051
2052         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2053         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2054         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2055 done:
2056         talloc_destroy(ctx);
2057         return result;
2058 }
2059
2060 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli, 
2061                                            TALLOC_CTX *mem_ctx,
2062                                            int argc, const char **argv) 
2063 {
2064         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2065         POLICY_HND connect_pol, domain_pol, user_pol;
2066         struct samr_PwInfo info;
2067         uint32_t rid;
2068
2069         if (argc != 2) {
2070                 printf("Usage: %s rid\n", argv[0]);
2071                 return NT_STATUS_OK;
2072         }
2073
2074         sscanf(argv[1], "%i", &rid);
2075
2076         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2077                                    &connect_pol);
2078
2079         if (!NT_STATUS_IS_OK(result)) {
2080                 goto done;
2081         }
2082
2083         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2084                                         &connect_pol,
2085                                         MAXIMUM_ALLOWED_ACCESS,
2086                                         &domain_sid,
2087                                         &domain_pol);
2088
2089         if (!NT_STATUS_IS_OK(result)) {
2090                 goto done;
2091         }
2092
2093         result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
2094                                        MAXIMUM_ALLOWED_ACCESS,
2095                                        rid, &user_pol);
2096
2097         if (!NT_STATUS_IS_OK(result)) {
2098                 goto done;
2099         }
2100
2101         result = rpccli_samr_GetUserPwInfo(cli, mem_ctx, &user_pol, &info);
2102         if (NT_STATUS_IS_OK(result)) {
2103                 printf("min_password_length: %d\n", info.min_password_length);
2104                 printf("%s\n",
2105                         NDR_PRINT_STRUCT_STRING(mem_ctx,
2106                                 samr_PasswordProperties, &info.password_properties));
2107         }
2108
2109  done:
2110         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2111         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2112         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2113
2114         return result;
2115 }
2116
2117 static void init_lsa_String(struct lsa_String *name, const char *s)
2118 {
2119         name->string = s;
2120 }
2121
2122 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
2123                                         TALLOC_CTX *mem_ctx,
2124                                         int argc, const char **argv)
2125 {
2126         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2127         struct lsa_String domain_name;
2128         struct samr_PwInfo info;
2129
2130         if (argc < 1 || argc > 3) {
2131                 printf("Usage: %s <domain>\n", argv[0]);
2132                 return NT_STATUS_OK;
2133         }
2134
2135         init_lsa_String(&domain_name, argv[1]);
2136
2137         result = rpccli_samr_GetDomPwInfo(cli, mem_ctx, &domain_name, &info);
2138
2139         if (NT_STATUS_IS_OK(result)) {
2140                 printf("min_password_length: %d\n", info.min_password_length);
2141                 display_password_properties(info.password_properties);
2142         }
2143
2144         return result;
2145 }
2146
2147 /* Look up domain name */
2148
2149 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, 
2150                                        TALLOC_CTX *mem_ctx,
2151                                        int argc, const char **argv) 
2152 {
2153         POLICY_HND connect_pol, domain_pol;
2154         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2155         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2156         fstring domain_name,sid_string;
2157         DOM_SID sid;
2158         
2159         if (argc != 2) {
2160                 printf("Usage: %s domain_name\n", argv[0]);
2161                 return NT_STATUS_OK;
2162         }
2163         
2164         sscanf(argv[1], "%s", domain_name);
2165         
2166         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
2167         
2168         if (!NT_STATUS_IS_OK(result))
2169                 goto done;
2170
2171         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2172                                         &connect_pol,
2173                                         access_mask,
2174                                         &domain_sid,
2175                                         &domain_pol);
2176
2177         if (!NT_STATUS_IS_OK(result))
2178                 goto done;
2179         
2180         result = rpccli_samr_lookup_domain(
2181                 cli, mem_ctx, &connect_pol, domain_name, &sid);
2182
2183         if (NT_STATUS_IS_OK(result)) {
2184                 sid_to_fstring(sid_string,&sid);
2185                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
2186                        domain_name,sid_string);
2187         }
2188
2189         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2190         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2191 done:
2192         return result;
2193 }
2194
2195 /* Change user password */
2196
2197 static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli, 
2198                                     TALLOC_CTX *mem_ctx,
2199                                     int argc, const char **argv) 
2200 {
2201         POLICY_HND connect_pol, domain_pol;
2202         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2203         const char *user, *oldpass, *newpass;
2204         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2205
2206         if (argc < 3) {
2207                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2208                 return NT_STATUS_INVALID_PARAMETER;
2209         }
2210
2211         user = argv[1];
2212         oldpass = argv[2];
2213         newpass = argv[3];
2214         
2215         /* Get sam policy handle */
2216
2217         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2218                                    &connect_pol);
2219
2220         if (!NT_STATUS_IS_OK(result))
2221                 goto done;
2222
2223         /* Get domain policy handle */
2224
2225         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2226                                         &connect_pol,
2227                                         access_mask,
2228                                         &domain_sid,
2229                                         &domain_pol);
2230
2231         if (!NT_STATUS_IS_OK(result))
2232                 goto done;
2233
2234         /* Change user password */
2235         result = rpccli_samr_chgpasswd_user(cli, mem_ctx, user, newpass, oldpass);
2236
2237         if (!NT_STATUS_IS_OK(result))
2238                 goto done;
2239
2240         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2241         if (!NT_STATUS_IS_OK(result)) goto done;
2242
2243         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2244         if (!NT_STATUS_IS_OK(result)) goto done;
2245
2246  done:
2247         return result;
2248 }
2249
2250
2251 /* Change user password */
2252
2253 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli, 
2254                                     TALLOC_CTX *mem_ctx,
2255                                     int argc, const char **argv) 
2256 {
2257         POLICY_HND connect_pol, domain_pol;
2258         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2259         const char *user, *oldpass, *newpass;
2260         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2261         SAM_UNK_INFO_1 info;
2262         SAMR_CHANGE_REJECT reject;
2263
2264         if (argc < 3) {
2265                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2266                 return NT_STATUS_INVALID_PARAMETER;
2267         }
2268
2269         user = argv[1];
2270         oldpass = argv[2];
2271         newpass = argv[3];
2272         
2273         /* Get sam policy handle */
2274
2275         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2276                                    &connect_pol);
2277
2278         if (!NT_STATUS_IS_OK(result))
2279                 goto done;
2280
2281         /* Get domain policy handle */
2282
2283         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2284                                         &connect_pol,
2285                                         access_mask,
2286                                         &domain_sid,
2287                                         &domain_pol);
2288
2289         if (!NT_STATUS_IS_OK(result))
2290                 goto done;
2291
2292         /* Change user password */
2293         result = rpccli_samr_chgpasswd3(cli, mem_ctx, user, newpass, oldpass, &info, &reject);
2294
2295         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2296         
2297                 display_sam_unk_info_1(&info);
2298
2299                 switch (reject.reject_reason) {
2300                         case SAMR_REJECT_TOO_SHORT:
2301                                 d_printf("SAMR_REJECT_TOO_SHORT\n");
2302                                 break;
2303                         case SAMR_REJECT_IN_HISTORY:
2304                                 d_printf("SAMR_REJECT_IN_HISTORY\n");
2305                                 break;
2306                         case SAMR_REJECT_COMPLEXITY:
2307                                 d_printf("SAMR_REJECT_COMPLEXITY\n");
2308                                 break;
2309                         case SAMR_REJECT_OTHER:
2310                                 d_printf("SAMR_REJECT_OTHER\n");
2311                                 break;
2312                         default:
2313                                 d_printf("unknown reject reason: %d\n", reject.reject_reason);
2314                                 break;
2315                 }
2316         }
2317
2318         if (!NT_STATUS_IS_OK(result))
2319                 goto done;
2320
2321         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2322         if (!NT_STATUS_IS_OK(result)) goto done;
2323
2324         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2325         if (!NT_STATUS_IS_OK(result)) goto done;
2326
2327  done:
2328         return result;
2329 }
2330
2331 /* List of commands exported by this module */
2332
2333 struct cmd_set samr_commands[] = {
2334
2335         { "SAMR" },
2336
2337         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
2338         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
2339         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
2340         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
2341         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
2342         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
2343         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
2344         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
2345         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
2346         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
2347         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
2348         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
2349
2350         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
2351         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
2352         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
2353         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
2354         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
2355         { "deletedomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group,      NULL, PI_SAMR, NULL,        "Delete domain group",     "" },
2356         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
2357         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
2358         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
2359         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
2360
2361         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
2362         { "chgpasswd2",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2,            NULL, PI_SAMR, NULL, "Change user password", "" },
2363         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
2364         { NULL }
2365 };