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