Use rpccli_samr_EnumDomainGroups in rpcclient.
[vlendec/samba-autobuild/.git] / source3 / rpcclient / cmd_samr.c
1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Andrew Tridgell              1992-2000,
6    Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7    Copyright (C) Elrond                            2000,
8    Copyright (C) Tim Potter                        2000
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpcclient.h"
26
27 extern DOM_SID domain_sid;
28
29 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(struct samr_DispEntryGeneral *r)
245 {
246         printf("index: 0x%x ", r->idx);
247         printf("RID: 0x%x ", r->rid);
248         printf("acb: 0x%08x ", r->acct_flags);
249         printf("Account: %s\t", r->account_name.string);
250         printf("Name: %s\t", r->full_name.string);
251         printf("Desc: %s\n", r->description.string);
252 }
253
254 static void display_sam_info_2(struct samr_DispEntryFull *r)
255 {
256         printf("index: 0x%x ", r->idx);
257         printf("RID: 0x%x ", r->rid);
258         printf("acb: 0x%08x ", r->acct_flags);
259         printf("Account: %s\t", r->account_name.string);
260         printf("Desc: %s\n", r->description.string);
261 }
262
263 static void display_sam_info_3(struct samr_DispEntryFullGroup *r)
264 {
265         printf("index: 0x%x ", r->idx);
266         printf("RID: 0x%x ", r->rid);
267         printf("acb: 0x%08x ", r->acct_flags);
268         printf("Account: %s\t", r->account_name.string);
269         printf("Desc: %s\n", r->description.string);
270 }
271
272 static void display_sam_info_4(struct samr_DispEntryAscii *r)
273 {
274         printf("index: 0x%x ", r->idx);
275         printf("Account: %s\n", r->account_name.string);
276 }
277
278 static void display_sam_info_5(struct samr_DispEntryAscii *r)
279 {
280         printf("index: 0x%x ", r->idx);
281         printf("Account: %s\n", r->account_name.string);
282 }
283
284 /****************************************************************************
285  Try samr_connect4 first, then samr_connect2 if it fails
286  ****************************************************************************/
287 static NTSTATUS try_samr_connects(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
288                                   uint32 access_mask, POLICY_HND *connect_pol)
289 {
290         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
291
292         result = rpccli_samr_Connect4(cli, mem_ctx,
293                                       cli->cli->desthost,
294                                       SAMR_CONNECT_W2K,
295                                       access_mask,
296                                       connect_pol);
297         if (!NT_STATUS_IS_OK(result)) {
298                 result = rpccli_samr_Connect2(cli, mem_ctx,
299                                               cli->cli->desthost,
300                                               access_mask,
301                                               connect_pol);
302         }
303         return result;
304 }
305
306 /**********************************************************************
307  * Query user information
308  */
309 static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli,
310                                     TALLOC_CTX *mem_ctx,
311                                     int argc, const char **argv)
312 {
313         POLICY_HND connect_pol, domain_pol, user_pol;
314         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
315         uint32 info_level = 21;
316         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
317         SAM_USERINFO_CTR *user_ctr;
318         fstring server;
319         uint32 user_rid = 0;
320
321         if ((argc < 2) || (argc > 4)) {
322                 printf("Usage: %s rid [info level] [access mask] \n", argv[0]);
323                 return NT_STATUS_OK;
324         }
325
326         sscanf(argv[1], "%i", &user_rid);
327
328         if (argc > 2)
329                 sscanf(argv[2], "%i", &info_level);
330
331         if (argc > 3)
332                 sscanf(argv[3], "%x", &access_mask);
333
334
335         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
336         strupper_m(server);
337
338         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
339                                    &connect_pol);
340
341         if (!NT_STATUS_IS_OK(result))
342                 goto done;
343
344         result = rpccli_samr_OpenDomain(cli, mem_ctx,
345                                         &connect_pol,
346                                         MAXIMUM_ALLOWED_ACCESS,
347                                         &domain_sid,
348                                         &domain_pol);
349         if (!NT_STATUS_IS_OK(result))
350                 goto done;
351
352         result = rpccli_samr_OpenUser(cli, mem_ctx,
353                                       &domain_pol,
354                                       access_mask,
355                                       user_rid,
356                                       &user_pol);
357
358         if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) &&
359             (user_rid == 0)) {
360
361                 /* Probably this was a user name, try lookupnames */
362                 struct samr_Ids rids, types;
363                 struct lsa_String lsa_acct_name;
364
365                 init_lsa_String(&lsa_acct_name, argv[1]);
366
367                 result = rpccli_samr_LookupNames(cli, mem_ctx,
368                                                  &domain_pol,
369                                                  1,
370                                                  &lsa_acct_name,
371                                                  &rids,
372                                                  &types);
373
374                 if (NT_STATUS_IS_OK(result)) {
375                         result = rpccli_samr_OpenUser(cli, mem_ctx,
376                                                       &domain_pol,
377                                                       access_mask,
378                                                       rids.ids[0],
379                                                       &user_pol);
380                 }
381         }
382
383
384         if (!NT_STATUS_IS_OK(result))
385                 goto done;
386
387         ZERO_STRUCT(user_ctr);
388
389         result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
390                                          info_level, &user_ctr);
391
392         if (!NT_STATUS_IS_OK(result))
393                 goto done;
394
395         switch (user_ctr->switch_value) {
396         case 7:
397                 display_sam_user_info_7(user_ctr->info.id7);
398                 break;
399         case 9:
400                 display_sam_user_info_9(user_ctr->info.id9);
401                 break;
402         case 16:
403                 display_sam_user_info_16(user_ctr->info.id16);
404                 break;
405         case 21:
406                 display_sam_user_info_21(user_ctr->info.id21);
407                 break;
408         default:
409                 printf("Unsupported infolevel: %d\n", info_level);
410                 break;
411         }
412
413         rpccli_samr_Close(cli, mem_ctx, &user_pol);
414         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
415         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
416
417 done:
418         return result;
419 }
420
421 /****************************************************************************
422  display group info
423  ****************************************************************************/
424 static void display_group_info1(struct samr_GroupInfoAll *info1)
425 {
426         printf("\tGroup Name:\t%s\n", info1->name.string);
427         printf("\tDescription:\t%s\n", info1->description.string);
428         printf("\tGroup Attribute:%d\n", info1->attributes);
429         printf("\tNum Members:%d\n", info1->num_members);
430 }
431
432 /****************************************************************************
433  display group info
434  ****************************************************************************/
435 static void display_group_info2(struct lsa_String *info2)
436 {
437         printf("\tGroup Description:%s\n", info2->string);
438 }
439
440
441 /****************************************************************************
442  display group info
443  ****************************************************************************/
444 static void display_group_info3(struct samr_GroupInfoAttributes *info3)
445 {
446         printf("\tGroup Attribute:%d\n", info3->attributes);
447 }
448
449
450 /****************************************************************************
451  display group info
452  ****************************************************************************/
453 static void display_group_info4(struct lsa_String *info4)
454 {
455         printf("\tGroup Description:%s\n", info4->string);
456 }
457
458 /****************************************************************************
459  display group info
460  ****************************************************************************/
461 static void display_group_info5(struct samr_GroupInfoAll *info5)
462 {
463         printf("\tGroup Name:\t%s\n", info5->name.string);
464         printf("\tDescription:\t%s\n", info5->description.string);
465         printf("\tGroup Attribute:%d\n", info5->attributes);
466         printf("\tNum Members:%d\n", info5->num_members);
467 }
468
469 /****************************************************************************
470  display sam sync structure
471  ****************************************************************************/
472 static void display_group_info(union samr_GroupInfo *info,
473                                enum samr_GroupInfoEnum level)
474 {
475         switch (level) {
476                 case 1:
477                         display_group_info1(&info->all);
478                         break;
479                 case 2:
480                         display_group_info2(&info->name);
481                         break;
482                 case 3:
483                         display_group_info3(&info->attributes);
484                         break;
485                 case 4:
486                         display_group_info4(&info->description);
487                         break;
488                 case 5:
489                         display_group_info5(&info->all2);
490                         break;
491         }
492 }
493
494 /***********************************************************************
495  * Query group information
496  */
497 static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli,
498                                      TALLOC_CTX *mem_ctx,
499                                      int argc, const char **argv)
500 {
501         POLICY_HND connect_pol, domain_pol, group_pol;
502         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
503         enum samr_GroupInfoEnum info_level = GROUPINFOALL;
504         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
505         union samr_GroupInfo *group_info = NULL;
506         fstring                 server;
507         uint32 group_rid;
508
509         if ((argc < 2) || (argc > 4)) {
510                 printf("Usage: %s rid [info level] [access mask]\n", argv[0]);
511                 return NT_STATUS_OK;
512         }
513
514         sscanf(argv[1], "%i", &group_rid);
515
516         if (argc > 2)
517                 info_level = atoi(argv[2]);
518
519         if (argc > 3)
520                 sscanf(argv[3], "%x", &access_mask);
521
522         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
523         strupper_m(server);
524
525         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
526                                    &connect_pol);
527
528         if (!NT_STATUS_IS_OK(result))
529                 goto done;
530
531         result = rpccli_samr_OpenDomain(cli, mem_ctx,
532                                         &connect_pol,
533                                         MAXIMUM_ALLOWED_ACCESS,
534                                         &domain_sid,
535                                         &domain_pol);
536
537         if (!NT_STATUS_IS_OK(result))
538                 goto done;
539
540         result = rpccli_samr_OpenGroup(cli, mem_ctx,
541                                        &domain_pol,
542                                        access_mask,
543                                        group_rid,
544                                        &group_pol);
545
546         if (!NT_STATUS_IS_OK(result))
547                 goto done;
548
549         result = rpccli_samr_QueryGroupInfo(cli, mem_ctx,
550                                             &group_pol,
551                                             info_level,
552                                             &group_info);
553         if (!NT_STATUS_IS_OK(result)) {
554                 goto done;
555         }
556
557         display_group_info(group_info, info_level);
558
559         rpccli_samr_Close(cli, mem_ctx, &group_pol);
560         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
561         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
562 done:
563         return result;
564 }
565
566 /* Query groups a user is a member of */
567
568 static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli,
569                                           TALLOC_CTX *mem_ctx,
570                                           int argc, const char **argv)
571 {
572         POLICY_HND              connect_pol,
573                                 domain_pol,
574                                 user_pol;
575         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
576         uint32                  user_rid;
577         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
578         int                     i;
579         fstring                 server;
580         struct samr_RidWithAttributeArray *rid_array = NULL;
581
582         if ((argc < 2) || (argc > 3)) {
583                 printf("Usage: %s rid [access mask]\n", argv[0]);
584                 return NT_STATUS_OK;
585         }
586
587         sscanf(argv[1], "%i", &user_rid);
588
589         if (argc > 2)
590                 sscanf(argv[2], "%x", &access_mask);
591
592         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
593         strupper_m(server);
594
595         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
596                                    &connect_pol);
597
598         if (!NT_STATUS_IS_OK(result))
599                 goto done;
600
601         result = rpccli_samr_OpenDomain(cli, mem_ctx,
602                                         &connect_pol,
603                                         MAXIMUM_ALLOWED_ACCESS,
604                                         &domain_sid, &domain_pol);
605
606         if (!NT_STATUS_IS_OK(result))
607                 goto done;
608
609         result = rpccli_samr_OpenUser(cli, mem_ctx,
610                                       &domain_pol,
611                                       access_mask,
612                                       user_rid,
613                                       &user_pol);
614
615         if (!NT_STATUS_IS_OK(result))
616                 goto done;
617
618         result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
619                                               &user_pol,
620                                               &rid_array);
621
622         if (!NT_STATUS_IS_OK(result))
623                 goto done;
624
625         for (i = 0; i < rid_array->count; i++) {
626                 printf("\tgroup rid:[0x%x] attr:[0x%x]\n",
627                        rid_array->rids[i].rid,
628                        rid_array->rids[i].attributes);
629         }
630
631         rpccli_samr_Close(cli, mem_ctx, &user_pol);
632         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
633         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
634  done:
635         return result;
636 }
637
638 /* Query aliases a user is a member of */
639
640 static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli,
641                                            TALLOC_CTX *mem_ctx,
642                                            int argc, const char **argv)
643 {
644         POLICY_HND              connect_pol, domain_pol;
645         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
646         DOM_SID                *sids;
647         size_t                     num_sids;
648         uint32                  access_mask = MAXIMUM_ALLOWED_ACCESS;
649         int                     i;
650         fstring                 server;
651         struct lsa_SidArray sid_array;
652         struct samr_Ids alias_rids;
653
654         if (argc < 3) {
655                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
656                 return NT_STATUS_INVALID_PARAMETER;
657         }
658
659         sids = NULL;
660         num_sids = 0;
661
662         for (i=2; i<argc; i++) {
663                 DOM_SID tmp_sid;
664                 if (!string_to_sid(&tmp_sid, argv[i])) {
665                         printf("%s is not a legal SID\n", argv[i]);
666                         return NT_STATUS_INVALID_PARAMETER;
667                 }
668                 result = add_sid_to_array(mem_ctx, &tmp_sid, &sids, &num_sids);
669                 if (!NT_STATUS_IS_OK(result)) {
670                         return result;
671                 }
672         }
673
674         if (num_sids) {
675                 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_sids);
676                 if (sid_array.sids == NULL)
677                         return NT_STATUS_NO_MEMORY;
678         } else {
679                 sid_array.sids = NULL;
680         }
681
682         for (i=0; i<num_sids; i++) {
683                 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[i]);
684                 if (!sid_array.sids[i].sid) {
685                         return NT_STATUS_NO_MEMORY;
686                 }
687         }
688
689         sid_array.num_sids = num_sids;
690
691         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
692         strupper_m(server);
693
694         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
695                                    &connect_pol);
696
697         if (!NT_STATUS_IS_OK(result))
698                 goto done;
699
700         if (StrCaseCmp(argv[1], "domain")==0)
701                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
702                                                 &connect_pol,
703                                                 access_mask,
704                                                 &domain_sid, &domain_pol);
705         else if (StrCaseCmp(argv[1], "builtin")==0)
706                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
707                                                 &connect_pol,
708                                                 access_mask,
709                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
710                                                 &domain_pol);
711         else {
712                 printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]);
713                 return NT_STATUS_INVALID_PARAMETER;
714         }
715
716         if (!NT_STATUS_IS_OK(result))
717                 goto done;
718
719         result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
720                                                 &domain_pol,
721                                                 &sid_array,
722                                                 &alias_rids);
723         if (!NT_STATUS_IS_OK(result))
724                 goto done;
725
726         for (i = 0; i < alias_rids.count; i++) {
727                 printf("\tgroup rid:[0x%x]\n", alias_rids.ids[i]);
728         }
729
730         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
731         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
732  done:
733         return result;
734 }
735
736 /* Query members of a group */
737
738 static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli,
739                                         TALLOC_CTX *mem_ctx,
740                                         int argc, const char **argv)
741 {
742         POLICY_HND connect_pol, domain_pol, group_pol;
743         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
744         uint32 group_rid;
745         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
746         int i;
747         fstring                 server;
748         unsigned int old_timeout;
749         struct samr_RidTypeArray *rids = NULL;
750
751         if ((argc < 2) || (argc > 3)) {
752                 printf("Usage: %s rid [access mask]\n", argv[0]);
753                 return NT_STATUS_OK;
754         }
755
756         sscanf(argv[1], "%i", &group_rid);
757
758         if (argc > 2)
759                 sscanf(argv[2], "%x", &access_mask);
760
761         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
762         strupper_m(server);
763
764         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
765                                    &connect_pol);
766
767         if (!NT_STATUS_IS_OK(result))
768                 goto done;
769
770         result = rpccli_samr_OpenDomain(cli, mem_ctx,
771                                         &connect_pol,
772                                         MAXIMUM_ALLOWED_ACCESS,
773                                         &domain_sid,
774                                         &domain_pol);
775
776         if (!NT_STATUS_IS_OK(result))
777                 goto done;
778
779         result = rpccli_samr_OpenGroup(cli, mem_ctx,
780                                        &domain_pol,
781                                        access_mask,
782                                        group_rid,
783                                        &group_pol);
784
785         if (!NT_STATUS_IS_OK(result))
786                 goto done;
787
788         /* Make sure to wait for our DC's reply */
789         old_timeout = cli_set_timeout(cli->cli, MAX(cli->cli->timeout,30000)); /* 30 seconds. */
790
791         result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
792                                               &group_pol,
793                                               &rids);
794
795         cli_set_timeout(cli->cli, old_timeout);
796
797         if (!NT_STATUS_IS_OK(result))
798                 goto done;
799
800         for (i = 0; i < rids->count; i++) {
801                 printf("\trid:[0x%x] attr:[0x%x]\n", rids->rids[i],
802                        rids->types[i]);
803         }
804
805         rpccli_samr_Close(cli, mem_ctx, &group_pol);
806         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
807         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
808  done:
809         return result;
810 }
811
812 /* Enumerate domain users */
813
814 static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
815                                         TALLOC_CTX *mem_ctx,
816                                         int argc, const char **argv)
817 {
818         POLICY_HND connect_pol, domain_pol;
819         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
820         uint32 start_idx, size, num_dom_users, i;
821         char **dom_users;
822         uint32 *dom_rids;
823         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
824         uint32 acb_mask = ACB_NORMAL;
825         bool got_connect_pol = False, got_domain_pol = False;
826
827         if ((argc < 1) || (argc > 3)) {
828                 printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
829                 return NT_STATUS_OK;
830         }
831
832         if (argc > 1)
833                 sscanf(argv[1], "%x", &access_mask);
834
835         if (argc > 2)
836                 sscanf(argv[2], "%x", &acb_mask);
837
838         /* Get sam policy handle */
839
840         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
841                                    &connect_pol);
842
843         if (!NT_STATUS_IS_OK(result))
844                 goto done;
845
846         got_connect_pol = True;
847
848         /* Get domain policy handle */
849
850         result = rpccli_samr_OpenDomain(cli, mem_ctx,
851                                         &connect_pol,
852                                         access_mask,
853                                         &domain_sid,
854                                         &domain_pol);
855
856         if (!NT_STATUS_IS_OK(result))
857                 goto done;
858
859         got_domain_pol = True;
860
861         /* Enumerate domain users */
862
863         start_idx = 0;
864         size = 0xffff;
865
866         do {
867                 result = rpccli_samr_enum_dom_users(
868                         cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
869                         size, &dom_users, &dom_rids, &num_dom_users);
870
871                 if (NT_STATUS_IS_OK(result) ||
872                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
873
874                         for (i = 0; i < num_dom_users; i++)
875                                printf("user:[%s] rid:[0x%x]\n",
876                                        dom_users[i], dom_rids[i]);
877                 }
878
879         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
880
881  done:
882         if (got_domain_pol)
883                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
884
885         if (got_connect_pol)
886                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
887
888         return result;
889 }
890
891 /* Enumerate domain groups */
892
893 static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli,
894                                          TALLOC_CTX *mem_ctx,
895                                          int argc, const char **argv)
896 {
897         POLICY_HND connect_pol, domain_pol;
898         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
899         uint32 start_idx, size, num_dom_groups, i;
900         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
901         struct samr_SamArray *dom_groups = NULL;
902         bool got_connect_pol = False, got_domain_pol = False;
903
904         if ((argc < 1) || (argc > 2)) {
905                 printf("Usage: %s [access_mask]\n", argv[0]);
906                 return NT_STATUS_OK;
907         }
908
909         if (argc > 1)
910                 sscanf(argv[1], "%x", &access_mask);
911
912         /* Get sam policy handle */
913
914         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
915                                    &connect_pol);
916
917         if (!NT_STATUS_IS_OK(result))
918                 goto done;
919
920         got_connect_pol = True;
921
922         /* Get domain policy handle */
923
924         result = rpccli_samr_OpenDomain(cli, mem_ctx,
925                                         &connect_pol,
926                                         access_mask,
927                                         &domain_sid,
928                                         &domain_pol);
929
930         if (!NT_STATUS_IS_OK(result))
931                 goto done;
932
933         got_domain_pol = True;
934
935         /* Enumerate domain groups */
936
937         start_idx = 0;
938         size = 0xffff;
939
940         do {
941                 result = rpccli_samr_EnumDomainGroups(cli, mem_ctx,
942                                                       &domain_pol,
943                                                       &start_idx,
944                                                       &dom_groups,
945                                                       size,
946                                                       &num_dom_groups);
947                 if (NT_STATUS_IS_OK(result) ||
948                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
949
950                         for (i = 0; i < num_dom_groups; i++)
951                                 printf("group:[%s] rid:[0x%x]\n",
952                                        dom_groups->entries[i].name.string,
953                                        dom_groups->entries[i].idx);
954                 }
955
956         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
957
958  done:
959         if (got_domain_pol)
960                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
961
962         if (got_connect_pol)
963                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
964
965         return result;
966 }
967
968 /* Enumerate alias groups */
969
970 static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
971                                          TALLOC_CTX *mem_ctx,
972                                          int argc, const char **argv)
973 {
974         POLICY_HND connect_pol, domain_pol;
975         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
976         uint32 start_idx, size, num_als_groups, i;
977         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
978         struct samr_SamArray *als_groups = NULL;
979         bool got_connect_pol = False, got_domain_pol = False;
980
981         if ((argc < 2) || (argc > 3)) {
982                 printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
983                 return NT_STATUS_OK;
984         }
985
986         if (argc > 2)
987                 sscanf(argv[2], "%x", &access_mask);
988
989         /* Get sam policy handle */
990
991         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
992                                    &connect_pol);
993
994         if (!NT_STATUS_IS_OK(result))
995                 goto done;
996
997         got_connect_pol = True;
998
999         /* Get domain policy handle */
1000
1001         if (StrCaseCmp(argv[1], "domain")==0)
1002                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1003                                                 &connect_pol,
1004                                                 access_mask,
1005                                                 &domain_sid,
1006                                                 &domain_pol);
1007         else if (StrCaseCmp(argv[1], "builtin")==0)
1008                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1009                                                 &connect_pol,
1010                                                 access_mask,
1011                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1012                                                 &domain_pol);
1013         else
1014                 return NT_STATUS_OK;
1015
1016         if (!NT_STATUS_IS_OK(result))
1017                 goto done;
1018
1019         got_domain_pol = True;
1020
1021         /* Enumerate alias groups */
1022
1023         start_idx = 0;
1024         size = 0xffff;          /* Number of groups to retrieve */
1025
1026         do {
1027                 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx,
1028                                                        &domain_pol,
1029                                                        &start_idx,
1030                                                        &als_groups,
1031                                                        size,
1032                                                        &num_als_groups);
1033
1034                 if (NT_STATUS_IS_OK(result) ||
1035                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1036
1037                         for (i = 0; i < num_als_groups; i++)
1038                                 printf("group:[%s] rid:[0x%x]\n",
1039                                        als_groups->entries[i].name.string,
1040                                        als_groups->entries[i].idx);
1041                 }
1042         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1043
1044  done:
1045         if (got_domain_pol)
1046                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1047
1048         if (got_connect_pol)
1049                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1050
1051         return result;
1052 }
1053
1054 /* Enumerate domains */
1055
1056 static NTSTATUS cmd_samr_enum_domains(struct rpc_pipe_client *cli,
1057                                       TALLOC_CTX *mem_ctx,
1058                                       int argc, const char **argv)
1059 {
1060         POLICY_HND connect_pol;
1061         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1062         uint32 start_idx, size, num_entries, i;
1063         uint32 access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1064         bool got_connect_pol = false;
1065         struct samr_SamArray *sam = NULL;
1066
1067         if ((argc < 1) || (argc > 2)) {
1068                 printf("Usage: %s [access mask]\n", argv[0]);
1069                 return NT_STATUS_OK;
1070         }
1071
1072         if (argc > 2) {
1073                 sscanf(argv[2], "%x", &access_mask);
1074         }
1075
1076         /* Get sam policy handle */
1077
1078         result = try_samr_connects(cli, mem_ctx,
1079                                    access_mask,
1080                                    &connect_pol);
1081
1082         if (!NT_STATUS_IS_OK(result)) {
1083                 goto done;
1084         }
1085
1086         got_connect_pol = true;
1087
1088         /* Enumerate alias groups */
1089
1090         start_idx = 0;
1091         size = 0xffff;
1092
1093         do {
1094                 result = rpccli_samr_EnumDomains(cli, mem_ctx,
1095                                                  &connect_pol,
1096                                                  &start_idx,
1097                                                  &sam,
1098                                                  size,
1099                                                  &num_entries);
1100
1101                 if (NT_STATUS_IS_OK(result) ||
1102                     NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1103
1104                         for (i = 0; i < num_entries; i++)
1105                                 printf("name:[%s] idx:[0x%x]\n",
1106                                        sam->entries[i].name.string,
1107                                        sam->entries[i].idx);
1108                 }
1109         } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
1110
1111  done:
1112         if (got_connect_pol) {
1113                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1114         }
1115
1116         return result;
1117 }
1118
1119
1120 /* Query alias membership */
1121
1122 static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli,
1123                                         TALLOC_CTX *mem_ctx,
1124                                         int argc, const char **argv)
1125 {
1126         POLICY_HND connect_pol, domain_pol, alias_pol;
1127         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1128         uint32 alias_rid, i;
1129         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1130         struct lsa_SidArray sid_array;
1131
1132         if ((argc < 3) || (argc > 4)) {
1133                 printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]);
1134                 return NT_STATUS_OK;
1135         }
1136
1137         sscanf(argv[2], "%i", &alias_rid);
1138
1139         if (argc > 3)
1140                 sscanf(argv[3], "%x", &access_mask);
1141
1142         /* Open SAMR handle */
1143
1144         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1145                                    &connect_pol);
1146
1147         if (!NT_STATUS_IS_OK(result))
1148                 goto done;
1149
1150         /* Open handle on domain */
1151
1152         if (StrCaseCmp(argv[1], "domain")==0)
1153                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1154                                                 &connect_pol,
1155                                                 MAXIMUM_ALLOWED_ACCESS,
1156                                                 &domain_sid,
1157                                                 &domain_pol);
1158         else if (StrCaseCmp(argv[1], "builtin")==0)
1159                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1160                                                 &connect_pol,
1161                                                 MAXIMUM_ALLOWED_ACCESS,
1162                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1163                                                 &domain_pol);
1164         else
1165                 return NT_STATUS_OK;
1166
1167         if (!NT_STATUS_IS_OK(result))
1168                 goto done;
1169
1170         /* Open handle on alias */
1171
1172         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1173                                        &domain_pol,
1174                                        access_mask,
1175                                        alias_rid,
1176                                        &alias_pol);
1177         if (!NT_STATUS_IS_OK(result))
1178                 goto done;
1179
1180         result = rpccli_samr_GetMembersInAlias(cli, mem_ctx,
1181                                                &alias_pol,
1182                                                &sid_array);
1183
1184         if (!NT_STATUS_IS_OK(result))
1185                 goto done;
1186
1187         for (i = 0; i < sid_array.num_sids; i++) {
1188                 fstring sid_str;
1189
1190                 sid_to_fstring(sid_str, sid_array.sids[i].sid);
1191                 printf("\tsid:[%s]\n", sid_str);
1192         }
1193
1194         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1195         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1196         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1197  done:
1198         return result;
1199 }
1200
1201 /* Query alias info */
1202
1203 static NTSTATUS cmd_samr_query_aliasinfo(struct rpc_pipe_client *cli,
1204                                          TALLOC_CTX *mem_ctx,
1205                                          int argc, const char **argv)
1206 {
1207         POLICY_HND connect_pol, domain_pol, alias_pol;
1208         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1209         uint32_t alias_rid;
1210         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1211         union samr_AliasInfo *info = NULL;
1212         enum samr_AliasInfoEnum level = ALIASINFOALL;
1213
1214         if ((argc < 3) || (argc > 4)) {
1215                 printf("Usage: %s builtin|domain rid [level] [access mask]\n",
1216                         argv[0]);
1217                 return NT_STATUS_OK;
1218         }
1219
1220         sscanf(argv[2], "%i", &alias_rid);
1221
1222         if (argc > 3) {
1223                 level = atoi(argv[3]);
1224         }
1225
1226         if (argc > 4) {
1227                 sscanf(argv[4], "%x", &access_mask);
1228         }
1229
1230         /* Open SAMR handle */
1231
1232         result = try_samr_connects(cli, mem_ctx,
1233                                    SEC_FLAG_MAXIMUM_ALLOWED,
1234                                    &connect_pol);
1235
1236         if (!NT_STATUS_IS_OK(result)) {
1237                 goto done;
1238         }
1239
1240         /* Open handle on domain */
1241
1242         if (strequal(argv[1], "domain")) {
1243
1244                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1245                                                 &connect_pol,
1246                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1247                                                 &domain_sid,
1248                                                 &domain_pol);
1249
1250         } else if (strequal(argv[1], "builtin")) {
1251
1252                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1253                                                 &connect_pol,
1254                                                 SEC_FLAG_MAXIMUM_ALLOWED,
1255                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1256                                                 &domain_pol);
1257
1258         } else {
1259                 return NT_STATUS_OK;
1260         }
1261
1262         if (!NT_STATUS_IS_OK(result)) {
1263                 goto done;
1264         }
1265
1266         /* Open handle on alias */
1267
1268         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1269                                        &domain_pol,
1270                                        access_mask,
1271                                        alias_rid,
1272                                        &alias_pol);
1273         if (!NT_STATUS_IS_OK(result)) {
1274                 goto done;
1275         }
1276
1277         result = rpccli_samr_QueryAliasInfo(cli, mem_ctx,
1278                                             &alias_pol,
1279                                             level,
1280                                             &info);
1281
1282         if (!NT_STATUS_IS_OK(result)) {
1283                 goto done;
1284         }
1285
1286         switch (level) {
1287                 case ALIASINFOALL:
1288                         printf("Name: %s\n", info->all.name.string);
1289                         printf("Description: %s\n", info->all.description.string);
1290                         printf("Num Members: %d\n", info->all.num_members);
1291                         break;
1292                 case ALIASINFONAME:
1293                         printf("Name: %s\n", info->name.string);
1294                         break;
1295                 case ALIASINFODESCRIPTION:
1296                         printf("Description: %s\n", info->description.string);
1297                         break;
1298                 default:
1299                         break;
1300         }
1301
1302         rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1303         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1304         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1305  done:
1306         return result;
1307 }
1308
1309
1310 /* Query delete an alias membership */
1311
1312 static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli,
1313                                       TALLOC_CTX *mem_ctx,
1314                                       int argc, const char **argv)
1315 {
1316         POLICY_HND connect_pol, domain_pol, alias_pol;
1317         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1318         uint32 alias_rid;
1319         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1320
1321         if (argc != 3) {
1322                 printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
1323                 return NT_STATUS_OK;
1324         }
1325
1326         alias_rid = strtoul(argv[2], NULL, 10);
1327
1328         /* Open SAMR handle */
1329
1330         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1331                                    &connect_pol);
1332
1333         if (!NT_STATUS_IS_OK(result))
1334                 goto done;
1335
1336         /* Open handle on domain */
1337
1338         if (StrCaseCmp(argv[1], "domain")==0)
1339                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1340                                                 &connect_pol,
1341                                                 MAXIMUM_ALLOWED_ACCESS,
1342                                                 &domain_sid,
1343                                                 &domain_pol);
1344         else if (StrCaseCmp(argv[1], "builtin")==0)
1345                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1346                                                 &connect_pol,
1347                                                 MAXIMUM_ALLOWED_ACCESS,
1348                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1349                                                 &domain_pol);
1350         else
1351                 return NT_STATUS_INVALID_PARAMETER;
1352
1353         if (!NT_STATUS_IS_OK(result))
1354                 goto done;
1355
1356         /* Open handle on alias */
1357
1358         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1359                                        &domain_pol,
1360                                        access_mask,
1361                                        alias_rid,
1362                                        &alias_pol);
1363         if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
1364                 /* Probably this was a user name, try lookupnames */
1365                 struct samr_Ids rids, types;
1366                 struct lsa_String lsa_acct_name;
1367
1368                 init_lsa_String(&lsa_acct_name, argv[2]);
1369
1370                 result = rpccli_samr_LookupNames(cli, mem_ctx,
1371                                                  &domain_pol,
1372                                                  1,
1373                                                  &lsa_acct_name,
1374                                                  &rids,
1375                                                  &types);
1376
1377                 if (NT_STATUS_IS_OK(result)) {
1378                         result = rpccli_samr_OpenAlias(cli, mem_ctx,
1379                                                        &domain_pol,
1380                                                        access_mask,
1381                                                        rids.ids[0],
1382                                                        &alias_pol);
1383                 }
1384         }
1385
1386         result = rpccli_samr_DeleteDomAlias(cli, mem_ctx,
1387                                             &alias_pol);
1388
1389         if (!NT_STATUS_IS_OK(result))
1390                 goto done;
1391
1392         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1393         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1394  done:
1395         return result;
1396 }
1397
1398 /* Query display info */
1399
1400 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli,
1401                                         TALLOC_CTX *mem_ctx,
1402                                         int argc, const char **argv)
1403 {
1404         POLICY_HND connect_pol, domain_pol;
1405         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1406         uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries = 0, i;
1407         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1408         uint32 info_level = 1;
1409         union samr_DispInfo info;
1410         int loop_count = 0;
1411         bool got_params = False; /* Use get_query_dispinfo_params() or not? */
1412         uint32_t total_size, returned_size;
1413
1414         if (argc > 6) {
1415                 printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
1416                 return NT_STATUS_OK;
1417         }
1418
1419         if (argc >= 2)
1420                 sscanf(argv[1], "%i", &info_level);
1421
1422         if (argc >= 3)
1423                 sscanf(argv[2], "%i", &start_idx);
1424
1425         if (argc >= 4) {
1426                 sscanf(argv[3], "%i", &max_entries);
1427                 got_params = True;
1428         }
1429
1430         if (argc >= 5) {
1431                 sscanf(argv[4], "%i", &max_size);
1432                 got_params = True;
1433         }
1434
1435         if (argc >= 6)
1436                 sscanf(argv[5], "%x", &access_mask);
1437
1438         /* Get sam policy handle */
1439
1440         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1441                                    &connect_pol);
1442
1443         if (!NT_STATUS_IS_OK(result))
1444                 goto done;
1445
1446         /* Get domain policy handle */
1447
1448         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1449                                         &connect_pol,
1450                                         access_mask,
1451                                         &domain_sid,
1452                                         &domain_pol);
1453
1454         if (!NT_STATUS_IS_OK(result))
1455                 goto done;
1456
1457         /* Query display info */
1458
1459         do {
1460
1461                 if (!got_params)
1462                         get_query_dispinfo_params(
1463                                 loop_count, &max_entries, &max_size);
1464
1465                 result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
1466                                                       &domain_pol,
1467                                                       info_level,
1468                                                       start_idx,
1469                                                       max_entries,
1470                                                       max_size,
1471                                                       &total_size,
1472                                                       &returned_size,
1473                                                       &info);
1474
1475                 loop_count++;
1476
1477                 switch (info_level) {
1478                         case 1:
1479                                 num_entries = info.info1.count;
1480                                 break;
1481                         case 2:
1482                                 num_entries = info.info2.count;
1483                                 break;
1484                         case 3:
1485                                 num_entries = info.info3.count;
1486                                 break;
1487                         case 4:
1488                                 num_entries = info.info4.count;
1489                                 break;
1490                         case 5:
1491                                 num_entries = info.info5.count;
1492                                 break;
1493                         default:
1494                                 break;
1495                 }
1496
1497                 start_idx += num_entries;
1498
1499                 if (NT_STATUS_IS_ERR(result))
1500                         break;
1501
1502                 if (num_entries == 0)
1503                         break;
1504
1505                 for (i = 0; i < num_entries; i++) {
1506                         switch (info_level) {
1507                         case 1:
1508                                 display_sam_info_1(&info.info1.entries[i]);
1509                                 break;
1510                         case 2:
1511                                 display_sam_info_2(&info.info2.entries[i]);
1512                                 break;
1513                         case 3:
1514                                 display_sam_info_3(&info.info3.entries[i]);
1515                                 break;
1516                         case 4:
1517                                 display_sam_info_4(&info.info4.entries[i]);
1518                                 break;
1519                         case 5:
1520                                 display_sam_info_5(&info.info5.entries[i]);
1521                                 break;
1522                         }
1523                 }
1524         } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1525
1526         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1527         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1528  done:
1529         return result;
1530 }
1531
1532 /* Query domain info */
1533
1534 static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli,
1535                                        TALLOC_CTX *mem_ctx,
1536                                        int argc, const char **argv)
1537 {
1538         POLICY_HND connect_pol, domain_pol;
1539         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1540         uint32 switch_level = 2;
1541         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1542         union samr_DomainInfo *info = NULL;
1543
1544         if (argc > 3) {
1545                 printf("Usage: %s [info level] [access mask]\n", argv[0]);
1546                 return NT_STATUS_OK;
1547         }
1548
1549         if (argc > 1)
1550                 sscanf(argv[1], "%i", &switch_level);
1551
1552         if (argc > 2)
1553                 sscanf(argv[2], "%x", &access_mask);
1554
1555         /* Get sam policy handle */
1556
1557         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1558                                    &connect_pol);
1559
1560         if (!NT_STATUS_IS_OK(result))
1561                 goto done;
1562
1563         /* Get domain policy handle */
1564
1565         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1566                                         &connect_pol,
1567                                         access_mask,
1568                                         &domain_sid,
1569                                         &domain_pol);
1570
1571         if (!NT_STATUS_IS_OK(result))
1572                 goto done;
1573
1574         /* Query domain info */
1575
1576         result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1577                                              &domain_pol,
1578                                              switch_level,
1579                                              &info);
1580
1581         if (!NT_STATUS_IS_OK(result))
1582                 goto done;
1583
1584         /* Display domain info */
1585
1586         switch (switch_level) {
1587         case 1:
1588                 display_sam_dom_info_1(&info->info1);
1589                 break;
1590         case 2:
1591                 display_sam_dom_info_2(&info->info2);
1592                 break;
1593         case 3:
1594                 display_sam_dom_info_3(&info->info3);
1595                 break;
1596         case 4:
1597                 display_sam_dom_info_4(&info->info4);
1598                 break;
1599         case 5:
1600                 display_sam_dom_info_5(&info->info5);
1601                 break;
1602         case 6:
1603                 display_sam_dom_info_6(&info->info6);
1604                 break;
1605         case 7:
1606                 display_sam_dom_info_7(&info->info7);
1607                 break;
1608         case 8:
1609                 display_sam_dom_info_8(&info->info8);
1610                 break;
1611         case 9:
1612                 display_sam_dom_info_9(&info->info9);
1613                 break;
1614         case 12:
1615                 display_sam_dom_info_12(&info->info12);
1616                 break;
1617         case 13:
1618                 display_sam_dom_info_13(&info->info13);
1619                 break;
1620
1621         default:
1622                 printf("cannot display domain info for switch value %d\n",
1623                        switch_level);
1624                 break;
1625         }
1626
1627  done:
1628
1629         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1630         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1631         return result;
1632 }
1633
1634 /* Create domain user */
1635
1636 static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
1637                                          TALLOC_CTX *mem_ctx,
1638                                          int argc, const char **argv)
1639 {
1640         POLICY_HND connect_pol, domain_pol, user_pol;
1641         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1642         struct lsa_String acct_name;
1643         uint32 acb_info;
1644         uint32 acct_flags, user_rid;
1645         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1646         uint32_t access_granted = 0;
1647
1648         if ((argc < 2) || (argc > 3)) {
1649                 printf("Usage: %s username [access mask]\n", argv[0]);
1650                 return NT_STATUS_OK;
1651         }
1652
1653         init_lsa_String(&acct_name, argv[1]);
1654
1655         if (argc > 2)
1656                 sscanf(argv[2], "%x", &access_mask);
1657
1658         /* Get sam policy handle */
1659
1660         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1661                                    &connect_pol);
1662
1663         if (!NT_STATUS_IS_OK(result))
1664                 goto done;
1665
1666         /* Get domain policy handle */
1667
1668         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1669                                         &connect_pol,
1670                                         access_mask,
1671                                         &domain_sid,
1672                                         &domain_pol);
1673
1674         if (!NT_STATUS_IS_OK(result))
1675                 goto done;
1676
1677         /* Create domain user */
1678
1679         acb_info = ACB_NORMAL;
1680         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
1681                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
1682                      SAMR_USER_ACCESS_SET_PASSWORD |
1683                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
1684                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
1685
1686         result = rpccli_samr_CreateUser2(cli, mem_ctx,
1687                                          &domain_pol,
1688                                          &acct_name,
1689                                          acb_info,
1690                                          acct_flags,
1691                                          &user_pol,
1692                                          &access_granted,
1693                                          &user_rid);
1694
1695         if (!NT_STATUS_IS_OK(result))
1696                 goto done;
1697
1698         result = rpccli_samr_Close(cli, mem_ctx, &user_pol);
1699         if (!NT_STATUS_IS_OK(result)) goto done;
1700
1701         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1702         if (!NT_STATUS_IS_OK(result)) goto done;
1703
1704         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1705         if (!NT_STATUS_IS_OK(result)) goto done;
1706
1707  done:
1708         return result;
1709 }
1710
1711 /* Create domain group */
1712
1713 static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli,
1714                                           TALLOC_CTX *mem_ctx,
1715                                           int argc, const char **argv)
1716 {
1717         POLICY_HND connect_pol, domain_pol, group_pol;
1718         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1719         struct lsa_String grp_name;
1720         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1721         uint32_t rid = 0;
1722
1723         if ((argc < 2) || (argc > 3)) {
1724                 printf("Usage: %s groupname [access mask]\n", argv[0]);
1725                 return NT_STATUS_OK;
1726         }
1727
1728         init_lsa_String(&grp_name, argv[1]);
1729
1730         if (argc > 2)
1731                 sscanf(argv[2], "%x", &access_mask);
1732
1733         /* Get sam policy handle */
1734
1735         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1736                                    &connect_pol);
1737
1738         if (!NT_STATUS_IS_OK(result))
1739                 goto done;
1740
1741         /* Get domain policy handle */
1742
1743         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1744                                         &connect_pol,
1745                                         access_mask,
1746                                         &domain_sid,
1747                                         &domain_pol);
1748
1749         if (!NT_STATUS_IS_OK(result))
1750                 goto done;
1751
1752         /* Create domain user */
1753         result = rpccli_samr_CreateDomainGroup(cli, mem_ctx,
1754                                                &domain_pol,
1755                                                &grp_name,
1756                                                MAXIMUM_ALLOWED_ACCESS,
1757                                                &group_pol,
1758                                                &rid);
1759
1760         if (!NT_STATUS_IS_OK(result))
1761                 goto done;
1762
1763         result = rpccli_samr_Close(cli, mem_ctx, &group_pol);
1764         if (!NT_STATUS_IS_OK(result)) goto done;
1765
1766         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1767         if (!NT_STATUS_IS_OK(result)) goto done;
1768
1769         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1770         if (!NT_STATUS_IS_OK(result)) goto done;
1771
1772  done:
1773         return result;
1774 }
1775
1776 /* Create domain alias */
1777
1778 static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli,
1779                                           TALLOC_CTX *mem_ctx,
1780                                           int argc, const char **argv)
1781 {
1782         POLICY_HND connect_pol, domain_pol, alias_pol;
1783         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1784         struct lsa_String alias_name;
1785         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
1786         uint32_t rid = 0;
1787
1788         if ((argc < 2) || (argc > 3)) {
1789                 printf("Usage: %s aliasname [access mask]\n", argv[0]);
1790                 return NT_STATUS_OK;
1791         }
1792
1793         init_lsa_String(&alias_name, argv[1]);
1794
1795         if (argc > 2)
1796                 sscanf(argv[2], "%x", &access_mask);
1797
1798         /* Get sam policy handle */
1799
1800         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1801                                    &connect_pol);
1802
1803         if (!NT_STATUS_IS_OK(result))
1804                 goto done;
1805
1806         /* Get domain policy handle */
1807
1808         result = rpccli_samr_OpenDomain(cli, mem_ctx,
1809                                         &connect_pol,
1810                                         access_mask,
1811                                         &domain_sid,
1812                                         &domain_pol);
1813
1814         if (!NT_STATUS_IS_OK(result))
1815                 goto done;
1816
1817         /* Create domain user */
1818
1819         result = rpccli_samr_CreateDomAlias(cli, mem_ctx,
1820                                             &domain_pol,
1821                                             &alias_name,
1822                                             MAXIMUM_ALLOWED_ACCESS,
1823                                             &alias_pol,
1824                                             &rid);
1825
1826         if (!NT_STATUS_IS_OK(result))
1827                 goto done;
1828
1829         result = rpccli_samr_Close(cli, mem_ctx, &alias_pol);
1830         if (!NT_STATUS_IS_OK(result)) goto done;
1831
1832         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1833         if (!NT_STATUS_IS_OK(result)) goto done;
1834
1835         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1836         if (!NT_STATUS_IS_OK(result)) goto done;
1837
1838  done:
1839         return result;
1840 }
1841
1842 /* Lookup sam names */
1843
1844 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
1845                                       TALLOC_CTX *mem_ctx,
1846                                       int argc, const char **argv)
1847 {
1848         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1849         POLICY_HND connect_pol, domain_pol;
1850         uint32 num_names;
1851         struct samr_Ids rids, name_types;
1852         int i;
1853         struct lsa_String *names = NULL;;
1854
1855         if (argc < 3) {
1856                 printf("Usage: %s  domain|builtin name1 [name2 [name3] [...]]\n", argv[0]);
1857                 printf("check on the domain SID: S-1-5-21-x-y-z\n");
1858                 printf("or check on the builtin SID: S-1-5-32\n");
1859                 return NT_STATUS_OK;
1860         }
1861
1862         /* Get sam policy and domain handles */
1863
1864         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1865                                    &connect_pol);
1866
1867         if (!NT_STATUS_IS_OK(result))
1868                 goto done;
1869
1870         if (StrCaseCmp(argv[1], "domain")==0)
1871                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1872                                                 &connect_pol,
1873                                                 MAXIMUM_ALLOWED_ACCESS,
1874                                                 &domain_sid,
1875                                                 &domain_pol);
1876         else if (StrCaseCmp(argv[1], "builtin")==0)
1877                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1878                                                 &connect_pol,
1879                                                 MAXIMUM_ALLOWED_ACCESS,
1880                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1881                                                 &domain_pol);
1882         else
1883                 return NT_STATUS_OK;
1884
1885         if (!NT_STATUS_IS_OK(result))
1886                 goto done;
1887
1888         /* Look up names */
1889
1890         num_names = argc - 2;
1891
1892         if ((names = TALLOC_ARRAY(mem_ctx, struct lsa_String, num_names)) == NULL) {
1893                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1894                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1895                 result = NT_STATUS_NO_MEMORY;
1896                 goto done;
1897         }
1898
1899         for (i = 0; i < num_names; i++) {
1900                 init_lsa_String(&names[i], argv[i + 2]);
1901         }
1902
1903         result = rpccli_samr_LookupNames(cli, mem_ctx,
1904                                          &domain_pol,
1905                                          num_names,
1906                                          names,
1907                                          &rids,
1908                                          &name_types);
1909
1910         if (!NT_STATUS_IS_OK(result))
1911                 goto done;
1912
1913         /* Display results */
1914
1915         for (i = 0; i < num_names; i++)
1916                 printf("name %s: 0x%x (%d)\n", names[i].string, rids.ids[i],
1917                        name_types.ids[i]);
1918
1919         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1920         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1921  done:
1922         return result;
1923 }
1924
1925 /* Lookup sam rids */
1926
1927 static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli,
1928                                      TALLOC_CTX *mem_ctx,
1929                                      int argc, const char **argv)
1930 {
1931         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1932         POLICY_HND connect_pol, domain_pol;
1933         uint32_t num_rids, *rids;
1934         struct lsa_Strings names;
1935         struct samr_Ids types;
1936
1937         int i;
1938
1939         if (argc < 3) {
1940                 printf("Usage: %s domain|builtin rid1 [rid2 [rid3] [...]]\n", argv[0]);
1941                 return NT_STATUS_OK;
1942         }
1943
1944         /* Get sam policy and domain handles */
1945
1946         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1947                                    &connect_pol);
1948
1949         if (!NT_STATUS_IS_OK(result))
1950                 goto done;
1951
1952         if (StrCaseCmp(argv[1], "domain")==0)
1953                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1954                                                 &connect_pol,
1955                                                 MAXIMUM_ALLOWED_ACCESS,
1956                                                 &domain_sid,
1957                                                 &domain_pol);
1958         else if (StrCaseCmp(argv[1], "builtin")==0)
1959                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
1960                                                 &connect_pol,
1961                                                 MAXIMUM_ALLOWED_ACCESS,
1962                                                 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
1963                                                 &domain_pol);
1964         else
1965                 return NT_STATUS_OK;
1966
1967         if (!NT_STATUS_IS_OK(result))
1968                 goto done;
1969
1970         /* Look up rids */
1971
1972         num_rids = argc - 2;
1973
1974         if ((rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids)) == NULL) {
1975                 rpccli_samr_Close(cli, mem_ctx, &domain_pol);
1976                 rpccli_samr_Close(cli, mem_ctx, &connect_pol);
1977                 result = NT_STATUS_NO_MEMORY;
1978                 goto done;
1979         }
1980
1981         for (i = 0; i < argc - 2; i++)
1982                 sscanf(argv[i + 2], "%i", &rids[i]);
1983
1984         result = rpccli_samr_LookupRids(cli, mem_ctx,
1985                                         &domain_pol,
1986                                         num_rids,
1987                                         rids,
1988                                         &names,
1989                                         &types);
1990
1991         if (!NT_STATUS_IS_OK(result) &&
1992             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
1993                 goto done;
1994
1995         /* Display results */
1996
1997         for (i = 0; i < num_rids; i++) {
1998                 printf("rid 0x%x: %s (%d)\n",
1999                         rids[i], names.names[i].string, types.ids[i]);
2000         }
2001
2002         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2003         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2004  done:
2005         return result;
2006 }
2007
2008 /* Delete domain group */
2009
2010 static NTSTATUS cmd_samr_delete_dom_group(struct rpc_pipe_client *cli,
2011                                          TALLOC_CTX *mem_ctx,
2012                                          int argc, const char **argv)
2013 {
2014         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2015         POLICY_HND connect_pol, domain_pol, group_pol;
2016         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2017
2018         if ((argc < 2) || (argc > 3)) {
2019                 printf("Usage: %s groupname\n", argv[0]);
2020                 return NT_STATUS_OK;
2021         }
2022
2023         if (argc > 2)
2024                 sscanf(argv[2], "%x", &access_mask);
2025
2026         /* Get sam policy and domain handles */
2027
2028         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2029                                    &connect_pol);
2030
2031         if (!NT_STATUS_IS_OK(result))
2032                 goto done;
2033
2034         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2035                                         &connect_pol,
2036                                         MAXIMUM_ALLOWED_ACCESS,
2037                                         &domain_sid,
2038                                         &domain_pol);
2039
2040         if (!NT_STATUS_IS_OK(result))
2041                 goto done;
2042
2043         /* Get handle on group */
2044
2045         {
2046                 struct samr_Ids group_rids, name_types;
2047                 struct lsa_String lsa_acct_name;
2048
2049                 init_lsa_String(&lsa_acct_name, argv[1]);
2050
2051                 result = rpccli_samr_LookupNames(cli, mem_ctx,
2052                                                  &domain_pol,
2053                                                  1,
2054                                                  &lsa_acct_name,
2055                                                  &group_rids,
2056                                                  &name_types);
2057                 if (!NT_STATUS_IS_OK(result))
2058                         goto done;
2059
2060                 result = rpccli_samr_OpenGroup(cli, mem_ctx,
2061                                                &domain_pol,
2062                                                access_mask,
2063                                                group_rids.ids[0],
2064                                                &group_pol);
2065
2066                 if (!NT_STATUS_IS_OK(result))
2067                         goto done;
2068         }
2069
2070         /* Delete group */
2071
2072         result = rpccli_samr_DeleteDomainGroup(cli, mem_ctx,
2073                                                &group_pol);
2074
2075         if (!NT_STATUS_IS_OK(result))
2076                 goto done;
2077
2078         /* Display results */
2079
2080         rpccli_samr_Close(cli, mem_ctx, &group_pol);
2081         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2082         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2083
2084  done:
2085         return result;
2086 }
2087
2088 /* Delete domain user */
2089
2090 static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli,
2091                                          TALLOC_CTX *mem_ctx,
2092                                          int argc, const char **argv)
2093 {
2094         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2095         POLICY_HND connect_pol, domain_pol, user_pol;
2096         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2097
2098         if ((argc < 2) || (argc > 3)) {
2099                 printf("Usage: %s username\n", argv[0]);
2100                 return NT_STATUS_OK;
2101         }
2102
2103         if (argc > 2)
2104                 sscanf(argv[2], "%x", &access_mask);
2105
2106         /* Get sam policy and domain handles */
2107
2108         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2109                                    &connect_pol);
2110
2111         if (!NT_STATUS_IS_OK(result))
2112                 goto done;
2113
2114         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2115                                         &connect_pol,
2116                                         MAXIMUM_ALLOWED_ACCESS,
2117                                         &domain_sid,
2118                                         &domain_pol);
2119
2120         if (!NT_STATUS_IS_OK(result))
2121                 goto done;
2122
2123         /* Get handle on user */
2124
2125         {
2126                 struct samr_Ids user_rids, name_types;
2127                 struct lsa_String lsa_acct_name;
2128
2129                 init_lsa_String(&lsa_acct_name, argv[1]);
2130
2131                 result = rpccli_samr_LookupNames(cli, mem_ctx,
2132                                                  &domain_pol,
2133                                                  1,
2134                                                  &lsa_acct_name,
2135                                                  &user_rids,
2136                                                  &name_types);
2137
2138                 if (!NT_STATUS_IS_OK(result))
2139                         goto done;
2140
2141                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2142                                               &domain_pol,
2143                                               access_mask,
2144                                               user_rids.ids[0],
2145                                               &user_pol);
2146
2147                 if (!NT_STATUS_IS_OK(result))
2148                         goto done;
2149         }
2150
2151         /* Delete user */
2152
2153         result = rpccli_samr_DeleteUser(cli, mem_ctx,
2154                                         &user_pol);
2155
2156         if (!NT_STATUS_IS_OK(result))
2157                 goto done;
2158
2159         /* Display results */
2160
2161         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2162         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2163         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2164
2165  done:
2166         return result;
2167 }
2168
2169 /**********************************************************************
2170  * Query user security object
2171  */
2172 static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
2173                                     TALLOC_CTX *mem_ctx,
2174                                     int argc, const char **argv)
2175 {
2176         POLICY_HND connect_pol, domain_pol, user_pol, *pol;
2177         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2178         uint32 sec_info = DACL_SECURITY_INFORMATION;
2179         fstring server;
2180         uint32 user_rid = 0;
2181         TALLOC_CTX *ctx = NULL;
2182         SEC_DESC_BUF *sec_desc_buf=NULL;
2183         bool domain = False;
2184
2185         ctx=talloc_init("cmd_samr_query_sec_obj");
2186
2187         if ((argc < 1) || (argc > 3)) {
2188                 printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
2189                 printf("\tSpecify rid for security on user, -d for security on domain\n");
2190                 talloc_destroy(ctx);
2191                 return NT_STATUS_OK;
2192         }
2193
2194         if (argc > 1) {
2195                 if (strcmp(argv[1], "-d") == 0)
2196                         domain = True;
2197                 else
2198                         sscanf(argv[1], "%i", &user_rid);
2199         }
2200
2201         if (argc == 3) {
2202                 sec_info = atoi(argv[2]);
2203         }
2204
2205         slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
2206         strupper_m(server);
2207         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2208                                    &connect_pol);
2209
2210         if (!NT_STATUS_IS_OK(result))
2211                 goto done;
2212
2213         if (domain || user_rid)
2214                 result = rpccli_samr_OpenDomain(cli, mem_ctx,
2215                                                 &connect_pol,
2216                                                 MAXIMUM_ALLOWED_ACCESS,
2217                                                 &domain_sid,
2218                                                 &domain_pol);
2219
2220         if (!NT_STATUS_IS_OK(result))
2221                 goto done;
2222
2223         if (user_rid)
2224                 result = rpccli_samr_OpenUser(cli, mem_ctx,
2225                                               &domain_pol,
2226                                               MAXIMUM_ALLOWED_ACCESS,
2227                                               user_rid,
2228                                               &user_pol);
2229
2230         if (!NT_STATUS_IS_OK(result))
2231                 goto done;
2232
2233         /* Pick which query pol to use */
2234
2235         pol = &connect_pol;
2236
2237         if (domain)
2238                 pol = &domain_pol;
2239
2240         if (user_rid)
2241                 pol = &user_pol;
2242
2243         /* Query SAM security object */
2244
2245         result = rpccli_samr_QuerySecurity(cli, mem_ctx,
2246                                            pol,
2247                                            sec_info,
2248                                            &sec_desc_buf);
2249
2250         if (!NT_STATUS_IS_OK(result))
2251                 goto done;
2252
2253         display_sec_desc(sec_desc_buf->sd);
2254
2255         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2256         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2257         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2258 done:
2259         talloc_destroy(ctx);
2260         return result;
2261 }
2262
2263 static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli,
2264                                            TALLOC_CTX *mem_ctx,
2265                                            int argc, const char **argv)
2266 {
2267         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2268         POLICY_HND connect_pol, domain_pol, user_pol;
2269         struct samr_PwInfo info;
2270         uint32_t rid;
2271
2272         if (argc != 2) {
2273                 printf("Usage: %s rid\n", argv[0]);
2274                 return NT_STATUS_OK;
2275         }
2276
2277         sscanf(argv[1], "%i", &rid);
2278
2279         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2280                                    &connect_pol);
2281
2282         if (!NT_STATUS_IS_OK(result)) {
2283                 goto done;
2284         }
2285
2286         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2287                                         &connect_pol,
2288                                         MAXIMUM_ALLOWED_ACCESS,
2289                                         &domain_sid,
2290                                         &domain_pol);
2291
2292         if (!NT_STATUS_IS_OK(result)) {
2293                 goto done;
2294         }
2295
2296         result = rpccli_samr_OpenUser(cli, mem_ctx,
2297                                       &domain_pol,
2298                                       MAXIMUM_ALLOWED_ACCESS,
2299                                       rid,
2300                                       &user_pol);
2301
2302         if (!NT_STATUS_IS_OK(result)) {
2303                 goto done;
2304         }
2305
2306         result = rpccli_samr_GetUserPwInfo(cli, mem_ctx, &user_pol, &info);
2307         if (NT_STATUS_IS_OK(result)) {
2308                 printf("min_password_length: %d\n", info.min_password_length);
2309                 printf("%s\n",
2310                         NDR_PRINT_STRUCT_STRING(mem_ctx,
2311                                 samr_PasswordProperties, &info.password_properties));
2312         }
2313
2314  done:
2315         rpccli_samr_Close(cli, mem_ctx, &user_pol);
2316         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2317         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2318
2319         return result;
2320 }
2321
2322 static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
2323                                         TALLOC_CTX *mem_ctx,
2324                                         int argc, const char **argv)
2325 {
2326         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2327         struct lsa_String domain_name;
2328         struct samr_PwInfo info;
2329
2330         if (argc < 1 || argc > 3) {
2331                 printf("Usage: %s <domain>\n", argv[0]);
2332                 return NT_STATUS_OK;
2333         }
2334
2335         init_lsa_String(&domain_name, argv[1]);
2336
2337         result = rpccli_samr_GetDomPwInfo(cli, mem_ctx, &domain_name, &info);
2338
2339         if (NT_STATUS_IS_OK(result)) {
2340                 printf("min_password_length: %d\n", info.min_password_length);
2341                 display_password_properties(info.password_properties);
2342         }
2343
2344         return result;
2345 }
2346
2347 /* Look up domain name */
2348
2349 static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli,
2350                                        TALLOC_CTX *mem_ctx,
2351                                        int argc, const char **argv)
2352 {
2353         POLICY_HND connect_pol, domain_pol;
2354         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2355         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2356         fstring sid_string;
2357         struct lsa_String domain_name;
2358         DOM_SID *sid = NULL;
2359
2360         if (argc != 2) {
2361                 printf("Usage: %s domain_name\n", argv[0]);
2362                 return NT_STATUS_OK;
2363         }
2364
2365         init_lsa_String(&domain_name, argv[1]);
2366
2367         result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol);
2368
2369         if (!NT_STATUS_IS_OK(result))
2370                 goto done;
2371
2372         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2373                                         &connect_pol,
2374                                         access_mask,
2375                                         &domain_sid,
2376                                         &domain_pol);
2377
2378         if (!NT_STATUS_IS_OK(result))
2379                 goto done;
2380
2381         result = rpccli_samr_LookupDomain(cli, mem_ctx,
2382                                           &connect_pol,
2383                                           &domain_name,
2384                                           &sid);
2385
2386         if (NT_STATUS_IS_OK(result)) {
2387                 sid_to_fstring(sid_string, sid);
2388                 printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
2389                        argv[1], sid_string);
2390         }
2391
2392         rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2393         rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2394 done:
2395         return result;
2396 }
2397
2398 /* Change user password */
2399
2400 static NTSTATUS cmd_samr_chgpasswd2(struct rpc_pipe_client *cli,
2401                                     TALLOC_CTX *mem_ctx,
2402                                     int argc, const char **argv)
2403 {
2404         POLICY_HND connect_pol, domain_pol;
2405         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2406         const char *user, *oldpass, *newpass;
2407         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2408
2409         if (argc < 3) {
2410                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2411                 return NT_STATUS_INVALID_PARAMETER;
2412         }
2413
2414         user = argv[1];
2415         oldpass = argv[2];
2416         newpass = argv[3];
2417
2418         /* Get sam policy handle */
2419
2420         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2421                                    &connect_pol);
2422
2423         if (!NT_STATUS_IS_OK(result))
2424                 goto done;
2425
2426         /* Get domain policy handle */
2427
2428         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2429                                         &connect_pol,
2430                                         access_mask,
2431                                         &domain_sid,
2432                                         &domain_pol);
2433
2434         if (!NT_STATUS_IS_OK(result))
2435                 goto done;
2436
2437         /* Change user password */
2438         result = rpccli_samr_chgpasswd_user(cli, mem_ctx, user, newpass, oldpass);
2439
2440         if (!NT_STATUS_IS_OK(result))
2441                 goto done;
2442
2443         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2444         if (!NT_STATUS_IS_OK(result)) goto done;
2445
2446         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2447         if (!NT_STATUS_IS_OK(result)) goto done;
2448
2449  done:
2450         return result;
2451 }
2452
2453
2454 /* Change user password */
2455
2456 static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli,
2457                                     TALLOC_CTX *mem_ctx,
2458                                     int argc, const char **argv)
2459 {
2460         POLICY_HND connect_pol, domain_pol;
2461         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2462         const char *user, *oldpass, *newpass;
2463         uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
2464         struct samr_DomInfo1 *info = NULL;
2465         struct samr_ChangeReject *reject = NULL;
2466
2467         if (argc < 3) {
2468                 printf("Usage: %s username oldpass newpass\n", argv[0]);
2469                 return NT_STATUS_INVALID_PARAMETER;
2470         }
2471
2472         user = argv[1];
2473         oldpass = argv[2];
2474         newpass = argv[3];
2475
2476         /* Get sam policy handle */
2477
2478         result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2479                                    &connect_pol);
2480
2481         if (!NT_STATUS_IS_OK(result))
2482                 goto done;
2483
2484         /* Get domain policy handle */
2485
2486         result = rpccli_samr_OpenDomain(cli, mem_ctx,
2487                                         &connect_pol,
2488                                         access_mask,
2489                                         &domain_sid,
2490                                         &domain_pol);
2491
2492         if (!NT_STATUS_IS_OK(result))
2493                 goto done;
2494
2495         /* Change user password */
2496         result = rpccli_samr_chgpasswd3(cli, mem_ctx,
2497                                         user,
2498                                         newpass,
2499                                         oldpass,
2500                                         &info,
2501                                         &reject);
2502
2503         if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
2504
2505                 display_sam_dom_info_1(info);
2506
2507                 switch (reject->reason) {
2508                         case SAMR_REJECT_TOO_SHORT:
2509                                 d_printf("SAMR_REJECT_TOO_SHORT\n");
2510                                 break;
2511                         case SAMR_REJECT_IN_HISTORY:
2512                                 d_printf("SAMR_REJECT_IN_HISTORY\n");
2513                                 break;
2514                         case SAMR_REJECT_COMPLEXITY:
2515                                 d_printf("SAMR_REJECT_COMPLEXITY\n");
2516                                 break;
2517                         case SAMR_REJECT_OTHER:
2518                                 d_printf("SAMR_REJECT_OTHER\n");
2519                                 break;
2520                         default:
2521                                 d_printf("unknown reject reason: %d\n",
2522                                         reject->reason);
2523                                 break;
2524                 }
2525         }
2526
2527         if (!NT_STATUS_IS_OK(result))
2528                 goto done;
2529
2530         result = rpccli_samr_Close(cli, mem_ctx, &domain_pol);
2531         if (!NT_STATUS_IS_OK(result)) goto done;
2532
2533         result = rpccli_samr_Close(cli, mem_ctx, &connect_pol);
2534         if (!NT_STATUS_IS_OK(result)) goto done;
2535
2536  done:
2537         return result;
2538 }
2539
2540 /* List of commands exported by this module */
2541
2542 struct cmd_set samr_commands[] = {
2543
2544         { "SAMR" },
2545
2546         { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
2547         { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
2548         { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
2549         { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
2550         { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
2551         { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
2552         { "queryaliasinfo",     RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasinfo,   NULL, PI_SAMR, NULL,    "Query alias info",       "" },
2553         { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
2554         { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
2555         { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
2556         { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
2557         { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
2558         { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
2559         { "enumdomains",        RPC_RTYPE_NTSTATUS, cmd_samr_enum_domains,          NULL, PI_SAMR, NULL,        "Enumerate domains",  "" },
2560
2561         { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
2562         { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
2563         { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
2564         { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
2565         { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
2566         { "deletedomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_group,      NULL, PI_SAMR, NULL,        "Delete domain group",     "" },
2567         { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
2568         { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
2569         { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
2570         { "getusrdompwinfo",    RPC_RTYPE_NTSTATUS, cmd_samr_get_usrdom_pwinfo,     NULL, PI_SAMR, NULL, "Retrieve user domain password info", "" },
2571
2572         { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
2573         { "chgpasswd2",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd2,            NULL, PI_SAMR, NULL, "Change user password", "" },
2574         { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd3,            NULL, PI_SAMR, NULL, "Change user password", "" },
2575         { NULL }
2576 };